summaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorJack Ma <jack4it@gmail.com>2026-07-24 00:26:16 +0000
committerJakub Kicinski <kuba@kernel.org>2026-07-30 16:09:22 -0700
commit53531e6a644a48c2d5a9423f084ae4e91ec6019a (patch)
tree7bd8e48524858041fd8c3ab24db043dcf66e33e0 /net/ipv4
parent61a878bafdf67748cde1358c0533b9dc73bda789 (diff)
net: nexthop: add NHA_DST_PORT for fdb nexthops
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 <jack4it@gmail.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20260724-b4-vxlan-fdb-port-v5-1-cd1c6aeee058@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/nexthop.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 0f1e21a5c812..af1dcb8ea427 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -39,6 +39,7 @@ static const struct nla_policy rtm_nh_policy_new[] = {
[NHA_ENCAP_TYPE] = { .type = NLA_U16 },
[NHA_ENCAP] = { .type = NLA_NESTED },
[NHA_FDB] = { .type = NLA_FLAG },
+ [NHA_DST_PORT] = NLA_POLICY_MIN(NLA_BE16, 1),
[NHA_RES_GROUP] = { .type = NLA_NESTED },
[NHA_HW_STATS_ENABLE] = NLA_POLICY_MAX(NLA_U32, true),
};
@@ -956,6 +957,9 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *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;
@@ -1055,6 +1059,9 @@ static size_t nh_nlmsg_size_single(struct nexthop *nh)
break;
}
+ if (nhi->dst_port)
+ sz += nla_total_size(2); /* NHA_DST_PORT */
+
if (nhi->fib_nhc.nhc_lwtstate) {
sz += lwtunnel_get_encap_size(nhi->fib_nhc.nhc_lwtstate);
sz += nla_total_size(2); /* NHA_ENCAP_TYPE */
@@ -2965,8 +2972,10 @@ static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,
nhi->family = cfg->nh_family;
nhi->fib_nhc.nhc_scope = RT_SCOPE_LINK;
- if (cfg->nh_fdb)
+ if (cfg->nh_fdb) {
nhi->fdb_nh = 1;
+ nhi->dst_port = cfg->nh_dst_port;
+ }
if (cfg->nh_blackhole) {
nhi->reject_nh = 1;
@@ -3156,6 +3165,15 @@ static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,
cfg->nh_fdb = nla_get_flag(tb[NHA_FDB]);
}
+ 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 gateway");
+ goto out;
+ }
+ cfg->nh_dst_port = nla_get_be16(tb[NHA_DST_PORT]);
+ }
+
if (tb[NHA_GROUP]) {
if (nhm->nh_family != AF_UNSPEC) {
NL_SET_ERR_MSG(extack, "Invalid family for group");