From patchwork Wed Feb 11 00:30:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 438614 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 9C65B1401B1 for ; Wed, 11 Feb 2015 11:31:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752347AbbBKAaz (ORCPT ); Tue, 10 Feb 2015 19:30:55 -0500 Received: from mail-ie0-f173.google.com ([209.85.223.173]:33568 "EHLO mail-ie0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752323AbbBKAax (ORCPT ); Tue, 10 Feb 2015 19:30:53 -0500 Received: by iecar1 with SMTP id ar1so515914iec.0 for ; Tue, 10 Feb 2015 16:30:53 -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=Y/XvNs/b58b1Vibwb8hYlLTgGoGIhBrXaq1ayMVNjHM=; b=kk63uSV1mPDDQz14MJcxiG0sxszO9McHH4GnyeB6Agej2p7hBzFnXXyaFLQT8aWyHk W62JSpbHnwl3xK3vjsY5dXiz2odZmpVvSGHaLpJjy5eT7958w02Gs/IXKj2MMbcQVEW2 FYwmJ1mFIXWdRFaBC/Un7LCjScngV54pMXz7Vaut+a2oN/KorvstB+KvB6CeqSBedWVU tJrY3qObNpqYZthmh3XPll5nmmMR6dlOHf+UyS1mCHv+KFUezCy2ZSgtwyvXmk4uCj6A dRFTHzCnc+uyAShFzevIDhgMfU84sv6w564/3Mit3eSF+NYFjl8jh3JCx5ECzzRPVWHE 6w/w== 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=Y/XvNs/b58b1Vibwb8hYlLTgGoGIhBrXaq1ayMVNjHM=; b=fooTJ3gWKVJT11wClr6iqY0OztRgJ+TIWhfhulgM2Fwo5GZ+88l5EwTE9mt+TjmYrp 56yx233M1AtxeXZsghypxU1u7djCKA+AYc2oEhgbEaOxA6++flHn9UZBHBe2Bz8SM6hK U1UJBBXKZLLqj0e20UHzh9QnlMuIrhlGMtezMgp5daro1kdbEbS9gOqVofe2h7InqKGN ARduqv14SnaIWxP1SBsRCuUSqYJjAdXGBbyYwfT0m4eaD0tslkv07kT5I67K0JEA+22e Odlnj0FV4po8wxqwEUQbR05mzQkv4EtN52DYAJaLCEklxSX/q+5a/WW1gzOt34qlOc/N lM7Q== X-Gm-Message-State: ALoCoQnM6GC8KXPDqfG1pPepJTvyVbGqT2lDSSXn//ieuD8oHFQKAnz3wmospn3UnPgXc1hJN7Y0 X-Received: by 10.50.107.7 with SMTP id gy7mr466043igb.49.1423614653262; Tue, 10 Feb 2015 16:30:53 -0800 (PST) Received: from tomh.mtv.corp.google.com ([172.18.117.126]) by mx.google.com with ESMTPSA id v39sm9655295iov.17.2015.02.10.16.30.52 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 10 Feb 2015 16:30:52 -0800 (PST) From: Tom Herbert To: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH net-next 5/7] net: Infrastructure for CHECKSUM_PARTIAL with remote checsum offload Date: Tue, 10 Feb 2015 16:30:31 -0800 Message-Id: <1423614633-25042-6-git-send-email-therbert@google.com> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1423614633-25042-1-git-send-email-therbert@google.com> References: <1423614633-25042-1-git-send-email-therbert@google.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds infrastructure so that remote checksum offload can set CHECKSUM_PARTIAL instead of calling csum_partial and writing the modfied checksum field. Add skb_remcsum_adjust_partial function to set an skb for using CHECKSUM_PARTIAL with remote checksum offload. Changed skb_remcsum_process and skb_gro_remcsum_process to take a boolean argument to indicate if checksum partial can be set or the checksum needs to be modified using the normal algorithm. Signed-off-by: Tom Herbert --- drivers/net/vxlan.c | 4 ++-- include/linux/netdevice.h | 19 ++++++++++++++++++- include/linux/skbuff.h | 15 ++++++++++++++- net/core/dev.c | 1 + net/ipv4/fou.c | 4 ++-- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 30310a6..4f04443 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -580,7 +580,7 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, } skb_gro_remcsum_process(skb, (void *)vh + hdrlen, - start, offset, grc); + start, offset, grc, true); skb->remcsum_offload = 1; @@ -1171,7 +1171,7 @@ static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, vh = (struct vxlanhdr *)(udp_hdr(skb) + 1); - skb_remcsum_process(skb, (void *)vh + hdrlen, start, offset); + skb_remcsum_process(skb, (void *)vh + hdrlen, start, offset, true); return vh; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 43fd0a4..5897b4e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1923,6 +1923,9 @@ struct napi_gro_cb { /* Number of segments aggregated. */ u16 count; + /* Start offset for remote checksum offload */ + u16 gro_remcsum_start; + /* jiffies when first packet was created/queued */ unsigned long age; @@ -2244,6 +2247,12 @@ static inline void skb_gro_postpull_rcsum(struct sk_buff *skb, __sum16 __skb_gro_checksum_complete(struct sk_buff *skb); +static inline bool skb_at_gro_remcsum_start(struct sk_buff *skb) +{ + return (NAPI_GRO_CB(skb)->gro_remcsum_start - skb_headroom(skb) == + skb_gro_offset(skb)); +} + static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb, bool zero_okay, __sum16 check) @@ -2251,6 +2260,7 @@ static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb, return ((skb->ip_summed != CHECKSUM_PARTIAL || skb_checksum_start_offset(skb) < skb_gro_offset(skb)) && + !skb_at_gro_remcsum_start(skb) && NAPI_GRO_CB(skb)->csum_cnt == 0 && (!zero_okay || check)); } @@ -2337,12 +2347,19 @@ static inline void skb_gro_remcsum_init(struct gro_remcsum *grc) static inline void skb_gro_remcsum_process(struct sk_buff *skb, void *ptr, int start, int offset, - struct gro_remcsum *grc) + struct gro_remcsum *grc, + bool nopartial) { __wsum delta; BUG_ON(!NAPI_GRO_CB(skb)->csum_valid); + if (!nopartial) { + NAPI_GRO_CB(skb)->gro_remcsum_start = + ((unsigned char *)ptr + start) - skb->head; + return; + } + delta = remcsum_adjust(ptr, NAPI_GRO_CB(skb)->csum, start, offset); /* Adjust skb->csum since we changed the packet */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index da6028a..30007af 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3104,16 +3104,29 @@ do { \ compute_pseudo(skb, proto)); \ } while (0) +static inline void skb_remcsum_adjust_partial(struct sk_buff *skb, void *ptr, + u16 start, u16 offset) +{ + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum_start = ((unsigned char *)ptr + start) - skb->head; + skb->csum_offset = offset - start; +} + /* Update skbuf and packet to reflect the remote checksum offload operation. * When called, ptr indicates the starting point for skb->csum when * ip_summed is CHECKSUM_COMPLETE. If we need create checksum complete * here, skb_postpull_rcsum is done so skb->csum start is ptr. */ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, - int start, int offset) + int start, int offset, bool nopartial) { __wsum delta; + if (!nopartial) { + skb_remcsum_adjust_partial(skb, ptr, start, offset); + return; + } + if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { __skb_checksum_complete(skb); skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); diff --git a/net/core/dev.c b/net/core/dev.c index d030575..48c6ecb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4024,6 +4024,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff NAPI_GRO_CB(skb)->flush = 0; NAPI_GRO_CB(skb)->free = 0; NAPI_GRO_CB(skb)->udp_mark = 0; + NAPI_GRO_CB(skb)->gro_remcsum_start = 0; /* Setup for GRO checksum validation */ switch (skb->ip_summed) { diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 7fa8d36..d320f57 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -75,7 +75,7 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, return NULL; guehdr = (struct guehdr *)&udp_hdr(skb)[1]; - skb_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset); + skb_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset, true); return guehdr; } @@ -230,7 +230,7 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, } skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen, - start, offset, grc); + start, offset, grc, true); skb->remcsum_offload = 1;