From nobody Sat Jul 11 19:26:22 2026 X-Original-To: dev-commits-src-all@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 4gyJbS2gXkz6lWZR for ; Sat, 11 Jul 2026 19:26:28 +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 4gyJbR63KWz3YTj for ; Sat, 11 Jul 2026 19:26:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783797987; 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=n7B17u3bgDo17SY5YzTVcHAs7JrceUCpc5CwwLAICIzP4OKcTmTTv4bCEr9udMYL1coUW5 MGx+H9Lteev2/eZXnCGLHzaIOdLuWLjWTjlIXLMejF2cVqRRtH85HfMGhSz2rODhVSTX9A /6oArsFRF5YKNq/6o7jjkRDXlTxzBUoS62AO5eSsewZbv/IkXr965tI4ZUKpDM8TxyM1Wl 8yzFXmv2ehgJMfL2z9wvsajEizeRNX7O9ddr3dpZ3KkPRWGoBorny52dQnqe+VcyAYHhNE bbsv/PgaPuhxXprU33PBQKCfYATvgzxin4i1Xz1gMomCvLdd0WVbPnGJUJYA2g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1783797987; a=rsa-sha256; cv=none; b=sCcvf4p0sAL+BvfQ55gd9vfbr5afRozFx58RJqW/+2/rsjlXodjSjkBTqvpADNZ3Dh+Aml CjAtYBoyavOH7EkLECr9rZ9Mh5eru4ImwfZjAvViuptJXX/rAZ6euGDkT4fJcc7AHGZlXR OZC7XnOeb75hZHByr2nDy1eZjO0Y00+CltHIN8Ml4cAULUdRaNIkErvdinKJhE808n3Nym 1Ec/lh0iNYPywcemfbpjL55zqFORDKy6cBVz7z7be1Zkf8Efn0M67ugOYEyxW+jwVYRDWJ fP02kVhfmHY+25+UgAQoQR1RfLFrQw5werv3QkoG7A6qS7NcfqXrpdI0KBfMbw== 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=1783797987; 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=dYJ2BtUvaAzQ5df+LQCUhIGXzLXft03ySd+7cvwqQJSBBoEhU4liSMJruM4xeSmnfJ7xFw B4CbRH4Zy0GaEm4dD/OlBBKS856OygLeVzRfYPGH0yyMZ6lyU0KIsN6BAR5eo+ND2dl+wg LnJRHonBaIutbRAfNsm/Bdl9p0h43j0dVHmgBA6c1kNgTonyy1ELrUR0B77OtSNdAPYJ29 kcGQb5lWTittIPz3gM5vuPo8I70ohptX1tX5IrfaJrlinMs3fO/DQjW2wz7L4kvlsrVIMx tUqfGkjPd/r3Sdp9ZObrHWsoNg/ts+YKniAJi+BiggtFQvy9lqGZyw6Ul+8Lwg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gyJbR4S7WztpP for ; Sat, 11 Jul 2026 19:26:27 +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 all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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); }