Skip to content

Commit

Permalink
Merge "Add mirroring metadata for port mirroring"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Sep 6, 2016
2 parents f6b7478 + dfb1921 commit bbefef8
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 29 deletions.
179 changes: 161 additions & 18 deletions dp-core/vr_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,20 @@ vif_free(struct vr_interface *vif)
}
}

if (vif->vif_in_mirror_md) {
vif->vif_in_mirror_md_len = 0;
vif->vif_in_mirror_md_size = 0;
vr_free(vif->vif_in_mirror_md, VR_INTERFACE_MIRROR_META_OBJECT);
vif->vif_in_mirror_md = NULL;
}

if (vif->vif_out_mirror_md) {
vif->vif_out_mirror_md_len = 0;
vif->vif_out_mirror_md_size = 0;
vr_free(vif->vif_out_mirror_md, VR_INTERFACE_MIRROR_META_OBJECT);
vif->vif_out_mirror_md = NULL;
}

vr_free(vif, VR_INTERFACE_OBJECT);

return;
Expand Down Expand Up @@ -1723,6 +1737,81 @@ vif_set_flags(struct vr_interface *vif, vr_interface_req *req)
return;
}

static int
vr_interface_mirror_md_set(struct vr_interface *vif, vr_interface_req *req)
{
/*
* If metadata is removed from request, make our metadata len to
* zero, so that it does not get used in packet processeing. The
* memory will get freed only at the time of deletion of interface
* _size hold the allocated memory size, so that we would not over
* shoot while copying.
* It is also assumed that the interface metadata does not change
* once allocated
*/
if (!req->vifr_in_mirror_md_size)
vif->vif_in_mirror_md_len = 0;

if (!req->vifr_out_mirror_md_size)
vif->vif_out_mirror_md_len = 0;

if (req->vifr_in_mirror_md_size) {
if (!vif->vif_in_mirror_md) {
/*
* If there is no mirror md already, ensure we dont create
* more than the max size
*/
if (req->vifr_in_mirror_md_size > VIF_MAX_MIRROR_MD_SIZE)
req->vifr_in_mirror_md_size = VIF_MAX_MIRROR_MD_SIZE;

vif->vif_in_mirror_md =
vr_zalloc(req->vifr_in_mirror_md_size,
VR_INTERFACE_MIRROR_META_OBJECT);
if (!vif->vif_in_mirror_md)
return -ENOMEM;

vif->vif_in_mirror_md_size = req->vifr_in_mirror_md_size;
} else {
/*
* If mirror md already exists, we dont want the new len to
* be more than that
*/
if (req->vifr_in_mirror_md_size > vif->vif_in_mirror_md_size) {
req->vifr_in_mirror_md_size = vif->vif_in_mirror_md_size;
}
}

memcpy(vif->vif_in_mirror_md,
req->vifr_in_mirror_md, req->vifr_in_mirror_md_size);
vif->vif_in_mirror_md_len = req->vifr_in_mirror_md_size;
}

if (req->vifr_out_mirror_md_size) {
if (!vif->vif_out_mirror_md) {
if (req->vifr_out_mirror_md_size > VIF_MAX_MIRROR_MD_SIZE)
req->vifr_out_mirror_md_size = VIF_MAX_MIRROR_MD_SIZE;

vif->vif_out_mirror_md =
vr_zalloc(req->vifr_out_mirror_md_size,
VR_INTERFACE_MIRROR_META_OBJECT);
if (!vif->vif_out_mirror_md)
return -ENOMEM;

vif->vif_out_mirror_md_size = req->vifr_out_mirror_md_size;
} else {
if (req->vifr_out_mirror_md_size > vif->vif_out_mirror_md_size) {
req->vifr_out_mirror_md_size = vif->vif_out_mirror_md_size;
}
}

memcpy(vif->vif_out_mirror_md,
req->vifr_out_mirror_md, req->vifr_out_mirror_md_size);
vif->vif_out_mirror_md_len = req->vifr_out_mirror_md_size;
}

return 0;
}

