OSDN Git Service

veth: take into account device reconfiguration for xdp_features flag
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 9 Mar 2023 12:25:30 +0000 (13:25 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sat, 11 Mar 2023 05:33:48 +0000 (21:33 -0800)
Take into account tx/rx queues reconfiguration setting device
xdp_features flag. Moreover consider NETIF_F_GRO flag in order to enable
ndo_xdp_xmit callback.

Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/veth.c

index 1bb54de..293dc3b 100644 (file)
@@ -1257,6 +1257,26 @@ static int veth_enable_range_safe(struct net_device *dev, int start, int end)
        return 0;
 }
 
+static void veth_set_xdp_features(struct net_device *dev)
+{
+       struct veth_priv *priv = netdev_priv(dev);
+       struct net_device *peer;
+
+       peer = rcu_dereference(priv->peer);
+       if (peer && peer->real_num_tx_queues <= dev->real_num_rx_queues) {
+               xdp_features_t val = NETDEV_XDP_ACT_BASIC |
+                                    NETDEV_XDP_ACT_REDIRECT |
+                                    NETDEV_XDP_ACT_RX_SG;
+
+               if (priv->_xdp_prog || veth_gro_requested(dev))
+                       val |= NETDEV_XDP_ACT_NDO_XMIT |
+                              NETDEV_XDP_ACT_NDO_XMIT_SG;
+               xdp_set_features_flag(dev, val);
+       } else {
+               xdp_clear_features_flag(dev);
+       }
+}
+
 static int veth_set_channels(struct net_device *dev,
                             struct ethtool_channels *ch)
 {
@@ -1323,6 +1343,12 @@ out:
                if (peer)
                        netif_carrier_on(peer);
        }
+
+       /* update XDP supported features */
+       veth_set_xdp_features(dev);
+       if (peer)
+               veth_set_xdp_features(peer);
+
        return err;
 
 revert:
@@ -1489,7 +1515,10 @@ static int veth_set_features(struct net_device *dev,
                err = veth_napi_enable(dev);
                if (err)
                        return err;
+
+               xdp_features_set_redirect_target(dev, true);
        } else {
+               xdp_features_clear_redirect_target(dev);
                veth_napi_del(dev);
        }
        return 0;
@@ -1570,10 +1599,15 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                        peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
                        peer->max_mtu = max_mtu;
                }
+
+               xdp_features_set_redirect_target(dev, true);
        }
 
        if (old_prog) {
                if (!prog) {
+                       if (!veth_gro_requested(dev))
+                               xdp_features_clear_redirect_target(dev);
+
                        if (dev->flags & IFF_UP)
                                veth_disable_xdp(dev);
 
@@ -1686,10 +1720,6 @@ static void veth_setup(struct net_device *dev)
        dev->hw_enc_features = VETH_FEATURES;
        dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
        netif_set_tso_max_size(dev, GSO_MAX_SIZE);
-
-       dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                           NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-                           NETDEV_XDP_ACT_NDO_XMIT_SG;
 }
 
 /*
@@ -1857,6 +1887,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
                goto err_queues;
 
        veth_disable_gro(dev);
+       /* update XDP supported features */
+       veth_set_xdp_features(dev);
+       veth_set_xdp_features(peer);
+
        return 0;
 
 err_queues: