From: Steven Smith Date: Thu, 28 May 2009 10:54:20 +0000 (+0100) Subject: It turns out that Windows occasionally generates packets in which the X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=27e6ddf035a3516695e11b95f7913eaa5519a082;p=people%2Fssmith%2Fnc2-2.6.27.bak%2F.git It turns out that Windows occasionally generates packets in which the IP and TCP headers are in different fragments. Make sure that the backends can handle this. --- diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c index f95acb83..30d43f4f 100644 --- a/drivers/xen/netback/xenbus.c +++ b/drivers/xen/netback/xenbus.c @@ -112,6 +112,16 @@ static int netback_probe(struct xenbus_device *dev, goto abort_transaction; } + /* We can cope with transmit checksum offload packets + in which the TCP and IP headers are in separate + fragments. */ + err = xenbus_printf(xbt, dev->nodename, + "feature-tx-csum-split-header", "%d", 1); + if (err) { + message = "writing feature-tx-csum-split-header"; + goto abort_transaction; + } + /* * We don't support rx-flip path (except old guests who don't * grok this feature flag). diff --git a/net/core/dev.c b/net/core/dev.c index f740552f..ca3939bd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1741,6 +1741,18 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, } #if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN) +static int skb_pull_up_to(struct sk_buff *skb, void *ptr) +{ + if (ptr < (void *)skb_tail_pointer(skb)) + return 1; + if (__pskb_pull_tail(skb, + ptr - (void *)skb->data - skb_headlen(skb))) { + return 1; + } else { + return 0; + } +} + inline int skb_checksum_setup(struct sk_buff *skb) { struct iphdr *iph; @@ -1757,7 +1769,7 @@ inline int skb_checksum_setup(struct sk_buff *skb) iph = ip_hdr(skb); th = skb_network_header(skb) + 4 * iph->ihl; - if (th >= skb_tail_pointer(skb)) + if (!skb_pull_up_to(skb, iph + 1)) goto out; skb->csum_start = th - skb->head; @@ -1776,7 +1788,7 @@ inline int skb_checksum_setup(struct sk_buff *skb) goto out; } - if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb)) + if (!skb_pull_up_to(skb, th + skb->csum_offset + 2)) goto out; #ifdef CONFIG_XEN