static int
vr_interface_change(struct vr_interface *vif, vr_interface_req *req)
{
Expand Down Expand Up @@ -1754,6 +1843,10 @@ vr_interface_change(struct vr_interface *vif, vr_interface_req *req)
vif->vif_nh_id = (unsigned short)req->vifr_nh_id;
vif->vif_qos_map_index = req->vifr_qos_map_index;

ret = vr_interface_mirror_md_set(vif, req);
if (ret)
return ret;

if ((ret = vif_fat_flow_add(vif, req)))
return ret;

Expand Down Expand Up @@ -1786,14 +1879,14 @@ vr_interface_add(vr_interface_req *req, bool need_response)

if (!router || ((unsigned int)req->vifr_idx >= router->vr_max_interfaces)) {
ret = -EINVAL;
goto generate_resp;
goto error;
}

if (req->vifr_type >= VIF_TYPE_MAX && (ret = -EINVAL))
goto generate_resp;
goto error;

if (!vif_transport_valid(req))
goto generate_resp;
goto error;

vif = __vrouter_get_interface(router, req->vifr_idx);
if (vif) {
Expand All @@ -1804,35 +1897,29 @@ vr_interface_add(vr_interface_req *req, bool need_response)
vif = vr_zalloc(sizeof(*vif), VR_INTERFACE_OBJECT);
if (!vif) {
ret = -ENOMEM;
goto generate_resp;
goto error;
}

vif->vif_stats = vr_zalloc(vr_num_cpus *
sizeof(struct vr_interface_stats), VR_INTERFACE_STATS_OBJECT);
if (!vif->vif_stats) {
ret = -ENOMEM;
goto generate_resp;
goto error;
}

for (i = 0; i < vr_num_cpus; i++) {
vif->vif_stats[i].vis_queue_ierrors_to_lcore = vr_zalloc(vr_num_cpus *
sizeof(uint64_t), VR_INTERFACE_TO_LCORE_ERRORS_OBJECT);
if (!vif->vif_stats[i].vis_queue_ierrors_to_lcore) {
ret = -ENOMEM;
goto generate_resp;
goto error;
}
}

vif->vif_type = req->vifr_type;

vif_set_flags(vif, req);

vif->vif_mirror_id = req->vifr_mir_id;
if (!(vif->vif_flags & VIF_FLAG_MIRROR_RX) &&
!(vif->vif_flags & VIF_FLAG_MIRROR_TX)) {
vif->vif_mirror_id = VR_MAX_MIRROR_INDICES;
}

vif->vif_vrf = req->vifr_vrf;
vif->vif_vlan_id = VLAN_ID_INVALID;
vif->vif_mtu = req->vifr_mtu;
Expand All @@ -1845,10 +1932,19 @@ vr_interface_add(vr_interface_req *req, bool need_response)
vif->vif_nh_id = (unsigned short)req->vifr_nh_id;
vif->vif_qos_map_index = req->vifr_qos_map_index;

vif->vif_mirror_id = req->vifr_mir_id;
if (!(vif->vif_flags & VIF_FLAG_MIRROR_RX) &&
!(vif->vif_flags & VIF_FLAG_MIRROR_TX)) {
vif->vif_mirror_id = VR_MAX_MIRROR_INDICES;
}
ret = vr_interface_mirror_md_set(vif, req);
if (ret)
goto error;

if (req->vifr_mac) {
if (req->vifr_mac_size != sizeof(vif->vif_mac)) {
ret = -EINVAL;
goto generate_resp;
goto error;
}

memcpy(vif->vif_mac, req->vifr_mac, sizeof(vif->vif_mac));
Expand All @@ -1863,7 +1959,7 @@ vr_interface_add(vr_interface_req *req, bool need_response)

ret = vif_fat_flow_add(vif, req);
if (ret)
goto generate_resp;
goto error;

/*
* the order below is probably not intuitive, but we do this because
Expand All @@ -1875,7 +1971,7 @@ vr_interface_add(vr_interface_req *req, bool need_response)
vif->vif_tx = vif_discard_tx;
ret = vrouter_add_interface(vif, req);
if (ret)
goto generate_resp;
goto error;

ret = vif_drv_add(vif, req);
if (ret) {
Expand All @@ -1886,13 +1982,14 @@ vr_interface_add(vr_interface_req *req, bool need_response)
if (!ret)
vrouter_setup_vif(vif);

error:
if (ret && vif)
vif_free(vif);

generate_resp:
if (need_response)
vr_send_response(ret);

if (ret && vif)
vif_free(vif);

return ret;
}

Expand Down Expand Up @@ -1988,6 +2085,18 @@ __vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf,
req->vifr_src_mac_size = 0;
}

if (intf->vif_in_mirror_md_len) {
memcpy(req->vifr_in_mirror_md, intf->vif_in_mirror_md,
intf->vif_in_mirror_md_len);
req->vifr_in_mirror_md_size = intf->vif_in_mirror_md_len;
}

if (intf->vif_out_mirror_md_len) {
memcpy(req->vifr_out_mirror_md, intf->vif_out_mirror_md,
intf->vif_out_mirror_md_len);
req->vifr_out_mirror_md_size = intf->vif_out_mirror_md_len;
}

/* vif counters */
req->vifr_ibytes = 0;
req->vifr_ipackets = 0;
Expand Down Expand Up @@ -2107,6 +2216,18 @@ vr_interface_make_req(vr_interface_req *req, struct vr_interface *vif,
return 0;
}

unsigned int
vr_interface_req_get_size(void *req_p)
{
vr_interface_req *req = (vr_interface_req *)req_p;

/*
* Standard interface request size + both ingress and egress
* metadata size
*/
return ((4 * sizeof(*req)) + (2 * VIF_MAX_MIRROR_MD_SIZE));
}

static vr_interface_req *
vr_interface_req_get(void)
{
Expand All @@ -2131,6 +2252,14 @@ vr_interface_req_get(void)
if (req->vifr_queue_ierrors_to_lcore)
req->vifr_queue_ierrors_to_lcore_size = 0;

req->vifr_in_mirror_md_size = 0;
req->vifr_in_mirror_md = vr_zalloc(VIF_MAX_MIRROR_MD_SIZE,
VR_INTERFACE_REQ_MIRROR_META_OBJECT);

req->vifr_out_mirror_md_size = 0;
req->vifr_out_mirror_md = vr_zalloc(VIF_MAX_MIRROR_MD_SIZE,
VR_INTERFACE_REQ_MIRROR_META_OBJECT);

return req;
}

Expand Down Expand Up @@ -2173,6 +2302,20 @@ vr_interface_req_destroy(vr_interface_req *req)
req->vifr_queue_ierrors_to_lcore_size = 0;
}

if (req->vifr_in_mirror_md) {
vr_free(req->vifr_in_mirror_md,
VR_INTERFACE_REQ_MIRROR_META_OBJECT);
req->vifr_in_mirror_md_size = 0;
req->vifr_in_mirror_md = NULL;
}

if (req->vifr_out_mirror_md) {
vr_free(req->vifr_out_mirror_md,
VR_INTERFACE_REQ_MIRROR_META_OBJECT);
req->vifr_out_mirror_md_size = 0;
req->vifr_out_mirror_md = NULL;
}

vr_interface_req_free_fat_flow_config(req);

vr_free(req, VR_INTERFACE_REQ_OBJECT);
Expand Down
8 changes: 4 additions & 4 deletions dp-core/vr_mirror.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,14 +400,14 @@ vr_mirror(struct vrouter *router, uint8_t mirror_id, struct vr_packet *pkt,
if (!pkt->vp_if)
goto fail;

mirror_md_len = pkt->vp_if->vif_mirror_md_len;
mirror_md = pkt->vp_if->vif_mirror_md;
mirror_md_len = pkt->vp_if->vif_in_mirror_md_len;
mirror_md = pkt->vp_if->vif_in_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;
mirror_md_len = pkt->vp_nh->nh_dev->vif_out_mirror_md_len;
mirror_md = pkt->vp_nh->nh_dev->vif_out_mirror_md;
}

if (!mirror_md_len) {
Expand Down
1 change: 1 addition & 0 deletions dp-core/vr_sandesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct sandesh_object_md sandesh_md[] = {
},
[VR_INTERFACE_OBJECT_ID] = {
.obj_len = 4 * sizeof(vr_interface_req),
.obj_get_size = vr_interface_req_get_size,
.obj_type_string = "vr_interface_req",
},
[VR_NEXTHOP_OBJECT_ID] = {
Expand Down
7 changes: 6 additions & 1 deletion dp-core/vr_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,12 @@ vr_mem_stats_get(void)
stats_block[VR_QOS_MAP_OBJECT].ms_free);
response->vms_fc_object += (stats_block[VR_FC_OBJECT].ms_alloc -
stats_block[VR_FC_OBJECT].ms_free);

response->vms_interface_mirror_meta_object +=
(stats_block[VR_INTERFACE_MIRROR_META_OBJECT].ms_alloc -
stats_block[VR_INTERFACE_MIRROR_META_OBJECT].ms_free);
response->vms_interface_req_mirror_meta_object +=
(stats_block[VR_INTERFACE_REQ_MIRROR_META_OBJECT].ms_alloc -
stats_block[VR_INTERFACE_REQ_MIRROR_META_OBJECT].ms_free);
for (i = 0; i < VR_VROUTER_MAX_OBJECT; i++) {
alloced += stats_block[i].ms_alloc;
freed += stats_block[i].ms_free;
Expand Down
14 changes: 11 additions & 3 deletions include/vr_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define VIF_TYPE_MONITORING 9
#define VIF_TYPE_MAX 10


#define vif_is_virtual(vif) ((vif->vif_type == VIF_TYPE_VIRTUAL) ||\
(vif->vif_type == VIF_TYPE_VIRTUAL_VLAN))
#define vif_is_fabric(vif) (vif->vif_type == VIF_TYPE_PHYSICAL)
Expand Down Expand Up @@ -58,6 +59,7 @@


#define VR_INTERFACE_NAME_LEN 64
#define VIF_MAX_MIRROR_MD_SIZE 255

#define VIF_TRANSPORT_VIRTUAL 0
#define VIF_TRANSPORT_ETH 1
Expand Down Expand Up @@ -267,12 +269,16 @@ struct vr_interface {
unsigned char *vif_src_mac;
vr_htable_t vif_btable;
unsigned char vif_rewrite[VR_ETHER_HLEN];
int16_t vif_qos_map_index;
unsigned char *vif_in_mirror_md;
unsigned char *vif_out_mirror_md;
unsigned char vif_in_mirror_md_len;
unsigned char vif_in_mirror_md_size;
unsigned char vif_out_mirror_md_len;
unsigned char vif_out_mirror_md_size;
unsigned char vif_name[VR_INTERFACE_NAME_LEN];
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 Expand Up @@ -317,6 +323,8 @@ extern int vif_vrf_table_get(struct vr_interface *, vr_vrf_assign_req *);
extern unsigned int vif_vrf_table_get_nh(struct vr_interface *, unsigned short);
extern int vif_vrf_table_set(struct vr_interface *, unsigned int,
int, unsigned int);
extern unsigned int vr_interface_req_get_size(void *);

#if defined(__linux__) && defined(__KERNEL__)
extern void vr_set_vif_ptr(struct net_device *dev, void *vif);
#endif
Expand Down

0 comments on commit bbefef8

Please sign in to comment.