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>
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)