4.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Toshiaki Makita makita.toshiaki@lab.ntt.co.jp
[ Upstream commit ecbc42ca5d665e9238a4cdb595024d2e6cf87f2d ]
When received packets are dropped in virtio_net driver, received packets counter is incremented but bytes counter is not. As a result, for instance if we drop all packets by XDP, only received is counted and bytes stays 0, which looks inconsistent. IMHO received packets/bytes should be counted if packets are produced by the hypervisor, like what common NICs on physical machines are doing. So fix the bytes counter.
Signed-off-by: Toshiaki Makita makita.toshiaki@lab.ntt.co.jp Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/virtio_net.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-)
--- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -551,7 +551,8 @@ static struct sk_buff *receive_small(str 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; @@ -567,6 +568,7 @@ static struct sk_buff *receive_small(str int err;
len -= vi->hdr_len; + *rbytes += len;
rcu_read_lock(); xdp_prog = rcu_dereference(rq->xdp_prog); @@ -666,11 +668,13 @@ static struct sk_buff *receive_big(struc 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;
@@ -688,7 +692,8 @@ static struct sk_buff *receive_mergeable 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); @@ -702,6 +707,7 @@ static struct sk_buff *receive_mergeable int err;
head_skb = NULL; + *rbytes += len - vi->hdr_len;
rcu_read_lock(); xdp_prog = rcu_dereference(rq->xdp_prog); @@ -831,6 +837,7 @@ static struct sk_buff *receive_mergeable goto err_buf; }
+ *rbytes += len; page = virt_to_head_page(buf);
truesize = mergeable_ctx_to_truesize(ctx); @@ -886,6 +893,7 @@ err_skb: dev->stats.rx_length_errors++; break; } + *rbytes += len; page = virt_to_head_page(buf); put_page(page); } @@ -896,14 +904,13 @@ xdp_xmit: 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); @@ -915,23 +922,22 @@ static int receive_buf(struct virtnet_in } 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;
@@ -948,12 +954,11 @@ static int receive_buf(struct virtnet_in 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 @@ -1203,13 +1208,13 @@ static int virtnet_receive(struct receiv
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++; } }