Skip to content

Commit

Permalink
Merge "Mirroring Changes for Static/Dynamic Mirroring" into R3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Jul 26, 2016
2 parents 81945c6 + 7b054f5 commit 6c21bbc
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 103 deletions.
3 changes: 2 additions & 1 deletion dp-core/vr_datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,8 @@ vr_virtual_input(unsigned short vrf, struct vr_interface *vif,
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);
vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &mfmd,
MIRROR_TYPE_PORT_RX);
}


Expand Down
6 changes: 4 additions & 2 deletions dp-core/vr_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,12 +829,14 @@ vr_flow_action(struct vrouter *router, struct vr_flow_entry *fe,
if (fe->fe_mirror_id < VR_MAX_MIRROR_INDICES) {
mirror_fmd = *fmd;
mirror_fmd.fmd_ecmp_nh_index = -1;
vr_mirror(router, fe->fe_mirror_id, pkt, &mirror_fmd);
vr_mirror(router, fe->fe_mirror_id, pkt, &mirror_fmd,
MIRROR_TYPE_ACL);
}
if (fe->fe_sec_mirror_id < VR_MAX_MIRROR_INDICES) {
mirror_fmd = *fmd;
mirror_fmd.fmd_ecmp_nh_index = -1;
vr_mirror(router, fe->fe_sec_mirror_id, pkt, &mirror_fmd);
vr_mirror(router, fe->fe_sec_mirror_id, pkt, &mirror_fmd,
MIRROR_TYPE_ACL);
}
}

Expand Down
3 changes: 2 additions & 1 deletion dp-core/vr_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,8 @@ eth_tx(struct vr_interface *vif, struct vr_packet *pkt,
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);
vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &m_fmd,
MIRROR_TYPE_PORT_TX);
}

ret = hif_ops->hif_tx(vif, pkt);
Expand Down
147 changes: 90 additions & 57 deletions dp-core/vr_mirror.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,18 @@ vr_mirror_change(struct vr_mirror_entry *mirror, vr_mirror_req *req,
{
struct vr_nexthop *nh_old = mirror->mir_nh;

if (mirror->mir_flags & VR_MIRROR_FLAG_MARKED_DELETE) {
mirror->mir_flags &= ~VR_MIRROR_FLAG_MARKED_DELETE;
if (mirror->mir_flags & VR_MIRROR_FLAG_MARKED_DELETE)
mirror->mir_users++;
}

mirror->mir_flags |= req->mirr_flags;
mirror->mir_nh = nh_new;
vrouter_put_nexthop(nh_old);
mirror->mir_flags = req->mirr_flags;
mirror->mir_flags &= ~VR_MIRROR_FLAG_MARKED_DELETE;
mirror->mir_rid = req->mirr_rid;
mirror->mir_vni = req->mirr_vni;
if (nh_old != nh_new) {
mirror->mir_nh = nh_new;
if (nh_old)
vrouter_put_nexthop(nh_old);
}

return 0;
}
Expand Down Expand Up @@ -143,16 +147,12 @@ vr_mirror_add(vr_mirror_req *req)
}

mirror = __vrouter_get_mirror(req->mirr_rid, req->mirr_index);
if (mirror) {
vr_mirror_change(mirror, req, nh);
} else {
if (!mirror) {
mirror = vr_zalloc(sizeof(*mirror), VR_MIRROR_OBJECT);
mirror->mir_users++;
mirror->mir_nh = nh;
mirror->mir_rid = req->mirr_rid;
mirror->mir_flags = req->mirr_flags;
router->vr_mirrors[req->mirr_index] = mirror;
}
ret = vr_mirror_change(mirror, req, nh);
router->vr_mirrors[req->mirr_index] = mirror;

generate_resp:
vr_send_response(ret);
Expand All @@ -172,6 +172,7 @@ vr_mirror_make_req(vr_mirror_req *req, struct vr_mirror_entry *mirror,
req->mirr_users = mirror->mir_users;
req->mirr_flags = mirror->mir_flags;
req->mirr_rid = mirror->mir_rid;
req->mirr_vni = mirror->mir_vni;
return;
}

Expand Down Expand Up @@ -365,27 +366,28 @@ vr_mirror_meta_entry_del(struct vrouter *router, unsigned int index)
}

