diff options
author | Ivan Vecera <ivecera@redhat.com> | 2015-07-23 10:37:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-27 17:49:54 -0400 |
commit | c5c62f1bb0e1fc94ab77ec01e92ccab5cb249742 (patch) | |
tree | 9af57b09b0e0e113743161f4029a21f8624f655f | |
parent | 1513069edcf8dd86cfd8d5daef482b97d6b93df6 (diff) |
macvtap: fix network header pointer for VLAN tagged pkts
Network header is set with offset ETH_HLEN but it is not true for VLAN
(multiple-)tagged and results in checksum issues in lower devices.
v2: leave skb->protocol untouched (thx Vlad), comment added
v3: moved after skb_probe_transport_header() call (thx Toshiaki)
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/macvtap.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 3b933bb5a8d5..edd77342773a 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -719,6 +719,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
719 | struct virtio_net_hdr vnet_hdr = { 0 }; | 719 | struct virtio_net_hdr vnet_hdr = { 0 }; |
720 | int vnet_hdr_len = 0; | 720 | int vnet_hdr_len = 0; |
721 | int copylen = 0; | 721 | int copylen = 0; |
722 | int depth; | ||
722 | bool zerocopy = false; | 723 | bool zerocopy = false; |
723 | size_t linear; | 724 | size_t linear; |
724 | ssize_t n; | 725 | ssize_t n; |
@@ -804,6 +805,12 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
804 | 805 | ||
805 | skb_probe_transport_header(skb, ETH_HLEN); | 806 | skb_probe_transport_header(skb, ETH_HLEN); |
806 | 807 | ||
808 | /* Move network header to the right position for VLAN tagged packets */ | ||
809 | if ((skb->protocol == htons(ETH_P_8021Q) || | ||
810 | skb->protocol == htons(ETH_P_8021AD)) && | ||
811 | __vlan_get_protocol(skb, skb->protocol, &depth) != 0) | ||
812 | skb_set_network_header(skb, depth); | ||
813 | |||
807 | rcu_read_lock(); | 814 | rcu_read_lock(); |
808 | vlan = rcu_dereference(q->vlan); | 815 | vlan = rcu_dereference(q->vlan); |
809 | /* copy skb_ubuf_info for callback when skb has no error */ | 816 | /* copy skb_ubuf_info for callback when skb has no error */ |