If the queue of xdp xmit is not an independent queue, then when the xdp xmit used all the desc, the xmit from the __dev_queue_xmit() may encounter the following error. net ens4: Unexpected TXQ (0) queue failure: -28 This patch adds a check whether sq is full in XDP Xmit. Thanks. Xuan Zhuo (2): virtio_net: separate the logic of checking whether sq is full virtio_net: add checking sq is full inside xdp xmit drivers/net/virtio_net.c | 78 ++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 31 deletions(-) -- 2.32.0.3.g01195cf9f
Xuan Zhuo
2023-Mar-06 04:15 UTC
[PATCH net 1/2] virtio_net: separate the logic of checking whether sq is full
Separate the logic of checking whether sq is full. The subsequent patch will reuse this func. Signed-off-by: Xuan Zhuo <xuanzhuo at linux.alibaba.com> --- drivers/net/virtio_net.c | 59 ++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fb5e68ed3ec2..777de0ec0b1b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1750,6 +1750,40 @@ static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi) u64_stats_update_end(&sq->stats.syncp); } +static void check_sq_full(struct virtnet_info *vi, struct net_device *dev, + struct send_queue *sq) +{ + bool use_napi = sq->napi.weight; + int qnum; + + qnum = sq - vi->sq; + + /* If running out of space, stop queue to avoid getting packets that we + * are then unable to transmit. + * An alternative would be to force queuing layer to requeue the skb by + * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be + * returned in a normal path of operation: it means that driver is not + * maintaining the TX queue stop/start state properly, and causes + * the stack to do a non-trivial amount of useless work. + * Since most packets only take 1 or 2 ring slots, stopping the queue + * early means 16 slots are typically wasted. + */ + if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { + netif_stop_subqueue(dev, qnum); + if (use_napi) { + if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) + virtqueue_napi_schedule(&sq->napi, sq->vq); + } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { + /* More just got used, free them then recheck. */ + free_old_xmit_skbs(sq, false); + if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { + netif_start_subqueue(dev, qnum); + virtqueue_disable_cb(sq->vq); + } + } + } +} + static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) { if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) @@ -1989,30 +2023,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) nf_reset_ct(skb); } - /* If running out of space, stop queue to avoid getting packets that we - * are then unable to transmit. - * An alternative would be to force queuing layer to requeue the skb by - * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be - * returned in a normal path of operation: it means that driver is not - * maintaining the TX queue stop/start state properly, and causes - * the stack to do a non-trivial amount of useless work. - * Since most packets only take 1 or 2 ring slots, stopping the queue - * early means 16 slots are typically wasted. - */ - if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { - netif_stop_subqueue(dev, qnum); - if (use_napi) { - if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) - virtqueue_napi_schedule(&sq->napi, sq->vq); - } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { - /* More just got used, free them then recheck. */ - free_old_xmit_skbs(sq, false); - if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { - netif_start_subqueue(dev, qnum); - virtqueue_disable_cb(sq->vq); - } - } - } + check_sq_full(vi, dev, sq); if (kick || netif_xmit_stopped(txq)) { if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) { -- 2.32.0.3.g01195cf9f
Xuan Zhuo
2023-Mar-06 04:15 UTC
[PATCH net 2/2] virtio_net: add checking sq is full inside xdp xmit
If the queue of xdp xmit is not an independent queue, then when the xdp xmit used all the desc, the xmit from the __dev_queue_xmit() may encounter the following error. net ens4: Unexpected TXQ (0) queue failure: -28 This patch adds a check whether sq is full in XDP Xmit. Reported-by: Yichun Zhang <yichun at openresty.com> Signed-off-by: Xuan Zhuo <xuanzhuo at linux.alibaba.com> --- drivers/net/virtio_net.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 777de0ec0b1b..3001b9a548e5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -302,6 +302,8 @@ struct padded_vnet_hdr { static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf); static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf); +static void check_sq_full(struct virtnet_info *vi, struct net_device *dev, + struct send_queue *sq); static bool is_xdp_frame(void *ptr) { @@ -341,6 +343,16 @@ static int rxq2vq(int rxq) return rxq * 2; } +static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) +{ + if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) + return false; + else if (q < vi->curr_queue_pairs) + return true; + else + return false; +} + static inline struct virtio_net_hdr_mrg_rxbuf *skb_vnet_hdr(struct sk_buff *skb) { return (struct virtio_net_hdr_mrg_rxbuf *)skb->cb; @@ -686,6 +698,9 @@ static int virtnet_xdp_xmit(struct net_device *dev, } ret = nxmit; + if (!is_xdp_raw_buffer_queue(vi, sq - vi->sq)) + check_sq_full(vi, dev, sq); + if (flags & XDP_XMIT_FLUSH) { if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) kicks = 1; @@ -1784,16 +1799,6 @@ static void check_sq_full(struct virtnet_info *vi, struct net_device *dev, } } -static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) -{ - if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) - return false; - else if (q < vi->curr_queue_pairs) - return true; - else - return false; -} - static void virtnet_poll_cleantx(struct receive_queue *rq) { struct virtnet_info *vi = rq->vq->vdev->priv; -- 2.32.0.3.g01195cf9f
Alexander H Duyck
2023-Mar-06 16:49 UTC
[PATCH net 0/2] add checking sq is full inside xdp xmit
On Mon, 2023-03-06 at 12:15 +0800, Xuan Zhuo wrote:> If the queue of xdp xmit is not an independent queue, then when the xdp > xmit used all the desc, the xmit from the __dev_queue_xmit() may encounter > the following error. > > net ens4: Unexpected TXQ (0) queue failure: -28 > > This patch adds a check whether sq is full in XDP Xmit. > > Thanks. > > Xuan Zhuo (2): > virtio_net: separate the logic of checking whether sq is full > virtio_net: add checking sq is full inside xdp xmit > > drivers/net/virtio_net.c | 78 ++++++++++++++++++++++++---------------- > 1 file changed, 47 insertions(+), 31 deletions(-) > > -- > 2.32.0.3.g01195cf9f >Series looks good to me. Reviewed-by: Alexander Duyck <alexanderduyck at fb.com>
Michael S. Tsirkin
2023-Mar-06 17:58 UTC
[PATCH net 0/2] add checking sq is full inside xdp xmit
On Mon, Mar 06, 2023 at 12:15:33PM +0800, Xuan Zhuo wrote:> If the queue of xdp xmit is not an independent queue, then when the xdp > xmit used all the desc, the xmit from the __dev_queue_xmit() may encounter > the following error. > > net ens4: Unexpected TXQ (0) queue failure: -28 > > This patch adds a check whether sq is full in XDP Xmit. > > Thanks.Acked-by: Michael S. Tsirkin <mst at redhat.com> needed for stable?> Xuan Zhuo (2): > virtio_net: separate the logic of checking whether sq is full > virtio_net: add checking sq is full inside xdp xmit > > drivers/net/virtio_net.c | 78 ++++++++++++++++++++++++---------------- > 1 file changed, 47 insertions(+), 31 deletions(-) > > -- > 2.32.0.3.g01195cf9f