Hello list!

Currently our pxeloader prefer to get NFS server information by its own instead of using cached one.

This is how it is done:
pxe_open() indirectly opens socket (PXENV_UDP_OPEN, with cached IP from BOOTPLAYER). After that, bootp() resolve is done, resulting in (probably) more "valid" server address.

Current code incorrectly assumes that DHCP server returns the same IP address for given MAC regardless of other parameters. If this is not true, outgoing packets are send via cached IP (since the only way to change source IP is to reopen pxe handle), but receive filter is programmed to use "new" one. This leads to random timeouts in some DHCP configurations.

What we can probably do:
1) try cached server address if any without doing DHCP (possibly breaking some users setups) 2) try to reopen PXE handle with new address (netif_close() / netif_open(), which is complicated due to many open/close calls reading 'old' address)
3) save address/gw and restore them (if differs) before/after bootp().
4) probably a bunch of others

Patch implementing (3) is attached.
I'll commit it on the end of next week if there will be no objections.




Index: sys/boot/i386/libi386/pxe.c
===================================================================
--- sys/boot/i386/libi386/pxe.c (revision 239353)
+++ sys/boot/i386/libi386/pxe.c (working copy)
@@ -255,11 +255,17 @@ pxe_open(struct open_file *f, ...)
     char temp[FNAME_SIZE];
     int error = 0;
     int i;
+    struct in_addr _myip, _gateip, _rootip;
+    struct iodesc *d;
        
     va_start(args, f);
     devname = va_arg(args, char*);
     va_end(args);
 
+    _myip.s_addr = INADDR_ANY;
+    _gateip.s_addr = INADDR_ANY;
+    _rootip.s_addr = INADDR_ANY;
+
     /* On first open, do netif open, mount, etc. */
     if (pxe_opens == 0) {
        /* Find network interface. */
@@ -271,6 +277,16 @@ pxe_open(struct open_file *f, ...)
            }
            if (pxe_debug)
                printf("pxe_open: netif_open() succeeded\n");
+           if (bootplayer.yip != INADDR_ANY) {
+               _myip.s_addr = bootplayer.yip;
+               _rootip.s_addr = bootplayer.sip;
+               _gateip.s_addr = bootplayer.gip;
+               if (pxe_debug) {
+                   printf("pxe_open: cached myip: %s\n", inet_ntoa(_myip));
+                   printf("pxe_open: cached gw: %s\n", inet_ntoa(_gateip));
+                   printf("pxe_open: cached server: %s\n", inet_ntoa(_rootip));
+               }
+           }
        }
        if (rootip.s_addr == 0) {
                /*
@@ -280,9 +296,24 @@ pxe_open(struct open_file *f, ...)
                 * which brought us to life and a default rootpath.
                 */
                bootp(pxe_sock, BOOTP_PXE);
+               if (_myip.s_addr != INADDR_ANY && _myip.s_addr != myip.s_addr) {
+                       if (!(d = socktodesc(pxe_sock))) {
+                               printf("pxe_open: bad socket. %d\n", pxe_sock);
+                               return (ENXIO);
+                       }
+                       if (pxe_debug) {
+                               printf("pxe_open: reverting IP back to %s\n",
+                                   inet_ntoa(_myip));
+                               printf("pxe_open: (unused)DHCP IP is %s\n",
+                                   inet_ntoa(myip));
+                       }
+                       myip = _myip;
+                       gateip = _gateip;
+                       d->myip = myip;
+               }
                if (rootip.s_addr == 0)
                        rootip.s_addr = bootplayer.sip;
-               if (!rootpath[0])
+               if ((!rootpath[0]) || (!strcmp(rootpath, "/")))
                        strcpy(rootpath, PXENFSROOTPATH);
 
                for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++)
@@ -297,6 +328,7 @@ pxe_open(struct open_file *f, ...)
                }
                printf("pxe_open: server addr: %s\n", inet_ntoa(rootip));
                printf("pxe_open: server path: %s\n", rootpath);
+               printf("pxe_open: local addr: %s\n", inet_ntoa(myip));
                printf("pxe_open: gateway ip:  %s\n", inet_ntoa(gateip));
 
                setenv("boot.netif.ip", inet_ntoa(myip), 1);
@@ -590,6 +622,9 @@ pxe_netif_probe(struct netif *nif, void *machdep_h
 
        bzero(udpopen_p, sizeof(*udpopen_p));
        udpopen_p->src_ip = bootplayer.yip;
+#ifdef PXE_DEBUG
+       printf("pxe_netif_probe: IP=%s\n", inet_ntoa(udpopen->src_ip));
+#endif
        pxe_call(PXENV_UDP_OPEN);
 
        if (udpopen_p->status != 0) {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[email protected]"

Reply via email to