From owner-freebsd-net@FreeBSD.ORG Fri Jul 26 14:51:38 2013 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 1C97677D for ; Fri, 26 Jul 2013 14:51:38 +0000 (UTC) (envelope-from melifaro@yandex-team.ru) Received: from forward-corp1g.mail.yandex.net (forward-corp1g.mail.yandex.net [IPv6:2a02:6b8:0:1402::10]) by mx1.freebsd.org (Postfix) with ESMTP id A39302F81 for ; Fri, 26 Jul 2013 14:51:37 +0000 (UTC) Received: from smtpcorp4.mail.yandex.net (smtpcorp4.mail.yandex.net [95.108.252.2]) by forward-corp1g.mail.yandex.net (Yandex) with ESMTP id 8F2DA3660149 for ; Fri, 26 Jul 2013 18:51:33 +0400 (MSK) Received: from smtpcorp4.mail.yandex.net (localhost [127.0.0.1]) by smtpcorp4.mail.yandex.net (Yandex) with ESMTP id 7679D2C00D9 for ; Fri, 26 Jul 2013 18:51:33 +0400 (MSK) Received: from dhcp170-36-red.yandex.net (dhcp170-36-red.yandex.net [95.108.170.36]) by smtpcorp4.mail.yandex.net (nwsmtp/Yandex) with ESMTP id Fjh5ceiw6T-pXxeCXI7; Fri, 26 Jul 2013 18:51:33 +0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1374850293; bh=PG3tAwxHVveTSdodvC0hlowbSpA+lu1cfQwEKXzD5fg=; h=Message-ID:Date:From:User-Agent:MIME-Version:To:Subject: Content-Type; b=Ex9D2eRRMLHYuAlTXoRCu6Wr66PTF7LJlmeJCThDwMzwKgUZdK+1ncWEeVnIsk8MS fUecmAH+J6woLU+4bxHzPvlSAaIHyty5WiCyuHJk9t8GAQv8sKl6+91noyXLuJQL7k GWoh1nMN/GvJcPh6BT8UOW+bVLjdnuRV+VKQZoRo= Authentication-Results: smtpcorp4.mail.yandex.net; dkim=pass header.i=@yandex-team.ru Message-ID: <51F28CBD.8040501@yandex-team.ru> Date: Fri, 26 Jul 2013 18:50:37 +0400 From: "Alexander V. Chernikov" User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:17.0) Gecko/20130418 Thunderbird/17.0.5 MIME-Version: 1.0 To: freebsd-net@freebsd.org Subject: [patch] pxeloader sometimes "freezes" if called via pxechain Content-Type: multipart/mixed; boundary="------------060004010402060108050100" X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Jul 2013 14:51:38 -0000 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--