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,56 @@ } 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: + KASSERT(lle->la_flags & LLE_VALID, + ("%s: %p resolved but not valid?", __func__, lle)); + type = RTM_ADD; + 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, + }; + if (lle->ll_addr != NULL) + 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 +1538,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 Index: sys/netinet6/nd6.c =================================================================== --- sys/netinet6/nd6.c +++ sys/netinet6/nd6.c @@ -167,9 +167,9 @@ switch (evt) { case LLENTRY_RESOLVED: - type = RTM_ADD; KASSERT(lle->la_flags & LLE_VALID, ("%s: %p resolved but not valid?", __func__, lle)); + type = RTM_ADD; break; case LLENTRY_EXPIRED: type = RTM_DELETE; @@ -191,7 +191,7 @@ gw.sdl_alen = ifp->if_addrlen; gw.sdl_index = ifp->if_index; gw.sdl_type = ifp->if_type; - if (evt == LLENTRY_RESOLVED) + if (lle->ll_addr != NULL) 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;