struct receive_queue *rq,
                                     void *buf, void *ctx,
                                     unsigned int len,
-                                    unsigned int *xdp_xmit)
+                                    unsigned int *xdp_xmit,
+                                    unsigned int *rbytes)
 {
        struct sk_buff *skb;
        struct bpf_prog *xdp_prog;
        int err;
 
        len -= vi->hdr_len;
+       *rbytes += len;
 
        rcu_read_lock();
        xdp_prog = rcu_dereference(rq->xdp_prog);
                                   struct virtnet_info *vi,
                                   struct receive_queue *rq,
                                   void *buf,
-                                  unsigned int len)
+                                  unsigned int len,
+                                  unsigned int *rbytes)
 {
        struct page *page = buf;
        struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE);
 
+       *rbytes += len - vi->hdr_len;
        if (unlikely(!skb))
                goto err;
 
                                         void *buf,
                                         void *ctx,
                                         unsigned int len,
-                                        unsigned int *xdp_xmit)
+                                        unsigned int *xdp_xmit,
+                                        unsigned int *rbytes)
 {
        struct virtio_net_hdr_mrg_rxbuf *hdr = buf;
        u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers);
        int err;
 
        head_skb = NULL;
+       *rbytes += len - vi->hdr_len;
 
        rcu_read_lock();
        xdp_prog = rcu_dereference(rq->xdp_prog);
                        goto err_buf;
                }
 
+               *rbytes += len;
                page = virt_to_head_page(buf);
 
                truesize = mergeable_ctx_to_truesize(ctx);
                        dev->stats.rx_length_errors++;
                        break;
                }
+               *rbytes += len;
                page = virt_to_head_page(buf);
                put_page(page);
        }
        return NULL;
 }
 
-static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
-                      void *buf, unsigned int len, void **ctx,
-                      unsigned int *xdp_xmit)
+static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
+                       void *buf, unsigned int len, void **ctx,
+                       unsigned int *xdp_xmit, unsigned int *rbytes)
 {
        struct net_device *dev = vi->dev;
        struct sk_buff *skb;
        struct virtio_net_hdr_mrg_rxbuf *hdr;
-       int ret;
 
        if (unlikely(len < vi->hdr_len + ETH_HLEN)) {
                pr_debug("%s: short packet %i\n", dev->name, len);
                } else {
                        put_page(virt_to_head_page(buf));
                }
-               return 0;
+               return;
        }
 
        if (vi->mergeable_rx_bufs)
-               skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit);
+               skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit,
+                                       rbytes);
        else if (vi->big_packets)
-               skb = receive_big(dev, vi, rq, buf, len);
+               skb = receive_big(dev, vi, rq, buf, len, rbytes);
        else
-               skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit);
+               skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, rbytes);
 
        if (unlikely(!skb))
-               return 0;
+               return;
 
        hdr = skb_vnet_hdr(skb);
 
-       ret = skb->len;
-
        if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID)
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 
                 ntohs(skb->protocol), skb->len, skb->pkt_type);
 
        napi_gro_receive(&rq->napi, skb);
-       return ret;
+       return;
 
 frame_err:
        dev->stats.rx_frame_errors++;
        dev_kfree_skb(skb);
-       return 0;
 }
 
 /* Unlike mergeable buffers, all buffers are allocated to the
 
                while (received < budget &&
                       (buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx))) {
-                       bytes += receive_buf(vi, rq, buf, len, ctx, xdp_xmit);
+                       receive_buf(vi, rq, buf, len, ctx, xdp_xmit, &bytes);
                        received++;
                }
        } else {
                while (received < budget &&
                       (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
-                       bytes += receive_buf(vi, rq, buf, len, NULL, xdp_xmit);
+                       receive_buf(vi, rq, buf, len, NULL, xdp_xmit, &bytes);
                        received++;
                }
        }