From dc58fb98fe1041e61cddb174f53ba195942d6375 Mon Sep 17 00:00:00 2001 From: t_jeang Date: Tue, 6 Jan 2009 12:06:02 +0000 Subject: [PATCH] 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. --- drivers/xen/netback/xenbus.c | 10 ++++++++++ net/core/dev.c | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c index a7835068..774da6df 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 be9c3f93..82d94393 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1399,14 +1399,26 @@ out_kfree_skb: } #ifdef CONFIG_XEN +static int skb_pull_up_to(struct sk_buff *skb, void *ptr) +{ + if (ptr < (void *)skb->tail) + 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) { if (skb->proto_csum_blank) { if (skb->protocol != htons(ETH_P_IP)) goto out; - skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl; - if (skb->h.raw >= skb->tail) + if (!skb_pull_up_to(skb, skb->nh.iph + 1)) goto out; + skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl; switch (skb->nh.iph->protocol) { case IPPROTO_TCP: skb->csum = offsetof(struct tcphdr, check); @@ -1421,7 +1433,7 @@ inline int skb_checksum_setup(struct sk_buff *skb) " %d packet", skb->nh.iph->protocol); goto out; } - if ((skb->h.raw + skb->csum + 2) > skb->tail) + if (!skb_pull_up_to(skb, skb->h.raw + skb->csum + 2)) goto out; skb->ip_summed = CHECKSUM_HW; skb->proto_csum_blank = 0; -- 2.39.5