aboutsummaryrefslogtreecommitdiff
path: root/sys/net/route
diff options
context:
space:
mode:
authorPouria Mousavizadeh Tehrani <pouria@FreeBSD.org>2026-07-08 19:55:46 +0000
committerPouria Mousavizadeh Tehrani <pouria@FreeBSD.org>2026-07-11 18:23:05 +0000
commitd05d1f25608230edd300d59b96da6521b409d4f3 (patch)
tree424cee9d05940b582f13d95f97bc436a2c52b83a /sys/net/route
parentc52bcd09c2a6736fe841fd72e3cfb74de5a35b03 (diff)
Diffstat (limited to 'sys/net/route')
-rw-r--r--sys/net/route/nhop.h8
-rw-r--r--sys/net/route/nhop_ctl.c68
-rw-r--r--sys/net/route/route_ctl.h1
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);