[ovs-dev] [PATCH v2 07/13] datapath: Remove checksum compat support

Pravin B Shelar pshelar at nicira.com
Tue Sep 3 21:00:25 UTC 2013


Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 datapath/Modules.mk                               |    2 -
 datapath/actions.c                                |   21 +-
 datapath/checksum.c                               |  271 ---------------------
 datapath/checksum.h                               |  173 -------------
 datapath/datapath.c                               |    3 -
 datapath/datapath.h                               |   10 -
 datapath/linux/Modules.mk                         |    3 +-
 datapath/linux/compat/include/linux/netdevice.h   |    7 -
 datapath/linux/compat/include/net/checksum.h      |   12 +-
 datapath/linux/compat/include/net/sctp/checksum.h |    5 -
 datapath/linux/compat/ip_tunnels_core.c           |    4 -
 datapath/linux/compat/skbuff-openvswitch.c        |   22 --
 datapath/linux/compat/utils.c                     |   39 +++
 datapath/linux/compat/vxlan.c                     |    1 -
 datapath/vlan.h                                   |    5 -
 datapath/vport-gre.c                              |    2 -
 datapath/vport-internal_dev.c                     |    7 -
 datapath/vport-lisp.c                             |   12 +-
 datapath/vport-netdev.c                           |    5 -
 datapath/vport-vxlan.c                            |    2 -
 20 files changed, 55 insertions(+), 551 deletions(-)
 delete mode 100644 datapath/checksum.c
 delete mode 100644 datapath/checksum.h
 create mode 100644 datapath/linux/compat/utils.c

diff --git a/datapath/Modules.mk b/datapath/Modules.mk
index ccf4dfa..e2a4dad 100644
--- a/datapath/Modules.mk
+++ b/datapath/Modules.mk
@@ -8,7 +8,6 @@ dist_modules = $(both_modules)	# Modules to distribute
 
 openvswitch_sources = \
 	actions.c \
-	checksum.c \
 	datapath.c \
 	dp_notify.c \
 	flow.c \
@@ -21,7 +20,6 @@ openvswitch_sources = \
 	vport-vxlan.c
 
 openvswitch_headers = \
-	checksum.h \
 	compat.h \
 	datapath.h \
 	flow.h \
diff --git a/datapath/actions.c b/datapath/actions.c
index 33633df..30ea1d2 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -34,7 +34,6 @@
 #include <net/dsfield.h>
 #include <net/sctp/checksum.h>
 
-#include "checksum.h"
 #include "datapath.h"
 #include "vlan.h"
 #include "vport.h"
@@ -60,7 +59,7 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
 	if (unlikely(err))
 		return err;
 
-	if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+	if (skb->ip_summed == CHECKSUM_COMPLETE)
 		skb->csum = csum_sub(skb->csum, csum_partial(skb->data
 					+ (2 * ETH_ALEN), VLAN_HLEN, 0));
 
@@ -117,7 +116,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla
 		if (!__vlan_put_tag(skb, skb->vlan_proto, current_tag))
 			return -ENOMEM;
 
-		if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+		if (skb->ip_summed == CHECKSUM_COMPLETE)
 			skb->csum = csum_add(skb->csum, csum_partial(skb->data
 					+ (2 * ETH_ALEN), VLAN_HLEN, 0));
 
@@ -134,16 +133,12 @@ static int set_eth_addr(struct sk_buff *skb,
 	if (unlikely(err))
 		return err;
 
-	if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
-		skb->csum = csum_sub(skb->csum, csum_partial(eth_hdr(skb),
-							     ETH_ALEN * 2, 0));
+	skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
 
 	memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN);
 	memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN);
 
-	if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
-		skb->csum = csum_add(skb->csum, csum_partial(eth_hdr(skb),
-							     ETH_ALEN * 2, 0));
+	ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
 
 	return 0;
 }
