aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3e2c041d76ac..ea672145f6a6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -70,7 +70,8 @@ static const unsigned long guest_offloads[] = {
70 VIRTIO_NET_F_GUEST_TSO4, 70 VIRTIO_NET_F_GUEST_TSO4,
71 VIRTIO_NET_F_GUEST_TSO6, 71 VIRTIO_NET_F_GUEST_TSO6,
72 VIRTIO_NET_F_GUEST_ECN, 72 VIRTIO_NET_F_GUEST_ECN,
73 VIRTIO_NET_F_GUEST_UFO 73 VIRTIO_NET_F_GUEST_UFO,
74 VIRTIO_NET_F_GUEST_CSUM
74}; 75};
75 76
76struct virtnet_stat_desc { 77struct virtnet_stat_desc {
@@ -364,7 +365,8 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx)
364static struct sk_buff *page_to_skb(struct virtnet_info *vi, 365static struct sk_buff *page_to_skb(struct virtnet_info *vi,
365 struct receive_queue *rq, 366 struct receive_queue *rq,
366 struct page *page, unsigned int offset, 367 struct page *page, unsigned int offset,
367 unsigned int len, unsigned int truesize) 368 unsigned int len, unsigned int truesize,
369 bool hdr_valid)
368{ 370{
369 struct sk_buff *skb; 371 struct sk_buff *skb;
370 struct virtio_net_hdr_mrg_rxbuf *hdr; 372 struct virtio_net_hdr_mrg_rxbuf *hdr;
@@ -386,7 +388,8 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
386 else 388 else
387 hdr_padded_len = sizeof(struct padded_vnet_hdr); 389 hdr_padded_len = sizeof(struct padded_vnet_hdr);
388 390
389 memcpy(hdr, p, hdr_len); 391 if (hdr_valid)
392 memcpy(hdr, p, hdr_len);
390 393
391 len -= hdr_len; 394 len -= hdr_len;
392 offset += hdr_padded_len; 395 offset += hdr_padded_len;
@@ -738,7 +741,8 @@ static struct sk_buff *receive_big(struct net_device *dev,
738 struct virtnet_rq_stats *stats) 741 struct virtnet_rq_stats *stats)
739{ 742{
740 struct page *page = buf; 743 struct page *page = buf;
741 struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE); 744 struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len,
745 PAGE_SIZE, true);
742 746
743 stats->bytes += len - vi->hdr_len; 747 stats->bytes += len - vi->hdr_len;
744 if (unlikely(!skb)) 748 if (unlikely(!skb))
@@ -841,7 +845,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
841 rcu_read_unlock(); 845 rcu_read_unlock();
842 put_page(page); 846 put_page(page);
843 head_skb = page_to_skb(vi, rq, xdp_page, 847 head_skb = page_to_skb(vi, rq, xdp_page,
844 offset, len, PAGE_SIZE); 848 offset, len,
849 PAGE_SIZE, false);
845 return head_skb; 850 return head_skb;
846 } 851 }
847 break; 852 break;
@@ -897,7 +902,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
897 goto err_skb; 902 goto err_skb;
898 } 903 }
899 904
900 head_skb = page_to_skb(vi, rq, page, offset, len, truesize); 905 head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog);
901 curr_skb = head_skb; 906 curr_skb = head_skb;
902 907
903 if (unlikely(!curr_skb)) 908 if (unlikely(!curr_skb))
@@ -2334,9 +2339,6 @@ static int virtnet_clear_guest_offloads(struct virtnet_info *vi)
2334 if (!vi->guest_offloads) 2339 if (!vi->guest_offloads)
2335 return 0; 2340 return 0;
2336 2341
2337 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
2338 offloads = 1ULL << VIRTIO_NET_F_GUEST_CSUM;
2339
2340 return virtnet_set_guest_offloads(vi, offloads); 2342 return virtnet_set_guest_offloads(vi, offloads);
2341} 2343}
2342 2344
@@ -2346,8 +2348,6 @@ static int virtnet_restore_guest_offloads(struct virtnet_info *vi)
2346 2348
2347 if (!vi->guest_offloads) 2349 if (!vi->guest_offloads)
2348 return 0; 2350 return 0;
2349 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
2350 offloads |= 1ULL << VIRTIO_NET_F_GUEST_CSUM;
2351 2351
2352 return virtnet_set_guest_offloads(vi, offloads); 2352 return virtnet_set_guest_offloads(vi, offloads);
2353} 2353}
@@ -2365,8 +2365,9 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
2365 && (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) || 2365 && (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
2366 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) || 2366 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
2367 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) || 2367 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
2368 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO))) { 2368 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
2369 NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO, disable LRO first"); 2369 virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))) {
2370 NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO/CSUM, disable LRO/CSUM first");
2370 return -EOPNOTSUPP; 2371 return -EOPNOTSUPP;
2371 } 2372 }
2372 2373