rpms/kernel-xen-2.6/devel linux-2.6-forwarding_of_ip_summed.patch, NONE, 1.1.2.1 linux-2.6-kill_skbuff_hack.patch, NONE, 1.1.2.1 linux-2.6-treat_partial_as_unnecessary.patch, NONE, 1.1.2.1 linux-2.6-use_csum_start_offset_instead.patch, NONE, 1.1.2.1 kernel-xen.spec, 1.18.4.2, 1.18.4.3

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Fri Apr 27 18:38:26 UTC 2007


Author: ehabkost

Update of /cvs/dist/rpms/kernel-xen-2.6/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv4727

Modified Files:
      Tag: private-ehabkost-xen-3_0_5-branch
	kernel-xen.spec 
Added Files:
      Tag: private-ehabkost-xen-3_0_5-branch
	linux-2.6-forwarding_of_ip_summed.patch 
	linux-2.6-kill_skbuff_hack.patch 
	linux-2.6-treat_partial_as_unnecessary.patch 
	linux-2.6-use_csum_start_offset_instead.patch 
Log Message:
Adding Herbert Xu checksum patches (bug #223258)



linux-2.6-forwarding_of_ip_summed.patch:
 include/linux/skbuff.h  |    7 +++++++
 net/bridge/br_forward.c |    2 +-
 net/ipv4/ip_forward.c   |    2 +-
 net/ipv6/ip6_output.c   |    2 +-
 4 files changed, 10 insertions(+), 3 deletions(-)

--- NEW FILE linux-2.6-forwarding_of_ip_summed.patch ---
From: Herbert Xu <herbert.xu at redhat.com>
Subject: [1/4] [NET]: Allow forwarding of ip_summed except CHECKSUM_COMPLETE

Hi:

[NET]: Allow forwarding of ip_summed except CHECKSUM_COMPLETE

Right now Xen has a horrible hack that lets it forward packets with
partial checksums.  One of the reasons that CHECKSUM_PARTIAL and
CHECKSUM_COMPLETE were added is so that we can get rid of this hack
(where it creates two extra bits in the skbuff to essentially mirror
ip_summed without being destroyed by the forwarding code).

I had forgotten that I've already gone through all the deivce drivers
last time around to make sure that they're looking at ip_summed ==
CHECKSUM_PARTIAL rather than ip_summed != 0 on transmit.  In any case,
I've now done that again so it should definitely be safe.

Unfortunately nobody has yet added any code to update CHECKSUM_COMPLETE
values on forward so we I'm setting that to CHECKSUM_NONE.  This should
be safe to remove for bridging but I'd like to check that code path
first.

So here is the patch that lets us get rid of the hack by preserving
ip_summed (mostly) on forwarded packets.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -ur linux-2.6.20.i386.orig/include/linux/skbuff.h linux-2.6.20.i386/include/linux/skbuff.h
--- linux-2.6.20.i386.orig/include/linux/skbuff.h	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/include/linux/skbuff.h	2007-04-24 13:31:01.000000000 +1000
@@ -1494,5 +1494,12 @@
 	return skb_shinfo(skb)->gso_size;
 }
 
+static inline void skb_forward_csum(struct sk_buff *skb)
+{
+	/* Unfortunately we don't support this one.  Any brave souls? */
+	if (skb->ip_summed == CHECKSUM_COMPLETE)
+		skb->ip_summed = CHECKSUM_NONE;
+}
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff -ur linux-2.6.20.i386.orig/net/bridge/br_forward.c linux-2.6.20.i386/net/bridge/br_forward.c
--- linux-2.6.20.i386.orig/net/bridge/br_forward.c	2007-03-30 13:39:09.000000000 +1000
+++ linux-2.6.20.i386/net/bridge/br_forward.c	2007-04-24 13:31:01.000000000 +1000
@@ -71,7 +71,7 @@
 
 	indev = skb->dev;
 	skb->dev = to->dev;
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_forward_csum(skb);
 
 	NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
 			br_forward_finish);
diff -ur linux-2.6.20.i386.orig/net/ipv4/ip_forward.c linux-2.6.20.i386/net/ipv4/ip_forward.c
--- linux-2.6.20.i386.orig/net/ipv4/ip_forward.c	2007-03-30 13:39:10.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/ip_forward.c	2007-04-24 13:31:20.000000000 +1000
@@ -68,7 +68,7 @@
 	if (skb->pkt_type != PACKET_HOST)
 		goto drop;
 
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_forward_csum(skb);
 	
 	/*
 	 *	According to the RFC, we must first decrease the TTL field. If
diff -ur linux-2.6.20.i386.orig/net/ipv6/ip6_output.c linux-2.6.20.i386/net/ipv6/ip6_output.c
--- linux-2.6.20.i386.orig/net/ipv6/ip6_output.c	2007-03-30 13:39:11.000000000 +1000
+++ linux-2.6.20.i386/net/ipv6/ip6_output.c	2007-04-24 13:31:01.000000000 +1000
@@ -372,7 +372,7 @@
 		goto drop;
 	}
 
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_forward_csum(skb);
 
 	/*
 	 *	We DO NOT make any processing on



linux-2.6-kill_skbuff_hack.patch:
 drivers/xen/core/skbuff.c             |   35 ++++++++++++++++++
 drivers/xen/netback/loopback.c        |   10 -----
 drivers/xen/netback/netback.c         |   29 +++++++--------
 drivers/xen/netfront/netfront.c       |   37 ++++++++++---------
 include/linux/skbuff.h                |   10 +----
 net/core/dev.c                        |   63 ----------------------------------
 net/core/skbuff.c                     |    4 --
 net/ipv4/netfilter/ip_nat_proto_tcp.c |    7 ---
 net/ipv4/netfilter/ip_nat_proto_udp.c |    8 ----
 net/ipv4/xfrm4_output.c               |    6 ---
 10 files changed, 70 insertions(+), 139 deletions(-)

--- NEW FILE linux-2.6-kill_skbuff_hack.patch ---
From: Herbert Xu <herbert.xu at redhat.com>
Subject: [4/4] [XEN]: Kill skbuff hack

Hi:

This patch is based on the FC6 kernel.

[XEN]: Kill skbuff hack

Now that the Linux stack can accept packets with partial checksums and
relay them back out again, we can eliminate the skbuff hacks.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -ur linux-2.6.20.i386.orig/drivers/xen/core/skbuff.c linux-2.6.20.i386/drivers/xen/core/skbuff.c
--- linux-2.6.20.i386.orig/drivers/xen/core/skbuff.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/drivers/xen/core/skbuff.c	2007-04-24 15:50:03.000000000 +1000
@@ -9,6 +9,10 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/if_ether.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <net/ip.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/hypervisor.h>
@@ -78,6 +82,37 @@
 	return skb;
 }
 
+int skb_checksum_setup(struct sk_buff *skb)
+{
+	if (skb->protocol != htons(ETH_P_IP))
+		goto out;
+	skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
+	if (skb->h.raw >= skb->tail)
+		goto out;
+	switch (skb->nh.iph->protocol) {
+	case IPPROTO_TCP:
+		skb->csum_offset = offsetof(struct tcphdr, check);
+		break;
+	case IPPROTO_UDP:
+		skb->csum_offset = offsetof(struct udphdr, check);
+		break;
+	default:
+		if (net_ratelimit())
+			printk(KERN_ERR "Attempting to checksum a non-"
+			       "TCP/UDP packet, dropping a protocol"
+			       " %d packet", skb->nh.iph->protocol);
+		goto out;
+	}
+	if ((skb->h.raw + skb->csum_offset + 2) > skb->tail)
+		goto out;
+	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	return 0;
+out:
+	return -EPROTO;
+}
+EXPORT_SYMBOL(skb_checksum_setup);
+
 static void skbuff_ctor(void *buf, struct kmem_cache *cachep, unsigned long unused)
 {
 	int order = 0;
diff -ur linux-2.6.20.i386.orig/drivers/xen/netback/loopback.c linux-2.6.20.i386/drivers/xen/netback/loopback.c
--- linux-2.6.20.i386.orig/drivers/xen/netback/loopback.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/drivers/xen/netback/loopback.c	2007-04-24 15:50:03.000000000 +1000
@@ -149,16 +149,6 @@
 	np->stats.rx_bytes += skb->len;
 	np->stats.rx_packets++;
 
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		/* Defer checksum calculation. */
-		skb->proto_csum_blank = 1;
-		/* Must be a local packet: assert its integrity. */
-		skb->proto_data_valid = 1;
-	}
-
-	skb->ip_summed = skb->proto_data_valid ?
-		CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
-
 	skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
 	skb->protocol = eth_type_trans(skb, dev);
 	skb->dev      = dev;
diff -ur linux-2.6.20.i386.orig/drivers/xen/netback/netback.c linux-2.6.20.i386/drivers/xen/netback/netback.c
--- linux-2.6.20.i386.orig/drivers/xen/netback/netback.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/drivers/xen/netback/netback.c	2007-04-24 15:50:03.000000000 +1000
@@ -293,7 +293,6 @@
 		/* Copy only the header fields we use in this driver. */
 		nskb->dev = skb->dev;
 		nskb->ip_summed = skb->ip_summed;
-		nskb->proto_data_valid = skb->proto_data_valid;
 		dev_kfree_skb(skb);
 		skb = nskb;
 	}
@@ -677,9 +676,11 @@
 		id = meta[npo.meta_cons].id;
 		flags = nr_frags ? NETRXF_more_data : 0;
 
-		if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			/* local packet? */
 			flags |= NETRXF_csum_blank | NETRXF_data_validated;
-		else if (skb->proto_data_valid) /* remote but checksummed? */
+		else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+			/* remote but checksummed? */
 			flags |= NETRXF_data_validated;
 
 		if (meta[npo.meta_cons].copy)
@@ -1318,23 +1319,19 @@
 			netif_idx_release(pending_idx);
 		}
 
-		/*
-		 * Old frontends do not assert data_validated but we
-		 * can infer it from csum_blank so test both flags.
-		 */
-		if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank)) {
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-			skb->proto_data_valid = 1;
-		} else {
-			skb->ip_summed = CHECKSUM_NONE;
-			skb->proto_data_valid = 0;
-		}
-		skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank);
-
 		netbk_fill_frags(skb);
 
 		skb->dev      = netif->dev;
 		skb->protocol = eth_type_trans(skb, skb->dev);
+		skb->nh.raw   = skb->data;
+
+		if (txp->flags & NETTXF_csum_blank) {
+			if (skb_checksum_setup(skb)) {
+				kfree_skb(skb);
+				continue;
+			}
+		} else if (txp->flags & NETTXF_data_validated)
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		netif->stats.rx_bytes += skb->len;
 		netif->stats.rx_packets++;
