Skip to content

Commit

Permalink
virtio_net: make all RX paths handle erors consistently
Browse files Browse the repository at this point in the history
receive mergeable now handles errors internally.
Do same for big and small packet paths, otherwise
the logic is too hard to follow.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael S. Tsirkin authored and David S. Miller committed Dec 2, 2013
1 parent 8fc3b9e commit f121159
Showing 1 changed file with 37 additions and 17 deletions.
54 changes: 37 additions & 17 deletions drivers/net/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,35 @@ static struct sk_buff *page_to_skb(struct receive_queue *rq,
return skb;
}

static struct sk_buff *receive_small(void *buf, unsigned int len)
{
struct sk_buff * skb = buf;

len -= sizeof(struct virtio_net_hdr);
skb_trim(skb, len);

return skb;
}

static struct sk_buff *receive_big(struct net_device *dev,
struct receive_queue *rq,
void *buf,
unsigned int len)
{
struct page *page = buf;
struct sk_buff *skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);

if (unlikely(!skb))
goto err;

return skb;

err:
dev->stats.rx_dropped++;
give_pages(rq, page);
return NULL;
}

static struct sk_buff *receive_mergeable(struct net_device *dev,
struct receive_queue *rq,
void *buf,
Expand Down Expand Up @@ -392,7 +421,6 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
struct net_device *dev = vi->dev;
struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
struct sk_buff *skb;
struct page *page;
struct skb_vnet_hdr *hdr;

if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
Expand All @@ -407,23 +435,15 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
return;
}

if (!vi->mergeable_rx_bufs && !vi->big_packets) {
skb = buf;
len -= sizeof(struct virtio_net_hdr);
skb_trim(skb, len);
} else if (vi->mergeable_rx_bufs) {
if (vi->mergeable_rx_bufs)
skb = receive_mergeable(dev, rq, buf, len);
if (unlikely(!skb))
return;
} else {
page = buf;
skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
if (unlikely(!skb)) {
dev->stats.rx_dropped++;
give_pages(rq, page);
return;
}
}
else if (vi->big_packets)
skb = receive_big(dev, rq, buf, len);
else
skb = receive_small(buf, len);

if (unlikely(!skb))
return;

hdr = skb_vnet_hdr(skb);

Expand Down

0 comments on commit f121159

Please sign in to comment.