From nobody Thu Apr 30 22:07:48 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 4g67Zx6bP7z6cMbK for ; Thu, 30 Apr 2026 22:07:53 +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 "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g67Zx5Bt3z3kHY for ; Thu, 30 Apr 2026 22:07:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777586873; 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=GGh2RYm+FsCX8U2zHO9UaA0G9BQXtErgJm6q0jhk73o=; b=cUoeILTFip8EmF1CR67HdG8pOs2WF71sL7R7EB7k6dzP7jh5hx4hLvjY6senFxxzcb4p67 5BgdXM3IjhZRIHe6kWukYE85ALKEFGrFUMfT2RQblqYcf1YiSJksuffIwG22A/rYMg0dgG wGgfXflrz+fgRURgIDAwVwpxaK6N2qex3QcX7fZogH+HKe2fiQtTzd8kR4ht2kze+7lZ7k 0TKCt9LmmYBMpUGVy01Eivsl4yRwniuoeTFW2TVYn7w/PihMfQZahoU0awACaDP8M7zm2s ogA7i3qqWcTobr46dctqtoxURDZG9jfMUBPg7UYkCKa82jhPfUZMBFv4ZSmVlw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1777586873; a=rsa-sha256; cv=none; b=oNrMP3LrM1TQ8MdNcMFkNcCk//qm3HruONFBnDio+hKQ1jo9XjWe4vtCRXJWSPrT+0dFWn qU9c+PxGWsZ5ANYXLszmQfixmkkfWfSz7extHZEdWMejv7V7r8UgXd2hae0qt6hDIsvORQ xjd/MW9j3F0vp/OfoKK4jWzRSc2KcIrqX7wm4htKyG7yG/bqxa0rfb8kqtcPECIZTSeUXL oLgNTxhbv+OZQZOxiUymoABN65irSZlmAkWYumOsvxeQ62SpVgqLpuqubLgZKBmSv1LPn8 OiPOvoBZ52YqMnozFh4GeUf9MCmNAmh8TWybZz0Yvkuh2n7s6T+OpLSyoXExaQ== 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=1777586873; 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=GGh2RYm+FsCX8U2zHO9UaA0G9BQXtErgJm6q0jhk73o=; b=SbVAagvynOACRblNbNkb1GVfMUeQNOXXr94k4u9pvNYHuaO3isf0IZ2TvZVVx5Ep+k+c81 Wh2uztUK4odqj+QDonjFUPtR1FxkES+6Ehf6cLKJtOV72Up8tMDFy6d/UPxdAt2HEuAhGc V5fG0d/MKvxAZUpTt9aV+cFRkr3NtteYokuDinWYWQGv8L/zXNzSmt8dtAIAVqm6yTKJyn rxUyfAdIg/0ePpHH48VMtfVuPp6VNiNnLI5LC8x6Nhbq9da869DuIr5ibm7ceZPUbyPE9c fmGHJQdEDILxQQqkvkYifgb9g/2Tzt2Jro1UgvX+iJM8kQFv73Ldn4xQFVfH8Q== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g67Zx4m6zzVgd for ; Thu, 30 Apr 2026 22:07:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1c025 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Apr 2026 22:07:48 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Pouria Mousavizadeh Tehrani Subject: git: dd945c6ba4ff - main - routing: Implement merge of nhgrp in new multipath route 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 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: dd945c6ba4ff8d444c4cb90a911d96c66b6fc4aa Auto-Submitted: auto-generated Date: Thu, 30 Apr 2026 22:07:48 +0000 Message-Id: <69f3d2b4.1c025.47f28c2e@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=dd945c6ba4ff8d444c4cb90a911d96c66b6fc4aa commit dd945c6ba4ff8d444c4cb90a911d96c66b6fc4aa Author: Pouria Mousavizadeh Tehrani AuthorDate: 2026-03-31 19:13:48 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-04-30 22:05:32 +0000 routing: Implement merge of nhgrp in new multipath route Routing subsystem allows creating new multipath routes by nexthop groups (e.g RTA_MULTIPATH in netlink), in case of a second nexthop group on the same route, don't panic and merge the existing nhgrp with new one. Reviewed by: melifaro (except one comment) Differential Revision: https://reviews.freebsd.org/D56187 --- sys/net/route/nhgrp_ctl.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ sys/net/route/route_ctl.c | 5 ++- sys/net/route/route_var.h | 3 ++ 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/sys/net/route/nhgrp_ctl.c b/sys/net/route/nhgrp_ctl.c index 8a1fa2113a6c..7230e02195ee 100644 --- a/sys/net/route/nhgrp_ctl.c +++ b/sys/net/route/nhgrp_ctl.c @@ -632,6 +632,63 @@ append_nhops(struct nh_control *ctl, const struct nhgrp_object *gr_orig, return (nhg_priv); } +/* + * Merge nexthop group denoted by @gr_add with the nexthop group @gr_orig. + * + * Returns referenced nexthop group or NULL. In the latter case, @perror is + * filled with an error code. + * Note that function does NOT care if the next nexthops already exists + * in the @gr_orig. As a result, they will be added, resulting in the + * same nexthop being present multiple times in the new group. + */ +static struct nhgrp_priv * +merge_nhgrps(struct nh_control *ctl, const struct nhgrp_object *gr_orig, + const struct nhgrp_object *gr_add, int *perror) +{ + char storage[64]; + struct weightened_nhop *pnhops; + struct nhgrp_priv *nhg_priv; + const struct nhgrp_priv *orig_priv, *add_priv; + size_t sz; + int curr_nhops; + + orig_priv = NHGRP_PRIV_CONST(gr_orig); + add_priv = NHGRP_PRIV_CONST(gr_add); + curr_nhops = orig_priv->nhg_nh_count; + + *perror = 0; + + sz = (orig_priv->nhg_nh_count + orig_priv->nhg_nh_count) * + sizeof(struct weightened_nhop); + /* optimize for <= 4 paths, each path=16 bytes */ + if (sz <= sizeof(storage)) + pnhops = (struct weightened_nhop *)&storage[0]; + else { + pnhops = malloc(sz, M_TEMP, M_NOWAIT); + if (pnhops == NULL) { + *perror = ENOMEM; + return (NULL); + } + } + + /* First, copy nhops from first group */ + memcpy(pnhops, orig_priv->nhg_nh_weights, + orig_priv->nhg_nh_count * sizeof(struct weightened_nhop)); + memcpy(&pnhops[curr_nhops], add_priv->nhg_nh_weights, + add_priv->nhg_nh_count * sizeof(struct weightened_nhop)); + curr_nhops += add_priv->nhg_nh_count; + + nhg_priv = get_nhgrp(ctl, pnhops, curr_nhops, 0, perror); + + if (pnhops != (struct weightened_nhop *)&storage[0]) + free(pnhops, M_TEMP); + + if (nhg_priv == NULL) + return (NULL); + + return (nhg_priv); +} + /* * Creates/finds nexthop group based on @wn and @num_nhops. @@ -728,6 +785,8 @@ nhgrp_get_addition_group(struct rib_head *rh, struct route_nhop_data *rnd_orig, struct weightened_nhop wn[2] = {}; int error; + MPASS((!NH_IS_NHGRP(rnd_add->rnd_nhop))); + if (rnd_orig->rnd_nhop == NULL) { /* No paths to add to, just reference current nhop */ *rnd_new = *rnd_add; @@ -758,6 +817,46 @@ nhgrp_get_addition_group(struct rib_head *rh, struct route_nhop_data *rnd_orig, return (0); } +/* + * Creates new multipath group based on existing group/nhop in @rnd_orig and + * to-be-merged nhgrp @wn_add. + * Returns 0 on success and stores result in @rnd_new. + */ +int +nhgrp_get_merge_group(struct rib_head *rh, struct route_nhop_data *rnd_orig, + struct route_nhop_data *rnd_add, struct route_nhop_data *rnd_new) +{ + struct nh_control *ctl = rh->nh_control; + struct nhgrp_priv *nhg_priv; + struct weightened_nhop wn = {}; + int error; + + MPASS((NH_IS_NHGRP(rnd_add->rnd_nhop))); + + /* No paths to add to, Just give up */ + if (rnd_orig->rnd_nhop == NULL) + return (EINVAL); + + if (!NH_IS_NHGRP(rnd_orig->rnd_nhop)) { + wn.nh = rnd_orig->rnd_nhop; + wn.weight = rnd_orig->rnd_weight; + /* Get new nhop group with addition of nhops in nhgrp */ + nhg_priv = append_nhops(ctl, rnd_add->rnd_nhgrp, &wn, 1, + &error); + } else { + /* Get new nhop group with addition of nhops in nhgrp */ + nhg_priv = merge_nhgrps(ctl, rnd_orig->rnd_nhgrp, rnd_add->rnd_nhgrp, + &error); + } + + if (nhg_priv == NULL) + return (error); + rnd_new->rnd_nhgrp = nhg_priv->nhg; + rnd_new->rnd_weight = 0; + + return (0); +} + /* * Returns pointer to array of nexthops with weights for * given @nhg. Stores number of items in the array into @pnum_nhops. diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c index c6d8d43a73f4..fe00c762905d 100644 --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -858,7 +858,10 @@ add_route_flags_mpath(struct rib_head *rnh, struct rtentry *rt, struct route_nhop_data rnd_new; int error = 0; - error = nhgrp_get_addition_group(rnh, rnd_orig, rnd_add, &rnd_new); + if (!NH_IS_NHGRP(rnd_add->rnd_nhop)) + error = nhgrp_get_addition_group(rnh, rnd_orig, rnd_add, &rnd_new); + else + error = nhgrp_get_merge_group(rnh, rnd_orig, rnd_add, &rnd_new); if (error != 0) { if (error == EAGAIN) { /* diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h index 40433f1b37c0..df528c93262a 100644 --- a/sys/net/route/route_var.h +++ b/sys/net/route/route_var.h @@ -309,6 +309,9 @@ int nhgrp_get_filtered_group(struct rib_head *rh, const struct rtentry *rt, int nhgrp_get_addition_group(struct rib_head *rnh, struct route_nhop_data *rnd_orig, struct route_nhop_data *rnd_add, struct route_nhop_data *rnd_new); +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_ref_object(struct nhgrp_object *nhg); uint32_t nhgrp_get_idx(const struct nhgrp_object *nhg);