From: Jason Wang <jasow...@redhat.com>

This is a preparation for adding XDP offload support in virtio_net
driver. By storing XDP program in virtionet_info will make it
consistent with the offloaded program which will introduce in next
patches.

Signed-off-by: Jason Wang <jasow...@redhat.com>
Co-developed-by: Prashant Bhole <prashantbhole.li...@gmail.com>
Signed-off-by: Prashant Bhole <prashantbhole.li...@gmail.com>
---
 drivers/net/virtio_net.c | 62 ++++++++++++++++------------------------
 1 file changed, 25 insertions(+), 37 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4d7d5434cc5d..c8bbb1b90c1c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -137,8 +137,6 @@ struct receive_queue {
 
        struct napi_struct napi;
 
-       struct bpf_prog __rcu *xdp_prog;
-
        struct virtnet_rq_stats stats;
 
        /* Chain pages by the private ptr. */
@@ -229,6 +227,8 @@ struct virtnet_info {
 
        /* failover when STANDBY feature enabled */
        struct failover *failover;
+
+       struct bpf_prog __rcu *xdp_prog;
 };
 
 struct padded_vnet_hdr {
@@ -486,7 +486,6 @@ static int virtnet_xdp_xmit(struct net_device *dev,
                            int n, struct xdp_frame **frames, u32 flags)
 {
        struct virtnet_info *vi = netdev_priv(dev);
-       struct receive_queue *rq = vi->rq;
        struct bpf_prog *xdp_prog;
        struct send_queue *sq;
        unsigned int len;
@@ -501,7 +500,7 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
         * indicate XDP resources have been successfully allocated.
         */
-       xdp_prog = rcu_dereference(rq->xdp_prog);
+       xdp_prog = rcu_dereference(vi->xdp_prog);
        if (!xdp_prog)
                return -ENXIO;
 
@@ -649,7 +648,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
        stats->bytes += len;
 
        rcu_read_lock();
-       xdp_prog = rcu_dereference(rq->xdp_prog);
+       xdp_prog = rcu_dereference(vi->xdp_prog);
        if (xdp_prog) {
                struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
                struct xdp_frame *xdpf;
@@ -798,7 +797,7 @@ static struct sk_buff *receive_mergeable(struct net_device 
*dev,
        stats->bytes += len - vi->hdr_len;
 
        rcu_read_lock();
-       xdp_prog = rcu_dereference(rq->xdp_prog);
+       xdp_prog = rcu_dereference(vi->xdp_prog);
        if (xdp_prog) {
                struct xdp_frame *xdpf;
                struct page *xdp_page;
@@ -2060,7 +2059,7 @@ static int virtnet_set_channels(struct net_device *dev,
         * also when XDP is loaded all RX queues have XDP programs so we only
         * need to check a single RX queue.
         */
-       if (vi->rq[0].xdp_prog)
+       if (vi->xdp_prog)
                return -EINVAL;
 
        get_online_cpus();
@@ -2441,13 +2440,10 @@ static int virtnet_xdp_set(struct net_device *dev, 
struct bpf_prog *prog,
                return -ENOMEM;
        }
 
-       old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
+       old_prog = rtnl_dereference(vi->xdp_prog);
        if (!prog && !old_prog)
                return 0;
 
-       if (prog)
-               bpf_prog_add(prog, vi->max_queue_pairs - 1);
-
        /* Make sure NAPI is not using any XDP TX queues for RX. */
        if (netif_running(dev)) {
                for (i = 0; i < vi->max_queue_pairs; i++) {
@@ -2457,11 +2453,8 @@ static int virtnet_xdp_set(struct net_device *dev, 
struct bpf_prog *prog,
        }
 
        if (!prog) {
-               for (i = 0; i < vi->max_queue_pairs; i++) {
-                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
-                       if (i == 0)
-                               virtnet_restore_guest_offloads(vi);
-               }
+               rcu_assign_pointer(vi->xdp_prog, prog);
+               virtnet_restore_guest_offloads(vi);
                synchronize_net();
        }
 
@@ -2472,16 +2465,12 @@ static int virtnet_xdp_set(struct net_device *dev, 
struct bpf_prog *prog,
        vi->xdp_queue_pairs = xdp_qp;
 
        if (prog) {
-               for (i = 0; i < vi->max_queue_pairs; i++) {
-                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
-                       if (i == 0 && !old_prog)
-                               virtnet_clear_guest_offloads(vi);
-               }
+               rcu_assign_pointer(vi->xdp_prog, prog);
+               if (!old_prog)
+                       virtnet_clear_guest_offloads(vi);
        }
 
        for (i = 0; i < vi->max_queue_pairs; i++) {
-               if (old_prog)
-                       bpf_prog_put(old_prog);
                if (netif_running(dev)) {
                        virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
                        virtnet_napi_tx_enable(vi, vi->sq[i].vq,
@@ -2489,13 +2478,15 @@ static int virtnet_xdp_set(struct net_device *dev, 
struct bpf_prog *prog,
                }
        }
 
+       if (old_prog)
+               bpf_prog_put(old_prog);
+
        return 0;
 
 err:
        if (!prog) {
                virtnet_clear_guest_offloads(vi);
-               for (i = 0; i < vi->max_queue_pairs; i++)
-                       rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
+               rcu_assign_pointer(vi->xdp_prog, old_prog);
        }
 
        if (netif_running(dev)) {
@@ -2514,13 +2505,11 @@ static u32 virtnet_xdp_query(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
        const struct bpf_prog *xdp_prog;
-       int i;
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               xdp_prog = rtnl_dereference(vi->rq[i].xdp_prog);
-               if (xdp_prog)
-                       return xdp_prog->aux->id;
-       }
+       xdp_prog = rtnl_dereference(vi->xdp_prog);
+       if (xdp_prog)
+               return xdp_prog->aux->id;
+
        return 0;
 }
 
@@ -2657,18 +2646,17 @@ static void virtnet_free_queues(struct virtnet_info *vi)
 
 static void _free_receive_bufs(struct virtnet_info *vi)
 {
-       struct bpf_prog *old_prog;
+       struct bpf_prog *old_prog = rtnl_dereference(vi->xdp_prog);
        int i;
 
        for (i = 0; i < vi->max_queue_pairs; i++) {
                while (vi->rq[i].pages)
                        __free_pages(get_a_page(&vi->rq[i], GFP_KERNEL), 0);
-
-               old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
-               RCU_INIT_POINTER(vi->rq[i].xdp_prog, NULL);
-               if (old_prog)
-                       bpf_prog_put(old_prog);
        }
+
+       RCU_INIT_POINTER(vi->xdp_prog, NULL);
+       if (old_prog)
+               bpf_prog_put(old_prog);
 }
 
 static void free_receive_bufs(struct virtnet_info *vi)
-- 
2.20.1


Reply via email to