From nobody Sat Jul 11 19:26:22 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gyJbM0wKHz6lWSs for ; Sat, 11 Jul 2026 19:26:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gyJbL66JHz3Y6X for ; Sat, 11 Jul 2026 19:26:22 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783797982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=slvBS5HbU1RqsBja0y4If8PvL1aIRKSQ6uIBhvqWN+U=; b=BAFumViUHPahpwWBfDn4x1i6HsH0Blx6CXS74TxLb//fD6KrxTg2BYUd67uaO4KxydMHAC 2woPwzsR77h3Zaarx+ZsuBYPMEqhas0jwfVC1RMmlIob2naZcM3IPylw6GUbu2icmz8PXh qN3PE0RGuQch3suSR0BFuzhG63SGkXIYOPuNO5v0JlNEQMftIwgDCZKUA4dx7XYK8AE6GS OZovmyQS3w6W6OJuaG/Phz5vuJZ608vXOYtfQi5KwVt5Amf/T3fZ5fWiofOvhNLzLxOvld UceKxtLDTuN22o3lUi+Tc79oE8DEOuk+j8eBLFR9F/nSeYxzvDxsMNkLEljc2g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1783797982; a=rsa-sha256; cv=none; b=ud2A1TseQdEXs8GZTrfnWjJpeshYxtf0W3c0oFyAyef5oE1aE9r85XvDofXMnbGxV+8Nwx gnhgAgQnJYnMmIG1TTgZdlYraFBjoiCWuJSAG/NEfvSXdXMyRFXFBD3K7OqNhGmlMIhyXH KAgYlOVOH0hIiUaQxZ4T8GYAMfO9ksrqwelhDQM6Zqu6Ve6DRwmvOjdckJwq8AZEcUPqVe AYkUKSVFa6fcyJatf4SN9LBMv6XewECGwivBQRBzRLQltAOE+k75O1nqsbytEtXqqiwHGL 8kNfOgtc+kuOR9cBs8TyBs+h+Eq+p/4F4XHwvqWft0vp+HQWvmv5F/nbu0NL8Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783797982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=slvBS5HbU1RqsBja0y4If8PvL1aIRKSQ6uIBhvqWN+U=; b=J3kU8EZ1STErt3LBR7Z5QelKiEGVUDbdx69Ncm8DugfuGsocQorvuvmF6ghhrg5XCeth6U JLdoBmhUQx1u1/FPy3HfD4iHdI9nDHtciBC9rgfWjH+AsHkEebmb7mc5aIWaMJOfRP/sic 7VWtFE2H6dMFMkPJt9hG/WAF2UKQFDT9H9s1fG6+XlybjRCHhgyKma3XRp+yja14+EUSFl UNElsn5ne2cZjHWxO+lqDhA2LPqVTbv+jULjcMFYy8668jBOcQKlnA/QvwSaimeKgQl46X k/j5obF+IjFN48NwLxxQ1tUgEpqSbZONDl4g0oWcvcaJ5TREtS+Uetpg8M4a/Q== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gyJbL4ttszt9l for ; Sat, 11 Jul 2026 19:26:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25070 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 11 Jul 2026 19:26:22 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Pouria Mousavizadeh Tehrani Subject: git: d05d1f256082 - main - routing: Subscribe nhops to ifnet link events List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pouria X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d05d1f25608230edd300d59b96da6521b409d4f3 Auto-Submitted: auto-generated Date: Sat, 11 Jul 2026 19:26:22 +0000 Message-Id: <6a5298de.25070.b0bcc3b@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=d05d1f25608230edd300d59b96da6521b409d4f3 commit d05d1f25608230edd300d59b96da6521b409d4f3 Author: Pouria Mousavizadeh Tehrani AuthorDate: 2026-07-08 19:55:46 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-07-11 18:23:05 +0000 routing: Subscribe nhops to ifnet link events Update nexthop flags with interface link status events and instead of checking link status of interface for every packet only check the reachability flag of the final nexthop. Reviewed by: glebius Discussed with: markj Differential Revision: https://reviews.freebsd.org/D57375 --- sys/net/route.h | 4 +-- sys/net/route/nhop.h | 8 +----- sys/net/route/nhop_ctl.c | 68 +++++++++++++++++++++++++++++++++++++++++++++-- sys/net/route/route_ctl.h | 1 + sys/netinet/in_fib.c | 6 ++--- sys/netinet6/in6_fib.c | 6 ++--- 6 files changed, 75 insertions(+), 18 deletions(-) diff --git a/sys/net/route.h b/sys/net/route.h index d8cc12a39c61..b4440de19d96 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -205,6 +205,7 @@ EVENTHANDLER_DECLARE(rtnumfibs_change, rtnumfibs_change_t); #define NHF_BROADCAST 0x0100 /* RTF_BROADCAST */ #define NHF_GATEWAY 0x0200 /* RTF_GATEWAY */ #define NHF_HOST 0x0400 /* RTF_HOST */ +#define NHF_INVALID 0x0800 /* Nexthop is unreachable */ /* Nexthop request flags */ #define NHR_NONE 0x00 /* empty flags field */ @@ -368,9 +369,6 @@ struct rt_addrinfo { #ifdef _KERNEL -#define RT_LINK_IS_UP(ifp) (!((ifp)->if_capabilities & IFCAP_LINKSTATE) \ - || (ifp)->if_link_state == LINK_STATE_UP) - #define RO_NHFREE(_ro) do { \ if ((_ro)->ro_nh) { \ NH_FREE((_ro)->ro_nh); \ 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); diff --git a/sys/netinet/in_fib.c b/sys/netinet/in_fib.c index d8e373bf3dc2..d864bce07315 100644 --- a/sys/netinet/in_fib.c +++ b/sys/netinet/in_fib.c @@ -117,7 +117,7 @@ fib4_lookup(uint32_t fibnum, struct in_addr dst, uint32_t scopeid, if (nh != NULL) { nh = nhop_select(nh, flowid); /* Ensure route & ifp is UP */ - if (RT_LINK_IS_UP(nh->nh_ifp)) { + if (NH_IS_VALID(nh)) { if (flags & NHR_REF) nhop_ref_object(nh); return (nh); @@ -154,7 +154,7 @@ fib4_lookup(uint32_t fibnum, struct in_addr dst, uint32_t scopeid, if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { nh = nhop_select((RNTORT(rn))->rt_nhop, flowid); /* Ensure route & ifp is UP */ - if (RT_LINK_IS_UP(nh->nh_ifp)) { + if (NH_IS_VALID(nh)) { if (flags & NHR_REF) nhop_ref_object(nh); RIB_RUNLOCK(rh); @@ -320,7 +320,7 @@ fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst, uint32_t scopeid, if (rt != NULL) { struct nhop_object *nh = nhop_select(rnd.rnd_nhop, 0); /* Ensure route & ifp is UP */ - if (RT_LINK_IS_UP(nh->nh_ifp)) + if (NH_IS_VALID(nh)) return (nh); } diff --git a/sys/netinet6/in6_fib.c b/sys/netinet6/in6_fib.c index c851a5bd14c5..594a9dc0a24e 100644 --- a/sys/netinet6/in6_fib.c +++ b/sys/netinet6/in6_fib.c @@ -125,7 +125,7 @@ fib6_lookup(uint32_t fibnum, const struct in6_addr *dst6, if (nh != NULL) { nh = nhop_select(nh, flowid); /* Ensure route & ifp is UP */ - if (RT_LINK_IS_UP(nh->nh_ifp)) { + if (NH_IS_VALID(nh)) { if (flags & NHR_REF) nhop_ref_object(nh); return (nh); @@ -163,7 +163,7 @@ fib6_lookup(uint32_t fibnum, const struct in6_addr *dst6, if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { nh = nhop_select((RNTORT(rn))->rt_nhop, flowid); /* Ensure route & ifp is UP */ - if (RT_LINK_IS_UP(nh->nh_ifp)) { + if (NH_IS_VALID(nh)) { if (flags & NHR_REF) nhop_ref_object(nh); RIB_RUNLOCK(rh); @@ -335,7 +335,7 @@ fib6_lookup_debugnet(uint32_t fibnum, const struct in6_addr *dst6, if (rt != NULL) { struct nhop_object *nh = nhop_select(rnd.rnd_nhop, 0); /* Ensure route & ifp is UP */ - if (RT_LINK_IS_UP(nh->nh_ifp)) + if (NH_IS_VALID(nh)) return (nh); }