From owner-freebsd-arch@FreeBSD.ORG Mon Nov 7 19:41:57 2005 Return-Path: X-Original-To: arch@FreeBSD.org Delivered-To: freebsd-arch@FreeBSD.ORG Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A3EF516A428 for ; Mon, 7 Nov 2005 19:41:57 +0000 (GMT) (envelope-from glebius@FreeBSD.org) Received: from cell.sick.ru (cell.sick.ru [217.72.144.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0ABB343D5D for ; Mon, 7 Nov 2005 19:41:55 +0000 (GMT) (envelope-from glebius@FreeBSD.org) Received: from cell.sick.ru (glebius@localhost [127.0.0.1]) by cell.sick.ru (8.13.3/8.13.3) with ESMTP id jA7Jfr4q065638 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 7 Nov 2005 22:41:53 +0300 (MSK) (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by cell.sick.ru (8.13.3/8.13.1/Submit) id jA7Jfqou065637 for arch@freebsd.org; Mon, 7 Nov 2005 22:41:52 +0300 (MSK) (envelope-from glebius@FreeBSD.org) X-Authentication-Warning: cell.sick.ru: glebius set sender to glebius@FreeBSD.org using -f Date: Mon, 7 Nov 2005 22:41:52 +0300 From: Gleb Smirnoff To: arch@FreeBSD.org Message-ID: <20051107194152.GF91530@cell.sick.ru> References: <20051107140451.GU91530@cell.sick.ru> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="YkJPYEFdoxh/AXLE" Content-Disposition: inline In-Reply-To: <20051107140451.GU91530@cell.sick.ru> User-Agent: Mutt/1.5.6i Cc: Subject: Re: ARP request retransmitting X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Nov 2005 19:41:57 -0000 --YkJPYEFdoxh/AXLE Content-Type: text/plain; charset=koi8-r Content-Disposition: inline On Mon, Nov 07, 2005 at 05:04:51PM +0300, Gleb Smirnoff wrote: T> I suggest to keep sending ARP requests while there is a demand for T> this (we are trying to transmit packets to this particular IP), T> ratelimiting these requests to one per second. This will help in a T> quite common case, when some host on net is rebooting, and we are T> waiting for him to come up, and notice this only after 1 - 20 seconds T> since the time it is reachable. Here is code explaining what I am speaking about. -- Totus tuus, Glebius. GLEBIUS-RIPN GLEB-RIPE --YkJPYEFdoxh/AXLE Content-Type: text/plain; charset=koi8-r Content-Disposition: attachment; filename="arp.request.diff" Index: if_ether.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/if_ether.c,v retrieving revision 1.144 diff -u -r1.144 if_ether.c --- if_ether.c 4 Oct 2005 19:50:02 -0000 1.144 +++ if_ether.c 7 Nov 2005 19:39:10 -0000 @@ -79,14 +79,11 @@ /* timer values */ static int arpt_prune = (5*60*1); /* walk list every 5 minutes */ static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ -static int arpt_down = 20; /* once declared down, don't send for 20 sec */ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW, &arpt_prune, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, &arpt_keep, 0, ""); -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW, - &arpt_down, 0, ""); #define rt_expire rt_rmx.rmx_expire @@ -95,8 +92,7 @@ struct rtentry *la_rt; struct mbuf *la_hold; /* last packet until resolved/timeout */ u_short la_preempt; /* countdown for pre-expiry arps */ - u_short la_asked; /* #times we QUERIED following expiration */ -#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */ + u_short la_asked; /* # requests sent */ }; static LIST_HEAD(, llinfo_arp) llinfo_arp; @@ -104,13 +100,13 @@ static struct ifqueue arpintrq; static int arp_allocated; -static int arp_maxtries = 5; +static int arp_renew = 5; /* request this seconds before expiry */ static int useloopback = 1; /* use loopback interface for local traffic */ static int arp_proxyall = 0; static struct callout arp_callout; -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, - &arp_maxtries, 0, ""); +SYSCTL_INT(_net_link_ether_inet, OID_AUTO, renew, CTLFLAG_RW, + &arp_renew, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, &useloopback, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, @@ -150,7 +146,6 @@ if (rt->rt_refcnt > 1) { sdl->sdl_alen = 0; la->la_preempt = la->la_asked = 0; - rt->rt_flags &= ~RTF_REJECT; RT_UNLOCK(rt); continue; } @@ -448,8 +443,7 @@ /* * If entry has an expiry time and it is approaching, - * see if we need to send an ARP request within this - * arpt_down interval. + * send an ARP request. */ if ((rt->rt_expire != 0) && (time_uptime + la->la_preempt > rt->rt_expire)) { @@ -485,29 +479,33 @@ if (la->la_hold) m_freem(la->la_hold); la->la_hold = m; - if (rt->rt_expire) { - rt->rt_flags &= ~RTF_REJECT; - if (la->la_asked == 0 || rt->rt_expire != time_uptime) { - rt->rt_expire = time_uptime; - if (la->la_asked++ < arp_maxtries) { - struct in_addr sin = - SIN(rt->rt_ifa->ifa_addr)->sin_addr; - RT_UNLOCK(rt); - arprequest(ifp, &sin, &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); - return (EWOULDBLOCK); - } else { - rt->rt_flags |= RTF_REJECT; - rt->rt_expire += arpt_down; - la->la_asked = 0; - la->la_preempt = arp_maxtries; - } + KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry")); - } - } - RT_UNLOCK(rt); - return (EWOULDBLOCK); + /* + * Return EWOULDBLOCK if we are sending first request now, it + * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH + * in case we have already sent ARP requests. Retransmit the + * ARP request, but not faster than one request per second. + */ + if (la->la_asked == 0) + error = EWOULDBLOCK; /* First request. */ + else + error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH; + + if (la->la_asked++ == 0 || rt->rt_expire != time_uptime) { + struct in_addr sin = + SIN(rt->rt_ifa->ifa_addr)->sin_addr; + + rt->rt_expire = time_uptime; + RT_UNLOCK(rt); + + arprequest(ifp, &sin, &SIN(dst)->sin_addr, + IF_LLADDR(ifp)); + } else + RT_UNLOCK(rt); + + return (error); } /* @@ -786,9 +784,8 @@ } if (rt->rt_expire) rt->rt_expire = time_uptime + arpt_keep; - rt->rt_flags &= ~RTF_REJECT; la->la_asked = 0; - la->la_preempt = arp_maxtries; + la->la_preempt = arp_renew; hold = la->la_hold; la->la_hold = NULL; RT_UNLOCK(rt); --YkJPYEFdoxh/AXLE--