From 5dfa88c2a7136ab4ec1583789552e011bb1a785a Mon Sep 17 00:00:00 2001 From: Divakar Date: Fri, 13 May 2016 20:02:58 +0530 Subject: [PATCH] Disabling GRO when mirroring is enabled When the packets are received on Fabric interface, these are subjected to GRO before transmitting them to Tap interface. If Tx port mirroring is enabled on Tap interface, as of now, mirroring is applied after GRO of the packets. If the mirroring server is on another compute node, these mirrored packets have GSO enabled. Vrouter makes use of Linux GSO routines and these GSO routines expect that skb in skb_list of head_skb does not contain any linear data (skb_headlen should be zero). Due to GRO the skb_headle of some skb's in skb_list contains linear data resulting in GSO routiness hitting a BUG_ON. To over come this, the GRO needs to be applied post mirroring. To enabled GSO on the mirrored packets the skb's gso_len also need to be supplied. Instead of this fix, GRO is disabled if Tx port mirroring is enabled on Tap interface as stop gap fix till the complete fix is in place. Change-Id: I7dd86e1bd90fef60efa4c9dbac78e853952c4fdc closes-bug: #1577473 --- dp-core/vr_mirror.c | 1 + dp-core/vr_nexthop.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dp-core/vr_mirror.c b/dp-core/vr_mirror.c index 1babcea0e..cecf68297 100644 --- a/dp-core/vr_mirror.c +++ b/dp-core/vr_mirror.c @@ -404,6 +404,7 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, clone_len += mirror_md_len; nh = mirror->mir_nh; + pkt->vp_flags &= ~VP_FLAG_GRO; pkt = vr_pclone(pkt); if (!pkt) return 0; diff --git a/dp-core/vr_nexthop.c b/dp-core/vr_nexthop.c index 668587839..827f00b8e 100644 --- a/dp-core/vr_nexthop.c +++ b/dp-core/vr_nexthop.c @@ -1826,7 +1826,8 @@ nh_encap_l2(struct vr_packet *pkt, struct vr_nexthop *nh, stats = vr_inet_vrf_stats(fmd->fmd_dvrf, pkt->vp_cpu); - if ((pkt->vp_flags & VP_FLAG_GRO) && vif_is_virtual(vif)) { + if ((pkt->vp_flags & VP_FLAG_GRO) && vif_is_virtual(vif) && + (!(vif->vif_flags & VIF_FLAG_MIRROR_TX))) { if (vr_gro_input(pkt, nh)) { if (stats) stats->vrf_gros++; @@ -1889,7 +1890,8 @@ nh_encap_l3(struct vr_packet *pkt, struct vr_nexthop *nh, } } - if ((pkt->vp_flags & VP_FLAG_GRO) && vif_is_virtual(vif)) { + if ((pkt->vp_flags & VP_FLAG_GRO) && vif_is_virtual(vif) && + (!(vif->vif_flags & VIF_FLAG_MIRROR_TX))) { if (vr_gro_input(pkt, nh)) return 0; }