@@ -161,8 +156,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
 		if (likely(transport_len >= sizeof(struct udphdr))) {
 			struct udphdr *uh = udp_hdr(skb);
 
-			if (uh->check ||
-			    get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
+			if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
 				inet_proto_csum_replace4(&uh->check, skb,
 							 *addr, new_addr, 1);
 				if (!uh->check)
@@ -189,8 +183,7 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
 		if (likely(transport_len >= sizeof(struct udphdr))) {
 			struct udphdr *uh = udp_hdr(skb);
 
-			if (uh->check ||
-			    get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
+			if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
 				inet_proto_csum_replace16(&uh->check, skb,
 							  addr, new_addr, 1);
 				if (!uh->check)
@@ -311,7 +304,7 @@ static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port)
 {
 	struct udphdr *uh = udp_hdr(skb);
 
-	if (uh->check && get_ip_summed(skb) != OVS_CSUM_PARTIAL) {
+	if (uh->check && skb->ip_summed != CHECKSUM_PARTIAL) {
 		set_tp_port(skb, port, new_port, &uh->check);
 
 		if (!uh->check)
diff --git a/datapath/checksum.c b/datapath/checksum.c
deleted file mode 100644
index 5146c65..0000000
--- a/datapath/checksum.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2007-2011 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-
-#include "checksum.h"
-#include "datapath.h"
-
-#ifdef NEED_CSUM_NORMALIZE
-
-#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
-/* This code is based on skb_checksum_setup() from Xen's net/dev/core.c.  We
- * can't call this function directly because it isn't exported in all
- * versions. */
-static int vswitch_skb_checksum_setup(struct sk_buff *skb)
-{
-	struct iphdr *iph;
-	unsigned char *th;
-	int err = -EPROTO;
-	__u16 csum_start, csum_offset;
-
-	if (!skb->proto_csum_blank)
-		return 0;
-
-	if (skb->protocol != htons(ETH_P_IP))
-		goto out;
-
-	if (!pskb_may_pull(skb, skb_network_header(skb) + sizeof(struct iphdr) - skb->data))
-		goto out;
-
-	iph = ip_hdr(skb);
-	th = skb_network_header(skb) + 4 * iph->ihl;
-
-	csum_start = th - skb->head;
-	switch (iph->protocol) {
-	case IPPROTO_TCP:
-		csum_offset = offsetof(struct tcphdr, check);
-		break;
-	case IPPROTO_UDP:
-		csum_offset = offsetof(struct udphdr, check);
-		break;
-	default:
-		if (net_ratelimit())
-			pr_err("Attempting to checksum a non-TCP/UDP packet, "
-			       "dropping a protocol %d packet",
-			       iph->protocol);
-		goto out;
-	}
-
-	if (!pskb_may_pull(skb, th + csum_offset + 2 - skb->data))
-		goto out;
-
-	skb->proto_csum_blank = 0;
-	set_ip_summed(skb, OVS_CSUM_PARTIAL);
-	set_skb_csum_pointers(skb, csum_start, csum_offset);
-
-	err = 0;
-
-out:
-	return err;
-}
-#else
-static int vswitch_skb_checksum_setup(struct sk_buff *skb)
-{
-	return 0;
-}
-#endif /* not Xen old style checksums */
-
-/*
- *	compute_ip_summed - map external checksum state onto OVS representation
- *
- * @skb: Packet to manipulate.
- * @xmit: Whether we were on transmit path of network stack.  For example,
- *	  this is true for the internal dev vport because it receives skbs
- *	  that passed through dev_queue_xmit() but false for the netdev vport
- *	  because its packets come from netif_receive_skb().
- *
- * Older kernels (and various versions of Xen) were not explicit enough about
- * checksum offload parameters and rely on a combination of context and
- * non standard fields.  This deals with all those variations so that we
- * can internally manipulate checksum offloads without worrying about kernel
- * version.
- *
- * Types of checksums that we can receive (these all refer to L4 checksums):
- * 1. CHECKSUM_NONE: Device that did not compute checksum, contains full
- *	(though not verified) checksum in packet but not in skb->csum.  Packets
- *	from the bridge local port will also have this type.
- * 2. CHECKSUM_COMPLETE (CHECKSUM_HW): Good device that computes checksums,
- *	also the GRE module.  This is the same as CHECKSUM_NONE, except it has
- *	a valid skb->csum.  Importantly, both contain a full checksum (not
- *	verified) in the packet itself.  The only difference is that if the
- *	packet gets to L4 processing on this machine (not in DomU) we won't
- *	have to recompute the checksum to verify.  Most hardware devices do not
- *	produce packets with this type, even if they support receive checksum
- *	offloading (they produce type #5).
- * 3. CHECKSUM_PARTIAL (CHECKSUM_HW): Packet without full checksum and needs to
- *	be computed if it is sent off box.  Unfortunately on earlier kernels,
- *	this case is impossible to distinguish from #2, despite having opposite
- *	meanings.  Xen adds an extra field on earlier kernels (see #4) in order
- *	to distinguish the different states.
- * 4. CHECKSUM_UNNECESSARY (with proto_csum_blank true): This packet was
- *	generated locally by a Xen DomU and has a partial checksum.  If it is
- *	handled on this machine (Dom0 or DomU), then the checksum will not be
- *	computed.  If it goes off box, the checksum in the packet needs to be
- *	completed.  Calling skb_checksum_setup converts this to CHECKSUM_HW
- *	(CHECKSUM_PARTIAL) so that the checksum can be completed.  In later
- *	kernels, this combination is replaced with CHECKSUM_PARTIAL.
- * 5. CHECKSUM_UNNECESSARY (with proto_csum_blank false): Packet with a correct
- *	full checksum or using a protocol without a checksum.  skb->csum is
- *	undefined.  This is common from devices with receive checksum
- *	offloading.  This is somewhat similar to CHECKSUM_NONE, except that
- *	nobody will try to verify the checksum with CHECKSUM_UNNECESSARY.
- *
- * Note that on earlier kernels, CHECKSUM_COMPLETE and CHECKSUM_PARTIAL are
- * both defined as CHECKSUM_HW.  Normally the meaning of CHECKSUM_HW is clear
- * based on whether it is on the transmit or receive path.  After the datapath
- * it will be intepreted as CHECKSUM_PARTIAL.  If the packet already has a
- * checksum, we will panic.  Since we can receive packets with checksums, we
- * assume that all CHECKSUM_HW packets have checksums and map them to
- * CHECKSUM_NONE, which has a similar meaning (the it is only different if the
- * packet is processed by the local IP stack, in which case it will need to
- * be reverified).  If we receive a packet with CHECKSUM_HW that really means
- * CHECKSUM_PARTIAL, it will be sent with the wrong checksum.  However, there
- * shouldn't be any devices that do this with bridging.
- */
-int compute_ip_summed(struct sk_buff *skb, bool xmit)
-{
-	/* For our convenience these defines change repeatedly between kernel
-	 * versions, so we can't just copy them over...
-	 */
-	switch (skb->ip_summed) {
-	case CHECKSUM_NONE:
-		set_ip_summed(skb, OVS_CSUM_NONE);
-		break;
-	case CHECKSUM_UNNECESSARY:
-		set_ip_summed(skb, OVS_CSUM_UNNECESSARY);
-		break;
-#ifdef CHECKSUM_HW
-	/* In theory this could be either CHECKSUM_PARTIAL or CHECKSUM_COMPLETE.
-	 * However, on the receive side we should only get CHECKSUM_PARTIAL
-	 * packets from Xen, which uses some special fields to represent this
-	 * (see vswitch_skb_checksum_setup()).  Since we can only make one type
-	 * work, pick the one that actually happens in practice.
-	 *
-	 * On the transmit side (basically after skb_checksum_setup()
-	 * has been run or on internal dev transmit), packets with
-	 * CHECKSUM_COMPLETE aren't generated, so assume CHECKSUM_PARTIAL.
-	 */
-	case CHECKSUM_HW:
-		if (!xmit)
-			set_ip_summed(skb, OVS_CSUM_COMPLETE);
-		else
-			set_ip_summed(skb, OVS_CSUM_PARTIAL);
-		break;
-#else
-	case CHECKSUM_COMPLETE:
-		set_ip_summed(skb, OVS_CSUM_COMPLETE);
-		break;
-	case CHECKSUM_PARTIAL:
-		set_ip_summed(skb, OVS_CSUM_PARTIAL);
-		break;
-#endif
-	}
-
-	OVS_CB(skb)->csum_start = skb_headroom(skb) + skb_transport_offset(skb);
-
-	return vswitch_skb_checksum_setup(skb);
-}
-
-/*
- *     forward_ip_summed - map internal checksum state back onto native
- *			   kernel fields.
- *
- * @skb: Packet to manipulate.
- * @xmit: Whether we are about send on the transmit path the network stack.
- *	  This follows the same logic as the @xmit field in compute_ip_summed().
- *	  Generally, a given vport will have opposite values for @xmit passed to
- *	  these two functions.
- *
- * When a packet is about to egress from OVS take our internal fields (including
- * any modifications we have made) and recreate the correct representation for
- * this kernel.  This may do things like change the transport header offset.
- */
-void forward_ip_summed(struct sk_buff *skb, bool xmit)
-{
-	switch (get_ip_summed(skb)) {
-	case OVS_CSUM_NONE:
-		skb->ip_summed = CHECKSUM_NONE;
-		break;
-	case OVS_CSUM_UNNECESSARY:
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
-		skb->proto_data_valid = 1;
-#endif
-		break;
-#ifdef CHECKSUM_HW
-	case OVS_CSUM_COMPLETE:
-		if (!xmit)
-			skb->ip_summed = CHECKSUM_HW;
-		else
-			skb->ip_summed = CHECKSUM_NONE;
-		break;
-	case OVS_CSUM_PARTIAL:
-		if (!xmit) {
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
-			skb->proto_csum_blank = 1;
-#endif
-		} else {
-			skb->ip_summed = CHECKSUM_HW;
-		}
-		break;
-#else
-	case OVS_CSUM_COMPLETE:
-		skb->ip_summed = CHECKSUM_COMPLETE;
-		break;
-	case OVS_CSUM_PARTIAL:
-		skb->ip_summed = CHECKSUM_PARTIAL;
-		break;
-#endif
-	}
-
-	if (get_ip_summed(skb) == OVS_CSUM_PARTIAL)
-		skb_set_transport_header(skb, OVS_CB(skb)->csum_start -
-					      skb_headroom(skb));
-}
-
-u8 get_ip_summed(struct sk_buff *skb)
-{
-	return OVS_CB(skb)->ip_summed;
-}
-
-void set_ip_summed(struct sk_buff *skb, u8 ip_summed)
-{
-	OVS_CB(skb)->ip_summed = ip_summed;
-}
-
-void get_skb_csum_pointers(const struct sk_buff *skb, u16 *csum_start,
-			   u16 *csum_offset)
-{
-	*csum_start = OVS_CB(skb)->csum_start;
-	*csum_offset = skb->csum;
-}
-
-void set_skb_csum_pointers(struct sk_buff *skb, u16 csum_start,
-			   u16 csum_offset)
-{
-	OVS_CB(skb)->csum_start = csum_start;
-	skb->csum = csum_offset;
-}
-#endif /* NEED_CSUM_NORMALIZE */
diff --git a/datapath/checksum.h b/datapath/checksum.h
deleted file mode 100644
index a440c59..0000000
--- a/datapath/checksum.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2007-2011 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#ifndef CHECKSUM_H
-#define CHECKSUM_H 1
-
-#include <linux/skbuff.h>
-#include <linux/version.h>
-
-#include <net/checksum.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) || \
-	(defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID))
-#define NEED_CSUM_NORMALIZE
-#endif
-
-/* These are the same values as the checksum constants in 2.6.22+. */
-enum csum_type {
-	OVS_CSUM_NONE = 0,
-	OVS_CSUM_UNNECESSARY = 1,
-	OVS_CSUM_COMPLETE = 2,
-	OVS_CSUM_PARTIAL = 3,
-};
-
-#ifdef NEED_CSUM_NORMALIZE
-int compute_ip_summed(struct sk_buff *skb, bool xmit);
-void forward_ip_summed(struct sk_buff *skb, bool xmit);
-u8 get_ip_summed(struct sk_buff *skb);
-void set_ip_summed(struct sk_buff *skb, u8 ip_summed);
-void get_skb_csum_pointers(const struct sk_buff *skb, u16 *csum_start,
-			   u16 *csum_offset);
-void set_skb_csum_pointers(struct sk_buff *skb, u16 csum_start,
-			   u16 csum_offset);
-#else
-static inline int compute_ip_summed(struct sk_buff *skb, bool xmit)
-{
-	return 0;
-}
-
-static inline void forward_ip_summed(struct sk_buff *skb, bool xmit) { }
-
-static inline u8 get_ip_summed(struct sk_buff *skb)
-{
-	return skb->ip_summed;
-}
-
-static inline void set_ip_summed(struct sk_buff *skb, u8 ip_summed)
-{
-	skb->ip_summed = ip_summed;
-}
-
-static inline void get_skb_csum_pointers(const struct sk_buff *skb,
-					 u16 *csum_start, u16 *csum_offset)
-{
-	*csum_start = skb->csum_start;
-	*csum_offset = skb->csum_offset;
-}
-
-static inline void set_skb_csum_pointers(struct sk_buff *skb, u16 csum_start,
-					 u16 csum_offset)
-{
-	skb->csum_start = csum_start;
-	skb->csum_offset = csum_offset;
-}
-#endif
-
-/* This is really compatibility code that belongs in the compat directory.
- * However, it needs access to our normalized checksum values, so put it here.
- */
-#if defined(NEED_CSUM_NORMALIZE) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
-#define inet_proto_csum_replace4 rpl_inet_proto_csum_replace4
-static inline void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
-					    __be32 from, __be32 to,
-					    int pseudohdr)
-{
-	__be32 diff[] = { ~from, to };
-
-	if (get_ip_summed(skb) != OVS_CSUM_PARTIAL) {
-		*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
-				~csum_unfold(*sum)));
-		if (get_ip_summed(skb) == OVS_CSUM_COMPLETE && pseudohdr)
-			skb->csum = ~csum_partial((char *)diff, sizeof(diff),
-						~skb->csum);
-	} else if (pseudohdr)
-		*sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
-				csum_unfold(*sum)));
-}
-#endif
-
-#if defined(NEED_CSUM_NORMALIZE) || LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
-#define inet_proto_csum_replace16 rpl_inet_proto_csum_replace16
-static inline void inet_proto_csum_replace16(__sum16 *sum,
-					     struct sk_buff *skb,
-					     const __be32 *from,
-					     const __be32 *to,
-					     int pseudohdr)
-{
-	__be32 diff[] = {
-		~from[0], ~from[1], ~from[2], ~from[3],
-		to[0], to[1], to[2], to[3],
-	};
-	if (get_ip_summed(skb) != OVS_CSUM_PARTIAL) {
-		*sum = csum_fold(csum_partial(diff, sizeof(diff),
-				 ~csum_unfold(*sum)));
-		if (get_ip_summed(skb) == OVS_CSUM_COMPLETE && pseudohdr)
-			skb->csum = ~csum_partial(diff, sizeof(diff),
-						  ~skb->csum);
-	} else if (pseudohdr)
-		*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
-				  csum_unfold(*sum)));
-}
-#endif
-
-#ifdef NEED_CSUM_NORMALIZE
-static inline void update_csum_start(struct sk_buff *skb, int delta)
-{
-	if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
-		u16 csum_start, csum_offset;
-
-		get_skb_csum_pointers(skb, &csum_start, &csum_offset);
-		set_skb_csum_pointers(skb, csum_start + delta, csum_offset);
-	}
-}
-
-static inline int rpl_pskb_expand_head(struct sk_buff *skb, int nhead,
-				       int ntail, gfp_t gfp_mask)
-{
-	int err;
-	int old_headroom = skb_headroom(skb);
-
-	err = pskb_expand_head(skb, nhead, ntail, gfp_mask);
-	if (unlikely(err))
-		return err;
-
-	update_csum_start(skb, skb_headroom(skb) - old_headroom);
-
-	return 0;
-}
-#define pskb_expand_head rpl_pskb_expand_head
-
-static inline unsigned char *rpl__pskb_pull_tail(struct sk_buff *skb,
-						  int delta)
-{
-	unsigned char *ret;
-	int old_headroom = skb_headroom(skb);
-
-	ret = __pskb_pull_tail(skb, delta);
-	if (unlikely(!ret))
-		return ret;
-
-	update_csum_start(skb, skb_headroom(skb) - old_headroom);
-
-	return ret;
-}
-#define __pskb_pull_tail rpl__pskb_pull_tail
-#endif
-
-#endif /* checksum.h */
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 1f7560a..9ed213e 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -54,7 +54,6 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
-#include "checksum.h"
 #include "datapath.h"
 #include "flow.h"
 #include "vlan.h"
