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; }