diff -ur linux-2.6.20.i386.orig/drivers/xen/netfront/netfront.c linux-2.6.20.i386/drivers/xen/netfront/netfront.c
--- linux-2.6.20.i386.orig/drivers/xen/netfront/netfront.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/drivers/xen/netfront/netfront.c	2007-04-24 15:50:03.000000000 +1000
@@ -962,12 +962,12 @@
 	tx->flags = 0;
 	extra = NULL;
 
-	if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
+		/* local packet? */
 		tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
-#ifdef CONFIG_XEN
-	if (skb->proto_data_valid) /* remote but checksummed? */
+	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		/* remote but checksummed? */
 		tx->flags |= NETTXF_data_validated;
-#endif
 
 #ifdef HAVE_TSO
 	if (skb_is_gso(skb)) {
@@ -1388,20 +1388,10 @@
 		skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
 		skb->len += skb->data_len;
 
-		/*
-		 * Old backends do not assert data_validated but we
-		 * can infer it from csum_blank so test both flags.
-		 */
-		if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank))
+		if (rx->flags & NETRXF_csum_blank)
+			skb->ip_summed = CHECKSUM_PARTIAL;
+		else if (rx->flags & NETRXF_data_validated)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb->ip_summed = CHECKSUM_NONE;
-#ifdef CONFIG_XEN
-		skb->proto_data_valid = (skb->ip_summed != CHECKSUM_NONE);
-		skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank);
-#endif
-		np->stats.rx_packets++;
-		np->stats.rx_bytes += skb->len;
 
 		__skb_queue_tail(&rxq, skb);
 
@@ -1441,6 +1431,19 @@
 
 		/* Ethernet work: Delayed to here as it peeks the header. */
 		skb->protocol = eth_type_trans(skb, dev);
+		skb->nh.raw = skb->data;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			if (skb_checksum_setup(skb)) {
+				work_done--;
+				kfree_skb(skb);
+				np->stats.rx_errors++;
+				continue;
+			}
+		}
+
+		np->stats.rx_packets++;
+		np->stats.rx_bytes += skb->len;
 
 		/* Pass it up. */
 		netif_receive_skb(skb);
diff -ur linux-2.6.20.i386.orig/include/linux/skbuff.h linux-2.6.20.i386/include/linux/skbuff.h
--- linux-2.6.20.i386.orig/include/linux/skbuff.h	2007-04-24 15:16:44.000000000 +1000
+++ linux-2.6.20.i386/include/linux/skbuff.h	2007-04-24 15:50:03.000000000 +1000
@@ -205,8 +205,6 @@
  *	@local_df: allow local fragmentation
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
- *	@proto_data_valid: Protocol data validated since arriving at localhost
- *	@proto_csum_blank: Protocol csum must be added before leaving localhost
  *	@pkt_type: Packet class
  *	@fclone: skbuff clone status
  *	@ip_summed: Driver fed us an IP checksum
@@ -292,13 +290,7 @@
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-#ifndef CONFIG_XEN
 				ipvs_property:1;
-#else
-				ipvs_property:1,
-				proto_data_valid:1,
-				proto_csum_blank:1;
-#endif
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
@@ -1351,6 +1343,8 @@
 
 extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
 
+extern int skb_checksum_setup(struct sk_buff *skb);
+
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 				       int len, void *buffer)
 {
diff -ur linux-2.6.20.i386.orig/net/core/dev.c linux-2.6.20.i386/net/core/dev.c
--- linux-2.6.20.i386.orig/net/core/dev.c	2007-04-24 15:14:04.000000000 +1000
+++ linux-2.6.20.i386/net/core/dev.c	2007-04-24 15:50:03.000000000 +1000
@@ -117,12 +117,6 @@
 #include <linux/err.h>
 #include <linux/ctype.h>
 
-#ifdef CONFIG_XEN
-#include <net/ip.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#endif
-
 /*
  *	The list of packet types we will receive (as opposed to discard)
  *	and the routines to invoke.
@@ -1400,43 +1394,6 @@
 	}						\
 }
 
-#ifdef CONFIG_XEN
-inline int skb_checksum_setup(struct sk_buff *skb)
-{
-	if (skb->proto_csum_blank) {
-		if (skb->protocol != htons(ETH_P_IP))
-			goto out;
-		skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
-		if (skb->h.raw >= skb->tail)
-			goto out;
-		switch (skb->nh.iph->protocol) {
-		case IPPROTO_TCP:
-			skb->csum = offsetof(struct tcphdr, check);
-			break;
-		case IPPROTO_UDP:
-			skb->csum = offsetof(struct udphdr, check);
-			break;
-		default:
-			if (net_ratelimit())
-				printk(KERN_ERR "Attempting to checksum a non-"
-				       "TCP/UDP packet, dropping a protocol"
-				       " %d packet", skb->nh.iph->protocol);
-			goto out;
-		}
-		if ((skb->h.raw + skb->csum + 2) > skb->tail)
-			goto out;
-		skb->ip_summed = CHECKSUM_PARTIAL;
-		skb->proto_csum_blank = 0;
-	}
-	return 0;
-out:
-	return -EPROTO;
-}
-#else
-inline int skb_checksum_setup(struct sk_buff *skb) { return 0; }
-#endif
-
-
 /**
  *	dev_queue_xmit - transmit a buffer
  *	@skb: buffer to transmit
@@ -1469,12 +1426,6 @@
 	struct Qdisc *q;
 	int rc = -ENOMEM;
 
- 	/* If a checksum-deferred packet is forwarded to a device that needs a
- 	 * checksum, correct the pointers and force checksumming.
- 	 */
- 	if (skb_checksum_setup(skb))
- 		goto out_kfree_skb;
-
 	/* GSO will handle the following emulations directly. */
 	if (netif_needs_gso(dev, skb))
 		goto gso;
@@ -1853,19 +1804,6 @@
 	}
 #endif
 
-#ifdef CONFIG_XEN
-	switch (skb->ip_summed) {
-	case CHECKSUM_UNNECESSARY:
-		skb->proto_data_valid = 1;
-		break;
-	case CHECKSUM_PARTIAL:
-		/* XXX Implement me. */
-	default:
-		skb->proto_data_valid = 0;
-		break;
-	}
-#endif
-
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (!ptype->dev || ptype->dev == skb->dev) {
 			if (pt_prev) 
@@ -3630,7 +3568,6 @@
 EXPORT_SYMBOL(net_enable_timestamp);
 EXPORT_SYMBOL(net_disable_timestamp);
 EXPORT_SYMBOL(dev_get_flags);
-EXPORT_SYMBOL(skb_checksum_setup);
 
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 EXPORT_SYMBOL(br_handle_frame_hook);
diff -ur linux-2.6.20.i386.orig/net/core/skbuff.c linux-2.6.20.i386/net/core/skbuff.c
--- linux-2.6.20.i386.orig/net/core/skbuff.c	2007-04-24 15:08:07.000000000 +1000
+++ linux-2.6.20.i386/net/core/skbuff.c	2007-04-24 15:50:03.000000000 +1000
@@ -483,10 +483,6 @@
 	C(local_df);
 	n->cloned = 1;
 	n->nohdr = 0;
-#ifdef CONFIG_XEN
-	C(proto_data_valid);
-	C(proto_csum_blank);
-#endif
 	C(pkt_type);
 	C(ip_summed);
 	C(priority);
diff -ur linux-2.6.20.i386.orig/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.6.20.i386/net/ipv4/netfilter/ip_nat_proto_tcp.c
--- linux-2.6.20.i386.orig/net/ipv4/netfilter/ip_nat_proto_tcp.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/netfilter/ip_nat_proto_tcp.c	2007-04-24 15:50:03.000000000 +1000
@@ -129,15 +129,8 @@
 	if (hdrsize < sizeof(*hdr))
 		return 1;
 
-#ifdef CONFIG_XEN
-	if ((*pskb)->proto_csum_blank)
-		nf_csum_replace4(&hdr->check, oldip, newip);
-	else
-#endif
-	{
 	nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
 	nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
-	}
 	return 1;
 }
 
diff -ur linux-2.6.20.i386.orig/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.6.20.i386/net/ipv4/netfilter/ip_nat_proto_udp.c
--- linux-2.6.20.i386.orig/net/ipv4/netfilter/ip_nat_proto_udp.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/netfilter/ip_nat_proto_udp.c	2007-04-24 15:50:03.000000000 +1000
@@ -115,16 +115,8 @@
 	}
 
 	if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
-#ifdef CONFIG_XEN
-		if ((*pskb)->proto_csum_blank)
-			nf_csum_replace4(&hdr->check, oldip, newip);
-		else
-#endif
-		{
 		nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
 		nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0);
-		}
-
 		if (!hdr->check)
 			hdr->check = CSUM_MANGLED_0;
 	}
diff -ur linux-2.6.20.i386.orig/net/ipv4/xfrm4_output.c linux-2.6.20.i386/net/ipv4/xfrm4_output.c
--- linux-2.6.20.i386.orig/net/ipv4/xfrm4_output.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/xfrm4_output.c	2007-04-24 15:50:03.000000000 +1000
@@ -18,8 +18,6 @@
 #include <net/xfrm.h>
 #include <net/icmp.h>
 
