On 02/10/15(Fri) 16:03, Martin Pieuchot wrote:
> I'd like to change the behavior of arptfree() to stop checking the
> reference counter of the route:
>
> - to keep the logic for reference counting rout entries simple,
>
> - and to align it with the NDP behavior (see nd6_free()).
>
>
> With this diff expired ARP entries get removed from the routing table,
> no matter if there are still referenced (cached) or not. This is safe
> because removing an entry will mark it DOWN so it wont be used by code
> having a reference to it.
Let me rephrase that. As soon as the route is removed from the tree it
wont have the RTF_UP flag. This is enough for ip{6,}_output() & co to
re-call rtalloc(9) and re-clone the route if necessary.
So I'm still looking for oks.
> Index: netinet/if_ether.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/if_ether.c,v
> retrieving revision 1.170
> diff -u -p -r1.170 if_ether.c
> --- netinet/if_ether.c 28 Sep 2015 08:26:58 -0000 1.170
> +++ netinet/if_ether.c 2 Oct 2015 12:39:38 -0000
> @@ -91,7 +91,7 @@ int arpt_prune = (5*60*1); /* walk list
> int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
> int arpt_down = 20; /* once declared down, don't send for 20 secs */
>
> -void arptfree(struct llinfo_arp *);
> +void arptfree(struct rtentry *);
> void arptimer(void *);
> struct rtentry *arplookup(u_int32_t, int, int, u_int);
> void in_arpinput(struct mbuf *);
> @@ -141,7 +141,7 @@ arptimer(void *arg)
>
> nla = LIST_NEXT(la, la_list);
> if (rt->rt_expire && rt->rt_expire <= time_second)
> - arptfree(la); /* timer has expired; clear */
> + arptfree(rt); /* timer has expired; clear */
> }
> splx(s);
> }
> @@ -780,26 +780,20 @@ out:
> * Free an arp entry.
> */
> void
> -arptfree(struct llinfo_arp *la)
> +arptfree(struct rtentry *rt)
> {
> - struct rtentry *rt = la->la_rt;
> - struct sockaddr_dl *sdl;
> - u_int tid = 0;
> + struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
> + struct sockaddr_dl *sdl = SDL(rt->rt_gateway);
> + int s;
>
> - if (rt == NULL)
> - panic("arptfree");
> - if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
> - sdl->sdl_family == AF_LINK) {
> + if ((sdl != NULL) && (sdl->sdl_family == AF_LINK)) {
> sdl->sdl_alen = 0;
> la->la_asked = 0;
> - rt->rt_flags &= ~RTF_REJECT;
> - return;
> }
>
> - if (rt->rt_ifp)
> - tid = rt->rt_ifp->if_rdomain;
> -
> - rtdeletemsg(rt, tid);
> + s = splsoftnet();
> + rtdeletemsg(rt, rt->rt_ifp->if_rdomain);
> + splx(s);
> }
>
> /*
>