[NET]: Allow forwarding of ip_summed except CHECKSUM_COMPLETE
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 27 Mar 2007 06:22:20 +0000 (23:22 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Thu, 26 Apr 2007 05:28:16 +0000 (22:28 -0700)
Right now Xen has a horrible hack that lets it forward packets with
partial checksums.  One of the reasons that CHECKSUM_PARTIAL and
CHECKSUM_COMPLETE were added is so that we can get rid of this hack
(where it creates two extra bits in the skbuff to essentially mirror
ip_summed without being destroyed by the forwarding code).

I had forgotten that I've already gone through all the deivce drivers
last time around to make sure that they're looking at ip_summed ==
CHECKSUM_PARTIAL rather than ip_summed != 0 on transmit.  In any case,
I've now done that again so it should definitely be safe.

Unfortunately nobody has yet added any code to update CHECKSUM_COMPLETE
values on forward so we I'm setting that to CHECKSUM_NONE.  This should
be safe to remove for bridging but I'd like to check that code path
first.

So here is the patch that lets us get rid of the hack by preserving
ip_summed (mostly) on forwarded packets.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/skbuff.h
net/bridge/br_forward.c
net/ipv4/ip_forward.c
net/ipv6/ip6_output.c

index 37247901ebd2ffe9f8c5fde0987210a565eacdd8..1c19b2d55c2b999463f500e1e5aed800538035d6 100644 (file)
@@ -1654,5 +1654,12 @@ static inline int skb_is_gso(const struct sk_buff *skb)
        return skb_shinfo(skb)->gso_size;
 }
 
+static inline void skb_forward_csum(struct sk_buff *skb)
+{
+       /* Unfortunately we don't support this one.  Any brave souls? */
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->ip_summed = CHECKSUM_NONE;
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */
index 3e45c1a1aa96124f1bf525346aecf14b704f4311..ada7f495445c5ae24e1495df005c5411430a6f14 100644 (file)
@@ -71,7 +71,7 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
 
        indev = skb->dev;
        skb->dev = to->dev;
-       skb->ip_summed = CHECKSUM_NONE;
+       skb_forward_csum(skb);
 
        NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
                        br_forward_finish);
index 61b30d10067644538bda2207a4637b019c2ebdbb..9cb04df0054b6417b44498dabc75f55b55355011 100644 (file)
@@ -67,7 +67,7 @@ int ip_forward(struct sk_buff *skb)
        if (skb->pkt_type != PACKET_HOST)
                goto drop;
 
-       skb->ip_summed = CHECKSUM_NONE;
+       skb_forward_csum(skb);
 
        /*
         *      According to the RFC, we must first decrease the TTL field. If
index e2b8db6b9aef0f0319031ba1ff86052518cf66dc..be3f082a87ed410723edef3a938962c43274b1c4 100644 (file)
@@ -378,7 +378,7 @@ int ip6_forward(struct sk_buff *skb)
                goto drop;
        }
 
-       skb->ip_summed = CHECKSUM_NONE;
+       skb_forward_csum(skb);
 
        /*
         *      We DO NOT make any processing on