Index: sys/netinet/if_ether.c =================================================================== --- sys/netinet/if_ether.c +++ sys/netinet/if_ether.c @@ -186,7 +186,7 @@ static void arp_mark_lle_reachable(struct llentry *la); static void arp_iflladdr(void *arg __unused, struct ifnet *ifp); -static eventhandler_tag iflladdr_tag; +static eventhandler_tag iflladdr_tag, lle_event_eh; static const struct netisr_handler arp_nh = { .nh_name = "arp", @@ -1481,6 +1481,55 @@ } static void +arp_lle_event(void *arg __unused, struct llentry *lle, int evt) +{ + struct rt_addrinfo rtinfo; + struct sockaddr_in dst; + struct sockaddr_dl gw; + struct ifnet *ifp; + int type; + + LLE_WLOCK_ASSERT(lle); + + if (lltable_get_af(lle->lle_tbl) != AF_INET) + return; + + switch (evt) { + case LLENTRY_RESOLVED: + type = RTM_ADD; + KASSERT(lle->la_flags & LLE_VALID, + ("%s: %p resolved but not valid?", __func__, lle)); + break; + case LLENTRY_EXPIRED: + type = RTM_DELETE; + break; + default: + return; + } + + ifp = lltable_get_ifp(lle->lle_tbl); + bzero(&dst, sizeof(dst)); + bzero(&gw, sizeof(gw)); + bzero(&rtinfo, sizeof(rtinfo)); + lltable_fill_sa_entry(lle, (struct sockaddr *)&dst); + gw = (struct sockaddr_dl){ + .sdl_len = sizeof(gw), + .sdl_family = AF_LINK, + .sdl_alen = ifp->if_addrlen, + .sdl_index = ifp->if_index, + .sdl_type = ifp->if_type, + }; + bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen); + rtinfo = (struct rt_addrinfo){ + .rti_info[RTAX_DST] = (struct sockaddr *)&dst, + .rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw, + }; + rt_missmsg_fib(type, &rtinfo, RTF_HOST | RTF_LLDATA | ( + type == RTM_ADD ? RTF_UP : 0), 0, + (V_rt_add_addr_allfibs) ? RT_ALL_FIBS : ifp->if_fib); +} + +static void vnet_arp_init(void) { @@ -1488,6 +1537,8 @@ netisr_register(&arp_nh); iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY); + lle_event_eh = EVENTHANDLER_REGISTER(lle_event, + arp_lle_event, NULL, EVENTHANDLER_PRI_ANY); } #ifdef VIMAGE else @@ -1506,6 +1557,10 @@ vnet_arp_destroy(__unused void *arg) { + if (IS_DEFAULT_VNET(curvnet)) { + EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh); + EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag); + } netisr_unregister_vnet(&arp_nh); } VNET_SYSUNINIT(vnet_arp_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, Index: sys/netinet6/nd6.c =================================================================== --- sys/netinet6/nd6.c +++ sys/netinet6/nd6.c @@ -157,7 +157,6 @@ struct sockaddr_dl gw; struct ifnet *ifp; int type; - int fibnum; LLE_WLOCK_ASSERT(lle); @@ -185,19 +184,22 @@ lltable_fill_sa_entry(lle, (struct sockaddr *)&dst); dst.sin6_scope_id = in6_getscopezone(ifp, in6_addrscope(&dst.sin6_addr)); - gw.sdl_len = sizeof(struct sockaddr_dl); - gw.sdl_family = AF_LINK; - gw.sdl_alen = ifp->if_addrlen; - gw.sdl_index = ifp->if_index; - gw.sdl_type = ifp->if_type; - if (evt == LLENTRY_RESOLVED) - bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen); - rtinfo.rti_info[RTAX_DST] = (struct sockaddr *)&dst; - rtinfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; - rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY; - fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS : ifp->if_fib; + gw = (struct sockaddr_dl){ + .sdl_len = sizeof(gw), + .sdl_family = AF_LINK, + .sdl_alen = ifp->if_addrlen, + .sdl_index = ifp->if_index, + .sdl_type = ifp->if_type, + }; + bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen); + rtinfo = (struct rt_addrinfo){ + .rti_info[RTAX_DST] = (struct sockaddr *)&dst, + .rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw, + .rti_addrs = RTA_DST | RTA_GATEWAY, + }; rt_missmsg_fib(type, &rtinfo, RTF_HOST | RTF_LLDATA | ( - type == RTM_ADD ? RTF_UP: 0), 0, fibnum); + type == RTM_ADD ? RTF_UP: 0), 0, + (V_rt_add_addr_allfibs) ? RT_ALL_FIBS : ifp->if_fib); } /*