From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759368Ab3CZG3t (ORCPT ); Tue, 26 Mar 2013 02:29:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39467 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759477Ab3CZG31 (ORCPT ); Tue, 26 Mar 2013 02:29:27 -0400 From: Jason Wang To: davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: mst@redhat.com, Jason Wang , Eric Dumazet Subject: [net-next 2/5] tuntap: set transport header before passing it to kernel Date: Tue, 26 Mar 2013 14:19:56 +0800 Message-Id: <1364278799-37285-3-git-send-email-jasowang@redhat.com> In-Reply-To: <1364278799-37285-1-git-send-email-jasowang@redhat.com> References: <1364278799-37285-1-git-send-email-jasowang@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Signed-off-by: Jason Wang --- drivers/net/tun.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 95837c1..48cd73a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -70,6 +70,7 @@ #include #include +#include /* Uncomment to enable debugging */ /* #define TUN_DEBUG 1 */ @@ -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) @@ -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); -- 1.7.1