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