ia64/xen-unstable

changeset 9828:1020c52c58c1

The Xen checksum offload feature attempts to insert a TCP/UDP
checksums into already encrypted packets (esp4) in dom0. Obviously,
it is not possible to insert a checksum into an already encrypted
packet, so this patch inserts the checksum prior to encrypting
packets in net/ipv4/xfrm4_output.c.

To do this cleanly, the TCP/UDP header pointers need to be pointed to
the correct spot, so this functionality has been abstracted into a new
function.

This patch fixes bug 143 (verified by Jim Dykman). Earlier version
verified by Jon McCune.

Signed-off-by: James Dykman <dykman@us.ibm.com>
Signed-off-by: Jon Mason <jdmason@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Apr 22 10:41:53 2006 +0100 (2006-04-22)
parents b2323eefb79e
children e327fb66a8d9
files linux-2.6-xen-sparse/net/core/dev.c patches/linux-2.6.16/net-csum.patch
line diff
     1.1 --- a/linux-2.6-xen-sparse/net/core/dev.c	Sat Apr 22 10:37:24 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/net/core/dev.c	Sat Apr 22 10:41:53 2006 +0100
     1.3 @@ -1220,6 +1220,43 @@ int __skb_linearize(struct sk_buff *skb,
     1.4  	}						\
     1.5  }
     1.6  
     1.7 +#ifdef CONFIG_XEN
     1.8 +inline int skb_checksum_setup(struct sk_buff *skb)
     1.9 +{
    1.10 +	if (skb->proto_csum_blank) {
    1.11 +		if (skb->protocol != htons(ETH_P_IP))
    1.12 +			goto out;
    1.13 +		skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
    1.14 +		if (skb->h.raw >= skb->tail)
    1.15 +			goto out;
    1.16 +		switch (skb->nh.iph->protocol) {
    1.17 +		case IPPROTO_TCP:
    1.18 +			skb->csum = offsetof(struct tcphdr, check);
    1.19 +			break;
    1.20 +		case IPPROTO_UDP:
    1.21 +			skb->csum = offsetof(struct udphdr, check);
    1.22 +			break;
    1.23 +		default:
    1.24 +			if (net_ratelimit())
    1.25 +				printk(KERN_ERR "Attempting to checksum a non-"
    1.26 +				       "TCP/UDP packet, dropping a protocol"
    1.27 +				       " %d packet", skb->nh.iph->protocol);
    1.28 +			goto out;
    1.29 +		}
    1.30 +		if ((skb->h.raw + skb->csum + 2) > skb->tail)
    1.31 +			goto out;
    1.32 +		skb->ip_summed = CHECKSUM_HW;
    1.33 +		skb->proto_csum_blank = 0;
    1.34 +	}
    1.35 +	return 0;
    1.36 +out:
    1.37 +	return -EPROTO;
    1.38 +}
    1.39 +#else
    1.40 +inline int skb_checksum_setup(struct sk_buff *skb) {}
    1.41 +#endif
    1.42 +
    1.43 +
    1.44  /**
    1.45   *	dev_queue_xmit - transmit a buffer
    1.46   *	@skb: buffer to transmit
    1.47 @@ -1266,38 +1303,12 @@ int dev_queue_xmit(struct sk_buff *skb)
    1.48  	    __skb_linearize(skb, GFP_ATOMIC))
    1.49  		goto out_kfree_skb;
    1.50  
    1.51 -#ifdef CONFIG_XEN
    1.52 -	/* If a checksum-deferred packet is forwarded to a device that needs a
    1.53 -	 * checksum, correct the pointers and force checksumming.
    1.54 -	 */
    1.55 -	if (skb->proto_csum_blank) {
    1.56 -		if (skb->protocol != htons(ETH_P_IP))
    1.57 -			goto out_kfree_skb;
    1.58 -		skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
    1.59 -		if (skb->h.raw >= skb->tail)
    1.60 -			goto out_kfree_skb;
    1.61 -		switch (skb->nh.iph->protocol) {
    1.62 -		case IPPROTO_TCP:
    1.63 -			skb->csum = offsetof(struct tcphdr, check);
    1.64 -			break;
    1.65 -		case IPPROTO_UDP:
    1.66 -			skb->csum = offsetof(struct udphdr, check);
    1.67 -			break;
    1.68 -		default:
    1.69 -			if (net_ratelimit())
    1.70 -				printk(KERN_ERR "Attempting to checksum a non-"
    1.71 -				       "TCP/UDP packet, dropping a protocol"
    1.72 -				       " %d packet", skb->nh.iph->protocol);
    1.73 -			rc = -EPROTO;
    1.74 -			goto out_kfree_skb;
    1.75 -		}
    1.76 -		if ((skb->h.raw + skb->csum + 2) > skb->tail)
    1.77 -			goto out_kfree_skb;
    1.78 -		skb->ip_summed = CHECKSUM_HW;
    1.79 -		skb->proto_csum_blank = 0;
    1.80 -	}
    1.81 -#endif
    1.82 -
    1.83 + 	/* If a checksum-deferred packet is forwarded to a device that needs a
    1.84 + 	 * checksum, correct the pointers and force checksumming.
    1.85 + 	 */
    1.86 + 	if(skb_checksum_setup(skb))
    1.87 + 		goto out_kfree_skb;
    1.88 +  
    1.89  	/* If packet is not checksummed and device does not support
    1.90  	 * checksumming for this protocol, complete checksumming here.
    1.91  	 */
    1.92 @@ -3351,6 +3362,7 @@ EXPORT_SYMBOL(unregister_netdevice_notif
    1.93  EXPORT_SYMBOL(net_enable_timestamp);
    1.94  EXPORT_SYMBOL(net_disable_timestamp);
    1.95  EXPORT_SYMBOL(dev_get_flags);
    1.96 +EXPORT_SYMBOL(skb_checksum_setup);
    1.97  
    1.98  #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
    1.99  EXPORT_SYMBOL(br_handle_frame_hook);
     2.1 --- a/patches/linux-2.6.16/net-csum.patch	Sat Apr 22 10:37:24 2006 +0100
     2.2 +++ b/patches/linux-2.6.16/net-csum.patch	Sat Apr 22 10:41:53 2006 +0100
     2.3 @@ -39,3 +39,26 @@ diff -pruN ../pristine-linux-2.6.16/net/
     2.4   	*portptr = newport;
     2.5   	return 1;
     2.6   }
     2.7 +diff -r 601fa226a761 net/ipv4/xfrm4_output.c
     2.8 +--- a/net/ipv4/xfrm4_output.c	Wed Apr 19 18:52:30 2006
     2.9 ++++ b/net/ipv4/xfrm4_output.c	Thu Apr 20 15:49:40 2006
    2.10 +@@ -16,6 +16,8 @@
    2.11 + #include <net/ip.h>
    2.12 + #include <net/xfrm.h>
    2.13 + #include <net/icmp.h>
    2.14 ++
    2.15 ++extern int skb_checksum_setup(struct sk_buff *skb);
    2.16 + 
    2.17 + /* Add encapsulation header.
    2.18 +  *
    2.19 +@@ -103,6 +105,10 @@
    2.20 + 	struct xfrm_state *x = dst->xfrm;
    2.21 + 	int err;
    2.22 + 	
    2.23 ++	err = skb_checksum_setup(skb);
    2.24 ++	if (err)
    2.25 ++		goto error_nolock;
    2.26 ++
    2.27 + 	if (skb->ip_summed == CHECKSUM_HW) {
    2.28 + 		err = skb_checksum_help(skb, 0);
    2.29 + 		if (err)