No send queues will be allocated for XDP filters. Attempts to transmit packets when no XDP send queues exist will fail with EOPNOTSUPP.
Signed-off-by: Charlie Somerville <char...@charlie.bz> --- drivers/net/virtio_net.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 508408fbe78f..ed08998765e0 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -485,6 +485,10 @@ static struct send_queue *virtnet_xdp_sq(struct virtnet_info *vi) { unsigned int qp; + /* If no queue pairs are allocated for XDP use, return NULL */ + if (vi->xdp_queue_pairs == 0) + return NULL; + qp = vi->curr_queue_pairs - vi->xdp_queue_pairs + smp_processor_id(); return &vi->sq[qp]; } @@ -514,6 +518,11 @@ static int virtnet_xdp_xmit(struct net_device *dev, sq = virtnet_xdp_sq(vi); + /* No send queue exists if program was attached with XDP_NO_TX */ + if (unlikely(!sq)) { + return -EOPNOTSUPP; + } + if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) { ret = -EINVAL; drops = n; @@ -1464,7 +1473,7 @@ static int virtnet_poll(struct napi_struct *napi, int budget) if (xdp_xmit & VIRTIO_XDP_TX) { sq = virtnet_xdp_sq(vi); - if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) { + if (sq && virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) { u64_stats_update_begin(&sq->stats.syncp); sq->stats.kicks++; u64_stats_update_end(&sq->stats.syncp); @@ -2388,7 +2397,7 @@ static int virtnet_restore_guest_offloads(struct virtnet_info *vi) } static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog, - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, u32 flags) { unsigned long int max_sz = PAGE_SIZE - sizeof(struct padded_vnet_hdr); struct virtnet_info *vi = netdev_priv(dev); @@ -2418,7 +2427,7 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog, } curr_qp = vi->curr_queue_pairs - vi->xdp_queue_pairs; - if (prog) + if (prog && !(flags & XDP_FLAGS_NO_TX)) xdp_qp = nr_cpu_ids; /* XDP requires extra queues for XDP_TX */ @@ -2502,7 +2511,7 @@ static int virtnet_xdp(struct net_device *dev, struct netdev_bpf *xdp) { switch (xdp->command) { case XDP_SETUP_PROG: - return virtnet_xdp_set(dev, xdp->prog, xdp->extack); + return virtnet_xdp_set(dev, xdp->prog, xdp->extack, xdp->flags); default: return -EINVAL; } -- 2.30.0