]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.git/commitdiff
It turns out that Windows occasionally generates packets in which the
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Fri, 2 Oct 2009 11:58:57 +0000 (12:58 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Fri, 2 Oct 2009 11:58:57 +0000 (12:58 +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 31cef7204638a0a28758f52fdfde453b22fe503a..b5099d6cba051baf36b009db484960599424e25c 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 226bb6babc8f5741fd3b18e3e6fbf140e740087c..f84eed1567fd44073661cfbde72723c3edfcd13e 100644 (file)
@@ -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