As suggested by Jesse in the comment for patch "gre: Restructure
tunneling", following patch keeps skb->csum correct across ovs.

Signed-off-by: Pravin B Shelar <pshe...@nicira.com>
---
v3-v4:
- use correct len for csum.
v2-v3:
- moved skb_postpull_rcsum() to private ovs header.
- used ETH_ALEN to replace rcsum.
v1-v2:
- Fixed lisp and vlan_deaccel_tag()
---
 datapath/actions.c            |    8 ++++++++
 datapath/flow.c               |    2 ++
 datapath/vlan.h               |    5 +++++
 datapath/vport-gre.c          |    3 +--
 datapath/vport-internal_dev.c |    1 +
 datapath/vport-lisp.c         |    2 ++
 datapath/vport-netdev.c       |    5 +++--
 datapath/vport-vxlan.c        |    3 +--
 datapath/vport.h              |    6 ++++++
 9 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 0dac658..09d0c3f 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -132,9 +132,17 @@ static int set_eth_addr(struct sk_buff *skb,
        if (unlikely(err))
                return err;
 
+       if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+               skb->csum = csum_sub(skb->csum, csum_partial(eth_hdr(skb),
+                                                            ETH_ALEN * 2, 0));
+
        memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN);
        memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN);
 
+       if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+               skb->csum = csum_add(skb->csum, csum_partial(eth_hdr(skb),
+                                                            ETH_ALEN * 2, 0));
+
        return 0;
 }
 
diff --git a/datapath/flow.c b/datapath/flow.c
index 7f897bd..7604405 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -636,6 +636,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, 
struct sw_flow_key *key,
        memcpy(key->eth.dst, eth->h_dest, ETH_ALEN);
 
        __skb_pull(skb, 2 * ETH_ALEN);
+       /* We are going to push all headers that we pull, so no need to
+        * update skb->csum here. */
 
        if (vlan_tx_tag_present(skb))
                key->eth.tci = htons(vlan_get_tci(skb));
diff --git a/datapath/vlan.h b/datapath/vlan.h
index 5d3573b..46d0db3 100644
--- a/datapath/vlan.h
+++ b/datapath/vlan.h
@@ -93,6 +93,11 @@ static inline int vlan_deaccel_tag(struct sk_buff *skb)
        if (unlikely(!skb))
                return -ENOMEM;
 
+       if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+               skb->csum = csum_add(skb->csum,
+                                    csum_partial(skb->data + (2 * ETH_ALEN),
+                                                 VLAN_HLEN, 0));
+
        vlan_set_tci(skb, 0);
        return 0;
 }
diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
index add17d9..dae35ac 100644
--- a/datapath/vport-gre.c
+++ b/datapath/vport-gre.c
@@ -271,8 +271,7 @@ static int gre_rcv(struct sk_buff *skb)
        tnl_flags = gre_flags_to_tunnel_flags(gre_flags, is_gre64);
        tnl_tun_key_init(&tun_key, iph, key, tnl_flags);
 
-       __skb_pull(skb, hdr_len);
-       skb_postpull_rcsum(skb, skb_transport_header(skb), hdr_len + ETH_HLEN);
+       skb_pull_rcsum(skb, hdr_len);
 
        ovs_tnl_rcv(vport, skb, &tun_key);
        return 0;
diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c
index 9a159cd..7f0b3c1 100644
--- a/datapath/vport-internal_dev.c
+++ b/datapath/vport-internal_dev.c
@@ -281,6 +281,7 @@ static int internal_dev_recv(struct vport *vport, struct 
sk_buff *skb)
        skb->dev = netdev;
        skb->pkt_type = PACKET_HOST;
        skb->protocol = eth_type_trans(skb, netdev);
+       skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
        forward_ip_summed(skb, false);
 
        netif_rx(skb);
diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
index 3d0a315..209df59 100644
--- a/datapath/vport-lisp.c
+++ b/datapath/vport-lisp.c
@@ -240,6 +240,8 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
        ethh->h_source[0] = 0x02;
        ethh->h_proto = protocol;
 
+       ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+
        ovs_tnl_rcv(vport_from_priv(lisp_port), skb, &tun_key);
        goto out;
 
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 4e7342c..fe7e359 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -256,11 +256,12 @@ static void netdev_port_receive(struct vport *vport, 
struct sk_buff *skb)
        if (unlikely(!skb))
                return;
 
-       skb_push(skb, ETH_HLEN);
-
        if (unlikely(compute_ip_summed(skb, false)))
                goto error;
 
+       skb_push(skb, ETH_HLEN);
+       ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+
        vlan_copy_skb_tci(skb);
 
        ovs_vport_receive(vport, skb, NULL);
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
index d140c3b..708283e 100644
--- a/datapath/vport-vxlan.c
+++ b/datapath/vport-vxlan.c
@@ -129,8 +129,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                     vxh->vx_vni & htonl(0xff)))
                goto error;
 
-       __skb_pull(skb, VXLAN_HLEN);
-       skb_postpull_rcsum(skb, skb_transport_header(skb), VXLAN_HLEN + 
ETH_HLEN);
+       skb_pull_rcsum(skb, VXLAN_HLEN);
 
        key = cpu_to_be64(ntohl(vxh->vx_vni) >> 8);
 
diff --git a/datapath/vport.h b/datapath/vport.h
index 8d262a3..995889c 100644
--- a/datapath/vport.h
+++ b/datapath/vport.h
@@ -204,4 +204,10 @@ extern const struct vport_ops ovs_gre64_vport_ops;
 extern const struct vport_ops ovs_vxlan_vport_ops;
 extern const struct vport_ops ovs_lisp_vport_ops;
 
+static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb,
+                                     const void *start, unsigned int len)
+{
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->csum = csum_add(skb->csum, csum_partial(start, len, 0));
+}
 #endif /* vport.h */
-- 
1.7.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to