-extern int skb_checksum_setup(struct sk_buff *skb);
-
 static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 {
 	int mtu, ret = 0;
@@ -49,10 +47,6 @@
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	int err;
-	
-	err = skb_checksum_setup(skb);
-	if (err)
-		goto error_nolock;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		err = skb_checksum_help(skb);



linux-2.6-treat_partial_as_unnecessary.patch:
 include/linux/skbuff.h     |   16 +++++++++++-----
 include/net/tcp.h          |    2 +-
 include/net/udp.h          |    2 +-
 net/core/netpoll.c         |    2 +-
 net/ipv4/ipvs/ip_vs_core.c |    6 ++----
 net/ipv4/tcp_input.c       |    6 +++---
 net/ipv4/tcp_ipv4.c        |    3 +--
 net/ipv4/udp.c             |    6 +++---
 net/ipv6/raw.c             |    4 ++--
 net/ipv6/tcp_ipv6.c        |    3 +--
 net/ipv6/udp.c             |    4 ++--
 net/sctp/input.c           |    3 +--
 net/sunrpc/socklib.c       |    2 +-
 13 files changed, 30 insertions(+), 29 deletions(-)

--- NEW FILE linux-2.6-treat_partial_as_unnecessary.patch ---
From: Herbert Xu <herbert.xu at redhat.com>
Subject: [3/4] [NET]: Treat CHECKSUM_PARTIAL as CHECKSUM_UNNECESSARY

Hi:

[NET]: Treat CHECKSUM_PARTIAL as CHECKSUM_UNNECESSARY

When a transmitted packet is looped back directly, CHECKSUM_PARTIAL
maps to the semantics of CHECKSUM_UNNECESSARY.  Therefore we should
treat it as such in the stack.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -ur linux-2.6.20.i386.orig/include/linux/skbuff.h linux-2.6.20.i386/include/linux/skbuff.h
--- linux-2.6.20.i386.orig/include/linux/skbuff.h	2007-04-24 13:42:01.000000000 +1000
+++ linux-2.6.20.i386/include/linux/skbuff.h	2007-04-24 15:16:44.000000000 +1000
@@ -31,10 +31,11 @@
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
 
+/* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
-#define CHECKSUM_PARTIAL 1
-#define CHECKSUM_UNNECESSARY 2
-#define CHECKSUM_COMPLETE 3
+#define CHECKSUM_UNNECESSARY 1
+#define CHECKSUM_COMPLETE 2
+#define CHECKSUM_PARTIAL 3
 
 #define SKB_DATA_ALIGN(X)	(((X) + (SMP_CACHE_BYTES - 1)) & \
 				 ~(SMP_CACHE_BYTES - 1))
@@ -1401,6 +1402,11 @@
 
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
+static inline int skb_csum_unnecessary(const struct sk_buff *skb)
+{
+	return skb->ip_summed & CHECKSUM_UNNECESSARY;
+}
+
 /**
  *	skb_checksum_complete - Calculate checksum of an entire packet
  *	@skb: packet to process
@@ -1419,8 +1425,8 @@
  */
 static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
 {
-	return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-		__skb_checksum_complete(skb);
+	return skb_csum_unnecessary(skb) ?
+	       0 : __skb_checksum_complete(skb);
 }
 
 #ifdef CONFIG_NETFILTER
diff -ur linux-2.6.20.i386.orig/include/net/tcp.h linux-2.6.20.i386/include/net/tcp.h
--- linux-2.6.20.i386.orig/include/net/tcp.h	2007-03-30 13:39:07.000000000 +1000
+++ linux-2.6.20.i386/include/net/tcp.h	2007-04-24 15:16:44.000000000 +1000
@@ -816,7 +816,7 @@
 
 static inline int tcp_checksum_complete(struct sk_buff *skb)
 {
-	return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+	return !skb_csum_unnecessary(skb) &&
 		__tcp_checksum_complete(skb);
 }
 
diff -ur linux-2.6.20.i386.orig/include/net/udp.h linux-2.6.20.i386/include/net/udp.h
--- linux-2.6.20.i386.orig/include/net/udp.h	2007-03-30 13:39:07.000000000 +1000
+++ linux-2.6.20.i386/include/net/udp.h	2007-04-24 15:16:44.000000000 +1000
@@ -80,7 +80,7 @@
 
 static inline int udp_lib_checksum_complete(struct sk_buff *skb)
 {
-	return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+	return !skb_csum_unnecessary(skb) &&
 		__udp_lib_checksum_complete(skb);
 }
 
diff -ur linux-2.6.20.i386.orig/net/core/netpoll.c linux-2.6.20.i386/net/core/netpoll.c
--- linux-2.6.20.i386.orig/net/core/netpoll.c	2007-03-30 13:39:09.000000000 +1000
+++ linux-2.6.20.i386/net/core/netpoll.c	2007-04-24 15:16:44.000000000 +1000
@@ -86,7 +86,7 @@
 {
 	__wsum psum;
 
-	if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY)
+	if (uh->check == 0 || skb_csum_unnecessary(skb))
 		return 0;
 
 	psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
diff -ur linux-2.6.20.i386.orig/net/ipv4/ipvs/ip_vs_core.c linux-2.6.20.i386/net/ipv4/ipvs/ip_vs_core.c
--- linux-2.6.20.i386.orig/net/ipv4/ipvs/ip_vs_core.c	2007-03-30 13:39:10.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/ipvs/ip_vs_core.c	2007-04-24 15:16:44.000000000 +1000
@@ -680,8 +680,7 @@
 	}
 
 	/* Ensure the checksum is correct */
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
-	    ip_vs_checksum_complete(skb, ihl)) {
+	if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
 		/* Failed checksum! */
 		IP_VS_DBG(1, "Forward ICMP: failed checksum from %d.%d.%d.%d!\n",
 			  NIPQUAD(iph->saddr));
@@ -921,8 +920,7 @@
 	verdict = NF_DROP;
 
 	/* Ensure the checksum is correct */
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
-	    ip_vs_checksum_complete(skb, ihl)) {
+	if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
 		/* Failed checksum! */
 		IP_VS_DBG(1, "Incoming ICMP: failed checksum from %d.%d.%d.%d!\n",
 			  NIPQUAD(iph->saddr));
diff -ur linux-2.6.20.i386.orig/net/ipv4/tcp_input.c linux-2.6.20.i386/net/ipv4/tcp_input.c
--- linux-2.6.20.i386.orig/net/ipv4/tcp_input.c	2007-03-30 13:39:10.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/tcp_input.c	2007-04-24 15:16:44.000000000 +1000
@@ -3775,7 +3775,7 @@
 	int err;
 
 	local_bh_enable();
-	if (skb->ip_summed==CHECKSUM_UNNECESSARY)
+	if (skb_csum_unnecessary(skb))
 		err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
 	else
 		err = skb_copy_and_csum_datagram_iovec(skb, hlen,
@@ -3807,7 +3807,7 @@
 
 static inline int tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
 {
-	return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+	return !skb_csum_unnecessary(skb) &&
 		__tcp_checksum_complete_user(sk, skb);
 }
 
@@ -3825,7 +3825,7 @@
 	if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
 		tp->ucopy.dma_chan = get_softnet_dma();
 
-	if (tp->ucopy.dma_chan && skb->ip_summed == CHECKSUM_UNNECESSARY) {
+	if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) {
 
 		dma_cookie = dma_skb_copy_datagram_iovec(tp->ucopy.dma_chan,
 			skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list);
diff -ur linux-2.6.20.i386.orig/net/ipv4/tcp_ipv4.c linux-2.6.20.i386/net/ipv4/tcp_ipv4.c
--- linux-2.6.20.i386.orig/net/ipv4/tcp_ipv4.c	2007-04-24 15:09:28.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/tcp_ipv4.c	2007-04-24 15:16:44.000000000 +1000
@@ -1636,8 +1636,7 @@
 	 * Packet length and doff are validated by header prediction,
 	 * provided case of th->doff==0 is eliminated.
 	 * So, we defer the checks. */
-	if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
-	     tcp_v4_checksum_init(skb)))
+	if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
 		goto bad_packet;
 
 	th = skb->h.th;
diff -ur linux-2.6.20.i386.orig/net/ipv4/udp.c linux-2.6.20.i386/net/ipv4/udp.c
--- linux-2.6.20.i386.orig/net/ipv4/udp.c	2007-04-24 15:10:23.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/udp.c	2007-04-24 15:18:08.000000000 +1000
@@ -839,7 +839,7 @@
 	 * 	          (re-)compute it if message is truncated.
 	 * 	UDP-Lite: always needs to checksum, no HW support.
 	 */
-	copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
+	copy_only = skb_csum_unnecessary(skb);
 
 	if (is_udplite  ||  (!copy_only  &&  msg->msg_flags&MSG_TRUNC)) {
 		if (__udp_lib_checksum_complete(skb))
@@ -1095,7 +1095,7 @@
 		}
 	}
 
-	if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
+	if (sk->sk_filter && !skb_csum_unnecessary(skb)) {
 		if (__udp_lib_checksum_complete(skb))
 			goto drop;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1175,7 +1175,7 @@
 				      skb->len, IPPROTO_UDP, skb->csum       ))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+	if (!skb_csum_unnecessary(skb))
 		skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
 					       skb->nh.iph->daddr,
 					       skb->len, IPPROTO_UDP, 0);
diff -ur linux-2.6.20.i386.orig/net/ipv6/raw.c linux-2.6.20.i386/net/ipv6/raw.c
--- linux-2.6.20.i386.orig/net/ipv6/raw.c	2007-03-30 13:39:11.000000000 +1000
+++ linux-2.6.20.i386/net/ipv6/raw.c	2007-04-24 15:18:35.000000000 +1000
@@ -369,7 +369,7 @@
 				     skb->len, inet->num, skb->csum))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+	if (!skb_csum_unnecessary(skb))
 		skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr,
 					     &skb->nh.ipv6h->daddr,
 					     skb->len, inet->num, 0));
@@ -421,7 +421,7 @@
   		msg->msg_flags |= MSG_TRUNC;
   	}
 
-	if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
+	if (skb_csum_unnecessary(skb)) {
 		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	} else if (msg->msg_flags&MSG_TRUNC) {
 		if (__skb_checksum_complete(skb))
diff -ur linux-2.6.20.i386.orig/net/ipv6/tcp_ipv6.c linux-2.6.20.i386/net/ipv6/tcp_ipv6.c
--- linux-2.6.20.i386.orig/net/ipv6/tcp_ipv6.c	2007-04-24 15:10:43.000000000 +1000
+++ linux-2.6.20.i386/net/ipv6/tcp_ipv6.c	2007-04-24 15:16:44.000000000 +1000
@@ -1705,8 +1705,7 @@
 	if (!pskb_may_pull(skb, th->doff*4))
 		goto discard_it;
 
-	if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
-	     tcp_v6_checksum_init(skb)))
+	if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb))
 		goto bad_packet;
 
 	th = skb->h.th;
diff -ur linux-2.6.20.i386.orig/net/ipv6/udp.c linux-2.6.20.i386/net/ipv6/udp.c
--- linux-2.6.20.i386.orig/net/ipv6/udp.c	2007-03-30 13:39:11.000000000 +1000
+++ linux-2.6.20.i386/net/ipv6/udp.c	2007-04-24 15:19:35.000000000 +1000
@@ -144,7 +144,7 @@
 	/*
 	 * 	Decide whether to checksum and/or copy data.
 	 */
-	copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
+	copy_only = skb_csum_unnecessary(skb);
 
 	if (is_udplite  ||  (!copy_only  &&  msg->msg_flags&MSG_TRUNC)) {
 		if (__udp_lib_checksum_complete(skb))
@@ -382,7 +382,7 @@
 		    	     skb->len, IPPROTO_UDP, skb->csum             ))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+	if (!skb_csum_unnecessary(skb))
 		skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr,
 							 &skb->nh.ipv6h->daddr,
 							 skb->len, IPPROTO_UDP,
diff -ur linux-2.6.20.i386.orig/net/sctp/input.c linux-2.6.20.i386/net/sctp/input.c
--- linux-2.6.20.i386.orig/net/sctp/input.c	2007-03-30 13:39:11.000000000 +1000
+++ linux-2.6.20.i386/net/sctp/input.c	2007-04-24 15:16:44.000000000 +1000
@@ -144,8 +144,7 @@
 	__skb_pull(skb, skb->h.raw - skb->data);
 	if (skb->len < sizeof(struct sctphdr))
 		goto discard_it;
