aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-03-25 20:19:55 +0000
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:44:43 -0400
commit9b4d669bc06c215d64f56f1eb0d4eb96e14d689d (patch)
tree8fdb362eba001a0d55077b812345aedde53131e9 /drivers/net/macvtap.c
parentnetlink: remove duplicated NLMSG_ALIGN (diff)
downloadlinux-dev-9b4d669bc06c215d64f56f1eb0d4eb96e14d689d.tar.xz
linux-dev-9b4d669bc06c215d64f56f1eb0d4eb96e14d689d.zip
macvtap: set transport header before passing skb to lower device
Set the transport header for 1) some drivers (e.g ixgbe) needs l4 header 2) precise packet length estimation (introduced in 1def9238) needs l4 header to compute header length. For the packets with partial checksum, the patch just set the transport header to csum_start. Otherwise tries to use skb_flow_dissect() to get l4 offset, if it fails, just pretend no l4 header. Cc: Eric Dumazet <edumazet@google.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r--drivers/net/macvtap.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index a449439bd653..acf6450ceff5 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -21,6 +21,7 @@
#include <net/rtnetlink.h>
#include <net/sock.h>
#include <linux/virtio_net.h>
+#include <net/flow_keys.h>
/*
* A macvtap queue is the central object of this driver, it connects
@@ -645,6 +646,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
int vnet_hdr_len = 0;
int copylen = 0;
bool zerocopy = false;
+ struct flow_keys keys;
if (q->flags & IFF_VNET_HDR) {
vnet_hdr_len = q->vnet_hdr_sz;
@@ -725,6 +727,13 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
goto err_kfree;
}
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ skb_set_transport_header(skb, skb_checksum_start_offset(skb));
+ else if (skb_flow_dissect(skb, &keys))
+ skb_set_transport_header(skb, keys.thoff);
+ else
+ skb_set_transport_header(skb, ETH_HLEN);
+
rcu_read_lock_bh();
vlan = rcu_dereference_bh(q->vlan);
/* copy skb_ubuf_info for callback when skb has no error */