Skip to contentSkip to conversation

bonding: don't set oif to bond dev when getting NS target destination

PATCH Superseded Hangbin Liu 4 participants 7 messages Sep 8, 2025 – Sep 10, 2025

Subsystems (4)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/2 bonding: don't set oif to bond dev when getting NS target destination

Unlike IPv4, IPv6 routing strictly requires the source address to be valid on the outgoing interface. If the NS target is set to a remote VLAN interface, and the source address is also configured on a VLAN over a bond interface, setting the oif to the bond device will fail to retrieve the correct destination route.

Fix this by not setting the oif to the bond device when retrieving the NS target destination. This allows the correct destination device (the VLAN interface) to be determined, so that bond_verify_device_path can return the proper VLAN tags for sending NS messages.

---

v2: split the patch into 2 parts, the kernel change and test update (Jay Vosburgh)

---
 drivers/net/bonding/bond_main.c | 1 -
 1 file changed, 1 deletion(-)
drivers/net/bonding/bond_main.c +0 -1
index 257333c88710..30cf97f4e814 100644
@@ -3355,7 +3355,6 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
 		/* Find out through which dev should the packet go */
 		memset(&fl6, 0, sizeof(struct flowi6));
 		fl6.daddr = targets[i];
-		fl6.flowi6_oif = bond->dev->ifindex;
 
 		dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6);
 		if (dst->error) {
Signature · 1 line
2.50.1
#1 lore raw

PATCH v2 2/2 selftests: bonding: add vlan over bond testing

Add a vlan over bond testing to make sure arp/ns target works. Also change all the configs to mudules.

---

v2: split the patch into 2 parts, the kernel change and test update (Jay Vosburgh)

---
 .../drivers/net/bonding/bond_options.sh       | 59 +++++++++++++++++++
 .../selftests/drivers/net/bonding/config      | 21 +++----
 2 files changed, 70 insertions(+), 10 deletions(-)
tools/testing/selftests/drivers/net/bonding/bond_options.sh +59 -0
index 7bc148889ca7..b3eb8a919c71 100755
@@ -7,6 +7,7 @@ ALL_TESTS="
 	prio
 	arp_validate
 	num_grat_arp
+	vlan_over_bond
 "
 
 lib_dir=$(dirname "$0")
@@ -376,6 +377,64 @@ num_grat_arp()
 	done
 }
 
+vlan_over_bond_arp()
+{
+	local mode="$1"
+	RET=0
+
+	bond_reset "mode $mode arp_interval 100 arp_ip_target 192.0.3.10"
+	ip -n "${s_ns}" link add bond0.3 link bond0 type vlan id 3
+	ip -n "${s_ns}" link set bond0.3 up
+	ip -n "${s_ns}" addr add 192.0.3.1/24 dev bond0.3
+	ip -n "${s_ns}" addr add 2001:db8::3:1/64 dev bond0.3
+
+	slowwait_for_counter 5 5 tc_rule_handle_stats_get \
+		"dev eth0.3 ingress" 101 ".packets" "-n ${c_ns}" || RET=1
+	log_test "vlan over bond arp" "$mode"
+}
+
+vlan_over_bond_ns()
+{
+	local mode="$1"
+	RET=0
+
+	if skip_ns; then
+		log_test_skip "vlan_over_bond ns" "$mode"
+		return 0
+	fi
+
+	bond_reset "mode $mode arp_interval 100 ns_ip6_target 2001:db8::3:10"
+	ip -n "${s_ns}" link add bond0.3 link bond0 type vlan id 3
+	ip -n "${s_ns}" link set bond0.3 up
+	ip -n "${s_ns}" addr add 192.0.3.1/24 dev bond0.3
+	ip -n "${s_ns}" addr add 2001:db8::3:1/64 dev bond0.3
+
+	slowwait_for_counter 5 5 tc_rule_handle_stats_get \
+		"dev eth0.3 ingress" 102 ".packets" "-n ${c_ns}" || RET=1
+	log_test "vlan over bond ns" "$mode"
+}
+
+vlan_over_bond()
+{
+	# add vlan 3 for client
+	ip -n "${c_ns}" link add eth0.3 link eth0 type vlan id 3
+	ip -n "${c_ns}" link set eth0.3 up
+	ip -n "${c_ns}" addr add 192.0.3.10/24 dev eth0.3
+	ip -n "${c_ns}" addr add 2001:db8::3:10/64 dev eth0.3
+
+	# Add tc rule to check the vlan pkts
+	tc -n "${c_ns}" qdisc add dev eth0.3 clsact
+	tc -n "${c_ns}" filter add dev eth0.3 ingress protocol arp \
+		handle 101 flower skip_hw arp_op request \
+		arp_sip 192.0.3.1 arp_tip 192.0.3.10 action pass
+	tc -n "${c_ns}" filter add dev eth0.3 ingress protocol ipv6 \
+		handle 102 flower skip_hw ip_proto icmpv6 \
+		type 135 src_ip 2001:db8::3:1 action pass
+
+	vlan_over_bond_arp "active-backup"
+	vlan_over_bond_ns "active-backup"
+}
+
 trap cleanup EXIT
 
 setup_prepare
