diff options
| author | Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> | 2026-07-08 19:55:46 +0000 |
|---|---|---|
| committer | Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> | 2026-07-11 18:23:05 +0000 |
| commit | d05d1f25608230edd300d59b96da6521b409d4f3 (patch) | |
| tree | 424cee9d05940b582f13d95f97bc436a2c52b83a /sys/net/route | |
| parent | c52bcd09c2a6736fe841fd72e3cfb74de5a35b03 (diff) | |
Diffstat (limited to 'sys/net/route')
| -rw-r--r-- | sys/net/route/nhop.h | 8 | ||||
| -rw-r--r-- | sys/net/route/nhop_ctl.c | 68 | ||||
| -rw-r--r-- | sys/net/route/route_ctl.h | 1 |
3 files changed, 68 insertions, 9 deletions
diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h index 6c62ae2f2f5f..0ae41cbf8292 100644 --- a/sys/net/route/nhop.h +++ b/sys/net/route/nhop.h @@ -145,14 +145,8 @@ struct nhop_object { /* * Nhop validness. - * - * Currently we verify whether link is up or not on every packet, which can be - * quite costy. - * TODO: subscribe for the interface notifications and update the nexthops - * with NHF_INVALID flag. */ - -#define NH_IS_VALID(_nh) RT_LINK_IS_UP((_nh)->nh_ifp) +#define NH_IS_VALID(_nh) (!((_nh)->nh_flags & NHF_INVALID)) #define NH_IS_NHGRP(_nh) ((_nh)->nh_flags & NHF_MULTIPATH) #define NH_FREE(_nh) do { \ diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c index 9ef5bbc74a92..4f013908b338 100644 --- a/sys/net/route/nhop_ctl.c +++ b/sys/net/route/nhop_ctl.c @@ -90,6 +90,8 @@ static void fill_sdl_from_ifp(struct sockaddr_dl_short *sdl, const struct ifnet static void destroy_nhop_epoch(epoch_context_t ctx); static void destroy_nhop(struct nhop_object *nh); +static void nhops_ifnet_event(void *arg, struct ifnet *ifp, int state); +static void nhops_ifnet_link_event(void *arg, struct ifnet *ifp, int state); _Static_assert(__offsetof(struct nhop_object, nh_ifp) == 32, "nhop_object: wrong nh_ifp offset"); @@ -109,6 +111,10 @@ nhops_init(void) nhops_zone = uma_zcreate("routing nhops", NHOP_OBJECT_ALIGNED_SIZE + NHOP_PRIV_ALIGNED_SIZE, NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + EVENTHANDLER_REGISTER(ifnet_event, nhops_ifnet_event, NULL, + EVENTHANDLER_PRI_ANY); + EVENTHANDLER_REGISTER(ifnet_link_event, nhops_ifnet_link_event, NULL, + EVENTHANDLER_PRI_ANY); } /* @@ -1109,7 +1115,10 @@ nhops_iter_start(struct nhop_iter *iter) if (iter->rh != NULL) { struct nh_control *ctl = iter->rh->nh_control; - NHOPS_RLOCK(ctl); + if (iter->wlock) + NHOPS_WLOCK(ctl); + else + NHOPS_RLOCK(ctl); iter->_i = 0; iter->_next = CHT_FIRST(&ctl->nh_head, iter->_i); @@ -1147,7 +1156,10 @@ nhops_iter_stop(struct nhop_iter *iter) if (iter->rh != NULL) { struct nh_control *ctl = iter->rh->nh_control; - NHOPS_RUNLOCK(ctl); + if (iter->wlock) + NHOPS_WUNLOCK(ctl); + else + NHOPS_RUNLOCK(ctl); } } @@ -1317,3 +1329,55 @@ nhops_dump_sysctl(struct rib_head *rh, struct sysctl_req *w) return (0); } + +static void +nhops_ifnet_state_changed(struct ifnet *ifp, bool status) +{ + struct nhop_object *nh; + struct nhop_iter iter = { .fibnum = ifp->if_fib, .wlock = true }; + + for (iter.family = 1; iter.family <= AF_MAX; iter.family++) { + iter.rh = rt_tables_get_rnh_safe(iter.fibnum, iter.family); + for (nh = nhops_iter_start(&iter); nh != NULL; + nh = nhops_iter_next(&iter)) { + if (nh->nh_ifp != ifp) + continue; + + if (status) + nh->nh_flags &= ~NHF_INVALID; + else + nh->nh_flags |= NHF_INVALID; + } + nhops_iter_stop(&iter); + } +} + +static void +nhops_ifnet_event(void *arg __unused, struct ifnet *ifp, int state) +{ + + if ((ifp->if_flags & IFF_DYING) != 0 || + (state != IFNET_EVENT_UP && state != IFNET_EVENT_DOWN)) + return; + + nhops_ifnet_state_changed(ifp, state == IFNET_EVENT_UP); +} + +static void +nhops_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int state) +{ +#ifdef VIMAGE + /* + * rib_head will be calculated from V_tables in rt_tables_get_rnh + * and the VNET is destroyed. + */ + if (VNET_IS_SHUTTING_DOWN(ifp->if_vnet)) + return; +#endif + + if ((ifp->if_flags & IFF_DYING) != 0 || + (state != LINK_STATE_UP && state != LINK_STATE_DOWN)) + return; + + nhops_ifnet_state_changed(ifp, state == LINK_STATE_UP); +} diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h index 845df8ce1fbe..2e34b2a35c25 100644 --- a/sys/net/route/route_ctl.h +++ b/sys/net/route/route_ctl.h @@ -164,6 +164,7 @@ struct nhop_iter { struct rib_head *rh; int _i; struct nhop_priv *_next; + const bool wlock; }; struct nhop_object *nhops_iter_start(struct nhop_iter *iter); |
