|
@@ -114,6 +114,9 @@ struct virtnet_info {
|
|
|
/* # of queue pairs currently used by the driver */
|
|
|
u16 curr_queue_pairs;
|
|
|
|
|
|
+ /* # of XDP queue pairs currently used by the driver */
|
|
|
+ u16 xdp_queue_pairs;
|
|
|
+
|
|
|
/* I like... big packets and I cannot lie! */
|
|
|
bool big_packets;
|
|
|
|
|
@@ -1526,7 +1529,8 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog)
|
|
|
unsigned long int max_sz = PAGE_SIZE - sizeof(struct padded_vnet_hdr);
|
|
|
struct virtnet_info *vi = netdev_priv(dev);
|
|
|
struct bpf_prog *old_prog;
|
|
|
- int i;
|
|
|
+ u16 xdp_qp = 0, curr_qp;
|
|
|
+ int i, err;
|
|
|
|
|
|
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
|
|
|
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6)) {
|
|
@@ -1544,12 +1548,34 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ curr_qp = vi->curr_queue_pairs - vi->xdp_queue_pairs;
|
|
|
+ if (prog)
|
|
|
+ xdp_qp = nr_cpu_ids;
|
|
|
+
|
|
|
+ /* XDP requires extra queues for XDP_TX */
|
|
|
+ if (curr_qp + xdp_qp > vi->max_queue_pairs) {
|
|
|
+ netdev_warn(dev, "request %i queues but max is %i\n",
|
|
|
+ curr_qp + xdp_qp, vi->max_queue_pairs);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = virtnet_set_queues(vi, curr_qp + xdp_qp);
|
|
|
+ if (err) {
|
|
|
+ dev_warn(&dev->dev, "XDP Device queue allocation failure.\n");
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
if (prog) {
|
|
|
prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
|
|
|
- if (IS_ERR(prog))
|
|
|
+ if (IS_ERR(prog)) {
|
|
|
+ virtnet_set_queues(vi, curr_qp);
|
|
|
return PTR_ERR(prog);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ vi->xdp_queue_pairs = xdp_qp;
|
|
|
+ netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
|
|
|
+
|
|
|
for (i = 0; i < vi->max_queue_pairs; i++) {
|
|
|
old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
|
|
|
rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
|