From nobody Fri Jul 24 22:18:41 2026 Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D05D215075 for ; Thu, 23 Jul 2026 01:18:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784769497; cv=none; b=ayuUlEUex9zTsXLTV/UCRuMQhBgBb3pQSGBFNDffDfU0rV/qrQ1lj/rplhL3JX9IxnVWZMGSX0Eu+ETCKR+j62oPeJmLoAq75JKOiilY/b3+e0lXH+oQUj1e1y/u4xfG1aL35XmM0BHWLRicPHznU4JxOvsvBPwaiNOuXrqx42s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784769497; c=relaxed/simple; bh=Rp5wNPbGEoMLvDNy9Y0Os0AN018Ut17OejovDqyuNkI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YQ4av0gK7zDJT6ze8tNxep1t36iOhOrqo3gKbrDwnuvkaJs3lDt3+vhpz3kCM30T0lbC00SC8pXp5hRaWvMyX44N6Pp9z1b/fMsRlGj1pXm0gx0jarGwz71NQtjOSXJLc4kQUIbzvZvMUzjBpWGPF8fVYZ8eF94GefH5vTNeGcQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QNwVlL2n; arc=none smtp.client-ip=209.85.210.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QNwVlL2n" Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-84e3007a2b7so48445b3a.0 for ; Wed, 22 Jul 2026 18:18:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784769493; x=1785374293; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=HqDIk+Slnk3pOQnmJk8DItcgvMwolBNT8qPRkL5HwoQ=; b=QNwVlL2nKGi4c2p7vOkeUcf44ohGsg7aeN+NzknL2gqL8W3TQYPQsVjCSj9fQXb7LO 4k2Wv7vmLWxsiIpb3Vdskyh0IvVbvyfIUoThaBWgy5KCBIsweLYT/BCBWJUZLemHr1jM J0CikRQDOMs42Knj93BbrcRSHuybputv5Dg4zT8lJX5/HUVQNJIBkRYoi0uTVUmxOU38 nL8bZkV+NFFc0WXCWcZ4mxvIOCEKgGRkWVxrg+7qGkCYewVa9bMfY2As/aPwVwT7imPe GbOPAdzksGX88cC6HEKMNy/dlVMbkW8FUPWJw1jowcwTxp70gVuPZ3RnlPHyS4gC9DjM 8gFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784769493; x=1785374293; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=HqDIk+Slnk3pOQnmJk8DItcgvMwolBNT8qPRkL5HwoQ=; b=EN7RZKIRbjIgs2aPm3EJRM6ZeyafQfVeBEO/M/7fi8nDvEcFAY6Updk0Ewlcifjnn9 vCLqtghqJYpxWdZbnTKaCzAiQKXRH0hVDcFewVIodSCNXpdYfkOkhsWxP8PDgddCjbjU lq6u5F3xC4TiSkBHKHFtgzjHVQcQvjrjpX/d1DLpQhnp86AvcXKx7fDocqKRZ+kF1Fym oO3whZevDKJDa6s5/MHFnDS+5TS5gMIiMpkq3Gm8KhhOj2djgyxBmWlmgKrOihJ7TAq2 PukDZU/k2LJ428nzJiCWbQRWF6qblbDuNrGgiMt+SUcfNFH+14MKDoHa55OLOWqnfrTf y/4w== X-Forwarded-Encrypted: i=1; AHgh+RqnsL/GzNohCoupEOS2fRztGJwiZfnvsoQOhH96wDKpJqIAYA2jy36uJz9kJvB/b5W+DOXGAQjItT4MgGQ=@vger.kernel.org X-Gm-Message-State: AOJu0YzL2JkZDTUzy7tev6D4vBwVdbArFwtQABbMmzn0Gg3yBgGUx8SC JnMyDcXfqAawq0LXBKYXuc7Q+DqrRS2WL6YzQWr73B6OT7ofjbgvu1UW X-Gm-Gg: AR+sD12fUsuSxZyctYWCo8WvOJAO+Ss9REF8Lz/pcKgmLYYug/UbSwv2G+D/SfxC4fN YVumqLIoXK8P1Whjxxb39KYDIONbHo73WEM1w2jGORIaGfMcjGQDodheYCz3TXal2s1db68uSuT iR7QA+mWhk2yPSP4Qd8WItScMcu21kGJiM9w8tkuFt80lOYmyOYLVTai8/Wj2BmK0njgXrIQ3LS 2I8eDKb7i6Ngeef81pXAgY6KgJKwgQdvorCCKeB0c+60hkEVQfeSQQHASqVs1VnFQ8Nr5UYREbr NDC9bVusGn4xOShqLY2Jt1TTXErOJwGW7gNlQ4Cwl8SVHQWHQOx6i5H7yIkhKCjaCBYLq1CWvwe KJM87TmVD8xybJmzi0UZIjLGaoTRVbMg4BUXiCQ4bwAEGvLdnZbzzqQZxL6Ile/YMmAEtOWR6r6 auX25Xhm2/tQZ+Cv0= X-Received: by 2002:a05:6a00:1302:b0:845:dffa:3740 with SMTP id d2e1a72fcca58-84e2b7e5966mr1309708b3a.4.1784769492666; Wed, 22 Jul 2026 18:18:12 -0700 (PDT) Received: from CPC-mjac-HKWGEZ.localdomain ([70.37.26.37]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84e175ea5c7sm2089045b3a.53.2026.07.22.18.18.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Jul 2026 18:18:11 -0700 (PDT) From: Jack Ma Date: Thu, 23 Jul 2026 01:17:53 +0000 Subject: [PATCH net-next v4 1/3] net: nexthop: add NHA_DST_PORT for fdb nexthops Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-vxlan-fdb-port-v4-1-46e3a2dd88a3@gmail.com> References: <20260723-b4-vxlan-fdb-port-v4-0-46e3a2dd88a3@gmail.com> In-Reply-To: <20260723-b4-vxlan-fdb-port-v4-0-46e3a2dd88a3@gmail.com> To: David Ahern , Ido Schimmel , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Jack Ma X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784769488; l=4268; i=jack4it@gmail.com; s=20260712; h=from:subject:message-id; bh=Rp5wNPbGEoMLvDNy9Y0Os0AN018Ut17OejovDqyuNkI=; b=J64lXUoNus6ikn25PnuBFee7hwyLnvyUa8eyxsGKOQSNGfO7bufTkdBgDhOAHXcU+sGI2Evl4 v8YwRuJ4ROdBwoGEWE8iu4xOtvtMeS1znId1EcojIjWV0eXCsTNe7om X-Developer-Key: i=jack4it@gmail.com; a=ed25519; pk=x8xh2Md9yNDil0xBOA9WA/oqC3O4Eg4rdlIul4YUktU= Commit 1274e1cc4226 ("vxlan: ecmp support for mac fdb entries") lets a single inner MAC be reached through a group of remote VTEPs, with the kernel flow-hashing across the group members. Each member carries its own remote IP, but the UDP destination port is always taken from the VXLAN device (vxlan->cfg.dst_port) and cannot be set per member. Some deployments pack several receivers behind one underlay IP and tell them apart by UDP port, so they need a per-nexthop destination port to spread flows across (IP, port) tuples rather than IP alone. Add a netlink attribute NHA_DST_PORT (__be16, mirroring NDA_PORT) that carries an optional UDP destination port on an fdb nexthop. It is only accepted together with NHA_FDB and NHA_GATEWAY; it is stored in struct nh_info and echoed back on dump. The attribute is named generically rather than fdb-specific so it can be reused should another nexthop type ever need a destination port. This patch is control-plane plumbing only; the VXLAN datapath is wired up in a follow-up patch, so behaviour is unchanged for now. Signed-off-by: Jack Ma Reviewed-by: David Ahern Reviewed-by: Ido Schimmel --- include/net/nexthop.h | 2 ++ include/uapi/linux/nexthop.h | 3 +++ net/ipv4/nexthop.c | 20 +++++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/net/nexthop.h b/include/net/nexthop.h index 572e69cda4766..7673aaeff3e28 100644 --- a/include/net/nexthop.h +++ b/include/net/nexthop.h @@ -28,6 +28,7 @@ struct nh_config { u8 nh_protocol; u8 nh_blackhole; u8 nh_fdb; + __be16 nh_dst_port; u32 nh_flags; =20 int nh_ifindex; @@ -63,6 +64,7 @@ struct nh_info { u8 family; bool reject_nh; bool fdb_nh; + __be16 dst_port; =20 union { struct fib_nh_common fib_nhc; diff --git a/include/uapi/linux/nexthop.h b/include/uapi/linux/nexthop.h index bc49baf4a267f..59cf1cee93bd7 100644 --- a/include/uapi/linux/nexthop.h +++ b/include/uapi/linux/nexthop.h @@ -83,6 +83,9 @@ enum { /* u32; read-only; whether any driver collects HW stats */ NHA_HW_STATS_USED, =20 + /* be16; UDP destination port for an fdb nexthop (e.g. VXLAN) */ + NHA_DST_PORT, + __NHA_MAX, }; =20 diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index 6205bd57aa852..0021380b8c1de 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -39,6 +39,7 @@ static const struct nla_policy rtm_nh_policy_new[] =3D { [NHA_ENCAP_TYPE] =3D { .type =3D NLA_U16 }, [NHA_ENCAP] =3D { .type =3D NLA_NESTED }, [NHA_FDB] =3D { .type =3D NLA_FLAG }, + [NHA_DST_PORT] =3D NLA_POLICY_MIN(NLA_BE16, 1), [NHA_RES_GROUP] =3D { .type =3D NLA_NESTED }, [NHA_HW_STATS_ENABLE] =3D NLA_POLICY_MAX(NLA_U32, true), }; @@ -956,6 +957,9 @@ static int nh_fill_node(struct sk_buff *skb, struct nex= thop *nh, } else if (nhi->fdb_nh) { if (nla_put_flag(skb, NHA_FDB)) goto nla_put_failure; + if (nhi->dst_port && + nla_put_be16(skb, NHA_DST_PORT, nhi->dst_port)) + goto nla_put_failure; } else { const struct net_device *dev; =20 @@ -1055,6 +1059,9 @@ static size_t nh_nlmsg_size_single(struct nexthop *nh) break; } =20 + if (nhi->dst_port) + sz +=3D nla_total_size(2); /* NHA_DST_PORT */ + if (nhi->fib_nhc.nhc_lwtstate) { sz +=3D lwtunnel_get_encap_size(nhi->fib_nhc.nhc_lwtstate); sz +=3D nla_total_size(2); /* NHA_ENCAP_TYPE */ @@ -2956,8 +2963,10 @@ static struct nexthop *nexthop_create(struct net *ne= t, struct nh_config *cfg, nhi->family =3D cfg->nh_family; nhi->fib_nhc.nhc_scope =3D RT_SCOPE_LINK; =20 - if (cfg->nh_fdb) + if (cfg->nh_fdb) { nhi->fdb_nh =3D 1; + nhi->dst_port =3D cfg->nh_dst_port; + } =20 if (cfg->nh_blackhole) { nhi->reject_nh =3D 1; @@ -3147,6 +3156,15 @@ static int rtm_to_nh_config(struct net *net, struct = sk_buff *skb, cfg->nh_fdb =3D nla_get_flag(tb[NHA_FDB]); } =20 + if (tb[NHA_DST_PORT]) { + if (!tb[NHA_FDB] || !tb[NHA_GATEWAY]) { + NL_SET_ERR_MSG(extack, + "Destination port can only be set on fdb nexthops that have a g= ateway"); + goto out; + } + cfg->nh_dst_port =3D nla_get_be16(tb[NHA_DST_PORT]); + } + if (tb[NHA_GROUP]) { if (nhm->nh_family !=3D AF_UNSPEC) { NL_SET_ERR_MSG(extack, "Invalid family for group"); --=20 2.43.0 From nobody Fri Jul 24 22:18:41 2026 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12E292C11CA for ; Thu, 23 Jul 2026 01:18:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784769501; cv=none; b=HLtkMP1PSNV0Ld4lvLAzxUTbpfWNwijR6sb8gdpGxPJWUlvOiSeln/V3CTmx1eLKbSAMs0W39yzGSSMNgqcftREMMVrj6CUxWf+GMTjc996cPvtb0VKvo5++mPfglWFhA2L1NjSOV1NEJmqN+Xmve5PVgYjJ90B+BANIFHAMLss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784769501; c=relaxed/simple; bh=cmZk/X88g292ILT+JnceL6lS8EcLUQt5/rCxrfDM+ag=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=np3h3lr6IHCjnQr7KukQubTZbJYZ0typeI2lnASrFCu4yduybpJ8Mn0/g9dgg+VebQR+x06RRha6wSLVWm3lQv4V9Sx4WwnC6cGT1N2CypBmbv5YU9zS/CqH8dKkQ+qLT85YMuMoGuoul1i5cDtGTYSYf/zGIIpWAWoJDHLwDUw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=iAzki95u; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iAzki95u" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-ca766c1c9ccso81728a12.0 for ; Wed, 22 Jul 2026 18:18:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784769494; x=1785374294; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=UGBUPhCkGf4Z9PVVSo4mL4I1zGIBeZMASJ8gZ6MBIzs=; b=iAzki95uyqDwa7cjEJzpNHAh7jjHn76g9G1Z8o4dcmifV6Ql7UmIZLlWYCNU4/vJMt ZaY5gC3XgiTxAKzyLNVumQWDla2tVId9aPcN55eQZyEN3Kr5yDIRi0LKqU0X0oSHAY7r t4yYD17dLDiSigtQjLOhsruC3XLyj9xqoIWyXQ3q77ep5DOH7RN4ri86YrmzoSX8SvuM CrKCI5cJpWQF0maU9k3sWmtWQ9LY4+dYf9BCEZjF4FTVv90gmUTI8iSMv/TS8S4u4teq z+KJjXjFRHLFxby/7wRWeAYT8BneZGYZzqSZsYHtFwRGrVOz3/JoyjR5ua0txMNP2mV3 MSOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784769494; x=1785374294; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=UGBUPhCkGf4Z9PVVSo4mL4I1zGIBeZMASJ8gZ6MBIzs=; b=hQ5kKQL9yqNMJgBpnZ95JaRO5TdHiWj4yv+jCPHucCyiJltUu0fY5PuxAS8/VqENDR sX4RQHcqdIr+wamrR7DTKE9qbm/K/Q62ZJLmOx+taZZqca1Dfw0xkfTf8u+KmcwVjcr1 Kc1CLkSmPhoyWWkDmtEtT28D6LfVL8nGDDkOLIeiCdAnlZerPgJXUBtfwmCP6dY0/2JY +Dz6ueM/V3x41JitYGffwu81qXD0dNG5UnRKTgXHV8ackjguCpLkGVBmlyo5QaByRFGE 3p+o0JHvX7+0Q2UZDCqkMw31Eg8y7Bc6jz4m25mqA1b4StnFP+UK80/ipEoSeDAXi+Tz gSQg== X-Forwarded-Encrypted: i=1; AHgh+RpngT4PG9rIytq5mw+QEd8GIo09JSHnEZAvHbF6yjFQnk23uEwHF94IEUNRgdJfRO2bHjgsGur0tJpSjjw=@vger.kernel.org X-Gm-Message-State: AOJu0YwAaKC/aUPp0HSieksw7qe66bfUKCWgAr0r+bDUDWWnpAxB3u3u ZRMJaYs29FW1OmM5qEU61E+aXRMRNr4ltRnpLyyREggnBMHX+1id1N2r X-Gm-Gg: AR+sD12nW5BaXloQkBkusBfae93Mw8lxewqYPf6J7yuiY7VT9M7G/Drum0iBbIgKq+e 2w56GWDTcNmIgJB/DzuyPLFR3nG0vvVyGz9rbZN5g2QS0jYZuLb9KomK8aAOfAQDrrCQUXhjMkN kymY4q4SxbpbgXQlpCtdh8fpvRBIhfX0E5FaNi8Y9DABSl6ToDxdgU+qkZfQ4G8h6QGnJ5J0ELz E9Knkg1FrIj/T8z231NpqalzbpYDj9msTLjW+pK4YZ/UXTuokU/zPshoPljXlkawc+lo49Cct/2 /kA/9LUKbcmaheHwSJLG535lkd1SqTn0Ap6Hys5ZgkW5/84pqau1aE0+JPWWxIO6MS0r8LTCyhu C+w8AkYXQ1IzqkJrfa+C+ihKfWizcO9I0wPCCT2N8qA40HDzooLh3ueT0WXa8eCYKgDIAxlxr3v k+ZFQD5VkCm+AYadY= X-Received: by 2002:a05:6a00:94f7:b0:84c:5349:daa1 with SMTP id d2e1a72fcca58-84e2bc2ea4cmr1311124b3a.76.1784769494397; Wed, 22 Jul 2026 18:18:14 -0700 (PDT) Received: from CPC-mjac-HKWGEZ.localdomain ([70.37.26.37]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84e175ea5c7sm2089045b3a.53.2026.07.22.18.18.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Jul 2026 18:18:13 -0700 (PDT) From: Jack Ma Date: Thu, 23 Jul 2026 01:17:54 +0000 Subject: [PATCH net-next v4 2/3] vxlan: honor per-nexthop fdb destination port Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-vxlan-fdb-port-v4-2-46e3a2dd88a3@gmail.com> References: <20260723-b4-vxlan-fdb-port-v4-0-46e3a2dd88a3@gmail.com> In-Reply-To: <20260723-b4-vxlan-fdb-port-v4-0-46e3a2dd88a3@gmail.com> To: David Ahern , Ido Schimmel , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Jack Ma X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784769488; l=2195; i=jack4it@gmail.com; s=20260712; h=from:subject:message-id; bh=cmZk/X88g292ILT+JnceL6lS8EcLUQt5/rCxrfDM+ag=; b=9uuszWWcjPI/mbp9xj6Li57CE1j7vPm34gZ9jxIEawV/Qe7i9XKBSxm8e4zVa9VrMI1aIt0Wy NaYkLz/m9kDCnGRN40wAWH21AAZEXpG+ZbWrihU9GCI3EmkjekW6+HW X-Developer-Key: i=jack4it@gmail.com; a=ed25519; pk=x8xh2Md9yNDil0xBOA9WA/oqC3O4Eg4rdlIul4YUktU= When an fdb entry points at a nexthop group, vxlan_fdb_nh_path_select() resolves the selected leg's remote IP but leaves the UDP destination port at the device default (vxlan->cfg.dst_port). Extend nexthop_path_fdb_result() to also return the selected nexthop's NHA_DST_PORT (0 when unset) and have vxlan_fdb_nh_path_select() store it in rdst->remote_port. vxlan_xmit_one() already prefers rdst->remote_port when non-zero and falls back to the device port otherwise, so nexthops without a port are unaffected. This lets one fdb nexthop group load-balance a flow across legs that share an underlay IP but differ in UDP destination port. Signed-off-by: Jack Ma Reviewed-by: David Ahern Reviewed-by: Ido Schimmel --- include/net/nexthop.h | 4 +++- include/net/vxlan.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/net/nexthop.h b/include/net/nexthop.h index 7673aaeff3e28..f86c115074d7a 100644 --- a/include/net/nexthop.h +++ b/include/net/nexthop.h @@ -576,7 +576,8 @@ struct fib_nh_common *nexthop_fdb_nhc(struct nexthop *n= h) } =20 static inline struct fib_nh_common *nexthop_path_fdb_result(struct nexthop= *nh, - int hash) + int hash, + __be16 *dst_port) { struct nh_info *nhi; struct nexthop *nhp; @@ -585,6 +586,7 @@ static inline struct fib_nh_common *nexthop_path_fdb_re= sult(struct nexthop *nh, if (unlikely(!nhp)) return NULL; nhi =3D rcu_dereference(nhp->nh_info); + *dst_port =3D nhi->dst_port; return &nhi->fib_nhc; } #endif diff --git a/include/net/vxlan.h b/include/net/vxlan.h index dfba89695efcf..6e64757151b88 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -567,8 +567,9 @@ static inline bool vxlan_fdb_nh_path_select(struct next= hop *nh, struct vxlan_rdst *rdst) { struct fib_nh_common *nhc; + __be16 dst_port =3D 0; =20 - nhc =3D nexthop_path_fdb_result(nh, hash >> 1); + nhc =3D nexthop_path_fdb_result(nh, hash >> 1, &dst_port); if (unlikely(!nhc)) return false; =20 @@ -583,6 +584,8 @@ static inline bool vxlan_fdb_nh_path_select(struct next= hop *nh, break; } =20 + rdst->remote_port =3D dst_port; + return true; } =20 --=20 2.43.0 From nobody Fri Jul 24 22:18:41 2026 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7CAA61DA62E for ; Thu, 23 Jul 2026 01:18:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784769502; cv=none; b=TdLH2l2pxBscAv5dnsD+QKMlRoATAIO0AMKsxNxhgGsm0AFrMg65kf2UYV16kG6GHrB9Q9xjfj0A4A20YFWNH1OTpXXIHCbeY1vea+ysRfz5cB/IJWclrwaEtqIMwvCYXe4tk7JrbridcvLISa4lTztdBBguIjBJNGqFisc7Mos= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784769502; c=relaxed/simple; bh=5wHaj7ZOUiFnnwZQ/alCVlhWUyG6yyDr4ttHzSEM7CU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aBGJ1yl6kfW+NUsEDVuL7nJ0UhBCw+tScBy1Ua72Ly0SCLO7BMka0oHSE6zgPK3VbsfvRqmmlXNON44ISxuAAfMLZGfZXa4UmcbBAYlK7HOwG21j0kz4PdEf0nRJIF/owM8gbR8xlRBIC9rV81jeBEn1W1J5S6gzClpGWuT6Tcc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=GP2QWW+V; arc=none smtp.client-ip=209.85.210.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GP2QWW+V" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-8484f229529so39833b3a.2 for ; Wed, 22 Jul 2026 18:18:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784769496; x=1785374296; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GeXwCH2Ww/TWsye8893nOWAwkN7miADAvxyyLX+SPtU=; b=GP2QWW+VZOK2rom4sdPM+NHKPqWysNvVXzRrEHU+xSNf/JmjNHme1aeT4O4HJE4Q/6 0GZYTqOv/zOfXrVmvF6kAHQp9NOnqUehWD+xdMkK3he+Y6LuDFtHFuSUU3DChTRA8DnL AcU4vLRt+MTkv1CPqLn7ukNMCdwh0FsTI39e3OF1f73wagy8PPpYkQ2v6NSNuAfppx1/ YQyMd95Ozey7TJqZKcHJkpGUEgEn4TLh4NY07dFgbVceTEWpi/zjWVYmGgqdhBcfQs/f O5Exsh/lJm6s3ACal9t8pibT44Wff6P/3JSh1jho19NvVwQFD0jMirc7b/GO1yPbnsC2 cNgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784769496; x=1785374296; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=GeXwCH2Ww/TWsye8893nOWAwkN7miADAvxyyLX+SPtU=; b=kgFcmaz7rkkeysgGb67WdthwHdZHuJdvx0L15UHRcrPwTLnz8G7Q5CQibutIwAUBIg 3ni2SAJFbfsgAA9BFCAKcMZc/G25NP5PGxee6IWfTxjJNh59OP3vVAkRVzsOLj6N6MGJ XiPUgnxUNn4j0xMJif8eBKjtALv+8QM4T26ud5C7bmCIXubiOz1zFYZg/aNIDvTH9IA6 6inTziTfFZWBGanUwDJ818T5VuIwIg2MHLJyXy/el1th6917bzDPv2Dj+1dmJ86UyBZK ldctVZomNwIP+DFKLkP4V5DSrBYrcBot0xHzRa5PftDDDvTCJh3z+tJN+p4RwxMX25te 38XQ== X-Forwarded-Encrypted: i=1; AHgh+RqDNbfEweLh6Qr1mGF4En0WyIFeT034FXr1sfahqRv+PsXxP7/NApLVlBIf+QkNvvQImGnXpCJS0I4ZJBA=@vger.kernel.org X-Gm-Message-State: AOJu0Yw5o7jhxDRAv6n4iwWEuGhj3EJCqst17SYV966x2VEe5nj4r0w2 7TvhU4RQ/a76P/GxxG+rdw8M5Q1AKd3AHXCOC1iitj/JcK6n+je4mZ9l X-Gm-Gg: AR+sD13GFn/HBA14wEL2/tQIdzP1Mv0DFuodbfAuhcFT+vHUdgar1zgZ+muM0ii0ufi LNdHJOR+X3x/gTbTozhOi+WLACj2oavGZlLwwiE4imh04xJmlblFK+OQkkvEkNTSt/Tfgprm8vw ynkNg74NWCI2g8oBVk6jfCwjyC7GOLNS4VphtB54wXj7krPIZs2JQ5FkeWNQHJ/jxQylnuGPZSi CYLWv5XDsDkCa47EVmoJpi9t8Z1XEQ2hJa3WMQ6/tsKCnV0JhrtkPExd2avthTi3fqOvlgslqUr 1726WvzNtGweicZHuwjfEHMyB6N4/5s+FrhWkvgCJX0PzFDdFZGM0dYy6ufZh8m/Oj+JknkSX3v n6/uGxB7a8KqeBzf9GUUkbTFmSrh8DtHmTUfY60sEuA3jguq4wvRnBdves1tesCiRzr5OfqOR6S SeFZLjlQiKMFEaD3LLzx0iC6p28g== X-Received: by 2002:a05:6a00:b48:b0:848:438d:3665 with SMTP id d2e1a72fcca58-84e2bb3741dmr1332137b3a.41.1784769495728; Wed, 22 Jul 2026 18:18:15 -0700 (PDT) Received: from CPC-mjac-HKWGEZ.localdomain ([70.37.26.37]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84e175ea5c7sm2089045b3a.53.2026.07.22.18.18.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Jul 2026 18:18:14 -0700 (PDT) From: Jack Ma Date: Thu, 23 Jul 2026 01:17:55 +0000 Subject: [PATCH net-next v4 3/3] selftests: net: add coverage for fdb nexthop dst_port Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-vxlan-fdb-port-v4-3-46e3a2dd88a3@gmail.com> References: <20260723-b4-vxlan-fdb-port-v4-0-46e3a2dd88a3@gmail.com> In-Reply-To: <20260723-b4-vxlan-fdb-port-v4-0-46e3a2dd88a3@gmail.com> To: David Ahern , Ido Schimmel , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Jack Ma X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784769488; l=7289; i=jack4it@gmail.com; s=20260712; h=from:subject:message-id; bh=5wHaj7ZOUiFnnwZQ/alCVlhWUyG6yyDr4ttHzSEM7CU=; b=do5DeEEjrWxEHMZsOiwA73wLMesjbJiuvUygHyoHVnXmSeSdKj28drdit5lirzEPtdH3ETMB/ wVrI49sZeQNBROTonjjktLioRDLPskV/0QqzcP3JN//pRV+OMei5akt X-Developer-Key: i=jack4it@gmail.com; a=ed25519; pk=x8xh2Md9yNDil0xBOA9WA/oqC3O4Eg4rdlIul4YUktU= Add coverage for the new per-nexthop VXLAN destination port (NHA_DST_PORT). In fib_nexthops.sh, new ipv4_fdb_port_fcnal() and ipv6_fdb_port_fcnal() tests check that a dst_port is accepted on an fdb nexthop that has a gateway and echoed back on dump, that it is rejected without a gateway and rejected when zero, that a group may hold legs that differ only in UDP port, and that a portless fdb nexthop omits the attribute. The tests SKIP when iproute2 lacks the "dst_port" keyword. In test_vxlan_nh.sh, basic_tx_common() gains a second fdb nexthop group whose nexthop carries a destination port that differs from the VXLAN device default, plus a flower filter keyed on that port, to confirm the per-nexthop port is used on the wire. The test now requires an iproute2 with dst_port support. Signed-off-by: Jack Ma Reviewed-by: David Ahern Reviewed-by: Ido Schimmel --- tools/testing/selftests/net/fib_nexthops.sh | 81 ++++++++++++++++++++++++= ++++ tools/testing/selftests/net/test_vxlan_nh.sh | 34 +++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/se= lftests/net/fib_nexthops.sh index ac868a7316946..834ba1c0676c8 100755 --- a/tools/testing/selftests/net/fib_nexthops.sh +++ b/tools/testing/selftests/net/fib_nexthops.sh @@ -30,6 +30,7 @@ IPV4_TESTS=3D" ipv4_large_res_grp ipv4_compat_mode ipv4_fdb_grp_fcnal + ipv4_fdb_port_fcnal ipv4_mpath_select ipv4_torture ipv4_res_torture @@ -44,6 +45,7 @@ IPV6_TESTS=3D" ipv6_large_res_grp ipv6_compat_mode ipv6_fdb_grp_fcnal + ipv6_fdb_port_fcnal ipv6_mpath_select ipv6_torture ipv6_res_torture @@ -432,6 +434,15 @@ check_nexthop_fdb_support() fi } =20 +check_nexthop_fdb_port_support() +{ + $IP nexthop help 2>&1 | grep -q "dst_port" + if [ $? -ne 0 ]; then + echo "SKIP: iproute2 too old, missing nexthop dst_port support" + return $ksft_skip + fi +} + check_nexthop_res_support() { $IP nexthop help 2>&1 | grep -q resilient @@ -541,6 +552,41 @@ ipv6_fdb_grp_fcnal() $IP link del dev vx10 } =20 +ipv6_fdb_port_fcnal() +{ + echo + echo "IPv6 fdb nexthop dst_port functional" + echo "------------------------------------" + + check_nexthop_fdb_port_support + if [ $? -eq $ksft_skip ]; then + return $ksft_skip + fi + + # NHA_DST_PORT: optional per-nexthop VXLAN destination UDP port, + # letting an fdb nexthop group balance a flow across legs that share + # an underlay IP but listen on different UDP ports. + run_cmd "$IP nexthop add id 80 via 2001:db8:91::2 fdb dst_port 4790" + check_nexthop "id 80" "id 80 via 2001:db8:91::2 scope link fdb dst_port 4= 790" + log_test $? 0 "Fdb nexthop with dst_port" + + run_cmd "$IP nexthop add id 81 fdb dst_port 4790" + log_test $? 2 "Fdb nexthop with dst_port but no gateway" + + run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 fdb dst_port 0" + log_test $? 2 "Fdb nexthop with dst_port 0" + + run_cmd "$IP nexthop add id 82 via 2001:db8:91::2 fdb dst_port 4789" + run_cmd "$IP nexthop add id 83 via 2001:db8:91::3 fdb dst_port 5789" + run_cmd "$IP nexthop add id 106 group 82/83 fdb" + check_nexthop "id 106" "id 106 group 82/83 fdb" + log_test $? 0 "Fdb nexthop group with legs differing in dst_port" + + run_cmd "$IP nexthop add id 84 via 2001:db8:91::2 fdb" + check_nexthop "id 84" "id 84 via 2001:db8:91::2 scope link fdb" + log_test $? 0 "Fdb nexthop without dst_port omits dst_port" +} + ipv4_fdb_grp_fcnal() { local rc @@ -641,6 +687,41 @@ ipv4_fdb_grp_fcnal() $IP link del dev vx10 } =20 +ipv4_fdb_port_fcnal() +{ + echo + echo "IPv4 fdb nexthop dst_port functional" + echo "------------------------------------" + + check_nexthop_fdb_port_support + if [ $? -eq $ksft_skip ]; then + return $ksft_skip + fi + + # NHA_DST_PORT: optional per-nexthop VXLAN destination UDP port, + # letting an fdb nexthop group balance a flow across legs that share + # an underlay IP but listen on different UDP ports. + run_cmd "$IP nexthop add id 30 via 172.16.1.2 fdb dst_port 4790" + check_nexthop "id 30" "id 30 via 172.16.1.2 scope link fdb dst_port 4790" + log_test $? 0 "Fdb nexthop with dst_port" + + run_cmd "$IP nexthop add id 31 fdb dst_port 4790" + log_test $? 2 "Fdb nexthop with dst_port but no gateway" + + run_cmd "$IP nexthop add id 31 via 172.16.1.2 fdb dst_port 0" + log_test $? 2 "Fdb nexthop with dst_port 0" + + run_cmd "$IP nexthop add id 32 via 172.16.1.2 fdb dst_port 4789" + run_cmd "$IP nexthop add id 33 via 172.16.1.3 fdb dst_port 5789" + run_cmd "$IP nexthop add id 105 group 32/33 fdb" + check_nexthop "id 105" "id 105 group 32/33 fdb" + log_test $? 0 "Fdb nexthop group with legs differing in dst_port" + + run_cmd "$IP nexthop add id 34 via 172.16.1.2 fdb" + check_nexthop "id 34" "id 34 via 172.16.1.2 scope link fdb" + log_test $? 0 "Fdb nexthop without dst_port omits dst_port" +} + ipv4_mpath_select() { local rc dev match h addr diff --git a/tools/testing/selftests/net/test_vxlan_nh.sh b/tools/testing/s= elftests/net/test_vxlan_nh.sh index 20f3369f776b1..7b5dc1d37fa02 100755 --- a/tools/testing/selftests/net/test_vxlan_nh.sh +++ b/tools/testing/selftests/net/test_vxlan_nh.sh @@ -56,6 +56,16 @@ tc_stats_get() tc_rule_handle_stats_get "dev dummy1 egress" 101 ".packets" "-n $ns1" } =20 +nh_stats_get_port() +{ + ip -n "$ns1" -s -j nexthop show id 20 | jq ".[][\"group_stats\"][][\"pack= ets\"]" +} + +tc_stats_get_port() +{ + tc_rule_handle_stats_get "dev dummy1 egress" 102 ".packets" "-n $ns1" +} + basic_tx_common() { local af_str=3D$1; shift @@ -90,6 +100,26 @@ basic_tx_common() busywait "$BUSYWAIT_TIMEOUT" until_counter_is "=3D=3D 1" tc_stats_get > /= dev/null check_err $? "tc filter stats did not increase" =20 + # Add a second FDB nexthop group whose nexthop carries a per-nexthop + # destination port (NHA_DST_PORT) that differs from the VXLAN device + # default. Matching outer traffic must egress with that port, so a + # separate flower filter keyed on the new port catches it. + run_cmd "tc -n $ns1 filter add dev dummy1 egress proto $proto pref 1 hand= le 102 \ + flower ip_proto udp dst_ip $remote_addr dst_port 4790 action pass" + + run_cmd "ip -n $ns1 nexthop add id 2 via $remote_addr fdb dst_port 4790" + run_cmd "ip -n $ns1 nexthop add id 20 group 2 fdb" + + run_cmd "bridge -n $ns1 fdb add 00:11:22:33:44:66 dev vx0 self static nhi= d 20" + + run_cmd "ip netns exec $ns1 mausezahn vx0 -a own -b 00:11:22:33:44:66 -c = 1 -q" + + busywait "$BUSYWAIT_TIMEOUT" until_counter_is "=3D=3D 1" nh_stats_get_por= t > /dev/null + check_err $? "FDB nexthop group stats did not increase (with port)" + + busywait "$BUSYWAIT_TIMEOUT" until_counter_is "=3D=3D 1" tc_stats_get_por= t > /dev/null + check_err $? "tc filter stats did not increase (with port)" + log_test "VXLAN FDB nexthop: $af_str basic Tx" } =20 @@ -210,8 +240,8 @@ require_command arping require_command ndisc6 require_command jq =20 -if ! ip nexthop help 2>&1 | grep -q "stats"; then - echo "SKIP: iproute2 ip too old, missing nexthop stats support" +if ! ip nexthop help 2>&1 | grep -q "dst_port"; then + echo "SKIP: iproute2 ip too old, missing nexthop dst_port support" exit "$ksft_skip" fi =20 --=20 2.43.0