* [PATCH iproute2-next] ip nexthop: support fdb destination port
@ 2026-07-22 3:21 Jack Ma
2026-07-22 15:19 ` Ido Schimmel
0 siblings, 1 reply; 2+ messages in thread
From: Jack Ma @ 2026-07-22 3:21 UTC (permalink / raw)
To: netdev; +Cc: David Ahern, Stephen Hemminger, Jakub Kicinski, Jack Ma
The kernel gained NHA_FDB_PORT, an optional per-nexthop UDP destination
port for fdb nexthops. VXLAN uses it to reach several receivers that
share an underlay IP but listen on different ports, load-balancing a
flow across (IP, port) legs of one nexthop group.
Add the matching uapi value and wire it into `ip nexthop`:
ip nexthop add id 1 via 192.0.2.1 fdb port 4790
The port is parsed on add (sent as NHA_FDB_PORT, __be16, network order)
and printed back on dump/get.
Signed-off-by: Jack Ma <jack4it@gmail.com>
---
Kernel side (net-next), which adds NHA_FDB_PORT and is the reason for
this change:
[PATCH net-next v3 0/3] net: nexthop: per-nexthop UDP dst port for fdb
(VXLAN) nexthops
https://lore.kernel.org/netdev/20260721-b4-vxlan-fdb-port-v3-0-9aa0a543a78a@gmail.com/
---
include/uapi/linux/nexthop.h | 2 ++
ip/ipnexthop.c | 16 +++++++++++++++-
ip/nh_common.h | 1 +
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/nexthop.h b/include/uapi/linux/nexthop.h
index afbd064..e1e1a66 100644
--- a/include/uapi/linux/nexthop.h
+++ b/include/uapi/linux/nexthop.h
@@ -83,6 +83,8 @@ enum {
/* u32; read-only; whether any driver collects HW stats */
NHA_HW_STATS_USED,
+ NHA_FDB_PORT, /* be16; UDP dst port for an fdb nexthop (VXLAN) */
+
__NHA_MAX,
};
diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c
index 14b525a..4c33361 100644
--- a/ip/ipnexthop.c
+++ b/ip/ipnexthop.c
@@ -52,7 +52,7 @@ static void usage(void)
"SELECTOR := [ id ID ] [ dev DEV ] [ vrf NAME ] [ master DEV ]\n"
" [ groups ] [ fdb ]\n"
"BUCKET_SELECTOR := SELECTOR | [ nhid ID ]\n"
- "NH := { blackhole | [ via ADDRESS ] [ dev DEV ] [ onlink ]\n"
+ "NH := { blackhole | [ via ADDRESS ] [ dev DEV ] [ onlink ] [ fdb [ port PORT ] ]\n"
" [ encap ENCAPTYPE ENCAPHDR ] |\n"
" group GROUP [ fdb ] [ type TYPE [ TYPE_ARGS ] ] }\n"
"GROUP := [ <id[,weight]>/<id[,weight]>/... ]\n"
@@ -531,6 +531,8 @@ static int ipnh_parse_nhmsg(FILE *fp, const struct nhmsg *nhm, int len,
nhe->nh_blackhole = !!tb[NHA_BLACKHOLE];
nhe->nh_fdb = !!tb[NHA_FDB];
+ if (tb[NHA_FDB_PORT])
+ nhe->nh_fdb_port = rta_getattr_be16(tb[NHA_FDB_PORT]);
nhe->nh_family = nhm->nh_family;
nhe->nh_protocol = nhm->nh_protocol;
@@ -595,6 +597,10 @@ static void __print_nexthop_entry(FILE *fp, const char *jsobj,
if (nhe->nh_fdb)
print_null(PRINT_ANY, "fdb", "fdb", NULL);
+ if (nhe->nh_fdb_port)
+ print_uint(PRINT_ANY, "port", " port %u",
+ nhe->nh_fdb_port);
+
if ((show_details > 0 || show_stats) && nhe->nh_hw_stats_supported) {
open_json_object("hw_stats");
print_on_off(PRINT_ANY, "enabled", "hw_stats %s ",
@@ -1112,6 +1118,14 @@ static int ipnh_modify(int cmd, unsigned int flags, int argc, char **argv)
req.nhm.nh_family = AF_INET;
} else if (!strcmp(*argv, "fdb")) {
addattr_l(&req.n, sizeof(req), NHA_FDB, NULL, 0);
+ } else if (!strcmp(*argv, "port")) {
+ __u16 port;
+
+ NEXT_ARG();
+ if (get_u16(&port, *argv, 0))
+ invarg("\"port\" value is invalid\n", *argv);
+ addattr16(&req.n, sizeof(req), NHA_FDB_PORT,
+ htons(port));
} else if (!strcmp(*argv, "onlink")) {
nh_flags |= RTNH_F_ONLINK;
} else if (!strcmp(*argv, "group")) {
diff --git a/ip/nh_common.h b/ip/nh_common.h
index afbd16b..759c0c4 100644
--- a/ip/nh_common.h
+++ b/ip/nh_common.h
@@ -33,6 +33,7 @@ struct nh_entry {
bool nh_blackhole;
bool nh_fdb;
+ __u16 nh_fdb_port;
bool nh_hw_stats_supported;
bool nh_hw_stats_enabled;
---
base-commit: 35a237091c24858cac6c6679175bb6a628cbe400
change-id: 20260722-b4-vxlan-fdb-port-iproute2-13165877ba46
Best regards,
--
Jack Ma <jack4it@gmail.com>
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH iproute2-next] ip nexthop: support fdb destination port
2026-07-22 3:21 [PATCH iproute2-next] ip nexthop: support fdb destination port Jack Ma
@ 2026-07-22 15:19 ` Ido Schimmel
0 siblings, 0 replies; 2+ messages in thread
From: Ido Schimmel @ 2026-07-22 15:19 UTC (permalink / raw)
To: Jack Ma; +Cc: netdev, David Ahern, Stephen Hemminger, Jakub Kicinski
On Wed, Jul 22, 2026 at 03:21:33AM +0000, Jack Ma wrote:
> The kernel gained NHA_FDB_PORT, an optional per-nexthop UDP destination
> port for fdb nexthops. VXLAN uses it to reach several receivers that
> share an underlay IP but listen on different ports, load-balancing a
> flow across (IP, port) legs of one nexthop group.
>
> Add the matching uapi value and wire it into `ip nexthop`:
>
> ip nexthop add id 1 via 192.0.2.1 fdb port 4790
>
> The port is parsed on add (sent as NHA_FDB_PORT, __be16, network order)
> and printed back on dump/get.
FWIW, I don't post iproute2 changes before the kernel changes are
accepted. I put a link in the kernel cover letter to the repo where I
have the iproute2 patches.
>
> Signed-off-by: Jack Ma <jack4it@gmail.com>
> ---
> Kernel side (net-next), which adds NHA_FDB_PORT and is the reason for
> this change:
>
> [PATCH net-next v3 0/3] net: nexthop: per-nexthop UDP dst port for fdb
> (VXLAN) nexthops
> https://lore.kernel.org/netdev/20260721-b4-vxlan-fdb-port-v3-0-9aa0a543a78a@gmail.com/
> ---
> include/uapi/linux/nexthop.h | 2 ++
You need to perform this change in a separate patch. Example:
https://lore.kernel.org/netdev/20260320140847.1730633-2-justin.iurman@6wind.com/
> ip/ipnexthop.c | 16 +++++++++++++++-
> ip/nh_common.h | 1 +
> 3 files changed, 18 insertions(+), 1 deletion(-)
Missing update to the man page
>
> diff --git a/include/uapi/linux/nexthop.h b/include/uapi/linux/nexthop.h
> index afbd064..e1e1a66 100644
> --- a/include/uapi/linux/nexthop.h
> +++ b/include/uapi/linux/nexthop.h
> @@ -83,6 +83,8 @@ enum {
> /* u32; read-only; whether any driver collects HW stats */
> NHA_HW_STATS_USED,
>
> + NHA_FDB_PORT, /* be16; UDP dst port for an fdb nexthop (VXLAN) */
> +
> __NHA_MAX,
> };
>
> diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c
> index 14b525a..4c33361 100644
> --- a/ip/ipnexthop.c
> +++ b/ip/ipnexthop.c
> @@ -52,7 +52,7 @@ static void usage(void)
> "SELECTOR := [ id ID ] [ dev DEV ] [ vrf NAME ] [ master DEV ]\n"
> " [ groups ] [ fdb ]\n"
> "BUCKET_SELECTOR := SELECTOR | [ nhid ID ]\n"
> - "NH := { blackhole | [ via ADDRESS ] [ dev DEV ] [ onlink ]\n"
> + "NH := { blackhole | [ via ADDRESS ] [ dev DEV ] [ onlink ] [ fdb [ port PORT ] ]\n"
Assuming we go with "dst_port", you can drop "fdb". Only the kernel will
validate that "dst_port" is provided together with "fdb".
> " [ encap ENCAPTYPE ENCAPHDR ] |\n"
> " group GROUP [ fdb ] [ type TYPE [ TYPE_ARGS ] ] }\n"
> "GROUP := [ <id[,weight]>/<id[,weight]>/... ]\n"
> @@ -531,6 +531,8 @@ static int ipnh_parse_nhmsg(FILE *fp, const struct nhmsg *nhm, int len,
>
> nhe->nh_blackhole = !!tb[NHA_BLACKHOLE];
> nhe->nh_fdb = !!tb[NHA_FDB];
> + if (tb[NHA_FDB_PORT])
> + nhe->nh_fdb_port = rta_getattr_be16(tb[NHA_FDB_PORT]);
>
> nhe->nh_family = nhm->nh_family;
> nhe->nh_protocol = nhm->nh_protocol;
> @@ -595,6 +597,10 @@ static void __print_nexthop_entry(FILE *fp, const char *jsobj,
> if (nhe->nh_fdb)
> print_null(PRINT_ANY, "fdb", "fdb", NULL);
>
> + if (nhe->nh_fdb_port)
> + print_uint(PRINT_ANY, "port", " port %u",
The convention here is "port %u ", not " port %u". I think you added it
like that because there's a missing space in "fdb" above. Fix it while
you are at it.
> + nhe->nh_fdb_port);
> +
> if ((show_details > 0 || show_stats) && nhe->nh_hw_stats_supported) {
> open_json_object("hw_stats");
> print_on_off(PRINT_ANY, "enabled", "hw_stats %s ",
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-22 15:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-22 3:21 [PATCH iproute2-next] ip nexthop: support fdb destination port Jack Ma
2026-07-22 15:19 ` Ido Schimmel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox