[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 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |