bonding: add xdp_features support
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 4 May 2023 09:52:49 +0000 (11:52 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 5 May 2023 08:34:23 +0000 (09:34 +0100)
Introduce xdp_features support for bonding driver according to the slave
devices attached to the master one. xdp_features is required whenever we
want to xdp_redirect traffic into a bond device and then into selected
slaves attached to it.

Reviewed-by: Simon Horman <simon.horman@corigine.com>
Acked-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Jussi Maki <joamaki@gmail.com>
Tested-by: Jussi Maki <joamaki@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
include/net/bonding.h

index 710548dbd0c1d8e01ced8129207b3853ca9f0741..3fed888629f7b5d08fede3187fb5639d74185c13 100644 (file)
@@ -1789,6 +1789,26 @@ static void bond_ether_setup(struct net_device *bond_dev)
        bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 }
 
+void bond_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)
+               val &= slave->dev->xdp_features;
+
+       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 +2256,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
                        bpf_prog_inc(bond->xdp_prog);
        }
 
+       bond_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 +2505,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_set_features(bond_dev);
        kobject_put(&slave->kobj);
 
        return 0;
@@ -3930,6 +3953,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_set_features(bond_dev);
+               break;
        default:
                break;
        }
@@ -5874,6 +5900,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.
index f71d5517f8293ae634fd6e1b6c4fedec43a2322c..0498fc6731f898f6a238498d42a0f0ade6c67856 100644 (file)
@@ -877,6 +877,8 @@ static int bond_option_mode_set(struct bonding *bond,
                        netdev_update_features(bond->dev);
        }
 
+       bond_xdp_set_features(bond->dev);
+
        return 0;
 }
 
index c3843239517d539c15985f38b4887a888c940d9d..a60a24923b559972d72320588fe05de50ca4195e 100644 (file)
@@ -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_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);