aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-03-25 16:19:56 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:44:43 -0400
commit38502af77e07b5d6650b9ff99a0b482d86366592 (patch)
treefa2164acb8ee8d57d8134af49296b80801ff0e66
parent9b4d669bc06c215d64f56f1eb0d4eb96e14d689d (diff)
tuntap: set transport header before passing it to kernel
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 1def9238) 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>
-rw-r--r--drivers/net/tun.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 95837c1b197a..48cd73a2dc55 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -70,6 +70,7 @@
70#include <net/sock.h> 70#include <net/sock.h>
71 71
72#include <asm/uaccess.h> 72#include <asm/uaccess.h>
73#include <net/flow_keys.h>
73 74
74/* Uncomment to enable debugging */ 75/* Uncomment to enable debugging */
75/* #define TUN_DEBUG 1 */ 76/* #define TUN_DEBUG 1 */
@@ -1049,6 +1050,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1049 bool zerocopy = false; 1050 bool zerocopy = false;
1050 int err; 1051 int err;
1051 u32 rxhash; 1052 u32 rxhash;
1053 struct flow_keys keys;
1052 1054
1053 if (!(tun->flags & TUN_NO_PI)) { 1055 if (!(tun->flags & TUN_NO_PI)) {
1054 if ((len -= sizeof(pi)) > total_len) 1056 if ((len -= sizeof(pi)) > total_len)
@@ -1203,6 +1205,14 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1203 } 1205 }
1204 1206
1205 skb_reset_network_header(skb); 1207 skb_reset_network_header(skb);
1208
1209 if (skb->ip_summed == CHECKSUM_PARTIAL)
1210 skb_set_transport_header(skb, skb_checksum_start_offset(skb));
1211 else if (skb_flow_dissect(skb, &keys))
1212 skb_set_transport_header(skb, keys.thoff);
1213 else
1214 skb_reset_transport_header(skb);
1215
1206 rxhash = skb_get_rxhash(skb); 1216 rxhash = skb_get_rxhash(skb);
1207 netif_rx_ni(skb); 1217 netif_rx_ni(skb);
1208 1218