From d6703ada5dbe8638ac83d0f3801c12246852d513 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Tue, 22 Dec 2015 12:36:08 +0530 Subject: [PATCH] If needed, DP originated packets should undergo csum/gso updates For packets that are tunneled, vRouter updates the checksum offset of the packet to reflect tunnel addition. For mirrored packets, if the mirror destination (analyzer) is local, no tunnel headers (MPLSO(UDP/GRE)) are added and hence a checksum offset update is not done. This behavior is wrong since we do add mirror headers (and hence a tunnel) and the whole packet needs a checksum value. Change-Id: Ia8c184d0980e7880bff90ff53f178e657a6be311 Closes-BUG: #1528460 --- dp-core/vr_nexthop.c | 24 ++++++++++++++++++++++++ include/vr_packet.h | 11 +++++++++++ linux/vr_host_interface.c | 3 ++- linux/vrouter_mod.c | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/dp-core/vr_nexthop.c b/dp-core/vr_nexthop.c index fe1a57fea..fff09db51 100644 --- a/dp-core/vr_nexthop.c +++ b/dp-core/vr_nexthop.c @@ -1266,6 +1266,13 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, */ pkt_set_inner_network_header(pkt, pkt->vp_data); + if (pkt->vp_type == VP_TYPE_IP6) + pkt->vp_type = VP_TYPE_IP6OIP; + else if (pkt->vp_type == VP_TYPE_IP) + pkt->vp_type = VP_TYPE_IPOIP; + else + pkt->vp_type = VP_TYPE_IP; + /* * Calculate the partial checksum for udp header */ @@ -1338,6 +1345,12 @@ nh_vxlan_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, goto send_fail; pkt_set_network_header(pkt, pkt->vp_data); + + if (pkt->vp_type == VP_TYPE_IPOIP) + pkt->vp_type = VP_TYPE_IP; + else if (pkt->vp_type == VP_TYPE_IP6OIP) + pkt->vp_type = VP_TYPE_IP6; + /* * Change the packet type */ @@ -1476,6 +1489,11 @@ nh_mpls_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, pkt->vp_flags |= VP_FLAG_GSO; + if (pkt->vp_type == VP_TYPE_IPOIP) + pkt->vp_type = VP_TYPE_IP; + else if (pkt->vp_type == VP_TYPE_IP6OIP) + pkt->vp_type = VP_TYPE_IP6; + /* * Change the packet type */ @@ -1624,6 +1642,12 @@ nh_gre_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, goto send_fail; } pkt_set_network_header(pkt, pkt->vp_data); + + if (pkt->vp_type == VP_TYPE_IPOIP) + pkt->vp_type = VP_TYPE_IP; + else if (pkt->vp_type == VP_TYPE_IP6OIP) + pkt->vp_type = VP_TYPE_IP6; + if (pkt->vp_type == VP_TYPE_IP6) pkt->vp_type = VP_TYPE_IP6OIP; else if (pkt->vp_type == VP_TYPE_IP) diff --git a/include/vr_packet.h b/include/vr_packet.h index 728b8eed0..f25190d80 100644 --- a/include/vr_packet.h +++ b/include/vr_packet.h @@ -493,6 +493,17 @@ vr_pkt_type_is_overlay(unsigned short type) return false; } +static inline bool +vr_pkt_needs_csum_gso_update(struct vr_packet *pkt) +{ + if (pkt->vp_flags & VP_FLAG_FROM_DP) { + if (pkt->vp_flags & (VP_FLAG_CSUM_PARTIAL | VP_FLAG_GSO)) + return true; + } + + return false; +} + static inline bool vr_pkt_is_diag(struct vr_packet *pkt) { diff --git a/linux/vr_host_interface.c b/linux/vr_host_interface.c index 4dbfd8617..7d7949ba7 100644 --- a/linux/vr_host_interface.c +++ b/linux/vr_host_interface.c @@ -782,7 +782,8 @@ linux_if_tx(struct vr_interface *vif, struct vr_packet *pkt) skb_set_network_header(skb, (network_off - skb_headroom(skb))); skb_reset_mac_len(skb); } - } else if (vr_pkt_type_is_overlay(pkt->vp_type)) { + } else if (vr_pkt_type_is_overlay(pkt->vp_type) || + vr_pkt_needs_csum_gso_update(pkt)) { network_off = pkt_get_inner_network_header_off(pkt); if (network_off) { diff --git a/linux/vrouter_mod.c b/linux/vrouter_mod.c index 37fab038d..50e4defea 100644 --- a/linux/vrouter_mod.c +++ b/linux/vrouter_mod.c @@ -207,6 +207,7 @@ lh_palloc_head(struct vr_packet *pkt, unsigned int size) npkt->vp_ttl = pkt->vp_ttl; npkt->vp_flags = pkt->vp_flags; + npkt->vp_type = pkt->vp_type; skb_frag_list_init(skb_head); skb_frag_add_head(skb_head, skb);