From patchwork Tue Nov 4 17:06:52 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 406687 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 077821400B7 for ; Wed, 5 Nov 2014 04:07:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752375AbaKDRHa (ORCPT ); Tue, 4 Nov 2014 12:07:30 -0500 Received: from mail-ig0-f173.google.com ([209.85.213.173]:64298 "EHLO mail-ig0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752354AbaKDRH1 (ORCPT ); Tue, 4 Nov 2014 12:07:27 -0500 Received: by mail-ig0-f173.google.com with SMTP id r10so7078205igi.12 for ; Tue, 04 Nov 2014 09:07:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=sGKez0twevwwDnSXmfcxWTN8BLa8idTy/QStmHB0lSA=; b=Tv/gsYnnONG0ebihqK3DU0vJcqb3Qrm1mR5rvEuOU0m8uSORtOQZtjiIzQ9Xv23d/X B6N50ObX2FOfIL4l0pXzvjajg+GoJK78/xBxYbQRDvPUkJxq6eMSAnrqAighU27cyiNo weZvpm4clYhX7xH57HgFVe5pVVCOU0q2eeWbIp6eQozh/VTkTzVODCCvKALwFo20d7kZ jIzRTzzU6YAf87RqvcyQaREmAf86NC7ZuJ5cjhvG65n/+28DBbELdYTaTEtirZPhuWMI P5sr4SkzSJyVfSJrZO3/eIjm3QFejpyhmoinFHjgVX414E3rqelkQ+BFLb/PWuZtcZ0n GHBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=sGKez0twevwwDnSXmfcxWTN8BLa8idTy/QStmHB0lSA=; b=HAQ+M4SwfNAEqy71W+xPL60vunczylkdbXiLzt3x3kC0CefkQlWEkGHtEzrTATVJeI j+J/vVy4EeO6DMdBiwlpbdGOpuwHZREcHB4kHrw2SgwUrlPQIvKhjfSehS2sHqRT3soO RjIOJoWaP+OmOA2qKEYkMfj+cKx7xwpov1wHjbzNlgwMg82I9z58XKZ9TEjUBOrgmCNg Y3yNyPo/WtJPo6fPvpq4w1kXsqTSbdXDVmwxP8TFqnBRGls67myLpexmhlGjva+oQVse dcAumN2niFdiSXuK01jNdZH5i0HDOPdoDnNwy9pT+TQ1E4/53it3srOk07qx/A+6gLCm eIrQ== X-Gm-Message-State: ALoCoQnFZqFI0d0706rd9nbJoLOwSOISz02ExVMjuDp4v9uF7w/iRl3zFYg4Qva/p+A513WIJ9OV X-Received: by 10.50.51.100 with SMTP id j4mr25470880igo.39.1415120846028; Tue, 04 Nov 2014 09:07:26 -0800 (PST) Received: from tomh.mtv.corp.google.com ([172.18.117.126]) by mx.google.com with ESMTPSA id j36sm402221ioo.23.2014.11.04.09.07.25 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 04 Nov 2014 09:07:25 -0800 (PST) From: Tom Herbert To: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH v2 net-next 2/7] udp: Offload outer UDP tunnel csum if available Date: Tue, 4 Nov 2014 09:06:52 -0800 Message-Id: <1415120817-2105-3-git-send-email-therbert@google.com> X-Mailer: git-send-email 2.1.0.rc2.206.gedb03e5 In-Reply-To: <1415120817-2105-1-git-send-email-therbert@google.com> References: <1415120817-2105-1-git-send-email-therbert@google.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In __skb_udp_tunnel_segment if outer UDP checksums are enabled and ip_summed is not already CHECKSUM_PARTIAL, set up checksum offload if device features allow it. Signed-off-by: Tom Herbert --- net/ipv4/udp_offload.c | 52 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 6480cea..a774711 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -29,7 +29,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t features, struct sk_buff *(*gso_inner_segment)(struct sk_buff *skb, netdev_features_t features), - __be16 new_protocol) + __be16 new_protocol, bool is_ipv6) { struct sk_buff *segs = ERR_PTR(-EINVAL); u16 mac_offset = skb->mac_header; @@ -39,7 +39,9 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t enc_features; int udp_offset, outer_hlen; unsigned int oldlen; - bool need_csum; + bool need_csum = !!(skb_shinfo(skb)->gso_type & + SKB_GSO_UDP_TUNNEL_CSUM); + bool offload_csum = false, dont_encap = need_csum; oldlen = (u16)~skb->len; @@ -52,10 +54,12 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, skb_set_network_header(skb, skb_inner_network_offset(skb)); skb->mac_len = skb_inner_network_offset(skb); skb->protocol = new_protocol; + skb->encap_hdr_csum = need_csum; - need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM); - if (need_csum) - skb->encap_hdr_csum = 1; + /* Try to offload checksum if possible */ + offload_csum = !!(need_csum && + (skb->dev->features & + (is_ipv6 ? NETIF_F_V6_CSUM : NETIF_F_V4_CSUM))); /* segment inner packet. */ enc_features = skb->dev->hw_enc_features & features; @@ -72,11 +76,21 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, do { struct udphdr *uh; int len; - - skb_reset_inner_headers(skb); - skb->encapsulation = 1; + __be32 delta; + + if (dont_encap) { + skb->encapsulation = 0; + skb->ip_summed = CHECKSUM_NONE; + } else { + /* Only set up inner headers if we might be offloading + * inner checksum. + */ + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + } skb->mac_len = mac_len; + skb->protocol = protocol; skb_push(skb, outer_hlen); skb_reset_mac_header(skb); @@ -86,19 +100,25 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, uh = udp_hdr(skb); uh->len = htons(len); - if (need_csum) { - __be32 delta = htonl(oldlen + len); + if (!need_csum) + continue; + + delta = htonl(oldlen + len); + + uh->check = ~csum_fold((__force __wsum) + ((__force u32)uh->check + + (__force u32)delta)); - uh->check = ~csum_fold((__force __wsum) - ((__force u32)uh->check + - (__force u32)delta)); + if (offload_csum) { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct udphdr, check); + } else { uh->check = gso_make_checksum(skb, ~uh->check); if (uh->check == 0) uh->check = CSUM_MANGLED_0; } - - skb->protocol = protocol; } while ((skb = skb->next)); out: return segs; @@ -134,7 +154,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, } segs = __skb_udp_tunnel_segment(skb, features, gso_inner_segment, - protocol); + protocol, is_ipv6); out_unlock: rcu_read_unlock();