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;
>  
> 

Reply via email to