From 85ca42b0bd9825aadf1c31f9043c793471b36235 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Thu, 6 Oct 2016 18:38:00 +0530 Subject: [PATCH] Change in port mirroring tap locations For all types of virtual interfaces, the location from where we tap packets for RX port mirroring is in a common function where all the common virtual processing happens. For a vlan based sub-interface, this means that the port mirroring happens post untagging the packet and hence this is not a correct behavior. Hence, move the tap locations to the lowest layers of vif receive. Also, during transmission, since the tap is in the lowest common layer, sub interface mirroring does not work. Hence, move the taps to the highest layer of vif transmit. Also, add taps for vhost and physical interfaces. Change-Id: Ie42bfcedde2eba1167fa49e7ecd627b7762363e9 Closes-Bug: #1630889 --- dp-core/vr_datapath.c | 10 +------- dp-core/vr_interface.c | 56 +++++++++++++++++++++++++++++++++++------- dp-core/vr_mirror.c | 35 ++++++++++++++++++-------- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/dp-core/vr_datapath.c b/dp-core/vr_datapath.c index 6a1e33daf..289e1b078 100644 --- a/dp-core/vr_datapath.c +++ b/dp-core/vr_datapath.c @@ -595,7 +595,7 @@ unsigned int vr_virtual_input(unsigned short vrf, struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id) { - struct vr_forwarding_md fmd, mfmd; + struct vr_forwarding_md fmd; vr_init_forwarding_md(&fmd); fmd.fmd_vlan = vlan_id; @@ -610,14 +610,6 @@ vr_virtual_input(unsigned short vrf, struct vr_interface *vif, return 0; } - if (vif->vif_flags & VIF_FLAG_MIRROR_RX) { - mfmd = fmd; - mfmd.fmd_dvrf = vif->vif_vrf; - vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &mfmd, - MIRROR_TYPE_PORT_RX); - } - - /* * we really do not allow any broadcast packets from interfaces * that are part of transparent service chain, since transparent diff --git a/dp-core/vr_interface.c b/dp-core/vr_interface.c index 5880f8a99..113d2642f 100644 --- a/dp-core/vr_interface.c +++ b/dp-core/vr_interface.c @@ -231,6 +231,35 @@ vif_xconnect(struct vr_interface *vif, struct vr_packet *pkt, return 0; } +static inline void +vif_mirror(struct vr_interface *vif, struct vr_packet *pkt, + struct vr_forwarding_md *fmd, unsigned int txrx_mirror) +{ + unsigned int mirror_type; + struct vr_forwarding_md mfmd; + + if (!txrx_mirror) + return; + + if (txrx_mirror & VIF_FLAG_MIRROR_TX) + mirror_type = MIRROR_TYPE_PORT_TX; + else + mirror_type = MIRROR_TYPE_PORT_RX; + + if (!fmd) { + vr_init_forwarding_md(&mfmd); + } else { + mfmd = *fmd; + } + + mfmd.fmd_dvrf = vif->vif_vrf; + + vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &mfmd, mirror_type); + + return; +} + +/* agent driver */ static unsigned char * agent_set_rewrite(struct vr_interface *vif, struct vr_packet *pkt, struct vr_forwarding_md *fmd, unsigned char *rewrite, @@ -608,6 +637,8 @@ vhost_rx(struct vr_interface *vif, struct vr_packet *pkt, if (vif_mode_xconnect(vif)) return vif_xconnect(vif, pkt, &fmd); + vif_mirror(vif, pkt, &fmd, vif->vif_flags & VIF_FLAG_MIRROR_RX); + return vr_fabric_input(vif, pkt, vlan_id); } @@ -674,6 +705,8 @@ vhost_tx(struct vr_interface *vif, struct vr_packet *pkt, } } + vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX); + ret = hif_ops->hif_rx(vif, pkt); if (ret < 0) { ret = 0; @@ -737,6 +770,8 @@ vlan_rx(struct vr_interface *vif, struct vr_packet *pkt, stats->vis_ibytes += pkt_len(pkt); stats->vis_ipackets++; + vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX); + tos = vr_vlan_get_tos(pkt_data(pkt)); if (tos >= 0) pkt->vp_priority = tos; @@ -780,6 +815,8 @@ vlan_tx(struct vr_interface *vif, struct vr_packet *pkt, } } + vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX); + pvif = vif->vif_parent; if (!pvif) goto drop; @@ -886,6 +923,8 @@ vm_srx(struct vr_interface *vif, struct vr_packet *pkt, else vrf = vif->vif_vrf_table[vlan_id].va_vrf; + vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX); + return vr_virtual_input(vrf, vif, pkt, vlan_id); } @@ -910,6 +949,8 @@ vm_rx(struct vr_interface *vif, struct vr_packet *pkt, struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); struct vr_eth *eth = (struct vr_eth *)pkt_data(pkt); + vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX); + if (vlan_id != VLAN_ID_INVALID && vlan_id < VLAN_ID_MAX) { if (vif->vif_btable) { sub_vif = vif_bridge_get_sub_interface(vif->vif_btable, vlan_id, @@ -951,6 +992,8 @@ tun_rx(struct vr_interface *vif, struct vr_packet *pkt, stats->vis_ibytes += pkt_len(pkt); stats->vis_ipackets++; + vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX); + if (vif_mode_xconnect(vif)) pkt->vp_flags |= VP_FLAG_TO_ME; @@ -1036,6 +1079,8 @@ eth_rx(struct vr_interface *vif, struct vr_packet *pkt, stats->vis_ibytes += pkt_len(pkt); stats->vis_ipackets++; + vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX); + /* * please see the text on xconnect mode * @@ -1074,9 +1119,10 @@ eth_tx(struct vr_interface *vif, struct vr_packet *pkt, int ret, handled; bool stats_count = true, from_subvif = false; - struct vr_forwarding_md m_fmd; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); + vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX); + if (vif_is_virtual(vif)) { handled = vif_plug_mac_request(vif, pkt, fmd); if (handled) @@ -1108,13 +1154,6 @@ eth_tx(struct vr_interface *vif, struct vr_packet *pkt, stats->vis_opackets++; } - if (vif->vif_flags & VIF_FLAG_MIRROR_TX) { - vr_init_forwarding_md(&m_fmd); - m_fmd.fmd_dvrf = vif->vif_vrf; - vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &m_fmd, - MIRROR_TYPE_PORT_TX); - } - ret = hif_ops->hif_tx(vif, pkt); if (ret != 0) { if (!from_subvif) @@ -1220,7 +1259,6 @@ eth_drv_add(struct vr_interface *vif, vif->vif_mtu = 1514; } - if (vif->vif_type != VIF_TYPE_STATS) { vif->vif_tx = eth_tx; diff --git a/dp-core/vr_mirror.c b/dp-core/vr_mirror.c index 986df73b2..a36160780 100644 --- a/dp-core/vr_mirror.c +++ b/dp-core/vr_mirror.c @@ -349,7 +349,9 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt, struct vr_forwarding_md *fmd, mirror_type_t mtype) { bool reset = true; - unsigned int captured_len, clone_len = 0, mirror_md_len = 0; + unsigned int captured_len, clone_len = 0; + unsigned int mirror_md_len = 0, drop_reason; + void *mirror_md; unsigned char *buf; struct vr_nexthop *nh, *pkt_nh; @@ -404,14 +406,18 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt, } } } else if (mtype == MIRROR_TYPE_PORT_RX) { - if (!pkt->vp_if) + if (!pkt->vp_if) { + drop_reason = VP_DROP_INVALID_IF; goto fail; + } mirror_md_len = pkt->vp_if->vif_mirror_md_len; mirror_md = pkt->vp_if->vif_mirror_md; } else { - if (!pkt->vp_nh || !pkt->vp_nh->nh_dev) - goto fail; + if (!pkt->vp_nh || !pkt->vp_nh->nh_dev) { + drop_reason = VP_DROP_INVALID_NH; + goto fail; + } mirror_md_len = pkt->vp_nh->nh_dev->vif_mirror_md_len; mirror_md = pkt->vp_nh->nh_dev->vif_mirror_md; @@ -445,13 +451,18 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt, clone_len += pkt_nh->nh_encap_len; - if (vr_pcow(pkt, clone_len)) + if (vr_pcow(pkt, clone_len)) { + drop_reason = VP_DROP_PCOW_FAIL; goto fail; + } + clone_len = 0; if (!pkt_nh->nh_dev->vif_set_rewrite(pkt_nh->nh_dev, pkt, fmd, - pkt_nh->nh_data, pkt_nh->nh_encap_len)) - goto fail; + pkt_nh->nh_data, pkt_nh->nh_encap_len)) { + drop_reason = VP_DROP_REWRITE_FAIL; + goto fail; + } } } } @@ -460,15 +471,19 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt, vr_preset(pkt); if (clone_len) { - if (vr_pcow(pkt, clone_len)) + if (vr_pcow(pkt, clone_len)) { + drop_reason = VP_DROP_PCOW_FAIL; goto fail; + } } captured_len = htonl(pkt_len(pkt)); if (mirror_md_len) { buf = pkt_push(pkt, mirror_md_len); - if (!buf) + if (!buf) { + drop_reason = VP_DROP_PUSH; goto fail; + } memcpy(buf, mirror_md, mirror_md_len); } @@ -485,7 +500,7 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt, return 0; fail: - vr_pfree(pkt, VP_DROP_PUSH); + vr_pfree(pkt, drop_reason); return 0; }