Skip to content

Commit

Permalink
tuntap: set transport header before passing it to kernel
Browse files Browse the repository at this point in the history
Currently, for the packets receives from tuntap, before doing header check,
kernel just reset the transport header in netif_receive_skb() which pretends no
l4 header. This is suboptimal for precise packet length estimation (introduced
in 1def923) which needs correct l4 header for gso packets.

So this patch set the transport header to csum_start for partial checksum
packets, otherwise it first try skb_flow_dissect(), if it fails, just reset the
transport header.

Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jason Wang authored and David S. Miller committed Mar 26, 2013
1 parent 9b4d669 commit 38502af
Showing 1 changed file with 10 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#include <net/sock.h>

#include <asm/uaccess.h>
#include <net/flow_keys.h>

/* Uncomment to enable debugging */
/* #define TUN_DEBUG 1 */
Expand Down Expand Up @@ -1049,6 +1050,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
bool zerocopy = false;
int err;
u32 rxhash;
struct flow_keys keys;

if (!(tun->flags & TUN_NO_PI)) {
if ((len -= sizeof(pi)) > total_len)
Expand Down Expand Up @@ -1203,6 +1205,14 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
}

skb_reset_network_header(skb);

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_reset_transport_header(skb);

rxhash = skb_get_rxhash(skb);
netif_rx_ni(skb);

Expand Down

0 comments on commit 38502af

Please sign in to comment.