-	if ((skb->ip_summed != CHECKSUM_UNNECESSARY) &&
-	    (sctp_rcv_checksum(skb) < 0))
+	if (!skb_csum_unnecessary(skb) && sctp_rcv_checksum(skb) < 0)
 		goto discard_it;
 
 	skb_pull(skb, sizeof(struct sctphdr));
diff -ur linux-2.6.20.i386.orig/net/sunrpc/socklib.c linux-2.6.20.i386/net/sunrpc/socklib.c
--- linux-2.6.20.i386.orig/net/sunrpc/socklib.c	2007-03-30 13:39:12.000000000 +1000
+++ linux-2.6.20.i386/net/sunrpc/socklib.c	2007-04-24 15:16:44.000000000 +1000
@@ -154,7 +154,7 @@
 	desc.offset = sizeof(struct udphdr);
 	desc.count = skb->len - desc.offset;
 
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+	if (skb_csum_unnecessary(skb))
 		goto no_checksum;
 
 	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);



linux-2.6-use_csum_start_offset_instead.patch:
 include/linux/skbuff.h |    9 +++++++--
 net/core/dev.c         |   23 ++++++++++++++---------
 net/core/skbuff.c      |    2 +-
 net/ipv4/tcp_ipv4.c    |    2 ++
 net/ipv4/udp.c         |    1 +
 net/ipv6/tcp_ipv6.c    |    2 ++
 6 files changed, 27 insertions(+), 12 deletions(-)

--- NEW FILE linux-2.6-use_csum_start_offset_instead.patch ---
From: Herbert Xu <herbert.xu at redhat.com>
Subject: [2/4] [NET]: Use csum_start offset instead of skb_transport_header

Hi:

Note this is based on the upstream net-2.6.22 tree so merging it
into anything before that will require undoing the transport header
changes.  Let me know if there are problems merging it.

[NET]: Use csum_start offset instead of skb_transport_header

The skb transport pointer is currently used to specify the start
of the checksum region for transmit checksum offload.  Unfortunately,
the same pointer is also used during receive side processing.

This creates a problem when we want to retransmit a received
packet with partial checksums since the skb transport pointer
would be overwritten.

This patch solves this problem by creating a new 16-bit csum_start
offset value to replace the skb transport header for the purpose
of checksums.  This offset is calculated from skb->head so that
it does not have to change when skb->data changes.

No extra space is required since csum_offset itself fits within
a 16-bit word so we can use the other 16 bits for csum_start.

For backwards compatibility, just before we push a packet with
partial checksums off into the device driver, we set the skb
transport header to what it would have been under the old scheme.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -ur linux-2.6.20.i386.orig/include/linux/skbuff.h linux-2.6.20.i386/include/linux/skbuff.h
--- linux-2.6.20.i386.orig/include/linux/skbuff.h	2007-04-24 13:31:01.000000000 +1000
+++ linux-2.6.20.i386/include/linux/skbuff.h	2007-04-24 13:42:01.000000000 +1000
@@ -198,7 +198,9 @@
  *	@len: Length of actual data
  *	@data_len: Data length
  *	@mac_len: Length of link layer header
- *	@csum: Checksum
+ *	@csum: Checksum (must include start/offset pair)
+ *	@csum_start: Offset from skb->head where checksumming should start
+ *	@csum_offset: Offset from csum_start where checksum should be stored
  *	@local_df: allow local fragmentation
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
@@ -276,7 +278,10 @@
 				mac_len;
 	union {
 		__wsum		csum;
-		__u32		csum_offset;
+		struct {
+			__u16	csum_start;
+			__u16	csum_offset;
+		};
 	};
 	__u32			priority;
 	__u8			local_df:1,
diff -ur linux-2.6.20.i386.orig/net/core/dev.c linux-2.6.20.i386/net/core/dev.c
--- linux-2.6.20.i386.orig/net/core/dev.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/net/core/dev.c	2007-04-24 15:14:04.000000000 +1000
@@ -1176,7 +1176,7 @@
 int skb_checksum_help(struct sk_buff *skb)
 {
 	__wsum csum;
-	int ret = 0, offset = skb->h.raw - skb->data;
+	int ret = 0, offset;
 
 	if (skb->ip_summed == CHECKSUM_COMPLETE)
 		goto out_set_summed;
@@ -1192,14 +1192,16 @@
 			goto out;
 	}
 
+	offset = skb->csum_start - skb_headroom(skb);
 	BUG_ON(offset > (int)skb->len);
 	csum = skb_checksum(skb, offset, skb->len-offset, 0);
 
-	offset = skb->tail - skb->h.raw;
+	offset = skb_headlen(skb) - offset;
 	BUG_ON(offset <= 0);
 	BUG_ON(skb->csum_offset + 2 > offset);
 
-	*(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum);
+	*(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) =
+		csum_fold(csum);
 
 out_set_summed:
 	skb->ip_summed = CHECKSUM_NONE;
@@ -1494,12 +1496,15 @@
 	/* If packet is not checksummed and device does not support
 	 * checksumming for this protocol, complete checksumming here.
 	 */