@@ -295,8 +294,6 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
 		goto err;
 	}
 
-	forward_ip_summed(skb, true);
-
 	if (!skb_is_gso(skb))
 		err = queue_userspace_packet(ovs_dp_get_net(dp), dp_ifindex, skb, upcall_info);
 	else
diff --git a/datapath/datapath.h b/datapath/datapath.h
index 064211d..e3cd2f7 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <linux/u64_stats_sync.h>
 
-#include "checksum.h"
 #include "compat.h"
 #include "flow.h"
 #include "vlan.h"
@@ -94,11 +93,6 @@ struct datapath {
  * @pkt_key: The flow information extracted from the packet.  Must be nonnull.
  * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
  * packet is not being tunneled.
- * @ip_summed: Consistently stores L4 checksumming status across different
- * kernel versions.
- * @csum_start: Stores the offset from which to start checksumming independent
- * of the transport header on all kernel versions.
- * packet was not received on a tunnel.
  * @vlan_tci: Provides a substitute for the skb->vlan_tci field on kernels
  * before 2.6.27.
  */
@@ -106,10 +100,6 @@ struct ovs_skb_cb {
 	struct sw_flow		*flow;
 	struct sw_flow_key	*pkt_key;
 	struct ovs_key_ipv4_tunnel  *tun_key;
-#ifdef NEED_CSUM_NORMALIZE
-	enum csum_type		ip_summed;
-	u16			csum_start;
-#endif
 #ifdef NEED_VLAN_FIELD
 	u16			vlan_tci;
 #endif
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index 15c518a..085e8fd 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
@@ -16,7 +16,8 @@ openvswitch_sources += \
 	linux/compat/skbuff-openvswitch.c \
 	linux/compat/time.c	\
 	linux/compat/vxlan.c	\
-	linux/compat/workqueue.c
+	linux/compat/workqueue.c \
+	linux/compat/utils.c
 openvswitch_headers += \
 	linux/compat/gso.h \
 	linux/compat/include/asm/percpu.h \
diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h
index 2ceff22..bd7a4b0 100644
--- a/datapath/linux/compat/include/linux/netdevice.h
+++ b/datapath/linux/compat/include/linux/netdevice.h
@@ -82,13 +82,6 @@ extern void unregister_netdevice_many(struct list_head *head);
 extern void dev_disable_lro(struct net_device *dev);
 #endif
 
-#define skb_checksum_help rpl_skb_checksum_help
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-extern int skb_checksum_help(struct sk_buff *skb, int);
-#else
-extern int skb_checksum_help(struct sk_buff *skb);
-#endif
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) || \
     defined HAVE_RHEL_OVS_HOOK
 static inline int netdev_rx_handler_register(struct net_device *dev,
diff --git a/datapath/linux/compat/include/net/checksum.h b/datapath/linux/compat/include/net/checksum.h
index 502d02d..2bead4b 100644
--- a/datapath/linux/compat/include/net/checksum.h
+++ b/datapath/linux/compat/include/net/checksum.h
@@ -32,14 +32,14 @@ static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to)
 }
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
-#define inet_proto_csum_replace2(sum, skb, from, to, pseudohdr) \
-	inet_proto_csum_replace4(sum, skb, (__force __be32)(from), \
-					   (__force __be32)(to), pseudohdr)
-#endif
-
 #ifndef CSUM_MANGLED_0
 #define CSUM_MANGLED_0 ((__force __sum16)0xffff)
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+#define inet_proto_csum_replace16 rpl_inet_proto_csum_replace16
+void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
+			       const __be32 *from, const __be32 *to,
+			       int pseudohdr);
+#endif
 #endif /* checksum.h */
