diff options
author | glebius <glebius@FreeBSD.org> | 2005-11-08 12:05:57 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-11-08 12:05:57 +0000 |
commit | fbcfe1441aaf2a1431c26b44cf0dfa18788b5c9b (patch) | |
tree | 5cd4668559e287672d68fa8f0af954f5210ef559 /sys/netinet/if_ether.c | |
parent | e5230bfcdad73ee3f96ad386ca8db45c9cbc80a1 (diff) | |
download | FreeBSD-src-fbcfe1441aaf2a1431c26b44cf0dfa18788b5c9b.zip FreeBSD-src-fbcfe1441aaf2a1431c26b44cf0dfa18788b5c9b.tar.gz |
Rework ARP retransmission algorythm so that ARP requests are
retransmitted without suppression, while there is demand for
such ARP entry. As before, retransmission is rate limited to
one packet per second. Details:
- Remove net.link.ether.inet.host_down_time
- Do not set/clear RTF_REJECT flag on route, to
avoid rt_check() returning error. We will generate error
ourselves.
- Return EWOULDBLOCK on first arp_maxtries failed
requests , and return EHOSTDOWN/EHOSTUNREACH
on further requests.
- Retransmit ARP request always, independently from return
code. Ratelimit to 1 pps.
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r-- | sys/netinet/if_ether.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 89b7f40..a43e469 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -79,14 +79,11 @@ SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); /* 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 llinfo_arp { 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; @@ -150,7 +146,6 @@ arptimer(void * __unused unused) 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 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, /* * 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 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, 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 have tried less than arp_maxtries. It + * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH + * if we have already sent arp_maxtries ARP requests. Retransmit the + * ARP request, but not faster than one request per second. + */ + if (la->la_asked < arp_maxtries) + 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,7 +784,6 @@ match: } 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; hold = la->la_hold; |