Skip to contentSkip to conversation

add xdp_features support for bonding driver

PATCH Superseded Lorenzo Bianconi 2 participants 5 messages Apr 27, 2023

Subsystems (7)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover add xdp_features support for bonding driver

Introduce missing xdp_features support for bonding driver. xdp_features is required whenever we want to xdp_redirect traffic into a bond device and then into selected slaves attached to it.

Lorenzo Bianconi (2):
bonding: add xdp_features support selftests/bpf: add xdp_feature selftest for bond device

 drivers/net/bonding/bond_main.c               |  48 +++++++
 drivers/net/bonding/bond_options.c            |   2 +
 include/net/bonding.h                         |   1 +
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 121 ++++++++++++++++++
 4 files changed, 172 insertions(+)
Signature · 1 line
2.40.0
#1 lore raw

PATCH 1/2 bonding: add xdp_features support

Introduce xdp_features support for bonding driver according to the slave devices attached to the master one.

Fixes 66c0e13ad236 ("drivers: net: turn on XDP features")
---
 drivers/net/bonding/bond_main.c    | 48 ++++++++++++++++++++++++++++++
 drivers/net/bonding/bond_options.c |  2 ++
 include/net/bonding.h              |  1 +
 3 files changed, 51 insertions(+)
drivers/net/bonding/bond_main.c +48 -0
index 710548dbd0c1..f22e3fab14d4 100644
@@ -1789,6 +1789,45 @@ static void bond_ether_setup(struct net_device *bond_dev)
 	bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 }
 
+void bond_xdp_xdp_set_features(struct net_device *bond_dev)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+	xdp_features_t val = NETDEV_XDP_ACT_MASK;
+	struct list_head *iter;
+	struct slave *slave;
+
+	ASSERT_RTNL();
+
+	if (!bond_xdp_check(bond)) {
+		xdp_clear_features_flag(bond_dev);
+		return;
+	}
+
+	bond_for_each_slave(bond, slave, iter) {
+		struct net_device *dev = slave->dev;
+
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_BASIC)) {
+			xdp_clear_features_flag(bond_dev);
+			return;
+		}
+
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_REDIRECT))
+			val &= ~NETDEV_XDP_ACT_REDIRECT;
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_NDO_XMIT))
+			val &= ~NETDEV_XDP_ACT_NDO_XMIT;
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_XSK_ZEROCOPY))
+			val &= ~NETDEV_XDP_ACT_XSK_ZEROCOPY;
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_HW_OFFLOAD))
+			val &= ~NETDEV_XDP_ACT_HW_OFFLOAD;
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_RX_SG))
+			val &= ~NETDEV_XDP_ACT_RX_SG;
+		if (!(dev->xdp_features & NETDEV_XDP_ACT_NDO_XMIT_SG))
+			val &= ~NETDEV_XDP_ACT_NDO_XMIT_SG;
+	}
+
+	xdp_set_features_flag(bond_dev, val);
+}
+
 /* enslave device <slave> to bond device <master> */
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 		 struct netlink_ext_ack *extack)
@@ -2236,6 +2275,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 			bpf_prog_inc(bond->xdp_prog);
 	}
 
+	bond_xdp_xdp_set_features(bond_dev);
+
 	slave_info(bond_dev, slave_dev, "Enslaving as %s interface with %s link\n",
 		   bond_is_active_slave(new_slave) ? "an active" : "a backup",
 		   new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
@@ -2483,6 +2524,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	if (!netif_is_bond_master(slave_dev))
 		slave_dev->priv_flags &= ~IFF_BONDING;
 
+	bond_xdp_xdp_set_features(bond_dev);
 	kobject_put(&slave->kobj);
 
 	return 0;
@@ -3930,6 +3972,9 @@ static int bond_slave_netdev_event(unsigned long event,
 		/* Propagate to master device */
 		call_netdevice_notifiers(event, slave->bond->dev);
 		break;
+	case NETDEV_XDP_FEAT_CHANGE:
+		bond_xdp_xdp_set_features(bond_dev);
+		break;
 	default:
 		break;
 	}
@@ -5874,6 +5919,9 @@ void bond_setup(struct net_device *bond_dev)
 	if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP)
 		bond_dev->features |= BOND_XFRM_FEATURES;
 #endif /* CONFIG_XFRM_OFFLOAD */
+
+	if (bond_xdp_check(bond))
+		bond_dev->xdp_features = NETDEV_XDP_ACT_MASK;
 }
 
 /* Destroy a bonding device.
drivers/net/bonding/bond_options.c +2 -0
index f71d5517f829..2a899dda79d2 100644
@@ -877,6 +877,8 @@ static int bond_option_mode_set(struct bonding *bond,
 			netdev_update_features(bond->dev);
 	}
 
+	bond_xdp_xdp_set_features(bond->dev);
+
 	return 0;
 }
 
include/net/bonding.h +1 -0
index c3843239517d..fa70ba3de815 100644
@@ -659,6 +659,7 @@ void bond_destroy_sysfs(struct bond_net *net);
 void bond_prepare_sysfs_group(struct bonding *bond);
 int bond_sysfs_slave_add(struct slave *slave);
 void bond_sysfs_slave_del(struct slave *slave);
+void bond_xdp_xdp_set_features(struct net_device *bond_dev);
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 		 struct netlink_ext_ack *extack);
 int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
Signature · 1 line
2.40.0
#2 lore raw

PATCH 2/2 selftests/bpf: add xdp_feature selftest for bond device

In reply to Lorenzo Bianconi

Introduce selftests to check xdp_feature support for bond driver.

---
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 121 ++++++++++++++++++
 1 file changed, 121 insertions(+)
tools/testing/selftests/bpf/prog_tests/xdp_bonding.c +121 -0
index d19f79048ff6..c3b45745cbcc 100644
@@ -18,6 +18,7 @@
 #include <linux/if_bonding.h>
 #include <linux/limits.h>
 #include <linux/udp.h>
+#include <uapi/linux/netdev.h>
 
 #include "xdp_dummy.skel.h"
 #include "xdp_redirect_multi_kern.skel.h"
@@ -492,6 +493,123 @@ static void test_xdp_bonding_nested(struct skeletons *skeletons)
 	system("ip link del bond_nest2");
 }
 
+static void test_xdp_bonding_features(struct skeletons *skeletons)
+{
+	LIBBPF_OPTS(bpf_xdp_query_opts, query_opts);
+	int bond_idx, veth1_idx, err;
+	struct bpf_link *link = NULL;
+
+	if (!ASSERT_OK(system("ip link add bond type bond"), "add bond"))
+		goto out;
+
+	bond_idx = if_nametoindex("bond");
+	if (!ASSERT_GE(bond_idx, 0, "if_nametoindex bond"))
+		goto out;
+
+	/* query default xdp-feature for bond device */
+	err = bpf_xdp_query(bond_idx, XDP_FLAGS_DRV_MODE, &query_opts);
+	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
+		goto out;
+
+	if (!ASSERT_EQ(query_opts.feature_flags, NETDEV_XDP_ACT_MASK,
+		       "bond query_opts.feature_flags"))
+		goto out;
+
+	if (!ASSERT_OK(system("ip link add veth0 type veth peer name veth1"),
+		       "add veth{0,1} pair"))
+		goto out;
+
+	if (!ASSERT_OK(system("ip link add veth2 type veth peer name veth3"),
+		       "add veth{2,3} pair"))
+		goto out;
+
+	if (!ASSERT_OK(system("ip link set veth0 master bond"),
+		       "add veth0 to master bond"))
+		goto out;
+
+	/* xdp-feature for bond device should be obtained from the single slave
+	 * device (veth0)
+	 */
+	err = bpf_xdp_query(bond_idx, XDP_FLAGS_DRV_MODE, &query_opts);
+	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
+		goto out;
+
+	if (!ASSERT_EQ(query_opts.feature_flags,
+		       NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+		       NETDEV_XDP_ACT_RX_SG,
+		       "bond query_opts.feature_flags"))
+		goto out;
+
+	veth1_idx = if_nametoindex("veth1");
+	if (!ASSERT_GE(veth1_idx, 0, "if_nametoindex veth1"))
+		goto out;
+
+	link = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog,
+				       veth1_idx);
+	if (!ASSERT_OK_PTR(link, "attach program to veth1"))
+		goto out;
+
+	/* xdp-feature for veth0 are changed */
+	err = bpf_xdp_query(bond_idx, XDP_FLAGS_DRV_MODE, &query_opts);
+	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
+		goto out;
+
+	if (!ASSERT_EQ(query_opts.feature_flags,
+		       NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+		       NETDEV_XDP_ACT_RX_SG | NETDEV_XDP_ACT_NDO_XMIT |
+		       NETDEV_XDP_ACT_NDO_XMIT_SG,
+		       "bond query_opts.feature_flags"))
+		goto out;
+
+	if (!ASSERT_OK(system("ip link set veth2 master bond"),
+		       "add veth2 to master bond"))
+		goto out;
+
+	err = bpf_xdp_query(bond_idx, XDP_FLAGS_DRV_MODE, &query_opts);
+	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
+		goto out;
+
+	/* xdp-feature for bond device should be set to the most restrict
+	 * value obtained from attached slave devices (veth0 and veth2)
+	 */
+	if (!ASSERT_EQ(query_opts.feature_flags,
+		       NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+		       NETDEV_XDP_ACT_RX_SG,
+		       "bond query_opts.feature_flags"))
+		goto out;
+
+	if (!ASSERT_OK(system("ip link set veth2 nomaster"),
+		       "del veth2 to master bond"))
+		goto out;
+
+	err = bpf_xdp_query(bond_idx, XDP_FLAGS_DRV_MODE, &query_opts);
+	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
+		goto out;
+
+	if (!ASSERT_EQ(query_opts.feature_flags,
+		       NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+		       NETDEV_XDP_ACT_RX_SG | NETDEV_XDP_ACT_NDO_XMIT |
+		       NETDEV_XDP_ACT_NDO_XMIT_SG,
+		       "bond query_opts.feature_flags"))
+		goto out;
+
+	if (!ASSERT_OK(system("ip link set veth0 nomaster"),
+		       "del veth0 to master bond"))
+		goto out;
+
+	err = bpf_xdp_query(bond_idx, XDP_FLAGS_DRV_MODE, &query_opts);
+	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
+		goto out;
+
+	ASSERT_EQ(query_opts.feature_flags, NETDEV_XDP_ACT_MASK,
+		  "bond query_opts.feature_flags");
+out:
+	bpf_link__destroy(link);
+	system("ip link del veth0");
+	system("ip link del veth2");
+	system("ip link del bond");
+}
+
 static int libbpf_debug_print(enum libbpf_print_level level,
 			      const char *format, va_list args)
 {
@@ -546,6 +664,9 @@ void serial_test_xdp_bonding(void)
 	if (test__start_subtest("xdp_bonding_nested"))
 		test_xdp_bonding_nested(&skeletons);
 
+	if (test__start_subtest("xdp_bonding_features"))
+		test_xdp_bonding_features(&skeletons);
+
 	for (i = 0; i < ARRAY_SIZE(bond_test_cases); i++) {
 		struct bond_test_case *test_case = &bond_test_cases[i];
 
Signature · 1 line
2.40.0
#3 lore raw

Re: [PATCH net 2/2] selftests/bpf: add xdp_feature selftest for bond device

Quoted 7 lines · Lorenzo Bianconi

Introduce selftests to check xdp_feature support for bond driver.

---
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 121 ++++++++++++++++++
 1 file changed, 121 insertions(+)

Please always submit patches that touch bpf selftest via bpf tree. Otherwise BPF CI doesn't run on them.
We've seen failures in the past when such patches went through net tree.

#4 lore raw

Re: [PATCH net 2/2] selftests/bpf: add xdp_feature selftest for bond device

Quoted 12 lines · Lorenzo Bianconi
Quoted 7 lines

Introduce selftests to check xdp_feature support for bond driver.

---
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 121 ++++++++++++++++++
 1 file changed, 121 insertions(+)

Please always submit patches that touch bpf selftest via bpf tree. Otherwise BPF CI doesn't run on them.
We've seen failures in the past when such patches went through net tree.

ack, I will repost after the "guard" period splitting the series.

Regards,
Lorenzo