diff --git a/datapath/linux/compat/include/net/sctp/checksum.h b/datapath/linux/compat/include/net/sctp/checksum.h
index 11fb0b6..59d209b 100644
--- a/datapath/linux/compat/include/net/sctp/checksum.h
+++ b/datapath/linux/compat/include/net/sctp/checksum.h
@@ -2,12 +2,7 @@
 #define __SCTP_CHECKSUM_WRAPPER_H 1
 
 #include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
-#include <net/sctp/sctp.h>
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) */
 #include_next <net/sctp/checksum.h>
-#endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
 static inline __le32 sctp_compute_cksum(const struct sk_buff *skb,
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index 01cc2fb..f9f6cae 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -31,7 +31,6 @@
 #include <net/route.h>
 #include <net/xfrm.h>
 
-#include "checksum.h"
 #include "compat.h"
 #include "gso.h"
 
@@ -100,9 +99,6 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
 		skb->protocol = inner_proto;
 	}
 
-	if (unlikely(compute_ip_summed(skb, false)))
-		return -EPROTO;
-
 	nf_reset(skb);
 	secpath_reset(skb);
 	skb_clear_rxhash(skb);
diff --git a/datapath/linux/compat/skbuff-openvswitch.c b/datapath/linux/compat/skbuff-openvswitch.c
index 2707ef0..3baa09e 100644
--- a/datapath/linux/compat/skbuff-openvswitch.c
+++ b/datapath/linux/compat/skbuff-openvswitch.c
@@ -14,25 +14,3 @@ void __skb_warn_lro_forwarding(const struct sk_buff *skb)
 }
 
 #endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-int skb_checksum_help(struct sk_buff *skb, int inward)
