Jon Mason
2006-Apr-21 21:11 UTC
[Xen-devel] [PATCH] Fix IPSec for Xen checksum offload packets
# HG changeset patch # User Jon Mason <jdmason@us.ibm.com> # Node ID 4f83fe4a8606d4a1f56f4ddd0badc0809cfe8a8c # Parent 65894fff3649f58851fa59f38a66ab06e1244ba6 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> diff -r 65894fff3649 -r 4f83fe4a8606 linux-2.6-xen-sparse/net/core/dev.c --- a/linux-2.6-xen-sparse/net/core/dev.c Fri Apr 21 13:03:07 2006 +++ b/linux-2.6-xen-sparse/net/core/dev.c Fri Apr 21 21:04:39 2006 @@ -1220,62 +1220,15 @@ } \ } -/** - * dev_queue_xmit - transmit a buffer - * @skb: buffer to transmit - * - * Queue a buffer for transmission to a network device. The caller must - * have set the device and priority and built the buffer before calling - * this function. The function can be called from an interrupt. - * - * A negative errno code is returned on a failure. A success does not - * guarantee the frame will be transmitted as it may be dropped due - * to congestion or traffic shaping. - * - * ----------------------------------------------------------------------------------- - * I notice this method can also return errors from the queue disciplines, - * including NET_XMIT_DROP, which is a positive value. So, errors can also - * be positive. - * - * Regardless of the return value, the skb is consumed, so it is currently - * difficult to retry a send to this method. (You can bump the ref count - * before sending to hold a reference for retry if you are careful.) - * - * When calling this method, interrupts MUST be enabled. This is because - * the BH enable code must have IRQs enabled so that it will not deadlock. - * --BLG - */ - -int dev_queue_xmit(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct Qdisc *q; - int rc = -ENOMEM; - - if (skb_shinfo(skb)->frag_list && - !(dev->features & NETIF_F_FRAGLIST) && - __skb_linearize(skb, GFP_ATOMIC)) - goto out_kfree_skb; - - /* Fragmented skb is linearized if device does not support SG, - * or if at least one of fragments is in highmem and device - * does not support DMA from it. - */ - if (skb_shinfo(skb)->nr_frags && - (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && - __skb_linearize(skb, GFP_ATOMIC)) - goto out_kfree_skb; - #ifdef CONFIG_XEN - /* If a checksum-deferred packet is forwarded to a device that needs a - * checksum, correct the pointers and force checksumming. - */ +inline int skb_checksum_setup(struct sk_buff *skb) +{ if (skb->proto_csum_blank) { if (skb->protocol != htons(ETH_P_IP)) - goto out_kfree_skb; + goto out; skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl; if (skb->h.raw >= skb->tail) - goto out_kfree_skb; + goto out; switch (skb->nh.iph->protocol) { case IPPROTO_TCP: skb->csum = offsetof(struct tcphdr, check); @@ -1288,16 +1241,74 @@ printk(KERN_ERR "Attempting to checksum a non-" "TCP/UDP packet, dropping a protocol" " %d packet", skb->nh.iph->protocol); - rc = -EPROTO; - goto out_kfree_skb; + goto out; } if ((skb->h.raw + skb->csum + 2) > skb->tail) - goto out_kfree_skb; + goto out; skb->ip_summed = CHECKSUM_HW; skb->proto_csum_blank = 0; } + return 0; +out: + return -EPROTO; +} +#else +inline int skb_checksum_setup(struct sk_buff *skb) {} #endif + +/** + * dev_queue_xmit - transmit a buffer + * @skb: buffer to transmit + * + * Queue a buffer for transmission to a network device. The caller must + * have set the device and priority and built the buffer before calling + * this function. The function can be called from an interrupt. + * + * A negative errno code is returned on a failure. A success does not + * guarantee the frame will be transmitted as it may be dropped due + * to congestion or traffic shaping. + * + * ----------------------------------------------------------------------------------- + * I notice this method can also return errors from the queue disciplines, + * including NET_XMIT_DROP, which is a positive value. So, errors can also + * be positive. + * + * Regardless of the return value, the skb is consumed, so it is currently + * difficult to retry a send to this method. (You can bump the ref count + * before sending to hold a reference for retry if you are careful.) + * + * When calling this method, interrupts MUST be enabled. This is because + * the BH enable code must have IRQs enabled so that it will not deadlock. + * --BLG + */ + +int dev_queue_xmit(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + struct Qdisc *q; + int rc = -ENOMEM; + + if (skb_shinfo(skb)->frag_list && + !(dev->features & NETIF_F_FRAGLIST) && + __skb_linearize(skb, GFP_ATOMIC)) + goto out_kfree_skb; + + /* Fragmented skb is linearized if device does not support SG, + * or if at least one of fragments is in highmem and device + * does not support DMA from it. + */ + if (skb_shinfo(skb)->nr_frags && + (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && + __skb_linearize(skb, GFP_ATOMIC)) + goto out_kfree_skb; + + /* 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; + /* If packet is not checksummed and device does not support * checksumming for this protocol, complete checksumming here. */ @@ -3351,6 +3362,7 @@ 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 -r 65894fff3649 -r 4f83fe4a8606 patches/linux-2.6.16/net-csum.patch --- a/patches/linux-2.6.16/net-csum.patch Fri Apr 21 13:03:07 2006 +++ b/patches/linux-2.6.16/net-csum.patch Fri Apr 21 21:04:39 2006 @@ -39,3 +39,26 @@ *portptr = newport; return 1; } +diff -r 601fa226a761 net/ipv4/xfrm4_output.c +--- a/net/ipv4/xfrm4_output.c Wed Apr 19 18:52:30 2006 ++++ b/net/ipv4/xfrm4_output.c Thu Apr 20 15:49:40 2006 +@@ -16,6 +16,8 @@ + #include <net/ip.h> + #include <net/xfrm.h> + #include <net/icmp.h> ++ ++extern int skb_checksum_setup(struct sk_buff *skb); + + /* Add encapsulation header. + * +@@ -103,6 +105,10 @@ + struct xfrm_state *x = dst->xfrm; + int err; + ++ err = skb_checksum_setup(skb); ++ if (err) ++ goto error_nolock; ++ + if (skb->ip_summed == CHECKSUM_HW) { + err = skb_checksum_help(skb, 0); + if (err) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel