diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 50eb43e5bf45..328775eb9e28 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -73,6 +73,11 @@ struct veth_priv { struct bpf_prog *_xdp_prog; struct veth_rq *rq; unsigned int requested_headroom; + int last_xdp_disable_run; + int last_xdp_disable_gro; + int last_set_rx; + int last_set_err; + }; struct veth_xdp_tx_bq { @@ -997,7 +1002,7 @@ static bool veth_gro_requested(const struct net_device *dev) } static int veth_enable_xdp_range(struct net_device *dev, int start, int end, - bool napi_already_on) + bool napi_already_on, void *old_xdp) { struct veth_priv *priv = netdev_priv(dev); int err, i; @@ -1005,8 +1010,22 @@ static int veth_enable_xdp_range(struct net_device *dev, int start, int end, for (i = start; i < end; i++) { struct veth_rq *rq = &priv->rq[i]; - if (!napi_already_on) + if (!napi_already_on) { + if (rq->xdp_napi.napi_hash_node.pprev) { + int j; + + pr_err("queue nr %d already in hash table!" + "old xdp %d, nr rx queue %d, gro req %d, napi ptr is set %d," + "last set %d:%d, last down %d:%d", + i, !!old_xdp, dev->real_num_rx_queues, + veth_gro_requested(dev), !!rcu_access_pointer(rq->napi), + priv->last_set_rx, priv->last_set_err, + priv->last_xdp_disable_run, priv->last_xdp_disable_gro); + for (j = 0; j < min(2u, dev->real_num_rx_queues); ++j) + pr_err(" queue %d reg %d", j, xdp_rxq_info_is_reg(&priv->rq[j].xdp_rxq)); + } netif_napi_add(dev, &rq->xdp_napi, veth_poll, NAPI_POLL_WEIGHT); + } err = xdp_rxq_info_reg(&rq->xdp_rxq, dev, i, rq->xdp_napi.napi_id); if (err < 0) goto err_rxq_reg; @@ -1053,14 +1072,14 @@ static void veth_disable_xdp_range(struct net_device *dev, int start, int end, } } -static int veth_enable_xdp(struct net_device *dev) +static int veth_enable_xdp(struct net_device *dev, void *old_xdp) { bool napi_already_on = veth_gro_requested(dev) && (dev->flags & IFF_UP); struct veth_priv *priv = netdev_priv(dev); int err, i; if (!xdp_rxq_info_is_reg(&priv->rq[0].xdp_rxq)) { - err = veth_enable_xdp_range(dev, 0, dev->real_num_rx_queues, napi_already_on); + err = veth_enable_xdp_range(dev, 0, dev->real_num_rx_queues, napi_already_on, old_xdp); if (err) return err; @@ -1097,6 +1116,9 @@ static void veth_disable_xdp(struct net_device *dev) for (i = 0; i < dev->real_num_rx_queues; i++) rcu_assign_pointer(priv->rq[i].xdp_prog, NULL); + priv->last_xdp_disable_run = netif_running(dev); + priv->last_xdp_disable_gro = veth_gro_requested(dev); + if (!netif_running(dev) || !veth_gro_requested(dev)) { veth_napi_del(dev); @@ -1167,7 +1189,7 @@ static int veth_enable_range_safe(struct net_device *dev, int start, int end) /* these channels are freshly initialized, napi is not on there even * when GRO is requeste */ - err = veth_enable_xdp_range(dev, start, end, false); + err = veth_enable_xdp_range(dev, start, end, false, priv->_xdp_prog); if (err) return err; @@ -1249,6 +1271,8 @@ static int veth_set_channels(struct net_device *dev, if (peer) netif_carrier_on(peer); } + priv->last_set_rx = ch->rx_count; + priv->last_set_err = err; return err; revert: @@ -1267,7 +1291,7 @@ static int veth_open(struct net_device *dev) return -ENOTCONN; if (priv->_xdp_prog) { - err = veth_enable_xdp(dev); + err = veth_enable_xdp(dev, priv->_xdp_prog); if (err) return err; } else if (veth_gro_requested(dev)) { @@ -1480,7 +1504,7 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog, } if (dev->flags & IFF_UP) { - err = veth_enable_xdp(dev); + err = veth_enable_xdp(dev, old_prog); if (err) { NL_SET_ERR_MSG_MOD(extack, "Setup for XDP failed"); goto err;