diff options
| author | Jack Ma <jack4it@gmail.com> | 2026-07-24 00:26:16 +0000 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-07-30 16:09:22 -0700 |
| commit | 53531e6a644a48c2d5a9423f084ae4e91ec6019a (patch) | |
| tree | 7bd8e48524858041fd8c3ab24db043dcf66e33e0 /net/ipv4 | |
| parent | 61a878bafdf67748cde1358c0533b9dc73bda789 (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.c | 20 |
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"); |
