From: Steven Smith Date: Fri, 2 Oct 2009 11:58:57 +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=8347bd9dd052bff6a2d117d87b57ecbc362e9577;p=people%2Fssmith%2Fnc2-2.6.27.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 31cef720..b5099d6c 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 226bb6ba..f84eed15 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1753,6 +1753,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; @@ -1768,10 +1780,10 @@ inline int skb_checksum_setup(struct sk_buff *skb) goto out; 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; + th = skb_network_header(skb) + 4 * iph->ihl; skb->csum_start = th - skb->head; switch (iph->protocol) { case IPPROTO_TCP: @@ -1788,7 +1800,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