int
vr_mirror(struct vrouter *router, uint8_t mirror_id,
struct vr_packet *pkt, struct vr_forwarding_md *fmd)
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 = VR_MIRROR_PKT_HEAD_SPACE,
mirror_md_len = 0;
unsigned char default_mme[2] = {0xff, 0x0};
unsigned int captured_len, clone_len = 0, mirror_md_len = 0;
unsigned long sec, usec;

void *mirror_md;
unsigned char *buf;
struct vr_nexthop *nh, *pkt_nh;
struct vr_pcap *pcap;
struct vr_mirror_entry *mirror;
struct vr_mirror_meta_entry *mme;
unsigned char default_mme[2] = {0xff, 0x0};
struct vr_forwarding_md new_fmd;

/* If the packet is already mirrored, dont mirror again */
if (pkt->vp_flags & VP_FLAG_FROM_DP)
return 0;

if (mtype <= MIRROR_TYPE_UNKNOWN || mtype >= MIRROR_TYPE_MAX)
return 0;

mirror = router->vr_mirrors[mirror_id];
if (!mirror)
return 0;
Expand All @@ -399,48 +401,84 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id,
}
fmd = &new_fmd;

if (fmd->fmd_flow_index >= 0) {
mme = (struct vr_mirror_meta_entry *)vr_itable_get(router->vr_mirror_md,
fmd->fmd_flow_index);
if (!mme)
return 0;
mirror_md_len = mme->mirror_md_len;
mirror_md = mme->mirror_md;
fmd->fmd_dvrf = mme->mirror_vrf;
} else {
mirror_md_len = sizeof(default_mme);
mirror_md = default_mme;
}

clone_len += mirror_md_len;
nh = mirror->mir_nh;
if (!nh || !(nh->nh_flags & NH_FLAG_VALID))
return 0;

pkt = vr_pclone(pkt);
if (!pkt)
return 0;

/* If packet is from fabric, mirror it by adding the required L2
* header. If not get the processed headers by resetting the packet
* and mirror it
*/
if (pkt->vp_if && (pkt->vp_if->vif_type == VIF_TYPE_PHYSICAL)) {
pkt_nh = pkt->vp_nh;
if (pkt_nh && (pkt_nh->nh_flags & NH_FLAG_VALID) &&
(pkt_nh->nh_type == NH_ENCAP)) {
/* Mark as mirrored */
pkt->vp_flags |= VP_FLAG_FROM_DP;

/* Set the GSO and partial checksum flag */
pkt->vp_flags |= (VP_FLAG_FLOW_SET | VP_FLAG_GSO);
pkt->vp_flags &= ~VP_FLAG_GRO;

if (mirror->mir_flags & VR_MIRROR_FLAG_DYNAMIC) {

reset = false;
clone_len += sizeof(struct vr_pcap);

if (mtype == MIRROR_TYPE_ACL) {
if (fmd->fmd_flow_index >= 0) {
if (pkt_nh->nh_family == AF_INET)
clone_len += pkt_nh->nh_encap_len;
mme = (struct vr_mirror_meta_entry *)
vr_itable_get(router->vr_mirror_md, fmd->fmd_flow_index);
if (mme) {
mirror_md_len = mme->mirror_md_len;
mirror_md = mme->mirror_md;
}
}
} else if (mtype == MIRROR_TYPE_PORT_RX) {
if (!pkt->vp_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;

mirror_md_len = pkt->vp_nh->nh_dev->vif_mirror_md_len;
mirror_md = pkt->vp_nh->nh_dev->vif_mirror_md;
}

if (!mirror_md_len) {
mirror_md = default_mme;
mirror_md_len = sizeof(default_mme);
}

clone_len += mirror_md_len;
clone_len += VR_MIRROR_PKT_HEAD_SPACE;
} else {
clone_len += VR_VXLAN_HDR_LEN;
fmd->fmd_label = mirror->mir_vni;
}

if (pkt->vp_if && (pkt->vp_if->vif_type == VIF_TYPE_PHYSICAL)) {
/* No need to mirror the Tunnel headers. So packet cant be reset */
reset = false;

/* Identify whether the packet currently has L2 header. If not a
* port mirroring, we need to add the extra L2 header
*/
if (mtype == MIRROR_TYPE_ACL) {

pkt_nh = pkt->vp_nh;
if (pkt_nh && (pkt_nh->nh_flags & NH_FLAG_VALID) &&
(pkt_nh->nh_type == NH_ENCAP) &&
(pkt_nh->nh_family == AF_INET)) {

clone_len += pkt_nh->nh_encap_len;


if (vr_pcow(pkt, clone_len))
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,
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;
}
}
}
}
Expand All @@ -453,19 +491,14 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id,
goto fail;
}

pkt->vp_flags |= VP_FLAG_FROM_DP;
/* Set the GSO and partial checksum flag */
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)
goto fail;

