From d5c7566789e06f568d4155233aacc30b04e7a5c8 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 | 8 +------- dp-core/vr_interface.c | 44 ++++++++++++++++++++++++++++++++++-------- dp-core/vr_mirror.c | 27 ++++++++++++++++++-------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/dp-core/vr_datapath.c b/dp-core/vr_datapath.c index 2579be107..57c2cdecf 100644 --- a/dp-core/vr_datapath.c +++ b/dp-core/vr_datapath.c @@ -610,7 +610,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; @@ -621,12 +621,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); - } - /* * 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 ecdd32d86..3b21a94bc 100644 --- a/dp-core/vr_interface.c +++ b/dp-core/vr_interface.c @@ -231,6 +231,25 @@ 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) +{ + struct vr_forwarding_md mfmd; + + 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); + + 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 +627,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); + return vr_fabric_input(vif, pkt, vlan_id); } @@ -674,6 +695,8 @@ vhost_tx(struct vr_interface *vif, struct vr_packet *pkt, } } + vif_mirror(vif, pkt, fmd); + ret = hif_ops->hif_rx(vif, pkt); if (ret < 0) { ret = 0; @@ -736,6 +759,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); + if (vr_untag_pkt(pkt)) { stats->vis_ierrors++; vr_pfree(pkt, VP_DROP_PULL); @@ -770,6 +795,7 @@ vlan_tx(struct vr_interface *vif, struct vr_packet *pkt, vr_pset_data(pkt, pkt->vp_data); } + vif_mirror(vif, pkt, fmd); pvif = vif->vif_parent; if (!pvif) @@ -877,6 +903,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); + return vr_virtual_input(vrf, vif, pkt, vlan_id); } @@ -901,6 +929,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); + 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, @@ -942,6 +972,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); + if (vif_mode_xconnect(vif)) pkt->vp_flags |= VP_FLAG_TO_ME; @@ -1027,6 +1059,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); + /* * please see the text on xconnect mode * @@ -1065,9 +1099,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); + if (vif_is_virtual(vif)) { handled = vif_plug_mac_request(vif, pkt, fmd); if (handled) @@ -1099,12 +1134,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); - } - ret = hif_ops->hif_tx(vif, pkt); if (ret != 0) { if (!from_subvif) @@ -1210,7 +1239,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 10d4de8be..e6fdb7edc 100644 --- a/dp-core/vr_mirror.c +++ b/dp-core/vr_mirror.c @@ -377,8 +377,8 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt, struct vr_forwarding_md *fmd) { bool reset = true; - unsigned int captured_len, clone_len = VR_MIRROR_PKT_HEAD_SPACE, - mirror_md_len = 0; + unsigned int captured_len, clone_len = VR_MIRROR_PKT_HEAD_SPACE; + unsigned int mirror_md_len = 0, drop_reason; unsigned char default_mme[2] = {0xff, 0x0}; unsigned long sec, usec; @@ -437,14 +437,19 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, if (pkt_nh->nh_family == AF_INET) 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_family == AF_INET) { if (!pkt_nh->nh_dev->vif_set_rewrite(pkt_nh->nh_dev, pkt, fmd, - pkt_nh->nh_data, pkt_nh->nh_encap_len)) + pkt_nh->nh_data, pkt_nh->nh_encap_len)) { + drop_reason = VP_DROP_REWRITE_FAIL; goto fail; + } } } } @@ -454,8 +459,10 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, 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; + } } pkt->vp_flags |= VP_FLAG_FROM_DP; @@ -463,8 +470,10 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, pkt->vp_flags |= (VP_FLAG_FLOW_SET | VP_FLAG_GSO | VP_FLAG_CSUM_PARTIAL); pkt->vp_flags &= ~VP_FLAG_GRO; buf = pkt_push(pkt, mirror_md_len); - if (!buf) + if (!buf) { + drop_reason = VP_DROP_PUSH; goto fail; + } captured_len = htonl(pkt_len(pkt)); if (mirror_md_len) @@ -473,8 +482,10 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, if (mirror->mir_flags & VR_MIRROR_PCAP) { /* Add the pcap header */ pcap = (struct vr_pcap *)pkt_push(pkt, sizeof(struct vr_pcap)); - if (!pcap) + if (!pcap) { + drop_reason = VP_DROP_PUSH; goto fail; + } pcap->pcap_incl_len = captured_len; pcap->pcap_orig_len = captured_len; @@ -495,7 +506,7 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, return 0; fail: - vr_pfree(pkt, VP_DROP_PUSH); + vr_pfree(pkt, drop_reason); return 0; }