-	if (skb->ip_summed == CHECKSUM_PARTIAL &&
-	    (!(dev->features & NETIF_F_GEN_CSUM) &&
-	     (!(dev->features & NETIF_F_IP_CSUM) ||
-	      skb->protocol != htons(ETH_P_IP))))
-	      	if (skb_checksum_help(skb))
-	      		goto out_kfree_skb;
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		skb->h.raw = skb->head + skb->csum_start;
+
+		if (!(dev->features & NETIF_F_GEN_CSUM) &&
+		    (!(dev->features & NETIF_F_IP_CSUM) ||
+		     skb->protocol != htons(ETH_P_IP)))
+		      	if (skb_checksum_help(skb))
+		      		goto out_kfree_skb;
+	}
 
 gso:
 	spin_lock_prefetch(&dev->queue_lock);
diff -ur linux-2.6.20.i386.orig/net/core/skbuff.c linux-2.6.20.i386/net/core/skbuff.c
--- linux-2.6.20.i386.orig/net/core/skbuff.c	2007-04-24 13:18:41.000000000 +1000
+++ linux-2.6.20.i386/net/core/skbuff.c	2007-04-24 15:08:07.000000000 +1000
@@ -1422,7 +1422,7 @@
 	long csstart;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
-		csstart = skb->h.raw - skb->data;
+		csstart = skb->csum_start - skb_headroom(skb);
 	else
 		csstart = skb_headlen(skb);
 
diff -ur linux-2.6.20.i386.orig/net/ipv4/tcp_ipv4.c linux-2.6.20.i386/net/ipv4/tcp_ipv4.c
--- linux-2.6.20.i386.orig/net/ipv4/tcp_ipv4.c	2007-03-30 13:39:10.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/tcp_ipv4.c	2007-04-24 15:09:28.000000000 +1000
@@ -504,6 +504,7 @@
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		th->check = ~tcp_v4_check(th, len,
 					  inet->saddr, inet->daddr, 0);
+		skb->csum_start = skb->h.raw - skb->head;
 		skb->csum_offset = offsetof(struct tcphdr, check);
 	} else {
 		th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr,
@@ -526,6 +527,7 @@
 
 	th->check = 0;
 	th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
+	skb->csum_start = skb->h.raw - skb->head;
 	skb->csum_offset = offsetof(struct tcphdr, check);
 	skb->ip_summed = CHECKSUM_PARTIAL;
 	return 0;
diff -ur linux-2.6.20.i386.orig/net/ipv4/udp.c linux-2.6.20.i386/net/ipv4/udp.c
--- linux-2.6.20.i386.orig/net/ipv4/udp.c	2007-04-24 13:18:40.000000000 +1000
+++ linux-2.6.20.i386/net/ipv4/udp.c	2007-04-24 15:10:23.000000000 +1000
@@ -425,6 +425,7 @@
 		/*
 		 * Only one fragment on the socket.
 		 */
+		skb->csum_start = skb->h.raw - skb->head;
 		skb->csum_offset = offsetof(struct udphdr, check);
 		uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);
 	} else {
diff -ur linux-2.6.20.i386.orig/net/ipv6/tcp_ipv6.c linux-2.6.20.i386/net/ipv6/tcp_ipv6.c
--- linux-2.6.20.i386.orig/net/ipv6/tcp_ipv6.c	2007-03-30 13:39:11.000000000 +1000
+++ linux-2.6.20.i386/net/ipv6/tcp_ipv6.c	2007-04-24 15:10:43.000000000 +1000
@@ -948,6 +948,7 @@
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,  0);
+		skb->csum_start = skb->h.raw - skb->head;
 		skb->csum_offset = offsetof(struct tcphdr, check);
 	} else {
 		th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 
@@ -970,6 +971,7 @@
 	th->check = 0;
 	th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
 				     IPPROTO_TCP, 0);
+	skb->csum_start = skb->h.raw - skb->head;
 	skb->csum_offset = offsetof(struct tcphdr, check);
 	skb->ip_summed = CHECKSUM_PARTIAL;
 	return 0;




Index: kernel-xen.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel-xen-2.6/devel/kernel-xen.spec,v
retrieving revision 1.18.4.2
retrieving revision 1.18.4.3
diff -u -r1.18.4.2 -r1.18.4.3
--- kernel-xen.spec	26 Apr 2007 20:31:56 -0000	1.18.4.2
+++ kernel-xen.spec	27 Apr 2007 18:38:24 -0000	1.18.4.3
@@ -419,6 +419,12 @@
 Patch1610: linux-2.6-input-kill-stupid-messages.patch
 Patch1620: linux-2.6-serial-tickle-nmi.patch
 Patch1650: linux-2.6-serial-460800.patch
+# checksum fixes (bug #223258)
+Patch1660: linux-2.6-forwarding_of_ip_summed.patch
+Patch1661: linux-2.6-use_csum_start_offset_instead.patch
+Patch1662: linux-2.6-treat_partial_as_unnecessary.patch
+Patch1663: linux-2.6-kill_skbuff_hack.patch
+
 Patch1681: linux-2.6-xfs-umount-fix.patch
 Patch1682: linux-2.6-xfs_attr2.patch
 Patch1690: linux-2.6-PT_LOAD-align.patch
@@ -957,6 +963,13 @@
 #%patch1620 -p1
 # Allow to use 480600 baud on 16C950 UARTs
 %patch1650 -p1
+
+# checksum fixes (bug #223258)
+%patch1660 -p1
+%patch1661 -p1
+%patch1662 -p1
+%patch1663 -p1
+
 # Fix XFS umount bug.
 %patch1681 -p1
 # Fix attr2 corruption with btree data extents




More information about the fedora-cvs-commits mailing list