From nobody Sat Jul 11 19:26:23 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 4gyJbN1MY5z6lWkp for ; Sat, 11 Jul 2026 19:26:24 +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 4gyJbM6f9gz3YHW for ; Sat, 11 Jul 2026 19:26:23 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783797984; 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=bx8Y2Us19+maSnxQUsbXS1dqz2X0WcOF7t7Nsx8ZAHQ=; b=CoLx/JDcnLVVppodQG7QN0iKEizOzPI+sbVaCYW0gf4x6WQjusNy0kh8Sf2d5x7m/xyVbk NuJMJOWIpTrH3q8MGAZL+TF6h3V1U5LAwwykMk6M+0rZEkiUwUu8A9a6KurEOGtf0Lpmbs iya+n8SciB3Gqvy/G08uARiIuiFBH8XJzIyekvQOpkbg7+3gXVsH/JPB7b7fOZPVCLMu3k UlB+pnfynOk8exuPvaJJ7gAMbE68+b66FNShknwFOIHdmEvWuyFKxHNPcOq7tDIGmfhTl8 domtdphWvBTqrXDqXsQc6qgShenpd8yWrct1oP73cUW7p9Vi3+ErtM+mjjHsXA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1783797984; a=rsa-sha256; cv=none; b=CIO7Qexz/9OotZraEs4GXdR8KJaYNePLsqeHCrk039g/7mWLE/eHh5PtLFG8oMDmJvBAEU lfOR8awOGtGE0lrC39pFgb0YRPpyz4TAb4ZN6GwgWQZ0VgEsPYlaTFNoyuBhXstMP9CGaP aZ5pEnhAuKAWCIkUDVjcBDyJjpUQ4l2wfND19v5pXGtKrwA77DW3QKiIZ+f4Xo73IBYKUQ 78PNZxy0C5XPPr4r/eJ2EiwGUBTrWMHxxHztwmqtX8gb+IH7pZAF8kEf15wr25lE3kNb/p AqNkhibiha4nxGSZ74vvqo9DR2neUFT1E5JOM+bTdDqajqNsB7A8xjOudczstA== 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=1783797984; 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=bx8Y2Us19+maSnxQUsbXS1dqz2X0WcOF7t7Nsx8ZAHQ=; b=IKKnBVwdigEtiNmFXLipxmeCLwTEJVQZ89Wv/YQkI7AQQ822J25njwqnTMCNhnYpvWMyPS heyTCD0Vu/tbw73pSE6CPFpH5hOQZHyTiV2pezTCOF6XXllYUUzR1oJtIxvFg7kZsh7Ekl UjihVg4p2YTWa3T+4Lsj3ulaHCpl+WS4+e8Z7araiu1wI5DxZQbgyYS5L/ofssS5Ulw3Z/ 7DysqI/xmN6ZB9c3odJRhyqFddA8vZ0n00l05QmK16qYZL9y4YforKHOC5ZTvz4NCilTH7 V409y8DRmx+MzaTz/GcoRvMd5PwL3k7jZHGvoJ1Ua324t7yDBwW6PEebUNWhsg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gyJbM50rjztsV for ; Sat, 11 Jul 2026 19:26:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 27283 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 11 Jul 2026 19:26:23 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Pouria Mousavizadeh Tehrani Subject: git: be42ac4dceac - main - routing: Replace unreachable nhops in nhgrp 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: be42ac4dceacedb0e4f676a0614e14d125fab36b Auto-Submitted: auto-generated Date: Sat, 11 Jul 2026 19:26:23 +0000 Message-Id: <6a5298df.27283.68bf5741@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=be42ac4dceacedb0e4f676a0614e14d125fab36b commit be42ac4dceacedb0e4f676a0614e14d125fab36b Author: Pouria Mousavizadeh Tehrani AuthorDate: 2026-06-01 20:07:27 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-07-11 18:23:07 +0000 routing: Replace unreachable nhops in nhgrp If a nhop gets an interface event, revalidate the nhops and immediately try to recompile existing nexthop groups by replacing unreachable nexthops with reachable ones. If none are available, recompile them back to their normal position in nexthop group slots. Reviewed by: glebius Discussed with: markj Relnotes: yes Differential Revision: https://reviews.freebsd.org/D57389 --- sys/net/route/nhgrp_ctl.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- sys/net/route/nhop_ctl.c | 15 +++++++++-- sys/net/route/route_var.h | 1 + 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/sys/net/route/nhgrp_ctl.c b/sys/net/route/nhgrp_ctl.c index d684cd698284..ea1d3b089d9e 100644 --- a/sys/net/route/nhgrp_ctl.c +++ b/sys/net/route/nhgrp_ctl.c @@ -251,14 +251,29 @@ compile_nhgrp(struct nhgrp_priv *dst_priv, const struct weightened_nhop *x, struct nhgrp_object *dst; int i, slot_idx, remaining_slots; uint64_t remaining_sum, nh_weight, nh_slots; + bool one_reachable = true; slot_idx = 0; dst = dst_priv->nhg; /* Calculate sum of all weights with lowest metric */ - remaining_sum = 0; + remaining_sum = nh_weight = 0; for (i = 0; i < dst_priv->nhg_nh_count; i++) { - if (nhop_get_metric(x[i].nh) == metric) - remaining_sum += x[i].weight; + if (nhop_get_metric(x[i].nh) == metric) { + /* + * Temporary store weight of unreachable nhops in nh_weight + * to ensure we have at least one reachable nexthop. + */ + if (NH_IS_VALID(x[i].nh)) + remaining_sum += x[i].weight; + else + nh_weight += x[i].weight; + } + } + + /* If no reachable nhops exist, include all */ + if (remaining_sum == 0) { + remaining_sum = nh_weight; + one_reachable = false; } remaining_slots = num_slots; @@ -268,14 +283,18 @@ compile_nhgrp(struct nhgrp_priv *dst_priv, const struct weightened_nhop *x, if (nhop_get_metric(x[i].nh) != metric) continue; - /* Calculate number of slots for the current nexthop */ - if (remaining_sum > 0) { + /* + * Calculate number of slots for the current nexthop. + * Exclude unreachable nexthops if there is one reachable. + */ + if (remaining_sum > 0 && + (NH_IS_VALID(x[i].nh) || !one_reachable)) { nh_weight = (uint64_t)x[i].weight; nh_slots = (nh_weight * remaining_slots / remaining_sum); + remaining_sum -= x[i].weight; } else nh_slots = 0; - remaining_sum -= x[i].weight; remaining_slots -= nh_slots; FIB_NH_LOG(LOG_DEBUG3, x[0].nh, @@ -1066,6 +1085,41 @@ nhgrp_get_count(struct rib_head *rh) return (count); } +/* + * Recompile nexthop group without changing the slots. + * Since a nexthop might become reachable again soon, + * this avoids unnecessary memory allocation. + */ +static void +nhgrp_recompile_one(struct nhgrp_priv *nhg_priv) +{ + struct nhgrp_object *nhg = nhg_priv->nhg; + const struct weightened_nhop *wn; + uint32_t num_nhops, min_metric; + + wn = nhgrp_get_nhops(nhg, &num_nhops); + + /* dataplane only has the lowest metric nhops, just pick one */ + min_metric = nhop_get_metric(nhg->nhops[0]); + compile_nhgrp(nhg_priv, wn, nhg->nhg_size, min_metric); +} + +void +nhgrp_recompile(struct rib_head *rh) +{ + struct nh_control *ctl = rh->nh_control; + struct nhgrp_priv *nhg_priv; + + NHOPS_WLOCK_ASSERT(ctl); + + if (ctl->gr_head.items_count == 0) + return; + + CHT_SLIST_FOREACH(&ctl->gr_head, mpath, nhg_priv) { + nhgrp_recompile_one(nhg_priv); + } CHT_SLIST_FOREACH_END; +} + int nhgrp_dump_sysctl(struct rib_head *rh, struct sysctl_req *w) { diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c index 4f013908b338..d978e624e65d 100644 --- a/sys/net/route/nhop_ctl.c +++ b/sys/net/route/nhop_ctl.c @@ -1335,19 +1335,30 @@ nhops_ifnet_state_changed(struct ifnet *ifp, bool status) { struct nhop_object *nh; struct nhop_iter iter = { .fibnum = ifp->if_fib, .wlock = true }; + bool nhops_changed; for (iter.family = 1; iter.family <= AF_MAX; iter.family++) { + /* + * By tracking nhop changes, we avoid redundant nhgrp + * recompilation triggered by multiple events. + */ + nhops_changed = false; 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) + if (status && !NH_IS_VALID(nh)) { nh->nh_flags &= ~NHF_INVALID; - else + nhops_changed = true; + } else if (!status && NH_IS_VALID(nh)) { nh->nh_flags |= NHF_INVALID; + nhops_changed = true; + } } + if (iter.rh != NULL && nhops_changed) + nhgrp_recompile(iter.rh); nhops_iter_stop(&iter); } } diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h index df528c93262a..c91002e6c005 100644 --- a/sys/net/route/route_var.h +++ b/sys/net/route/route_var.h @@ -312,6 +312,7 @@ int nhgrp_get_addition_group(struct rib_head *rnh, int nhgrp_get_merge_group(struct rib_head *rnh, struct route_nhop_data *rnd_orig, struct route_nhop_data *rnd_add, struct route_nhop_data *rnd_new); +void nhgrp_recompile(struct rib_head *rh); void nhgrp_ref_object(struct nhgrp_object *nhg); uint32_t nhgrp_get_idx(const struct nhgrp_object *nhg);