[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Fix checksum errors when firewalling in domU



Another checksum offload problem was reported on xen-users, when using a 
domU as a firewall:
http://lists.xensource.com/archives/html/xen-users/2006-04/msg01150.html
It also fails without VLANs.

The path from dom0->domU with ip_summed==CHECKSUM_HW/proto_csum_blank==1 
is broken.
- skb_checksum_setup() assumes that a checksum will definitely be 
calculated in dev_queue_xmit(), but
   the destination device is netback, which is advertising NETIF_F_IP_CSUM 
---> no checksum. So, 
   added reset_proto_csum_blank() to skbuff.h, and call it in 
dev_queue_xmit() and xfrm4_output() AFTER
   the checksum is calculated.
- The CHECKSUM_HW/proto_csum_blank vars are getting lost/stomped in 
various places. 

Tested on -unstable changeset 9925:
- The network xm-tests on -bridge and -route
- A domU firewalling between two bridges (similar to the error report, but 
without VLANs)
- The IPSec tunnel config from a previous checksum bug. (#143?)
I had to update the patch for the renamed patches/linux-2.6.16.13 
directory this morning. It compiles, but 
I haven't retested.

Signed-off-by: Jim Dykman <dykman@xxxxxxxxxx>
Fix checksum errors when firewalling in domU

diff -r 1e3977e029fd linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Mon May  8 
18:21:41 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Tue May  9 
13:38:56 2006
@@ -172,6 +172,7 @@
                BUG_ON(ret);
                nskb->dev = skb->dev;
                nskb->proto_data_valid = skb->proto_data_valid;
+               nskb->proto_csum_blank = skb->proto_csum_blank;
                dev_kfree_skb(skb);
                skb = nskb;
        }
@@ -340,6 +341,8 @@
                        flags |= NETRXF_csum_blank | 
NETRXF_data_validated;
                else if (skb->proto_data_valid) /* remote but checksummed? 
*/
                        flags |= NETRXF_data_validated;
+               else if (skb->proto_csum_blank) /* forwarded, !checksummed 
*/
+                       flags |= NETRXF_csum_blank;
                if (make_rx_response(netif, id, status,
                                     (unsigned long)skb->data & 
~PAGE_MASK,
                                     size, flags) &&
@@ -669,7 +672,10 @@
                 * can infer it from csum_blank so test both flags.
                 */
                if (txreq.flags & 
(NETTXF_data_validated|NETTXF_csum_blank)) {
-                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       if (txreq.flags & NETTXF_csum_blank)
+                               skb->ip_summed = CHECKSUM_HW;
+                       else
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
                        skb->proto_data_valid = 1;
                } else {
                        skb->ip_summed = CHECKSUM_NONE;
diff -r 1e3977e029fd linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Mon May  8 
18:21:41 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Tue May  9 
13:38:56 2006
@@ -819,7 +819,10 @@
                 * can infer it from csum_blank so test both flags.
                 */
                if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank)) 
{
-                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       if (rx->flags & NETRXF_csum_blank)
+                               skb->ip_summed = CHECKSUM_HW;
+                       else
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
                        skb->proto_data_valid = 1;
                } else {
                        skb->ip_summed = CHECKSUM_NONE;
diff -r 1e3977e029fd linux-2.6-xen-sparse/include/linux/skbuff.h
--- a/linux-2.6-xen-sparse/include/linux/skbuff.h       Mon May  8 
18:21:41 2006
+++ b/linux-2.6-xen-sparse/include/linux/skbuff.h       Tue May  9 
13:38:56 2006
@@ -1281,6 +1281,14 @@
 extern void skb_init(void);
 extern void skb_add_mtu(int mtu);

+#ifdef CONFIG_XEN
+static inline void reset_proto_csum_blank(struct sk_buff *skb)
+{
+       skb->proto_csum_blank=0;
+}
+#else
+static inline void reset_proto_csum_blank(const struct sk_buff *skb) { }
+#endif
 /**
  *     skb_get_timestamp - get timestamp from a skb
  *     @skb: skb to get stamp from
diff -r 1e3977e029fd linux-2.6-xen-sparse/net/core/dev.c
--- a/linux-2.6-xen-sparse/net/core/dev.c       Mon May  8 18:21:41 2006
+++ b/linux-2.6-xen-sparse/net/core/dev.c       Tue May  9 13:38:56 2006
@@ -1246,7 +1246,6 @@
                if ((skb->h.raw + skb->csum + 2) > skb->tail)
                        goto out;
                skb->ip_summed = CHECKSUM_HW;
-               skb->proto_csum_blank = 0;
        }
        return 0;
 out:
@@ -1315,9 +1314,11 @@
        if (skb->ip_summed == CHECKSUM_HW &&
            (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
             (!(dev->features & NETIF_F_IP_CSUM) ||
-             skb->protocol != htons(ETH_P_IP))))
+             skb->protocol != htons(ETH_P_IP)))) {
                if (skb_checksum_help(skb, 0))
                        goto out_kfree_skb;
+               reset_proto_csum_blank(skb);
+       }

        spin_lock_prefetch(&dev->queue_lock);

diff -r 1e3977e029fd patches/linux-2.6.16.13/net-csum.patch
--- a/patches/linux-2.6.16.13/net-csum.patch    Mon May  8 18:21:41 2006
+++ b/patches/linux-2.6.16.13/net-csum.patch    Tue May  9 13:38:56 2006
@@ -40,8 +40,8 @@
        return 1;
  }
 diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/xfrm4_output.c 
./net/ipv4/xfrm4_output.c
---- ../pristine-linux-2.6.16.13/net/ipv4/xfrm4_output.c        2006-05-02 
22:38:44.000000000 +0100
-+++ ./net/ipv4/xfrm4_output.c  2006-05-04 17:41:37.000000000 +0100
+--- ../pristine-linux-2.6.16.13/net/ipv4/xfrm4_output.c        2006-05-02 
17:38:44.000000000 -0400
++++ ./net/ipv4/xfrm4_output.c  2006-05-09 13:08:15.000000000 -0400
 @@ -17,6 +17,8 @@
  #include <net/xfrm.h>
  #include <net/icmp.h>
@@ -51,7 +51,7 @@
  /* Add encapsulation header.
   *
   * In transport mode, the IP header will be moved forward to make space
-@@ -103,6 +105,10 @@ static int xfrm4_output_one(struct sk_bu
+@@ -103,10 +105,15 @@ static int xfrm4_output_one(struct sk_bu
        struct xfrm_state *x = dst->xfrm;
        int err;

@@ -62,3 +62,8 @@
        if (skb->ip_summed == CHECKSUM_HW) {
                err = skb_checksum_help(skb, 0);
                if (err)
+                       goto error_nolock;
++              reset_proto_csum_blank(skb);
+       }
+
+       if (x->props.mode) {

Attachment: vlanfw.patch
Description: Binary data

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.