]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.bak/.git/commitdiff
It turns out that Windows occasionally generates packets in which the
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:20 +0000 (11:54 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:20 +0000 (11:54 +0100)
IP and TCP headers are in different fragments.  Make sure that the
backends can handle this.

drivers/xen/netback/xenbus.c
net/core/dev.c

index f95acb835305f1e3cd71b2f3c79e65433851b641..30d43f4fb93756e80c62004dba584a779ad9884b 100644 (file)
@@ -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).
index f740552f33530e661f2e2ba836f4373009170d76..ca3939bd136174d23366ea34fdf9044da604beb8 100644 (file)
@@ -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