[patch] pxeloader sometimes "freezes" if called via pxechain

Alexander V. Chernikov melifaro at yandex-team.ru
Fri Jul 26 14:51:38 UTC 2013


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.




-------------- next part --------------
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) {


More information about the freebsd-net mailing list