captured_len = htonl(pkt_len(pkt));
if (mirror_md_len)
if (mirror_md_len) {

buf = pkt_push(pkt, mirror_md_len);
if (!buf)
goto fail;
memcpy(buf, mirror_md, mirror_md_len);

if (mirror->mir_flags & VR_MIRROR_PCAP) {
/* Add the pcap header */
pcap = (struct vr_pcap *)pkt_push(pkt, sizeof(struct vr_pcap));
if (!pcap)
Expand Down
16 changes: 9 additions & 7 deletions dp-core/vr_nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -1424,21 +1424,21 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh,
if (!fmd)
goto send_fail;

head_space = sizeof(struct vr_udp) + VR_ETHER_HLEN;

if (nh->nh_family == AF_INET)
head_space = VR_UDP_HEAD_SPACE;
head_space += sizeof(struct vr_ip);
else if (nh->nh_family == AF_INET6)
head_space = VR_UDP6_HEAD_SPACE;
head_space += sizeof(struct vr_ip6);
else
goto send_fail;

if (pkt_head_space(pkt) < head_space) {
tmp = vr_palloc_head(pkt, head_space);
if (!tmp)
tmp = vr_pexpand_head(pkt, head_space - pkt_head_space(pkt));
if (!tmp) {
goto send_fail;

}
pkt = tmp;
if (!pkt_reserve_head_space(pkt, head_space))
goto send_fail;
}

if (nh->nh_family == AF_INET) {
Expand All @@ -1463,6 +1463,7 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh,
ip = (struct vr_ip *)(pkt_data(pkt));
udp = (struct vr_udp *)((char *)ip + ip->ip_hl * 4);
udp->udp_csum = vr_ip_partial_csum(ip);
pkt->vp_flags |= VP_FLAG_CSUM_PARTIAL;

} else if (nh->nh_family == AF_INET6) {
if (nh_udp_tunnel6_helper(pkt, nh) == false) {
Expand All @@ -1472,6 +1473,7 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh,
ip6 = (struct vr_ip6 *)(pkt_data(pkt));
udp = (struct vr_udp *)((char *)ip6 + sizeof(struct vr_ip6));
udp->udp_csum = vr_ip6_partial_csum(ip6);
pkt->vp_flags |= VP_FLAG_CSUM_PARTIAL;
}


Expand Down
2 changes: 1 addition & 1 deletion include/nl_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ extern int vr_send_mirror_get(struct nl_client *, unsigned int, unsigned int);
extern int vr_send_mirror_delete(struct nl_client *,
unsigned int, unsigned int);
extern int vr_send_mirror_add(struct nl_client *, unsigned int,
unsigned int, int, unsigned int);
unsigned int, int, unsigned int, int);
extern void vr_mirror_req_destroy(vr_mirror_req *);
extern vr_mirror_req *vr_mirror_get_req_copy(vr_mirror_req *);

Expand Down
2 changes: 2 additions & 0 deletions include/vr_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ struct vr_interface {
unsigned short vif_vrf_table_users;
unsigned int vif_ip;
int16_t vif_qos_map_index;
unsigned short vif_mirror_md_len;
unsigned char *vif_mirror_md;
};

struct vr_interface_settings {
Expand Down
22 changes: 19 additions & 3 deletions include/vr_mirror.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,33 @@

#define VR_MAX_MIRROR_INDICES 255
#define VR_MIRROR_FLAG_MARKED_DELETE 0x1
#define VR_MIRROR_FLAG_DYNAMIC 0x2

#define VR_MIRROR_MME 0x1
#define VR_MIRROR_PCAP 0x2

struct vrouter;
struct vr_packet;

typedef enum {
MIRROR_TYPE_UNKNOWN,
MIRROR_TYPE_PORT_RX,
MIRROR_TYPE_PORT_TX,
MIRROR_TYPE_ACL,
MIRROR_TYPE_MAX
} mirror_type_t;

/* Mirror packet can be either MPLSoGre or MPLSoUDP. Lets calculate the
* highest for head space */
#define VR_MIRROR_PKT_HEAD_SPACE (sizeof(struct vr_pcap) + \
sizeof(struct vr_udp) + sizeof(struct vr_ip6) + \
VR_MPLS_HDR_LEN + sizeof(struct vr_udp) + sizeof(struct vr_ip) + \
VR_ETHER_HLEN)


struct vr_mirror_entry {
unsigned int mir_users:20;
unsigned int mir_flags:12;
unsigned int mir_rid;
int mir_vni;
struct vr_nexthop *mir_nh;
};

Expand All @@ -34,7 +50,7 @@ struct vr_forwarding_md;
extern int vr_mirror_init(struct vrouter *);
extern void vr_mirror_exit(struct vrouter *, bool);
extern int vr_mirror(struct vrouter *, uint8_t, struct vr_packet *,
struct vr_forwarding_md *);
struct vr_forwarding_md *, mirror_type_t);
extern struct vr_mirror_entry *vrouter_get_mirror(unsigned int, unsigned int);
extern int vrouter_put_mirror(struct vrouter *, unsigned int);
extern int vr_mirror_meta_entry_set(struct vrouter *, unsigned int,
Expand Down
7 changes: 0 additions & 7 deletions include/vr_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -826,13 +826,6 @@ struct vr_vxlan {

#define VR_VXLAN_IBIT 0x08000000
#define VR_VXLAN_RABIT 0x01000000
#define VR_UDP_HEAD_SPACE 62 /* eth + Ip + iP + udp */
#define VR_UDP6_HEAD_SPACE 82 /* eth + Ip + iP6 + udp */

/* Mirror packet can be either MPLSoGre or MPLSoUDP. Lets calculate the
* highest for head space */
#define VR_MIRROR_PKT_HEAD_SPACE (VR_UDP_HEAD_SPACE + sizeof(struct vr_pcap) + \
VR_MPLS_HDR_LEN + sizeof(struct vr_udp))

/*
* Mcast packet adds the following before replicating
Expand Down
1 change: 1 addition & 0 deletions sandesh/vr.sandesh
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ buffer sandesh vr_mirror_req {
5: i32 mirr_users;
6: i32 mirr_flags;
7: i32 mirr_marker;
8: i32 mirr_vni;
}

buffer sandesh vr_flow_req {
Expand Down

0 comments on commit 6c21bbc

Please sign in to comment.