-#else
-int skb_checksum_help(struct sk_buff *skb)
-#endif
-{
-	if (unlikely(skb_is_nonlinear(skb))) {
-		int err;
-
-		err = __skb_linearize(skb);
-		if (unlikely(err))
-			return err;
-	}
-
-#undef skb_checksum_help
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-	return skb_checksum_help(skb, 0);
-#else
-	return skb_checksum_help(skb);
-#endif
-}
diff --git a/datapath/linux/compat/utils.c b/datapath/linux/compat/utils.c
new file mode 100644
index 0000000..844d372
--- /dev/null
+++ b/datapath/linux/compat/utils.c
@@ -0,0 +1,39 @@
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+#include <net/checksum.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
+#include <linux/ratelimit.h>
+
+#include <net/sock.h>
+
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
+			       const __be32 *from, const __be32 *to,
+			       int pseudohdr)
+{
+	__be32 diff[] = {
+		~from[0], ~from[1], ~from[2], ~from[3],
+		to[0], to[1], to[2], to[3],
+	};
+	if (skb->ip_summed != CHECKSUM_PARTIAL) {
+		*sum = csum_fold(csum_partial(diff, sizeof(diff),
+					~csum_unfold(*sum)));
+		if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
+			skb->csum = ~csum_partial(diff, sizeof(diff),
+					~skb->csum);
+	} else if (pseudohdr)
+		*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
+					csum_unfold(*sum)));
+}
+#endif
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 9d8991d..780344e 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -51,7 +51,6 @@
 #include <net/netns/generic.h>
 #include <net/vxlan.h>
 