tools/testing/selftests/drivers/net/bonding/config +11 -10
index 4d16a69ffc65..cbd8b2769475 100644
@@ -1,12 +1,13 @@
-CONFIG_BONDING=y
-CONFIG_BRIDGE=y
-CONFIG_DUMMY=y
+CONFIG_BONDING=m
+CONFIG_BRIDGE=m
+CONFIG_DUMMY=m
 CONFIG_IPV6=y
-CONFIG_MACVLAN=y
-CONFIG_IPVLAN=y
-CONFIG_NET_ACT_GACT=y
-CONFIG_NET_CLS_FLOWER=y
+CONFIG_MACVLAN=m
+CONFIG_IPVLAN=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_NET_CLS_FLOWER=m
 CONFIG_NET_CLS_MATCHALL=m
-CONFIG_NET_SCH_INGRESS=y
-CONFIG_NLMON=y
-CONFIG_VETH=y
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NLMON=m
+CONFIG_VETH=m
+CONFIG_VLAN_8021Q=m
Signature · 1 line
2.50.1
maintainer
#2 lore raw

Re: [PATCHv2 2/2] selftests: bonding: add vlan over bond testing

Quoted 2 lines · On Mon, 8 Sep 2025 06:28:02 +0000 Hangbin Liu wrote:

Add a vlan over bond testing to make sure arp/ns target works. Also change all the configs to mudules.

Why are you switching everything to module?
The series needs to go to net, we should avoid unnecessary cleanups. And I think changing the config is unrelated to the selftest so it should be a standalone patch in the first place?

Signature · 1 line
pw-bot: cr
#3 lore raw

Re: [PATCHv2 2/2] selftests: bonding: add vlan over bond testing

Quoted 8 lines · Jakub Kicinski
Quoted 2 lines · On Mon, 8 Sep 2025 06:28:02 +0000 Hangbin Liu wrote:

Add a vlan over bond testing to make sure arp/ns target works. Also change all the configs to mudules.

Why are you switching everything to module?
The series needs to go to net, we should avoid unnecessary cleanups. And I think changing the config is unrelated to the selftest so it should be a standalone patch in the first place?

On my local testing, there will be a lot default interfaces if all modules build in. This could make the test environment more clean.
But it's just my preference. As you said, we can do it with a stand alone patch. I will re-post and drop the config update.

Thanks
hangbin

maintainer
#4 lore raw

Re: [PATCHv2 2/2] selftests: bonding: add vlan over bond testing

Quoted 5 lines · On Wed, 10 Sep 2025 02:03:52 +0000 Hangbin Liu wrote:
Quoted 4 lines · Jakub Kicinski
Quoted 2 lines · On Mon, 8 Sep 2025 06:28:02 +0000 Hangbin Liu wrote:

Add a vlan over bond testing to make sure arp/ns target works. Also change all the configs to mudules.

Quoted 8 lines
Quoted 4 lines

Why are you switching everything to module?
The series needs to go to net, we should avoid unnecessary cleanups. And I think changing the config is unrelated to the selftest so it should be a standalone patch in the first place?

On my local testing, there will be a lot default interfaces if all modules build in. This could make the test environment more clean.
But it's just my preference.

No strong opinion on my side. Your point is fair. On the other hand sometimes dealing with modules is tricky (especially with vng when building kernel with O=build/). But not sure how much we should care about shortcomings of tooling which can be fixed. It's okay for our CI.

Quoted 2 lines

As you said, we can do it with a stand alone
patch. I will re-post and drop the config update.

Yup! For net we should avoid it.

Tested-by on v2 1/2
#5 lore raw
In reply to Hangbin Liu

________________________________________
From: Hangbin Liu <[email protected]>
Sent: Sunday, September 7, 2025 11:28 PM
To: [email protected]
Cc: Jay Vosburgh; Andrew Lunn; David S. Miller; Eric Dumazet; Jakub Kicinski; Paolo Abeni; Simon Horman; Shuah Khan; [email protected]; Hangbin Liu; David Wilder
Subject: [EXTERNAL] [PATCHv2 1/2] bonding: don't set oif to bond dev when getting NS target destination

Quoted 37 lines

Unlike IPv4, IPv6 routing strictly requires the source address to be valid on the outgoing interface. If the NS target is set to a remote VLAN interface, and the source address is also configured on a VLAN over a bond interface, setting the oif to the bond device will fail to retrieve the correct destination route.

Fix this by not setting the oif to the bond device when retrieving the NS target destination. This allows the correct destination device (the VLAN interface) to be determined, so that bond_verify_device_path can return the proper VLAN tags for sending NS messages.

---

v2: split the patch into 2 parts, the kernel change and test update (Jay Vosburgh)

---
 drivers/net/bonding/bond_main.c | 1 -
 1 file changed, 1 deletion(-)
drivers/net/bonding/bond_main.c +0 -2
index 257333c88710..30cf97f4e814 100644
@@ -3355,7 +3355,6 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
                /* Find out through which dev should the packet go */
                memset(&fl6, 0, sizeof(struct flowi6));
                fl6.daddr = targets[i];
-               fl6.flowi6_oif = bond->dev->ifindex;
 
                dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6);
                if (dst->error) {
--
Quoted 1 line

2.50.1

I verified this solves the issue with a single level of vlan tags. Thanks for fixing this.

maintainer Acked-by on v2 1/2
#6 lore raw
In reply to Hangbin Liu
Quoted 11 lines · Hangbin Liu

Unlike IPv4, IPv6 routing strictly requires the source address to be valid on the outgoing interface. If the NS target is set to a remote VLAN interface, and the source address is also configured on a VLAN over a bond interface, setting the oif to the bond device will fail to retrieve the correct destination route.

Fix this by not setting the oif to the bond device when retrieving the NS target destination. This allows the correct destination device (the VLAN interface) to be determined, so that bond_verify_device_path can return the proper VLAN tags for sending NS messages.

Quoted 5 lines
Quoted 23 lines

---

v2: split the patch into 2 parts, the kernel change and test update (Jay Vosburgh)

---
drivers/net/bonding/bond_main.c | 1 -

1 file changed, 1 deletion(-)
drivers/net/bonding/bond_main.c +0 -1
index 257333c88710..30cf97f4e814 100644
@@ -3355,7 +3355,6 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
 		/* Find out through which dev should the packet go */
 		memset(&fl6, 0, sizeof(struct flowi6));
 		fl6.daddr = targets[i];
-		fl6.flowi6_oif = bond->dev->ifindex;
 
 		dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6);
 		if (dst->error) {
Signature · 1 line
2.50.1