diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 27 |
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 | ||
76 | struct virtnet_stat_desc { | 77 | struct virtnet_stat_desc { |
@@ -364,7 +365,8 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx) | |||
364 | static struct sk_buff *page_to_skb(struct virtnet_info *vi, | 365 | static 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 | ||