-#include "checksum.h"
 #include "compat.h"
 #include "gso.h"
 #include "vlan.h"
diff --git a/datapath/vlan.h b/datapath/vlan.h
index aee5551..1356aed 100644
--- a/datapath/vlan.h
+++ b/datapath/vlan.h
@@ -93,11 +93,6 @@ static inline int vlan_deaccel_tag(struct sk_buff *skb)
 	if (unlikely(!skb))
 		return -ENOMEM;
 
-	if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
-		skb->csum = csum_add(skb->csum,
-				     csum_partial(skb->data + (2 * ETH_ALEN),
-						  VLAN_HLEN, 0));
-
 	vlan_set_tci(skb, 0);
 	return 0;
 }
diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
index b9fff8a..7c65109 100644
--- a/datapath/vport-gre.c
+++ b/datapath/vport-gre.c
@@ -129,8 +129,6 @@ static int __send(struct vport *vport, struct sk_buff *skb,
 	__be32 saddr;
 	int err;
 
-	forward_ip_summed(skb, true);
-
 	/* Route lookup */
 	saddr = OVS_CB(skb)->tun_key->ipv4_src;
 	rt = find_route(ovs_dp_get_net(vport->dp),
diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c
index 904c0b3..f05f723 100644
--- a/datapath/vport-internal_dev.c
+++ b/datapath/vport-internal_dev.c
@@ -29,7 +29,6 @@
 #include <net/dst.h>
 #include <net/xfrm.h>
 
-#include "checksum.h"
 #include "datapath.h"
 #include "vlan.h"
 #include "vport-internal_dev.h"
@@ -80,11 +79,6 @@ static struct net_device_stats *internal_dev_sys_stats(struct net_device *netdev
 /* Called with rcu_read_lock_bh. */
 static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
-	if (unlikely(compute_ip_summed(skb, true))) {
-		kfree_skb(skb);
-		return 0;
-	}
-
 	vlan_copy_skb_tci(skb);
 
 	rcu_read_lock();
@@ -274,7 +268,6 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
 	skb->pkt_type = PACKET_HOST;
 	skb->protocol = eth_type_trans(skb, netdev);
 	skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
-	forward_ip_summed(skb, false);
 
 	netif_rx(skb);
 
diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
index 818a471..6eb101a 100644
--- a/datapath/vport-lisp.c
+++ b/datapath/vport-lisp.c
@@ -238,11 +238,6 @@ static void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb,
 	secpath_reset(skb);
 	vlan_set_tci(skb, 0);
 
-	if (unlikely(compute_ip_summed(skb, false))) {
-		kfree_skb(skb);
-		return;
-	}
-
 	ovs_vport_receive(vport, skb, tun_key);
 }
 
@@ -441,9 +436,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb)
 {
 	int err;
 
-	forward_ip_summed(skb, true);
-
-
 	if (skb_is_gso(skb)) {
 		struct sk_buff *nskb;
 		char cb[sizeof(skb->cb)];
@@ -462,7 +454,7 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb)
 			memcpy(nskb->cb, cb, sizeof(cb));
 			nskb = nskb->next;
 		}
-	} else if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		/* Pages aren't locked and could change at any time.
 		 * If this happens after we compute the checksum, the
 		 * checksum will be wrong.  We linearize now to avoid
@@ -479,8 +471,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb)
 			goto error;
 	}
 
-	set_ip_summed(skb, OVS_CSUM_NONE);
-
 	return skb;
 
 error:
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 1c2d7c5..c033816 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -29,7 +29,6 @@
 
 #include <net/llc.h>
 
-#include "checksum.h"
 #include "datapath.h"
 #include "vlan.h"
 #include "vport-internal_dev.h"
@@ -240,9 +239,6 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 	if (unlikely(!skb))
 		return;
 
-	if (unlikely(compute_ip_summed(skb, false)))
-		goto error;
-
 	skb_push(skb, ETH_HLEN);
 	ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
 
@@ -292,7 +288,6 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
 	}
 
 	skb->dev = netdev_vport->dev;
-	forward_ip_summed(skb, true);
 
 	if (vlan_tx_tag_present(skb) && !dev_supports_vlan_tx(skb->dev)) {
 		int features;
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
index 007e4ac..de49ab1 100644
--- a/datapath/vport-vxlan.c
+++ b/datapath/vport-vxlan.c
@@ -156,8 +156,6 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
 		goto error;
 	}
 
-	forward_ip_summed(skb, true);
-
 	/* Route lookup */
 	saddr = OVS_CB(skb)->tun_key->ipv4_src;
 	rt = find_route(ovs_dp_get_net(vport->dp),
-- 
1.7.1




More information about the dev mailing list