Claudio Jeker(cje...@diehard.n-r-g.com) on 2019.01.18 00:11:27 +0100: > On Thu, Jan 17, 2019 at 03:21:58PM -0700, Theo de Raadt wrote: > > - if (la_hold_total < LA_HOLD_TOTAL && la_hold_total < nmbclust / 64) > > { > > + if (la_hold_total < nmbclust / 64) { > > > > I have disagreed with claudio about this aspect of the diff. > > > > The refresh attempt is the crucial problem to fix, because of what it has > > done to tcp with slowstart etc. > > > > If refresh works, we may not need to increase the hold mbufs count at all. > > > > Secondly, I don't like how this is coupled to the MD nmbclust value. > > Some architectures have that very large, others very small, for other > > reasons. Bringing it into play here isn't right. > > Updated diff that changes this limit back to LA_HOLD_TOTAL (100) but > removes the la_hold_total < nmbclust / 64 check.
It works here. Code reads ok fwiw. /Benno > -- > :wq Claudio > > Index: if_ether.c > =================================================================== > RCS file: /cvs/src/sys/netinet/if_ether.c,v > retrieving revision 1.237 > diff -u -p -r1.237 if_ether.c > --- if_ether.c 30 Nov 2018 09:27:56 -0000 1.237 > +++ if_ether.c 17 Jan 2019 22:59:59 -0000 > @@ -67,8 +67,9 @@ > struct llinfo_arp { > LIST_ENTRY(llinfo_arp) la_list; > struct rtentry *la_rt; /* backpointer to rtentry */ > - long la_asked; /* last time we QUERIED */ > struct mbuf_list la_ml; /* packet hold queue */ > + time_t la_refreshed; /* when was refresh sent */ > + int la_asked; /* number of queries sent */ > }; > #define LA_HOLD_QUEUE 10 > #define LA_HOLD_TOTAL 100 > @@ -119,7 +120,7 @@ arptimer(void *arg) > LIST_FOREACH_SAFE(la, &arp_list, la_list, nla) { > struct rtentry *rt = la->la_rt; > > - if (rt->rt_expire && rt->rt_expire <= time_uptime) > + if (rt->rt_expire && rt->rt_expire < time_uptime) > arptfree(rt); /* timer has expired; clear */ > } > NET_UNLOCK(); > @@ -130,7 +131,6 @@ arp_rtrequest(struct ifnet *ifp, int req > { > struct sockaddr *gate = rt->rt_gateway; > struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; > - struct ifaddr *ifa; > > if (!arpinit_done) { > static struct timeout arptimer_to; > @@ -140,7 +140,7 @@ arp_rtrequest(struct ifnet *ifp, int req > IPL_SOFTNET, 0, "arp", NULL); > > timeout_set_proc(&arptimer_to, arptimer, &arptimer_to); > - timeout_add_sec(&arptimer_to, 1); > + timeout_add_sec(&arptimer_to, arpt_prune); > } > > if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_BROADCAST|RTF_MULTICAST)) > @@ -149,17 +149,12 @@ arp_rtrequest(struct ifnet *ifp, int req > switch (req) { > > case RTM_ADD: > - if (rt->rt_flags & RTF_CLONING || > - ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la)) { > - /* > - * Give this route an expiration time, even though > - * it's a "permanent" route, so that routes cloned > - * from it do not need their expiration time set. > - */ > - rt->rt_expire = time_uptime; > - if ((rt->rt_flags & RTF_CLONING) != 0) > - break; > + if (rt->rt_flags & RTF_CLONING) { > + rt->rt_expire = 0; > + break; > } > + if ((rt->rt_flags & RTF_LOCAL) && !la) > + rt->rt_expire = 0; > /* > * Announce a new entry if requested or warn the user > * if another station has this IP address. > @@ -179,7 +174,7 @@ arp_rtrequest(struct ifnet *ifp, int req > } > satosdl(gate)->sdl_type = ifp->if_type; > satosdl(gate)->sdl_index = ifp->if_index; > - if (la != 0) > + if (la != NULL) > break; /* This happens on a route change */ > /* > * Case 2: This route may come from cloning, or a manual route > @@ -195,18 +190,9 @@ arp_rtrequest(struct ifnet *ifp, int req > ml_init(&la->la_ml); > la->la_rt = rt; > rt->rt_flags |= RTF_LLINFO; > + if ((rt->rt_flags & RTF_LOCAL) == 0) > + rt->rt_expire = time_uptime; > LIST_INSERT_HEAD(&arp_list, la, la_list); > - > - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { > - if ((ifa->ifa_addr->sa_family == AF_INET) && > - ifatoia(ifa)->ia_addr.sin_addr.s_addr == > - satosin(rt_key(rt))->sin_addr.s_addr) > - break; > - } > - if (ifa) { > - KASSERT(ifa == rt->rt_ifa); > - rt->rt_expire = 0; > - } > break; > > case RTM_DELETE: > @@ -314,7 +300,7 @@ arpresolve(struct ifnet *ifp, struct rte > struct sockaddr *dst, u_char *desten) > { > struct arpcom *ac = (struct arpcom *)ifp; > - struct llinfo_arp *la = NULL; > + struct llinfo_arp *la; > struct sockaddr_dl *sdl; > struct rtentry *rt = NULL; > char addr[INET_ADDRSTRLEN]; > @@ -331,7 +317,7 @@ arpresolve(struct ifnet *ifp, struct rte > rt = rt_getll(rt0); > > if (ISSET(rt->rt_flags, RTF_REJECT) && > - (rt->rt_expire == 0 || time_uptime < rt->rt_expire)) { > + (rt->rt_expire == 0 || rt->rt_expire > time_uptime )) { > m_freem(m); > return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); > } > @@ -352,6 +338,9 @@ arpresolve(struct ifnet *ifp, struct rte > goto bad; > } > > + la = (struct llinfo_arp *)rt->rt_llinfo; > + KASSERT(la != NULL); > + > /* > * Check the address family and length is valid, the address > * is resolved; otherwise, try to resolve. > @@ -359,6 +348,17 @@ arpresolve(struct ifnet *ifp, struct rte > if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) && > sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { > memcpy(desten, LLADDR(sdl), sdl->sdl_alen); > + > + /* refresh ARP entry when timeout gets close */ > + if (rt->rt_expire != 0 && > + rt->rt_expire - arpt_keep / 8 < time_uptime && > + la->la_refreshed + 30 < time_uptime) { > + la->la_refreshed = time_uptime; > + arprequest(ifp, > + &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr, > + &satosin(dst)->sin_addr.s_addr, > + ac->ac_enaddr); > + } > return (0); > } > > @@ -370,9 +370,7 @@ arpresolve(struct ifnet *ifp, struct rte > * response yet. Insert mbuf in hold queue if below limit > * if above the limit free the queue without queuing the new packet. > */ > - la = (struct llinfo_arp *)rt->rt_llinfo; > - KASSERT(la != NULL); > - if (la_hold_total < LA_HOLD_TOTAL && la_hold_total < nmbclust / 64) { > + if (la_hold_total < LA_HOLD_TOTAL) { > struct mbuf *mh; > > if (ml_len(&la->la_ml) >= LA_HOLD_QUEUE) { > @@ -411,6 +409,7 @@ arpresolve(struct ifnet *ifp, struct rte > rt->rt_flags |= RTF_REJECT; > rt->rt_expire += arpt_down; > la->la_asked = 0; > + la->la_refreshed = 0; > la_hold_total -= ml_purge(&la->la_ml); > } > } > @@ -668,6 +667,7 @@ arpcache(struct ifnet *ifp, struct ether > } > > la->la_asked = 0; > + la->la_refreshed = 0; > while ((len = ml_len(&la->la_ml)) != 0) { > struct mbuf *mh; > >