Date: Fri, 26 Jul 2013 18:50:37 +0400 From: "Alexander V. Chernikov" <melifaro@yandex-team.ru> To: freebsd-net@freebsd.org Subject: [patch] pxeloader sometimes "freezes" if called via pxechain Message-ID: <51F28CBD.8040501@yandex-team.ru>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------060004010402060108050100 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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. --------------060004010402060108050100 Content-Type: text/plain; charset=UTF-8; name="pxechain_fix.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="pxechain_fix.diff" 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) { --------------060004010402060108050100--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?51F28CBD.8040501>