| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/22 16:16 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"VXLAN"
],
"FocusSymbols": [
"rtm_to_nh_config",
"nexthop_create",
"nh_fill_node"
],
"Reasoning": "The patch adds support for a new netlink attribute NHA_FDB_PORT to specify a UDP destination port for FDB nexthops (e.g., VXLAN). It modifies the nexthop netlink control path and VXLAN datapath. The netlink control path functions are good targets for fuzzing.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/22 16:16 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 853c32465e8d7dc6263152a8af3450c58b2f0102\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jul 22 16:16:36 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/include/net/nexthop.h b/include/net/nexthop.h\nindex 572e69cda4766d..19e8670d964d9d 100644\n--- a/include/net/nexthop.h\n+++ b/include/net/nexthop.h\n@@ -28,6 +28,7 @@ struct nh_config {\n \tu8\t\tnh_protocol;\n \tu8\t\tnh_blackhole;\n \tu8\t\tnh_fdb;\n+\t__be16\t\tnh_fdb_port;\n \tu32\t\tnh_flags;\n \n \tint\t\tnh_ifindex;\n@@ -63,6 +64,7 @@ struct nh_info {\n \tu8\t\t\tfamily;\n \tbool\t\t\treject_nh;\n \tbool\t\t\tfdb_nh;\n+\t__be16\t\t\tfdb_port;\n \n \tunion {\n \t\tstruct fib_nh_common\tfib_nhc;\n@@ -574,7 +576,8 @@ struct fib_nh_common *nexthop_fdb_nhc(struct nexthop *nh)\n }\n \n static inline struct fib_nh_common *nexthop_path_fdb_result(struct nexthop *nh,\n-\t\t\t\t\t\t\t int hash)\n+\t\t\t\t\t\t\t int hash,\n+\t\t\t\t\t\t\t __be16 *fdb_port)\n {\n \tstruct nh_info *nhi;\n \tstruct nexthop *nhp;\n@@ -583,6 +586,7 @@ static inline struct fib_nh_common *nexthop_path_fdb_result(struct nexthop *nh,\n \tif (unlikely(!nhp))\n \t\treturn NULL;\n \tnhi = rcu_dereference(nhp-\u003enh_info);\n+\t*fdb_port = nhi-\u003efdb_port;\n \treturn \u0026nhi-\u003efib_nhc;\n }\n #endif\ndiff --git a/include/net/vxlan.h b/include/net/vxlan.h\nindex dfba89695efcfa..de41b374688f29 100644\n--- a/include/net/vxlan.h\n+++ b/include/net/vxlan.h\n@@ -567,8 +567,9 @@ static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,\n \t\t\t\t\t struct vxlan_rdst *rdst)\n {\n \tstruct fib_nh_common *nhc;\n+\t__be16 fdb_port = 0;\n \n-\tnhc = nexthop_path_fdb_result(nh, hash \u003e\u003e 1);\n+\tnhc = nexthop_path_fdb_result(nh, hash \u003e\u003e 1, \u0026fdb_port);\n \tif (unlikely(!nhc))\n \t\treturn false;\n \n@@ -583,6 +584,8 @@ static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,\n \t\tbreak;\n \t}\n \n+\trdst-\u003eremote_port = fdb_port;\n+\n \treturn true;\n }\n \ndiff --git a/include/uapi/linux/nexthop.h b/include/uapi/linux/nexthop.h\nindex bc49baf4a267f0..e587bbf3b890a3 100644\n--- a/include/uapi/linux/nexthop.h\n+++ b/include/uapi/linux/nexthop.h\n@@ -83,6 +83,9 @@ enum {\n \t/* u32; read-only; whether any driver collects HW stats */\n \tNHA_HW_STATS_USED,\n \n+\t/* be16; UDP destination port for an fdb nexthop (e.g. VXLAN) */\n+\tNHA_FDB_PORT,\n+\n \t__NHA_MAX,\n };\n \ndiff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c\nindex 6205bd57aa8520..b82da3eff63c91 100644\n--- a/net/ipv4/nexthop.c\n+++ b/net/ipv4/nexthop.c\n@@ -39,6 +39,7 @@ static const struct nla_policy rtm_nh_policy_new[] = {\n \t[NHA_ENCAP_TYPE]\t= { .type = NLA_U16 },\n \t[NHA_ENCAP]\t\t= { .type = NLA_NESTED },\n \t[NHA_FDB]\t\t= { .type = NLA_FLAG },\n+\t[NHA_FDB_PORT]\t\t= NLA_POLICY_MIN(NLA_BE16, 1),\n \t[NHA_RES_GROUP]\t\t= { .type = NLA_NESTED },\n \t[NHA_HW_STATS_ENABLE]\t= NLA_POLICY_MAX(NLA_U32, true),\n };\n@@ -956,6 +957,9 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,\n \t} else if (nhi-\u003efdb_nh) {\n \t\tif (nla_put_flag(skb, NHA_FDB))\n \t\t\tgoto nla_put_failure;\n+\t\tif (nhi-\u003efdb_port \u0026\u0026\n+\t\t nla_put_be16(skb, NHA_FDB_PORT, nhi-\u003efdb_port))\n+\t\t\tgoto nla_put_failure;\n \t} else {\n \t\tconst struct net_device *dev;\n \n@@ -1055,6 +1059,9 @@ static size_t nh_nlmsg_size_single(struct nexthop *nh)\n \t\tbreak;\n \t}\n \n+\tif (nhi-\u003efdb_port)\n+\t\tsz += nla_total_size(2);\t/* NHA_FDB_PORT */\n+\n \tif (nhi-\u003efib_nhc.nhc_lwtstate) {\n \t\tsz += lwtunnel_get_encap_size(nhi-\u003efib_nhc.nhc_lwtstate);\n \t\tsz += nla_total_size(2); /* NHA_ENCAP_TYPE */\n@@ -2956,8 +2963,10 @@ static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,\n \tnhi-\u003efamily = cfg-\u003enh_family;\n \tnhi-\u003efib_nhc.nhc_scope = RT_SCOPE_LINK;\n \n-\tif (cfg-\u003enh_fdb)\n+\tif (cfg-\u003enh_fdb) {\n \t\tnhi-\u003efdb_nh = 1;\n+\t\tnhi-\u003efdb_port = cfg-\u003enh_fdb_port;\n+\t}\n \n \tif (cfg-\u003enh_blackhole) {\n \t\tnhi-\u003ereject_nh = 1;\n@@ -3147,6 +3156,15 @@ static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,\n \t\tcfg-\u003enh_fdb = nla_get_flag(tb[NHA_FDB]);\n \t}\n \n+\tif (tb[NHA_FDB_PORT]) {\n+\t\tif (!tb[NHA_FDB] || !tb[NHA_GATEWAY]) {\n+\t\t\tNL_SET_ERR_MSG(extack,\n+\t\t\t\t \"FDB port can only be set on fdb nexthops that have a gateway\");\n+\t\t\tgoto out;\n+\t\t}\n+\t\tcfg-\u003enh_fdb_port = nla_get_be16(tb[NHA_FDB_PORT]);\n+\t}\n+\n \tif (tb[NHA_GROUP]) {\n \t\tif (nhm-\u003enh_family != AF_UNSPEC) {\n \t\t\tNL_SET_ERR_MSG(extack, \"Invalid family for group\");\ndiff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh\nindex ac868a7316946a..1ce4f45fa6515f 100755\n--- a/tools/testing/selftests/net/fib_nexthops.sh\n+++ b/tools/testing/selftests/net/fib_nexthops.sh\n@@ -432,6 +432,15 @@ check_nexthop_fdb_support()\n \tfi\n }\n \n+check_nexthop_fdb_port_support()\n+{\n+\t$IP nexthop help 2\u003e\u00261 | grep -q \"fdb \\[ port\"\n+\tif [ $? -ne 0 ]; then\n+\t\techo \"SKIP: iproute2 too old, missing fdb nexthop port support\"\n+\t\treturn $ksft_skip\n+\tfi\n+}\n+\n check_nexthop_res_support()\n {\n \t$IP nexthop help 2\u003e\u00261 | grep -q resilient\n@@ -514,6 +523,31 @@ ipv6_fdb_grp_fcnal()\n \trun_cmd \"$IP nexthop replace id 72 via 2001:db8:91::2 fdb\"\n \tlog_test $? 2 \"Replace non-FDB nexthop to FDB nexthop while in a group\"\n \n+\t# NHA_FDB_PORT: optional per-nexthop VXLAN destination UDP port,\n+\t# letting an fdb nexthop group balance a flow across legs that share\n+\t# an underlay IP but listen on different UDP ports.\n+\tif check_nexthop_fdb_port_support; then\n+\t\trun_cmd \"$IP nexthop add id 80 via 2001:db8:91::2 fdb port 4790\"\n+\t\tcheck_nexthop \"id 80\" \"id 80 via 2001:db8:91::2 scope link fdb port 4790\"\n+\t\tlog_test $? 0 \"Fdb nexthop with port\"\n+\n+\t\trun_cmd \"$IP nexthop add id 81 fdb port 4790\"\n+\t\tlog_test $? 2 \"Fdb nexthop with port but no gateway\"\n+\n+\t\trun_cmd \"$IP nexthop add id 81 via 2001:db8:91::2 fdb port 0\"\n+\t\tlog_test $? 2 \"Fdb nexthop with port 0\"\n+\n+\t\trun_cmd \"$IP nexthop add id 82 via 2001:db8:91::2 fdb port 4789\"\n+\t\trun_cmd \"$IP nexthop add id 83 via 2001:db8:91::3 fdb port 5789\"\n+\t\trun_cmd \"$IP nexthop add id 106 group 82/83 fdb\"\n+\t\tcheck_nexthop \"id 106\" \"id 106 group 82/83 fdb\"\n+\t\tlog_test $? 0 \"Fdb nexthop group with legs differing in port\"\n+\n+\t\trun_cmd \"$IP nexthop add id 84 via 2001:db8:91::2 fdb\"\n+\t\tcheck_nexthop \"id 84\" \"id 84 via 2001:db8:91::2 scope link fdb\"\n+\t\tlog_test $? 0 \"Fdb nexthop without port omits port\"\n+\tfi\n+\n \trun_cmd \"$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100\"\n \trun_cmd \"$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self\"\n \tlog_test $? 0 \"Fdb mac add with nexthop group\"\n@@ -614,6 +648,31 @@ ipv4_fdb_grp_fcnal()\n \trun_cmd \"$IP nexthop replace id 20 via 172.16.1.2 fdb\"\n \tlog_test $? 2 \"Replace non-FDB nexthop to FDB nexthop while in a group\"\n \n+\t# NHA_FDB_PORT: optional per-nexthop VXLAN destination UDP port,\n+\t# letting an fdb nexthop group balance a flow across legs that share\n+\t# an underlay IP but listen on different UDP ports.\n+\tif check_nexthop_fdb_port_support; then\n+\t\trun_cmd \"$IP nexthop add id 30 via 172.16.1.2 fdb port 4790\"\n+\t\tcheck_nexthop \"id 30\" \"id 30 via 172.16.1.2 scope link fdb port 4790\"\n+\t\tlog_test $? 0 \"Fdb nexthop with port\"\n+\n+\t\trun_cmd \"$IP nexthop add id 31 fdb port 4790\"\n+\t\tlog_test $? 2 \"Fdb nexthop with port but no gateway\"\n+\n+\t\trun_cmd \"$IP nexthop add id 31 via 172.16.1.2 fdb port 0\"\n+\t\tlog_test $? 2 \"Fdb nexthop with port 0\"\n+\n+\t\trun_cmd \"$IP nexthop add id 32 via 172.16.1.2 fdb port 4789\"\n+\t\trun_cmd \"$IP nexthop add id 33 via 172.16.1.3 fdb port 5789\"\n+\t\trun_cmd \"$IP nexthop add id 105 group 32/33 fdb\"\n+\t\tcheck_nexthop \"id 105\" \"id 105 group 32/33 fdb\"\n+\t\tlog_test $? 0 \"Fdb nexthop group with legs differing in port\"\n+\n+\t\trun_cmd \"$IP nexthop add id 34 via 172.16.1.2 fdb\"\n+\t\tcheck_nexthop \"id 34\" \"id 34 via 172.16.1.2 scope link fdb\"\n+\t\tlog_test $? 0 \"Fdb nexthop without port omits port\"\n+\tfi\n+\n \trun_cmd \"$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100\"\n \trun_cmd \"$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self\"\n \tlog_test $? 0 \"Fdb mac add with nexthop group\"\ndiff --git a/tools/testing/selftests/net/test_vxlan_nh.sh b/tools/testing/selftests/net/test_vxlan_nh.sh\nindex 20f3369f776b15..34a24a4f95bf7b 100755\n--- a/tools/testing/selftests/net/test_vxlan_nh.sh\n+++ b/tools/testing/selftests/net/test_vxlan_nh.sh\n@@ -56,6 +56,16 @@ tc_stats_get()\n \ttc_rule_handle_stats_get \"dev dummy1 egress\" 101 \".packets\" \"-n $ns1\"\n }\n \n+nh_stats_get_port()\n+{\n+\tip -n \"$ns1\" -s -j nexthop show id 20 | jq \".[][\\\"group_stats\\\"][][\\\"packets\\\"]\"\n+}\n+\n+tc_stats_get_port()\n+{\n+\ttc_rule_handle_stats_get \"dev dummy1 egress\" 102 \".packets\" \"-n $ns1\"\n+}\n+\n basic_tx_common()\n {\n \tlocal af_str=$1; shift\n@@ -90,6 +100,27 @@ basic_tx_common()\n \tbusywait \"$BUSYWAIT_TIMEOUT\" until_counter_is \"== 1\" tc_stats_get \u003e /dev/null\n \tcheck_err $? \"tc filter stats did not increase\"\n \n+\t# Add a second FDB nexthop group whose nexthop carries a per-nexthop\n+\t# destination port (NHA_FDB_PORT) that differs from the VXLAN device\n+\t# default. Matching outer traffic must egress with that port, so a\n+\t# separate flower filter keyed on the new port catches it.\n+\tif ip nexthop help 2\u003e\u00261 | grep -q \"fdb \\[ port\"; then\n+\t\trun_cmd \"tc -n $ns1 filter add dev dummy1 egress proto $proto pref 1 handle 102 flower ip_proto udp dst_ip $remote_addr dst_port 4790 action pass\"\n+\n+\t\trun_cmd \"ip -n $ns1 nexthop add id 2 via $remote_addr fdb port 4790\"\n+\t\trun_cmd \"ip -n $ns1 nexthop add id 20 group 2 fdb\"\n+\n+\t\trun_cmd \"bridge -n $ns1 fdb add 00:11:22:33:44:66 dev vx0 self static nhid 20\"\n+\n+\t\trun_cmd \"ip netns exec $ns1 mausezahn vx0 -a own -b 00:11:22:33:44:66 -c 1 -q\"\n+\n+\t\tbusywait \"$BUSYWAIT_TIMEOUT\" until_counter_is \"== 1\" nh_stats_get_port \u003e /dev/null\n+\t\tcheck_err $? \"FDB nexthop group stats did not increase (with port)\"\n+\n+\t\tbusywait \"$BUSYWAIT_TIMEOUT\" until_counter_is \"== 1\" tc_stats_get_port \u003e /dev/null\n+\t\tcheck_err $? \"tc filter stats did not increase (with port)\"\n+\tfi\n+\n \tlog_test \"VXLAN FDB nexthop: $af_str basic Tx\"\n }\n \n"
} |
| 2/1 | 2026/07/22 16:16 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"VXLAN"
],
"FocusSymbols": [
"rtm_to_nh_config",
"nexthop_create",
"nh_fill_node"
],
"Reasoning": "The patch adds support for a new netlink attribute NHA_FDB_PORT to specify a UDP destination port for FDB nexthops (e.g., VXLAN). It modifies the nexthop netlink control path and VXLAN datapath. The netlink control path functions are good targets for fuzzing.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 853c32465e8d7dc6263152a8af3450c58b2f0102
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jul 22 16:16:36 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/net/nexthop.h b/include/net/nexthop.h
index 572e69cda4766d..19e8670d964d9d 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_fdb_port;
u32 nh_flags;
int nh_ifindex;
@@ -63,6 +64,7 @@ struct nh_info {
u8 family;
bool reject_nh;
bool fdb_nh;
+ __be16 fdb_port;
union {
struct fib_nh_common fib_nhc;
@@ -574,7 +576,8 @@ struct fib_nh_common *nexthop_fdb_nhc(struct nexthop *nh)
}
static inline struct fib_nh_common *nexthop_path_fdb_result(struct nexthop *nh,
- int hash)
+ int hash,
+ __be16 *fdb_port)
{
struct nh_info *nhi;
struct nexthop *nhp;
@@ -583,6 +586,7 @@ static inline struct fib_nh_common *nexthop_path_fdb_result(struct nexthop *nh,
if (unlikely(!nhp))
return NULL;
nhi = rcu_dereference(nhp->nh_info);
+ *fdb_port = nhi->fdb_port;
return &nhi->fib_nhc;
}
#endif
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index dfba89695efcfa..de41b374688f29 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -567,8 +567,9 @@ static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,
struct vxlan_rdst *rdst)
{
struct fib_nh_common *nhc;
+ __be16 fdb_port = 0;
- nhc = nexthop_path_fdb_result(nh, hash >> 1);
+ nhc = nexthop_path_fdb_result(nh, hash >> 1, &fdb_port);
if (unlikely(!nhc))
return false;
@@ -583,6 +584,8 @@ static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,
break;
}
+ rdst->remote_port = fdb_port;
+
return true;
}
diff --git a/include/uapi/linux/nexthop.h b/include/uapi/linux/nexthop.h
index bc49baf4a267f0..e587bbf3b890a3 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,
+ /* be16; UDP destination port for an fdb nexthop (e.g. VXLAN) */
+ NHA_FDB_PORT,
+
__NHA_MAX,
};
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 6205bd57aa8520..b82da3eff63c91 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_FDB_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->fdb_port &&
+ nla_put_be16(skb, NHA_FDB_PORT, nhi->fdb_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->fdb_port)
+ sz += nla_total_size(2); /* NHA_FDB_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 */
@@ -2956,8 +2963,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->fdb_port = cfg->nh_fdb_port;
+ }
if (cfg->nh_blackhole) {
nhi->reject_nh = 1;
@@ -3147,6 +3156,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_FDB_PORT]) {
+ if (!tb[NHA_FDB] || !tb[NHA_GATEWAY]) {
+ NL_SET_ERR_MSG(extack,
+ "FDB port can only be set on fdb nexthops that have a gateway");
+ goto out;
+ }
+ cfg->nh_fdb_port = nla_get_be16(tb[NHA_FDB_PORT]);
+ }
+
if (tb[NHA_GROUP]) {
if (nhm->nh_family != AF_UNSPEC) {
NL_SET_ERR_MSG(extack, "Invalid family for group");
diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
index ac868a7316946a..1ce4f45fa6515f 100755
--- a/tools/testing/selftests/net/fib_nexthops.sh
+++ b/tools/testing/selftests/net/fib_nexthops.sh
@@ -432,6 +432,15 @@ check_nexthop_fdb_support()
fi
}
+check_nexthop_fdb_port_support()
+{
+ $IP nexthop help 2>&1 | grep -q "fdb \[ port"
+ if [ $? -ne 0 ]; then
+ echo "SKIP: iproute2 too old, missing fdb nexthop port support"
+ return $ksft_skip
+ fi
+}
+
check_nexthop_res_support()
{
$IP nexthop help 2>&1 | grep -q resilient
@@ -514,6 +523,31 @@ ipv6_fdb_grp_fcnal()
run_cmd "$IP nexthop replace id 72 via 2001:db8:91::2 fdb"
log_test $? 2 "Replace non-FDB nexthop to FDB nexthop while in a group"
+ # NHA_FDB_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.
+ if check_nexthop_fdb_port_support; then
+ run_cmd "$IP nexthop add id 80 via 2001:db8:91::2 fdb port 4790"
+ check_nexthop "id 80" "id 80 via 2001:db8:91::2 scope link fdb port 4790"
+ log_test $? 0 "Fdb nexthop with port"
+
+ run_cmd "$IP nexthop add id 81 fdb port 4790"
+ log_test $? 2 "Fdb nexthop with port but no gateway"
+
+ run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 fdb port 0"
+ log_test $? 2 "Fdb nexthop with port 0"
+
+ run_cmd "$IP nexthop add id 82 via 2001:db8:91::2 fdb port 4789"
+ run_cmd "$IP nexthop add id 83 via 2001:db8:91::3 fdb 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 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 port omits port"
+ fi
+
run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
log_test $? 0 "Fdb mac add with nexthop group"
@@ -614,6 +648,31 @@ ipv4_fdb_grp_fcnal()
run_cmd "$IP nexthop replace id 20 via 172.16.1.2 fdb"
log_test $? 2 "Replace non-FDB nexthop to FDB nexthop while in a group"
+ # NHA_FDB_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.
+ if check_nexthop_fdb_port_support; then
+ run_cmd "$IP nexthop add id 30 via 172.16.1.2 fdb port 4790"
+ check_nexthop "id 30" "id 30 via 172.16.1.2 scope link fdb port 4790"
+ log_test $? 0 "Fdb nexthop with port"
+
+ run_cmd "$IP nexthop add id 31 fdb port 4790"
+ log_test $? 2 "Fdb nexthop with port but no gateway"
+
+ run_cmd "$IP nexthop add id 31 via 172.16.1.2 fdb port 0"
+ log_test $? 2 "Fdb nexthop with port 0"
+
+ run_cmd "$IP nexthop add id 32 via 172.16.1.2 fdb port 4789"
+ run_cmd "$IP nexthop add id 33 via 172.16.1.3 fdb 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 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 port omits port"
+ fi
+
run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
log_test $? 0 "Fdb mac add with nexthop group"
diff --git a/tools/testing/selftests/net/test_vxlan_nh.sh b/tools/testing/selftests/net/test_vxlan_nh.sh
index 20f3369f776b15..34a24a4f95bf7b 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"
}
+nh_stats_get_port()
+{
+ ip -n "$ns1" -s -j nexthop show id 20 | jq ".[][\"group_stats\"][][\"packets\"]"
+}
+
+tc_stats_get_port()
+{
+ tc_rule_handle_stats_get "dev dummy1 egress" 102 ".packets" "-n $ns1"
+}
+
basic_tx_common()
{
local af_str=$1; shift
@@ -90,6 +100,27 @@ basic_tx_common()
busywait "$BUSYWAIT_TIMEOUT" until_counter_is "== 1" tc_stats_get > /dev/null
check_err $? "tc filter stats did not increase"
+ # Add a second FDB nexthop group whose nexthop carries a per-nexthop
+ # destination port (NHA_FDB_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.
+ if ip nexthop help 2>&1 | grep -q "fdb \[ port"; then
+ run_cmd "tc -n $ns1 filter add dev dummy1 egress proto $proto pref 1 handle 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 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 nhid 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 "== 1" nh_stats_get_port > /dev/null
+ check_err $? "FDB nexthop group stats did not increase (with port)"
+
+ busywait "$BUSYWAIT_TIMEOUT" until_counter_is "== 1" tc_stats_get_port > /dev/null
+ check_err $? "tc filter stats did not increase (with port)"
+ fi
+
log_test "VXLAN FDB nexthop: $af_str basic Tx"
}
|
| 3/2 | 2026/07/22 16:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6408 output: 31 thoughts: 406 Thoughts: **Analyzing the VXLAN FDB Nexthop Patch** Okay, so I'm looking at this patch that introduces `NHA_FDB_PORT` support in nexthops, specifically for VXLAN FDB nexthops. This is core networking functionality, so it needs careful review. It looks like it touches quite a few files: `include/net/nexthop.h`, `include/net/vxlan.h`, `include/uapi/linux/nexthop.h`, `net/ipv4/nexthop.c`, and some selftests, which is what I'd expect for this kind of change. The primary function of this patch is allowing users to specify a UDP destination port for an FDB nexthop. Let's break down the functions modified and see what's being affected. It looks like we have: - `nexthop_path_fdb_result` in `include/net/nexthop.h` - `vxlan_fdb_nh_path_select` in `include/net/vxlan.h` - `nh_fill_node` in `net/ipv4/nexthop.c` - `nh_nlmsg_size_single` in `net/ipv4/nexthop.c` - `nexthop_create` in `net/ipv4/nexthop.c` - `rtm_to_nh_config` in `net/ipv4/nexthop.c` I need to confirm the configuration dependencies for this. Obviously, `CONFIG_VXLAN` is necessary for VXLAN support. As for the rest of the nexthop functionality, I think that is a standard part of IPv4 routing, not directly related to `CONFIG_IP_ROUTE_MULTIPATH`. Let's confirm that by checking `net/ipv4/nexthop.c` and `include/net/nexthop.h` dependencies. Looks like `net/ipv4/nexthop.c` is always compiled for IPv4, not under `CONFIG_IP_ROUTE_MULTIPATH`. Let's check `net/ipv4/Makefile` to be sure. |
| 4/2 | 2026/07/22 16:16 | tool | grepper |
0mArgs:{
"Expression": "nexthop.o",
"PathPrefix": "net/ipv4/Makefile"
}Results: {
"Output": "net/ipv4/Makefile=6=obj-y := route.o inetpeer.o protocol.o \\\n--\nnet/ipv4/Makefile-16-\t inet_fragment.o ping.o ip_tunnel_core.o gre_offload.o \\\nnet/ipv4/Makefile:17:\t metrics.o netlink.o nexthop.o udp_tunnel_stub.o\nnet/ipv4/Makefile-18-\n"
} |
| 5/2 | 2026/07/22 16:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7450 output: 31 thoughts: 42 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **IPv4 and VXLAN Concerns** Right, so this code is built assuming IPv4, no ifs, ands, or buts. Okay, that's fine for some contexts, but immediately I'm thinking about VXLAN. Is this going to play nicely with VXLAN-encapsulated traffic? The logic within `vxlan_fdb_nh_path_select` is critical here. It's used so it needs the right kernel configuration. I remember now: I'm pretty sure that function depends on `CONFIG_VXLAN` being enabled. If that's not set, the relevant parts of the VXLAN support are going to be missing and this whole thing could fall apart. I need to keep that dependency in mind when evaluating this, especially in a VXLAN environment. I'm going to make a mental note to verify the config. |
| 6/2 | 2026/07/22 16:16 | tool | grepper |
0mArgs:{
"Expression": "vxlan_fdb_nh_path_select",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/vxlan/vxlan_core.c=2650=static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,\n--\ndrivers/net/vxlan/vxlan_core.c-2663-\t\tgoto drop;\ndrivers/net/vxlan/vxlan_core.c:2664:\tdo_xmit = vxlan_fdb_nh_path_select(nh, hash, \u0026nh_rdst);\ndrivers/net/vxlan/vxlan_core.c-2665-\n--\ndrivers/net/vxlan/vxlan_core.c=2680=static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev,\n--\ndrivers/net/vxlan/vxlan_core.c-2697-\t}\ndrivers/net/vxlan/vxlan_core.c:2698:\tdo_xmit = vxlan_fdb_nh_path_select(nh, hash, \u0026nh_rdst);\ndrivers/net/vxlan/vxlan_core.c-2699-\trcu_read_unlock();\n--\ninclude/net/vxlan.h=534=static inline void vxlan_flag_attr_error(int attrtype,\n--\ninclude/net/vxlan.h-564-\ninclude/net/vxlan.h:565:static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,\ninclude/net/vxlan.h-566-\t\t\t\t\t u32 hash,\n"
} |
| 7/2 | 2026/07/22 16:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8134 output: 38 thoughts: 379 Thoughts: **Analyzing VXLAN Next Hop Configuration** Okay, so I need to make sure `CONFIG_VXLAN` is enabled. Let's start there. Now, let's see what else we're dealing with configuration-wise. I see `NHA_FDB_PORT` as a netlink attribute, which is useful. The core seems to revolve around `rtm_to_nh_config`, which gets called from `rtm_newnexthop` in `net/ipv4/nexthop.c`, and, importantly, `nexthop_create` which is itself called from `rtm_newnexthop`. I need to focus on a few key symbols here: `rtm_to_nh_config`, `nexthop_create`, `nh_fill_node`, and `vxlan_fdb_nh_path_select`. Let me see, is `vxlan_fdb_nh_path_select` in the hot path? Ah, yes, it's called from `vxlan_xmit_nh` and `vxlan_xmit_nhid`, which are themselves called from `vxlan_xmit`. And `vxlan_xmit` is the `ndo_start_xmit` for VXLAN – definitely a hot path! That's something we want to avoid if possible. Good, now looking at `rtm_to_nh_config`, `nexthop_create`, and `nh_fill_node` they look like they are all control path functions, dealing with netlink. That is good. I need to make sure I understand the function calls and the paths to them, but as far as I can see, these should not be in the hot path. Now, let's just make sure there aren't any other functions that are critical to this, let's see. Looks like `nexthop_path_fdb_result` is an inline function in `include/net/nexthop.h`. Okay. So, the key functions that warrant further scrutiny are: `rtm_to_nh_config`, `nexthop_create`, and `nh_fill_node`. Let's double check `rtm_to_nh_config` and `nexthop_create` again, just to make sure I am on the right track here. |
| 8/2 | 2026/07/22 16:17 | tool | grepper |
0mArgs:{
"Expression": "rtm_to_nh_config",
"PathPrefix": "net/ipv4/nexthop.c"
}Results: {
"Output": "net/ipv4/nexthop.c=3038=static int rtm_nh_get_timer(struct nlattr *attr, unsigned long fallback,\n--\nnet/ipv4/nexthop.c-3062-\nnet/ipv4/nexthop.c:3063:static int rtm_to_nh_config_grp_res(struct nlattr *res, struct nh_config *cfg,\nnet/ipv4/nexthop.c-3064-\t\t\t\t struct netlink_ext_ack *extack)\n--\nnet/ipv4/nexthop.c-3101-\nnet/ipv4/nexthop.c:3102:static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,\nnet/ipv4/nexthop.c-3103-\t\t\t struct nlmsghdr *nlh, struct nlattr **tb,\n--\nnet/ipv4/nexthop.c-3189-\t\tif (cfg-\u003enh_grp_type == NEXTHOP_GRP_TYPE_RES)\nnet/ipv4/nexthop.c:3190:\t\t\terr = rtm_to_nh_config_grp_res(tb[NHA_RES_GROUP],\nnet/ipv4/nexthop.c-3191-\t\t\t\t\t\t cfg, extack);\n--\nnet/ipv4/nexthop.c-3277-\nnet/ipv4/nexthop.c:3278:static int rtm_to_nh_config_rtnl(struct net *net, struct nlattr **tb,\nnet/ipv4/nexthop.c-3279-\t\t\t\t struct nh_config *cfg,\n--\nnet/ipv4/nexthop.c=3310=static int rtm_new_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,\n--\nnet/ipv4/nexthop.c-3324-\nnet/ipv4/nexthop.c:3325:\terr = rtm_to_nh_config(net, skb, nlh, tb, \u0026cfg, extack);\nnet/ipv4/nexthop.c-3326-\tif (err)\n--\nnet/ipv4/nexthop.c-3336-\nnet/ipv4/nexthop.c:3337:\terr = rtm_to_nh_config_rtnl(net, tb, \u0026cfg, extack);\nnet/ipv4/nexthop.c-3338-\tif (err)\n"
} |
| 9/2 | 2026/07/22 16:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9703 output: 129 thoughts: 209 Thoughts: **My Analysis of Next Hop Configuration** Okay, let's break this down. My goal is to understand how we're configuring the next-hop functionality. The key functions I need to focus on are `rtm_to_nh_config`, `nexthop_create`, and `nh_fill_node`. These seem to be the core building blocks. I see that the primary configuration in play is `VXLAN`. I'm curious if there are any other configurations involved, so I'll need to dig a little deeper to see if any others influence this part of the code. Alright, I found `NHA_FDB_PORT`, and it is part of `rtm_nh_policy_new` in `net/ipv4/nexthop.c`. This is definitely a functional part of the code I need to consider. Now, I'll set the `WorthFuzzing` flag to `true`. These functions seem like good candidates to test thoroughly. I'll make sure to prioritize fuzzing `rtm_to_nh_config`, `nexthop_create`, and `nh_fill_node`. To be certain, I want to confirm that `VXLAN` is the only configuration actively involved. I see `CONFIG_VXLAN` is tristate, so it's possible. Are there other configs that influence nexthop behavior? Hmm, `nexthop.o` appears to be compiled unconditionally for IPv4, so no, there don't appear to be any other configs. Now, I'm ready to use the `set-results` tool and move forward. |
| 10/2 | 2026/07/22 16:17 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"VXLAN"
],
"FocusSymbols": [
"rtm_to_nh_config",
"nexthop_create",
"nh_fill_node"
],
"Reasoning": "The patch adds support for a new netlink attribute NHA_FDB_PORT to specify a UDP destination port for FDB nexthops (e.g., VXLAN). It modifies the nexthop netlink control path and VXLAN datapath. The netlink control path functions are good targets for fuzzing.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"VXLAN"
],
"FocusSymbols": [
"rtm_to_nh_config",
"nexthop_create",
"nh_fill_node"
],
"Reasoning": "The patch adds support for a new netlink attribute NHA_FDB_PORT to specify a UDP destination port for FDB nexthops (e.g., VXLAN). It modifies the nexthop netlink control path and VXLAN datapath. The netlink control path functions are good targets for fuzzing.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|