From cb0fe903bb78685424902373a1a2890cb751b786 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Thu, 2 Jul 2015 15:16:20 +0530 Subject: [PATCH] Memory alloc and free statistics It will be useful to have statistics that track the memory allocated and freed in vRouter, specifically to debug memory leak issues. vRouter will track alloc and free statistics per object and export that information to applications. Change-Id: I7ca347eb76277cf1b581c9497dda76703be2be4e Closes-BUG: #1470798 --- dp-core/vr_bridge.c | 4 +- dp-core/vr_btable.c | 6 +- dp-core/vr_flow.c | 45 ++--- dp-core/vr_fragment.c | 32 ++-- dp-core/vr_htable.c | 4 +- dp-core/vr_index_table.c | 36 ++-- dp-core/vr_interface.c | 67 ++++--- dp-core/vr_ip_mtrie.c | 40 +++-- dp-core/vr_message.c | 14 +- dp-core/vr_mirror.c | 20 +-- dp-core/vr_nexthop.c | 35 ++-- dp-core/vr_route.c | 9 +- dp-core/vr_sandesh.c | 4 + dp-core/vr_stats.c | 270 +++++++++++++++++++++++++++- dp-core/vrouter.c | 11 +- dpdk/vr_dpdk_host.c | 32 ++-- dpdk/vr_dpdk_netlink.c | 4 +- dpdk/vr_dpdk_usocket.c | 31 ++-- freebsd/vrouter_mod.c | 4 +- host/vr_host_packet.c | 4 +- host/vrouter_host_mod.c | 10 +- include/vr_message.h | 1 + include/vrouter.h | 71 +++++++- linux/vr_fragment_assembler.c | 10 +- linux/vrouter_mod.c | 24 ++- sandesh/vr.sandesh | 61 +++++++ utils/SConscript | 6 +- utils/nl_util.c | 7 + utils/vrmemstats.c | 324 ++++++++++++++++++++++++++++++++++ 29 files changed, 979 insertions(+), 207 deletions(-) create mode 100644 utils/vrmemstats.c diff --git a/dp-core/vr_bridge.c b/dp-core/vr_bridge.c index 222f8e273..afe64508f 100644 --- a/dp-core/vr_bridge.c +++ b/dp-core/vr_bridge.c @@ -297,7 +297,7 @@ bridge_entry_make_req(struct vr_route_req *resp, struct vr_bridge_entry *ent) { memset(resp, 0, sizeof(struct vr_route_req)); resp->rtr_req.rtr_mac_size = VR_ETHER_ALEN; - resp->rtr_req.rtr_mac = vr_zalloc(VR_ETHER_ALEN); + resp->rtr_req.rtr_mac = vr_zalloc(VR_ETHER_ALEN, VR_ROUTE_REQ_MAC_OBJECT); if (!resp->rtr_req.rtr_mac) return -ENOMEM; VR_MAC_COPY(resp->rtr_req.rtr_mac, ent->be_key.be_mac); @@ -316,7 +316,7 @@ static void bridge_entry_req_destroy(struct vr_route_req *resp) { if (resp->rtr_req.rtr_mac) - vr_free(resp->rtr_req.rtr_mac); + vr_free(resp->rtr_req.rtr_mac, VR_ROUTE_REQ_MAC_OBJECT); } static int diff --git a/dp-core/vr_btable.c b/dp-core/vr_btable.c index 429ba7671..7f949ed4b 100644 --- a/dp-core/vr_btable.c +++ b/dp-core/vr_btable.c @@ -82,7 +82,7 @@ vr_btable_free(struct vr_btable *table) } } - vr_free(table); + vr_free(table, VR_BTABLE_OBJECT); return; } @@ -126,7 +126,7 @@ vr_btable_alloc(unsigned int num_entries, unsigned int entry_size) alloc_size = sizeof(*table) + (total_parts * (sizeof(void *))) + (total_parts * sizeof(struct vr_btable_partition)); - table = vr_zalloc(alloc_size); + table = vr_zalloc(alloc_size, VR_BTABLE_OBJECT); if (!table) return NULL; @@ -186,7 +186,7 @@ vr_btable_attach(struct iovec *iov, unsigned int iov_len, alloc_size += (sizeof(struct vr_btable_partition) * iov_len); - table = (struct vr_btable *)vr_zalloc(alloc_size); + table = (struct vr_btable *)vr_zalloc(alloc_size, VR_BTABLE_OBJECT); if (!table) return NULL; diff --git a/dp-core/vr_flow.c b/dp-core/vr_flow.c index d8fcf67d0..15c2a6db7 100644 --- a/dp-core/vr_flow.c +++ b/dp-core/vr_flow.c @@ -312,7 +312,7 @@ vr_flow_queue_free(struct vrouter *router, void *arg) vr_flow_set_forwarding_md(router, fe, vfq->vfq_index, &fmd); vr_flush_flow_queue(router, fe, &fmd, vfq); } - vr_free(vfq); + vr_free(vfq, VR_FLOW_QUEUE_OBJECT); return; } @@ -322,7 +322,7 @@ vr_flow_queue_free_defer(struct vr_flow_md *flmd, struct vr_flow_queue *vfq) struct vr_defer_data *vdd = flmd->flmd_defer_data; if (!vdd) { - vr_free(vfq); + vr_free(vfq, VR_FLOW_QUEUE_OBJECT); return; } @@ -377,7 +377,8 @@ vr_find_free_entry(struct vrouter *router, struct vr_flow *key, uint8_t type, if (fe) { *fe_index += index; if (need_hold) { - fe->fe_hold_list = vr_zalloc(sizeof(struct vr_flow_queue)); + fe->fe_hold_list = vr_zalloc(sizeof(struct vr_flow_queue), + VR_FLOW_QUEUE_OBJECT); if (!fe->fe_hold_list) { vr_reset_flow_entry(router, fe, *fe_index); fe = NULL; @@ -1126,7 +1127,7 @@ vr_flow_flush(void *arg) } exit_flush: - vr_free(flmd); + vr_free(flmd, VR_FLOW_METADATA_OBJECT); return; } @@ -1292,7 +1293,8 @@ vr_flow_schedule_transition(struct vrouter *router, vr_flow_req *req, struct vr_flow_md *flmd; struct vr_defer_data *defer = NULL; - flmd = (struct vr_flow_md *)vr_malloc(sizeof(*flmd)); + flmd = (struct vr_flow_md *)vr_malloc(sizeof(*flmd), + VR_FLOW_METADATA_OBJECT); if (!flmd) return -ENOMEM; @@ -1302,7 +1304,7 @@ vr_flow_schedule_transition(struct vrouter *router, vr_flow_req *req, if (fe->fe_hold_list) { defer = vr_get_defer_data(sizeof(*defer)); if (!defer) { - vr_free(flmd); + vr_free(flmd, VR_FLOW_METADATA_OBJECT); return -ENOMEM; } } @@ -1409,7 +1411,8 @@ vr_flow_set(struct vrouter *router, vr_flow_req *req) if ((req->fr_action == VR_FLOW_ACTION_HOLD) && (fe->fe_action != req->fr_action)) { if (!fe->fe_hold_list) { - fe->fe_hold_list = vr_zalloc(sizeof(struct vr_flow_queue)); + fe->fe_hold_list = vr_zalloc(sizeof(struct vr_flow_queue), + VR_FLOW_QUEUE_OBJECT); if (!fe->fe_hold_list) return -ENOMEM; } @@ -1479,17 +1482,17 @@ vr_flow_req_destroy(vr_flow_req *req) return; if (req->fr_file_path) { - vr_free(req->fr_file_path); + vr_free(req->fr_file_path, VR_FLOW_REQ_PATH_OBJECT); req->fr_file_path = NULL; } if (req->fr_hold_stat && req->fr_hold_stat_size) { - vr_free(req->fr_hold_stat); + vr_free(req->fr_hold_stat, VR_FLOW_HOLD_STAT_OBJECT); req->fr_hold_stat = NULL; req->fr_hold_stat_size = 0; } - vr_free(req); + vr_free(req, VR_FLOW_REQ_OBJECT); return; } @@ -1499,7 +1502,7 @@ vr_flow_req_get(vr_flow_req *ref_req) { unsigned int hold_stat_size; unsigned int num_cpus = vr_num_cpus; - vr_flow_req *req = vr_zalloc(sizeof(*req)); + vr_flow_req *req = vr_zalloc(sizeof(*req), VR_FLOW_REQ_OBJECT); if (!req) return NULL; @@ -1512,9 +1515,10 @@ vr_flow_req_get(vr_flow_req *ref_req) } if (vr_flow_path) { - req->fr_file_path = vr_zalloc(VR_UNIX_PATH_MAX); + req->fr_file_path = vr_zalloc(VR_UNIX_PATH_MAX, + VR_FLOW_REQ_PATH_OBJECT); if (!req->fr_file_path) { - vr_free(req); + vr_free(req, VR_FLOW_REQ_OBJECT); return NULL; } } @@ -1523,14 +1527,14 @@ vr_flow_req_get(vr_flow_req *ref_req) num_cpus = VR_FLOW_MAX_CPUS; hold_stat_size = num_cpus * sizeof(uint32_t); - req->fr_hold_stat = vr_zalloc(hold_stat_size); + req->fr_hold_stat = vr_zalloc(hold_stat_size, VR_FLOW_HOLD_STAT_OBJECT); if (!req->fr_hold_stat) { if (vr_flow_path && req->fr_file_path) { - vr_free(req->fr_file_path); + vr_free(req->fr_file_path, VR_FLOW_REQ_PATH_OBJECT); req->fr_file_path = NULL; } - vr_free(req); + vr_free(req, VR_FLOW_REQ_OBJECT); return NULL; } req->fr_hold_stat_size = num_cpus; @@ -1613,7 +1617,7 @@ vr_flow_table_info_destroy(struct vrouter *router) if (!router->vr_flow_table_info) return; - vr_free(router->vr_flow_table_info); + vr_free(router->vr_flow_table_info, VR_FLOW_TABLE_INFO_OBJECT); router->vr_flow_table_info = NULL; router->vr_flow_table_info_size = 0; @@ -1640,7 +1644,8 @@ vr_flow_table_info_init(struct vrouter *router) return 0; size = sizeof(struct vr_flow_table_info) + sizeof(uint32_t) * vr_num_cpus; - infop = (struct vr_flow_table_info *)vr_zalloc(size); + infop = (struct vr_flow_table_info *)vr_zalloc(size, + VR_FLOW_TABLE_INFO_OBJECT); if (!infop) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); @@ -1758,7 +1763,7 @@ static void vr_link_local_ports_exit(struct vrouter *router) { if (router->vr_link_local_ports) { - vr_free(router->vr_link_local_ports); + vr_free(router->vr_link_local_ports, VR_FLOW_LINK_LOCAL_OBJECT); router->vr_link_local_ports = NULL; router->vr_link_local_ports_size = 0; } @@ -1779,7 +1784,7 @@ vr_link_local_ports_init(struct vrouter *router) /* Bits to Bytes */ bytes /= 8; - router->vr_link_local_ports = vr_zalloc(bytes); + router->vr_link_local_ports = vr_zalloc(bytes, VR_FLOW_LINK_LOCAL_OBJECT); if (!router->vr_link_local_ports) return -1; router->vr_link_local_ports_size = bytes; diff --git a/dp-core/vr_fragment.c b/dp-core/vr_fragment.c index 6618b83c9..364d9fe9f 100644 --- a/dp-core/vr_fragment.c +++ b/dp-core/vr_fragment.c @@ -151,7 +151,7 @@ vr_fragment_queue_element_free(struct vr_fragment_queue_element *vfqe, vr_pfree(vfqe->fqe_pnode.pl_packet, drop_reason); } - vr_free(vfqe); + vr_free(vfqe, VR_FRAGMENT_QUEUE_ELEMENT_OBJECT); return; } @@ -165,7 +165,7 @@ fragment_free_frag(struct vr_fragment *frag) vr_fragment_queue_element_free(fqe, VP_DROP_FRAGMENTS); } - vr_free(frag); + vr_free(frag, VR_FRAGMENT_OBJECT); return; } @@ -217,7 +217,7 @@ vr_assembler_table_scan_exit(void) { if (vr_assembler_table_scan_timer) { vr_delete_timer(vr_assembler_table_scan_timer); - vr_free(vr_assembler_table_scan_timer); + vr_free(vr_assembler_table_scan_timer, VR_TIMER_OBJECT); vr_assembler_table_scan_timer = NULL; } @@ -229,7 +229,7 @@ vr_assembler_table_scan_init(void (*scanner)(void *)) { struct vr_timer *vtimer; - vr_assembler_table_scan_timer = vr_zalloc(sizeof(*vtimer)); + vr_assembler_table_scan_timer = vr_zalloc(sizeof(*vtimer), VR_TIMER_OBJECT); if (!vr_assembler_table_scan_timer) return -ENOMEM; @@ -239,7 +239,7 @@ vr_assembler_table_scan_init(void (*scanner)(void *)) vtimer->vt_msecs = (VR_ASSEMBLER_TIMEOUT_TIME * 1000) / VR_LINUX_ASSEMBLER_BUCKETS; if (vr_create_timer(vtimer)) { - vr_free(vtimer); + vr_free(vtimer, VR_TIMER_OBJECT); vr_assembler_table_scan_timer = NULL; } @@ -288,7 +288,7 @@ vr_fragment_assembler(struct vr_fragment **head_p, (list_length > VR_MAX_FRAGMENTS_PER_ASSEMBLER_QUEUE)) goto exit_assembly; - frag = vr_zalloc(sizeof(*frag)); + frag = vr_zalloc(sizeof(*frag), VR_FRAGMENT_OBJECT); if (!frag) { ret = -ENOMEM; goto exit_assembly; @@ -398,7 +398,7 @@ vr_fragment_enqueue(struct vrouter *router, goto fail; } - fqe = vr_malloc(sizeof(*fqe)); + fqe = vr_malloc(sizeof(*fqe), VR_FRAGMENT_QUEUE_ELEMENT_OBJECT); if (!fqe) { goto fail; } @@ -439,7 +439,7 @@ vr_fragment_enqueue(struct vrouter *router, fail: if (fqe) - vr_free(fqe); + vr_free(fqe, VR_FRAGMENT_QUEUE_ELEMENT_OBJECT); vr_pfree(pkt, VP_DROP_FRAGMENTS); return -1; @@ -592,7 +592,7 @@ fragment_table_scanner_init(struct vrouter *router, struct vr_btable *table) num_entries = vr_btable_entries(table); - scanner = vr_zalloc(sizeof(*scanner)); + scanner = vr_zalloc(sizeof(*scanner), VR_FRAGMENT_SCANNER_OBJECT); if (!scanner) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); return NULL; @@ -603,7 +603,7 @@ fragment_table_scanner_init(struct vrouter *router, struct vr_btable *table) scanner->sp_num_entries = num_entries; scanner->sp_last_scanned_entry = -1; - vtimer = vr_malloc(sizeof(*vtimer)); + vtimer = vr_malloc(sizeof(*vtimer), VR_TIMER_OBJECT); if (!vtimer) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); goto fail_init; @@ -622,7 +622,7 @@ fragment_table_scanner_init(struct vrouter *router, struct vr_btable *table) fail_init: if (scanner) - vr_free(scanner); + vr_free(scanner, VR_FRAGMENT_SCANNER_OBJECT); return NULL; } @@ -632,15 +632,17 @@ vr_fragment_table_scanner_exit(struct vrouter *router) { if (router->vr_fragment_table_scanner) { vr_delete_timer(router->vr_fragment_table_scanner); - vr_free(router->vr_fragment_table_scanner->vt_vr_arg); - vr_free(router->vr_fragment_table_scanner); + vr_free(router->vr_fragment_table_scanner->vt_vr_arg, + VR_FRAGMENT_SCANNER_OBJECT); + vr_free(router->vr_fragment_table_scanner, VR_TIMER_OBJECT); router->vr_fragment_table_scanner = NULL; } if (router->vr_fragment_otable_scanner) { vr_delete_timer(router->vr_fragment_otable_scanner); - vr_free(router->vr_fragment_otable_scanner->vt_vr_arg); - vr_free(router->vr_fragment_otable_scanner); + vr_free(router->vr_fragment_otable_scanner->vt_vr_arg, + VR_FRAGMENT_SCANNER_OBJECT); + vr_free(router->vr_fragment_otable_scanner, VR_TIMER_OBJECT); router->vr_fragment_otable_scanner = NULL; } diff --git a/dp-core/vr_htable.c b/dp-core/vr_htable.c index 758036d56..6c564b3ec 100644 --- a/dp-core/vr_htable.c +++ b/dp-core/vr_htable.c @@ -203,7 +203,7 @@ vr_htable_delete(vr_htable_t htable) if (table->otable) vr_btable_free(table->otable); - vr_free(table); + vr_free(table, VR_HTABLE_OBJECT); } vr_htable_t @@ -222,7 +222,7 @@ vr_htable_create(unsigned int entries, unsigned int oentries, return NULL; } - table = vr_zalloc(sizeof(struct vr_htable)); + table = vr_zalloc(sizeof(struct vr_htable), VR_HTABLE_OBJECT); if (!table) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, sizeof(struct vr_htable)); diff --git a/dp-core/vr_index_table.c b/dp-core/vr_index_table.c index 7e30f55ce..bbbeb9047 100644 --- a/dp-core/vr_index_table.c +++ b/dp-core/vr_index_table.c @@ -74,7 +74,7 @@ __vr_itable_del(struct vr_itbl *table, unsigned int index, if (*old) { ptr[id] = NULL; if (vr_stride_empty(ptr, table->stride_len[cnt]) == 1) { - vr_free(ptr); + vr_free(ptr, VR_ITABLE_OBJECT); return 1; } } @@ -92,7 +92,7 @@ __vr_itable_del(struct vr_itbl *table, unsigned int index, */ ptr[id] = NULL; if (vr_stride_empty(ptr, table->stride_len[cnt]) == 1) { - vr_free(ptr); + vr_free(ptr, VR_ITABLE_OBJECT); /* If the stride deleted is first, mark the head null */ if (cnt == 0) { @@ -178,7 +178,7 @@ __vr_itable_exit(struct vr_itbl *table, vr_itable_del_cb_t func, } /* All stride entries are delete invoked. Delete the stride now */ - vr_free(ptr); + vr_free(ptr, VR_ITABLE_OBJECT); return; } @@ -189,13 +189,13 @@ __vr_itable_exit(struct vr_itbl *table, vr_itable_del_cb_t func, /* Upper strides are deleted. Delete the current */ ptr[i] = NULL; - vr_free(ptr[i]); + vr_free(ptr[i], VR_ITABLE_OBJECT); } } /* Destruct the head as well*/ if (cnt == 0) { - vr_free(table->data); + vr_free(table->data, VR_ITABLE_OBJECT); table->data = NULL; } @@ -304,7 +304,8 @@ vr_itable_set(vr_itable_t t, unsigned int index, void *data) } if (!table->data) { - table->data = vr_zalloc(table->stride_len[0] * sizeof(void *)); + table->data = vr_zalloc(table->stride_len[0] * sizeof(void *), + VR_ITABLE_OBJECT); if (!table->data) { return VR_ITABLE_ERR_PTR; } @@ -315,7 +316,8 @@ vr_itable_set(vr_itable_t t, unsigned int index, void *data) id = (index >> table->stride_shift[i]) & (table->stride_len[i] - 1); if (!ptr[id]) { - ptr[id] = vr_zalloc(table->stride_len[i + 1] * sizeof(void *)); + ptr[id] = vr_zalloc(table->stride_len[i + 1] * sizeof(void *), + VR_ITABLE_OBJECT); /* To fix: We might return with some empty strides */ if (!ptr[id]) { return VR_ITABLE_ERR_PTR; @@ -351,9 +353,9 @@ vr_itable_delete(vr_itable_t t, vr_itable_del_cb_t func) __vr_itable_exit(table, func, table->data, 0, 0); /* Free the table itself */ - vr_free(table->stride_len); - vr_free(table->stride_shift); - vr_free(table); + vr_free(table->stride_len, VR_ITABLE_OBJECT); + vr_free(table->stride_shift, VR_ITABLE_OBJECT); + vr_free(table, VR_ITABLE_OBJECT); return; } @@ -386,7 +388,7 @@ vr_itable_create(unsigned int index_len, unsigned int stride_cnt, ...) goto fail; } - table = vr_zalloc(sizeof(struct vr_itbl)); + table = vr_zalloc(sizeof(struct vr_itbl), VR_ITABLE_OBJECT); if (!table) { goto fail; } @@ -394,12 +396,14 @@ vr_itable_create(unsigned int index_len, unsigned int stride_cnt, ...) table->index_len = index_len; table->stride_cnt = stride_cnt; - table->stride_shift = vr_zalloc(table->stride_cnt * sizeof(unsigned int)); + table->stride_shift = vr_zalloc(table->stride_cnt * sizeof(unsigned int), + VR_ITABLE_OBJECT); if (!table->stride_shift) { goto fail; } - table->stride_len = vr_zalloc(table->stride_cnt * sizeof(unsigned int)); + table->stride_len = vr_zalloc(table->stride_cnt * sizeof(unsigned int), + VR_ITABLE_OBJECT); if (!table->stride_len) { goto fail; } @@ -435,14 +439,14 @@ vr_itable_create(unsigned int index_len, unsigned int stride_cnt, ...) if (table) { if (table->stride_shift) { - vr_free(table->stride_shift); + vr_free(table->stride_shift, VR_ITABLE_OBJECT); } if (table->stride_len) { - vr_free(table->stride_len); + vr_free(table->stride_len, VR_ITABLE_OBJECT); } - vr_free(table); + vr_free(table, VR_ITABLE_OBJECT); } return NULL; diff --git a/dp-core/vr_interface.c b/dp-core/vr_interface.c index e9e7819ff..d4f728dd8 100644 --- a/dp-core/vr_interface.c +++ b/dp-core/vr_interface.c @@ -122,7 +122,7 @@ vr_interface_service_enable(struct vr_interface *vif) */ if (!vif->vif_vrf_table) { vif->vif_vrf_table = vr_malloc(sizeof(struct vr_vrf_assign) * - VIF_VRF_TABLE_ENTRIES); + VIF_VRF_TABLE_ENTRIES, VR_INTERFACE_VRF_TABLE_OBJECT); if (!vif->vif_vrf_table) return -ENOMEM; @@ -165,7 +165,7 @@ vr_interface_service_disable(struct vr_interface *vif) * takes care of freeing the memory */ if (vif->vif_vrf_table && !vif->vif_vrf_table_users) { - vr_free(vif->vif_vrf_table); + vr_free(vif->vif_vrf_table, VR_INTERFACE_VRF_TABLE_OBJECT); vif->vif_vrf_table = NULL; } @@ -780,16 +780,26 @@ vlan_tx(struct vr_interface *vif, struct vr_packet *pkt, static int vlan_drv_del(struct vr_interface *vif) { + int ret = 0; struct vr_interface *pvif; pvif = vif->vif_parent; if (!pvif) return 0; - if (pvif->vif_driver->drv_delete_sub_interface) - pvif->vif_driver->drv_delete_sub_interface(pvif, vif); + if (pvif->vif_driver->drv_delete_sub_interface) { + ret = pvif->vif_driver->drv_delete_sub_interface(pvif, vif); + if (ret) + goto exit_del; + } - return 0; +exit_del: + if (vif->vif_src_mac) { + vr_free(vif->vif_src_mac, VR_INTERFACE_MAC_OBJECT); + vif->vif_src_mac = NULL; + } + + return ret; } static int @@ -808,7 +818,7 @@ vlan_drv_add(struct vr_interface *vif, vr_interface_req *vifr) if (vifr->vifr_src_mac_size != VR_ETHER_ALEN) return -EINVAL; - vif->vif_src_mac = vr_malloc(VR_ETHER_ALEN); + vif->vif_src_mac = vr_malloc(VR_ETHER_ALEN, VR_INTERFACE_MAC_OBJECT); if (!vif->vif_src_mac) return -ENOMEM; @@ -1152,7 +1162,7 @@ eth_drv_add_sub_interface(struct vr_interface *pvif, struct vr_interface *vif) } else { if(!pvif->vif_sub_interfaces) { pvif->vif_sub_interfaces = vr_zalloc(VLAN_ID_MAX * - sizeof(struct vr_interface *)); + sizeof(struct vr_interface *), VR_INTERFACE_OBJECT); if (!pvif->vif_sub_interfaces) return -ENOMEM; /* @@ -1290,15 +1300,15 @@ vif_free(struct vr_interface *vif) return; if (vif->vif_stats) - vr_free(vif->vif_stats); + vr_free(vif->vif_stats, VR_INTERFACE_STATS_OBJECT); if (vif->vif_vrf_table) { - vr_free(vif->vif_vrf_table); + vr_free(vif->vif_vrf_table, VR_INTERFACE_VRF_TABLE_OBJECT); vif->vif_vrf_table = NULL; } if (vif->vif_sub_interfaces) { - vr_free(vif->vif_sub_interfaces); + vr_free(vif->vif_sub_interfaces, VR_INTERFACE_OBJECT); vif->vif_sub_interfaces = NULL; } @@ -1306,7 +1316,12 @@ vif_free(struct vr_interface *vif) vif_bridge_deinit(vif); } - vr_free(vif); + if (vif->vif_src_mac) { + vr_free(vif->vif_src_mac, VR_INTERFACE_MAC_OBJECT); + vif->vif_src_mac = NULL; + } + + vr_free(vif, VR_INTERFACE_OBJECT); return; } @@ -1725,14 +1740,14 @@ vr_interface_add(vr_interface_req *req, bool need_response) goto generate_resp; } - vif = vr_zalloc(sizeof(*vif)); + vif = vr_zalloc(sizeof(*vif), VR_INTERFACE_OBJECT); if (!vif) { ret = -ENOMEM; goto generate_resp; } vif->vif_stats = vr_zalloc(vr_num_cpus * - sizeof(struct vr_interface_stats)); + sizeof(struct vr_interface_stats), VR_INTERFACE_STATS_OBJECT); if (!vif->vif_stats) { ret = -ENOMEM; goto generate_resp; @@ -1956,18 +1971,19 @@ vr_interface_req_get(void) { vr_interface_req *req; - req = vr_zalloc(sizeof(*req)); + req = vr_zalloc(sizeof(*req), VR_INTERFACE_REQ_OBJECT); if (!req) return req; - req->vifr_mac = vr_zalloc(VR_ETHER_ALEN); + req->vifr_mac = vr_zalloc(VR_ETHER_ALEN, VR_INTERFACE_REQ_MAC_OBJECT); if (req->vifr_mac) req->vifr_mac_size = VR_ETHER_ALEN; - req->vifr_src_mac = vr_zalloc(VR_ETHER_ALEN); + req->vifr_src_mac = vr_zalloc(VR_ETHER_ALEN, VR_INTERFACE_REQ_MAC_OBJECT); if (req->vifr_src_mac) req->vifr_src_mac_size = 0; - req->vifr_name = vr_zalloc(VR_INTERFACE_NAME_LEN); + req->vifr_name = vr_zalloc(VR_INTERFACE_NAME_LEN, + VR_INTERFACE_REQ_NAME_OBJECT); return req; } @@ -1980,19 +1996,19 @@ vr_interface_req_destroy(vr_interface_req *req) return; if (req->vifr_mac) { - vr_free(req->vifr_mac); + vr_free(req->vifr_mac, VR_INTERFACE_REQ_MAC_OBJECT); req->vifr_mac_size = 0; } if (req->vifr_src_mac) { - vr_free(req->vifr_src_mac); + vr_free(req->vifr_src_mac, VR_INTERFACE_REQ_MAC_OBJECT); req->vifr_src_mac_size = 0; } if (req->vifr_name) - vr_free(req->vifr_name); + vr_free(req->vifr_name, VR_INTERFACE_REQ_NAME_OBJECT); - vr_free(req); + vr_free(req, VR_INTERFACE_REQ_OBJECT); return; } @@ -2229,7 +2245,7 @@ vif_vrf_table_set(struct vr_interface *vif, unsigned int vlan, */ if (!(vif->vif_flags & VIF_FLAG_SERVICE_IF) && !vif->vif_vrf_table_users) { - vr_free(vif->vif_vrf_table); + vr_free(vif->vif_vrf_table, VR_INTERFACE_VRF_TABLE_OBJECT); vif->vif_vrf_table = NULL; } @@ -2317,7 +2333,7 @@ vr_interface_exit(struct vrouter *router, bool soft_reset) } if (!soft_reset && router->vr_interfaces) { - vr_free(router->vr_interfaces); + vr_free(router->vr_interfaces, VR_INTERFACE_TABLE_OBJECT); router->vr_interfaces = NULL; router->vr_max_interfaces = 0; } @@ -2335,7 +2351,8 @@ vr_interface_init(struct vrouter *router) router->vr_max_interfaces = VR_MAX_INTERFACES; table_memory = router->vr_max_interfaces * sizeof(struct vr_interface *); - router->vr_interfaces = vr_zalloc(table_memory); + router->vr_interfaces = vr_zalloc(table_memory, + VR_INTERFACE_TABLE_OBJECT); if (!router->vr_interfaces && (ret = -ENOMEM)) return vr_module_error(ret, __FUNCTION__, __LINE__, table_memory); @@ -2355,7 +2372,7 @@ vr_interface_init(struct vrouter *router) cleanup: if (router->vr_interfaces) { - vr_free(router->vr_interfaces); + vr_free(router->vr_interfaces, VR_INTERFACE_TABLE_OBJECT); router->vr_interfaces = NULL; router->vr_max_interfaces = 0; } diff --git a/dp-core/vr_ip_mtrie.c b/dp-core/vr_ip_mtrie.c index 0fe33f783..6936bf5db 100644 --- a/dp-core/vr_ip_mtrie.c +++ b/dp-core/vr_ip_mtrie.c @@ -189,7 +189,8 @@ mtrie_alloc_bucket(struct mtrie_bkt_info *ip_bkt_info, unsigned char level, stru bkt_size = ip_bkt_info[level].bi_size; bkt = vr_zalloc(sizeof(struct ip_bucket) - + sizeof(struct ip_bucket_entry) * bkt_size); + + sizeof(struct ip_bucket_entry) * bkt_size, + VR_MTRIE_BUCKET_OBJECT); if (!bkt) return NULL; @@ -264,7 +265,7 @@ mtrie_free_entry(struct ip_bucket_entry *entry, unsigned int level) } entry->entry_bkt_p = NULL; - vr_free(bkt); + vr_free(bkt, VR_MTRIE_BUCKET_OBJECT); return; } @@ -414,7 +415,7 @@ ip_bucket_sched_for_free(struct ip_bucket *bkt, int level) vrouter_put_nexthop(tmp_ent->entry_nh_p); } } - vr_free(bkt); + vr_free(bkt, VR_MTRIE_BUCKET_OBJECT); } static void @@ -530,7 +531,7 @@ mtrie_dumper_make_response(struct vr_message_dumper *dumper, vr_route_req *resp, resp->rtr_nh_id = ent->entry_nh_p->nh_id; resp->rtr_index = ent->entry_bridge_index; if (resp->rtr_index != VR_BE_INVALID_INDEX) { - resp->rtr_mac = vr_zalloc(VR_ETHER_ALEN); + resp->rtr_mac = vr_zalloc(VR_ETHER_ALEN, VR_ROUTE_REQ_MAC_OBJECT); resp->rtr_mac_size = VR_ETHER_ALEN; lreq.rtr_req.rtr_mac = resp->rtr_mac; lreq.rtr_req.rtr_index = resp->rtr_index; @@ -608,7 +609,7 @@ mtrie_dump_entry(struct vr_message_dumper *dumper, struct ip_bucket_entry *ent, ret = mtrie_dumper_route_encode(dumper, &dump_resp); if (dump_resp.rtr_mac_size) { - vr_free(dump_resp.rtr_mac); + vr_free(dump_resp.rtr_mac, VR_ROUTE_REQ_MAC_OBJECT); dump_resp.rtr_mac_size = 0; dump_resp.rtr_mac = NULL; } @@ -980,7 +981,7 @@ mtrie_alloc_vrf(unsigned int vrf_id, unsigned int family) if (family == AF_INET6) index = 1; - mtrie = vr_zalloc(sizeof(struct ip_mtrie)); + mtrie = vr_zalloc(sizeof(struct ip_mtrie), VR_MTRIE_OBJECT); if (mtrie) { mtrie->root.entry_nh_p = vrouter_get_nexthop(0, NH_DISCARD_ID); mtrie->root.entry_bridge_index = VR_BE_INVALID_INDEX; @@ -1007,7 +1008,7 @@ mtrie_free_vrf(struct vr_rtable *rtable, unsigned int vrf_id) mtrie_free_entry(&mtrie->root, 0); vrf_tables[vrf_id] = NULL; - vr_free(mtrie); + vr_free(mtrie, VR_MTRIE_OBJECT); } return; @@ -1027,18 +1028,18 @@ mtrie_stats_cleanup(struct vr_rtable *rtable, bool soft_reset) if (soft_reset) { memset(mtrie_vrf_stats[i], 0, stats_memory_size); } else { - vr_free(mtrie_vrf_stats[i]); + vr_free(mtrie_vrf_stats[i], VR_MTRIE_STATS_OBJECT); mtrie_vrf_stats[i] = NULL; } } } if (!soft_reset) { - vr_free(mtrie_vrf_stats); + vr_free(mtrie_vrf_stats, VR_MTRIE_STATS_OBJECT); rtable->vrf_stats = mtrie_vrf_stats = NULL; if (invalid_vrf_stats) { - vr_free(invalid_vrf_stats); + vr_free(invalid_vrf_stats, VR_MTRIE_STATS_OBJECT); invalid_vrf_stats = NULL; } } else { @@ -1063,7 +1064,7 @@ mtrie_algo_deinit(struct vr_rtable *rtable, struct rtable_fspec *fs, if (!soft_reset) { vn_rtable[0] = vn_rtable[1] = NULL; - vr_free(rtable->algo_data); + vr_free(rtable->algo_data, VR_MTRIE_TABLE_OBJECT); rtable->algo_data = NULL; } @@ -1081,13 +1082,14 @@ mtrie_stats_init(struct vr_rtable *rtable) if (!mtrie_vrf_stats) { stats_memory = sizeof(void *) * rtable->algo_max_vrfs; - mtrie_vrf_stats = vr_zalloc(stats_memory); + mtrie_vrf_stats = vr_zalloc(stats_memory, VR_MTRIE_STATS_OBJECT); if (!mtrie_vrf_stats) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, stats_memory); for (i = 0; i < rtable->algo_max_vrfs; i++) { stats_memory = sizeof(struct vr_vrf_stats) * vr_num_cpus; - mtrie_vrf_stats[i] = vr_zalloc(stats_memory); + mtrie_vrf_stats[i] = vr_zalloc(stats_memory, + VR_MTRIE_STATS_OBJECT); if (!mtrie_vrf_stats[i] && (ret = -ENOMEM)) { vr_module_error(ret, __FUNCTION__, __LINE__, i); goto cleanup; @@ -1099,7 +1101,7 @@ mtrie_stats_init(struct vr_rtable *rtable) if (!invalid_vrf_stats) { invalid_vrf_stats = vr_zalloc(sizeof(struct vr_vrf_stats) * - vr_num_cpus); + vr_num_cpus, VR_MTRIE_STATS_OBJECT); if (!invalid_vrf_stats && (ret = -ENOMEM)) { vr_module_error(ret, __FUNCTION__, __LINE__, -1); goto cleanup; @@ -1115,18 +1117,18 @@ mtrie_stats_init(struct vr_rtable *rtable) for (--i; i >= 0; i--) { if (mtrie_vrf_stats[i]) { - vr_free(mtrie_vrf_stats[i]); + vr_free(mtrie_vrf_stats[i], VR_MTRIE_STATS_OBJECT); mtrie_vrf_stats[i] = NULL; } } if (mtrie_vrf_stats) { - vr_free(mtrie_vrf_stats); + vr_free(mtrie_vrf_stats, VR_MTRIE_STATS_OBJECT); mtrie_vrf_stats = NULL; } if (invalid_vrf_stats) { - vr_free(invalid_vrf_stats); + vr_free(invalid_vrf_stats, VR_MTRIE_STATS_OBJECT); invalid_vrf_stats = NULL; } @@ -1144,7 +1146,7 @@ mtrie_algo_init(struct vr_rtable *rtable, struct rtable_fspec *fs) if (!rtable->algo_data) { table_memory = 2 * sizeof(void *) * fs->rtb_max_vrfs; - rtable->algo_data = vr_zalloc(table_memory); + rtable->algo_data = vr_zalloc(table_memory, VR_MTRIE_TABLE_OBJECT); if (!rtable->algo_data) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, table_memory); } @@ -1180,7 +1182,7 @@ mtrie_algo_init(struct vr_rtable *rtable, struct rtable_fspec *fs) init_fail: if (rtable->algo_data) { - vr_free(rtable->algo_data); + vr_free(rtable->algo_data, VR_MTRIE_TABLE_OBJECT); rtable->algo_data = NULL; } diff --git a/dp-core/vr_message.c b/dp-core/vr_message.c index 3394e8be1..b8a9b731d 100644 --- a/dp-core/vr_message.c +++ b/dp-core/vr_message.c @@ -11,14 +11,14 @@ static char * vr_message_default_malloc(unsigned int size) { - return vr_malloc(size); + return vr_malloc(size, VR_MESSAGE_OBJECT); } static void vr_message_default_free(char *buf) { if (buf) - vr_free(buf); + vr_free(buf, VR_MESSAGE_OBJECT); return; } @@ -76,7 +76,7 @@ vr_message_queue_response(char *buf, int len) { struct vr_message *response; - response = vr_zalloc(sizeof(*response)); + response = vr_zalloc(sizeof(*response), VR_MESSAGE_RESPONSE_OBJECT); if (!response) return -ENOMEM; @@ -112,7 +112,7 @@ vr_message_free(struct vr_message *message) if (message) { if (message->vr_message_buf) vr_mtrans_free(message->vr_message_buf); - vr_free(message); + vr_free(message, VR_MESSAGE_RESPONSE_OBJECT); } return; @@ -271,7 +271,7 @@ vr_message_dump_exit(void *context, int ret) vr_message_queue_response(dumper->dump_buffer, dumper->dump_offset); - vr_free(dumper); + vr_free(dumper, VR_MESSAGE_DUMP_OBJECT); } return; @@ -290,13 +290,13 @@ vr_message_dump_init(void *req) if (!proto || !trans) return NULL; - dumper = vr_zalloc(sizeof(*dumper)); + dumper = vr_zalloc(sizeof(*dumper), VR_MESSAGE_DUMP_OBJECT); if (!dumper) return NULL; buf = trans->mtrans_alloc(VR_MESSAGE_PAGE_SIZE); if (!buf) { - vr_free(dumper); + vr_free(dumper, VR_MESSAGE_DUMP_OBJECT); return NULL; } diff --git a/dp-core/vr_mirror.c b/dp-core/vr_mirror.c index 1f9e92fe2..7a16cc165 100644 --- a/dp-core/vr_mirror.c +++ b/dp-core/vr_mirror.c @@ -55,7 +55,7 @@ vrouter_put_mirror(struct vrouter *router, unsigned int index) vr_delay_op(); vrouter_put_nexthop(mirror->mir_nh); - vr_free(mirror); + vr_free(mirror, VR_MIRROR_OBJECT); } return 0; @@ -146,7 +146,7 @@ vr_mirror_add(vr_mirror_req *req) if (mirror) { vr_mirror_change(mirror, req, nh); } else { - mirror = vr_zalloc(sizeof(*mirror)); + mirror = vr_zalloc(sizeof(*mirror), VR_MIRROR_OBJECT); mirror->mir_users++; mirror->mir_nh = nh; mirror->mir_rid = req->mirr_rid; @@ -275,9 +275,9 @@ vr_mirror_meta_destroy(struct vr_mirror_meta_entry *me) return; if (me->mirror_md) - vr_free(me->mirror_md); + vr_free(me->mirror_md, VR_MIRROR_META_OBJECT); - vr_free(me); + vr_free(me, VR_MIRROR_META_OBJECT); return; } @@ -327,13 +327,13 @@ vr_mirror_meta_entry_set(struct vrouter *router, unsigned int index, char *buf; struct vr_mirror_meta_entry *me, *me_old; - me = vr_malloc(sizeof(*me)); + me = vr_malloc(sizeof(*me), VR_MIRROR_META_OBJECT); if (!me) return -ENOMEM; - buf = vr_malloc(meta_data_len); + buf = vr_malloc(meta_data_len, VR_MIRROR_META_OBJECT); if (!buf) { - vr_free(me); + vr_free(me, VR_MIRROR_META_OBJECT); return -ENOMEM; } @@ -492,7 +492,7 @@ vr_mirror_exit(struct vrouter *router, bool soft_reset) } if (!soft_reset) { - vr_free(router->vr_mirrors); + vr_free(router->vr_mirrors, VR_MIRROR_TABLE_OBJECT); router->vr_mirrors = NULL; router->vr_max_mirror_indices = 0; } @@ -509,7 +509,7 @@ vr_mirror_init(struct vrouter *router) if (!router->vr_mirrors) { router->vr_max_mirror_indices = VR_MAX_MIRROR_INDICES; size = sizeof(struct vr_mirror_entry *) * router->vr_max_mirror_indices; - router->vr_mirrors = vr_zalloc(size); + router->vr_mirrors = vr_zalloc(size, VR_MIRROR_TABLE_OBJECT); if (!router->vr_mirrors) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); } @@ -526,7 +526,7 @@ vr_mirror_init(struct vrouter *router) cleanup: if (router->vr_mirrors) { - vr_free(router->vr_mirrors); + vr_free(router->vr_mirrors, VR_MIRROR_TABLE_OBJECT); router->vr_mirrors = NULL; } diff --git a/dp-core/vr_nexthop.c b/dp-core/vr_nexthop.c index 46a1b593f..553644ddc 100644 --- a/dp-core/vr_nexthop.c +++ b/dp-core/vr_nexthop.c @@ -94,12 +94,12 @@ vrouter_put_nexthop(struct vr_nexthop *nh) vrouter_put_nexthop(nh->nh_component_nh[i].cnh); } - vr_free(nh->nh_component_nh); + vr_free(nh->nh_component_nh, VR_NEXTHOP_COMPONENT_OBJECT); } if (nh->nh_dev) { vrouter_put_interface(nh->nh_dev); } - vr_free(nh); + vr_free(nh, VR_NEXTHOP_OBJECT); } return; @@ -1943,7 +1943,7 @@ nh_composite_add(struct vr_nexthop *nh, vr_nexthop_req *req) if (nh->nh_component_nh[i].cnh) vrouter_put_nexthop(nh->nh_component_nh[i].cnh); } - vr_free(nh->nh_component_nh); + vr_free(nh->nh_component_nh, VR_NEXTHOP_COMPONENT_OBJECT); nh->nh_component_nh = NULL; nh->nh_component_cnt = 0; } @@ -1956,7 +1956,7 @@ nh_composite_add(struct vr_nexthop *nh, vr_nexthop_req *req) return 0; nh->nh_component_nh = vr_zalloc(req->nhr_nh_list_size * - sizeof(struct vr_component_nh)); + sizeof(struct vr_component_nh), VR_NEXTHOP_COMPONENT_OBJECT); if (!nh->nh_component_nh) { return -ENOMEM; } @@ -1998,7 +1998,7 @@ nh_composite_add(struct vr_nexthop *nh, vr_nexthop_req *req) vrouter_put_nexthop(tmp_nh); } - vr_free(nh->nh_component_nh); + vr_free(nh->nh_component_nh, VR_NEXTHOP_COMPONENT_OBJECT); nh->nh_component_nh = NULL; nh->nh_component_cnt = 0; } @@ -2176,7 +2176,7 @@ vr_nexthop_add(vr_nexthop_req *req) goto generate_resp; len = ret; - nh = vr_zalloc(len); + nh = vr_zalloc(len, VR_NEXTHOP_OBJECT); if (!nh) { ret = -ENOMEM; goto generate_resp; @@ -2330,12 +2330,16 @@ vr_nexthop_make_req(vr_nexthop_req *req, struct vr_nexthop *nh) case NH_COMPOSITE: req->nhr_nh_list_size = nh->nh_component_cnt; if (nh->nh_component_cnt) { - req->nhr_nh_list = vr_zalloc(req->nhr_nh_list_size * sizeof(unsigned int)); + req->nhr_nh_list = + vr_zalloc(req->nhr_nh_list_size * sizeof(unsigned int), + VR_NEXTHOP_REQ_LIST_OBJECT); if (!req->nhr_nh_list) return -ENOMEM; req->nhr_label_list_size = nh->nh_component_cnt; - req->nhr_label_list = vr_zalloc(req->nhr_nh_list_size * sizeof(unsigned int)); + req->nhr_label_list = + vr_zalloc(req->nhr_nh_list_size * sizeof(unsigned int), + VR_NEXTHOP_REQ_LIST_OBJECT); /* don't bother about freeing. we will free it in req_destroy */ if (!req->nhr_label_list) return -ENOMEM; @@ -2394,7 +2398,8 @@ vr_nexthop_make_req(vr_nexthop_req *req, struct vr_nexthop *nh) } if (req->nhr_encap_size) { - req->nhr_encap = vr_zalloc(req->nhr_encap_size); + req->nhr_encap = vr_zalloc(req->nhr_encap_size, + VR_NEXTHOP_REQ_ENCAP_OBJECT); if (req->nhr_encap) { memcpy(req->nhr_encap, encap, req->nhr_encap_size); @@ -2410,7 +2415,7 @@ vr_nexthop_make_req(vr_nexthop_req *req, struct vr_nexthop *nh) static vr_nexthop_req * vr_nexthop_req_get(void) { - return vr_zalloc(sizeof(vr_nexthop_req)); + return vr_zalloc(sizeof(vr_nexthop_req), VR_NEXTHOP_REQ_OBJECT); } static void @@ -2420,24 +2425,24 @@ vr_nexthop_req_destroy(vr_nexthop_req *req) return; if (req->nhr_encap_size && req->nhr_encap) { - vr_free(req->nhr_encap); + vr_free(req->nhr_encap, VR_NEXTHOP_REQ_ENCAP_OBJECT); req->nhr_encap_size = 0; req->nhr_encap = NULL; } if (req->nhr_nh_list_size && req->nhr_nh_list) { - vr_free(req->nhr_nh_list); + vr_free(req->nhr_nh_list, VR_NEXTHOP_REQ_LIST_OBJECT); req->nhr_nh_list_size = 0; req->nhr_nh_list = NULL; } if (req->nhr_label_list_size && req->nhr_label_list) { - vr_free(req->nhr_label_list); + vr_free(req->nhr_label_list, VR_NEXTHOP_REQ_LIST_OBJECT); req->nhr_label_list = NULL; req->nhr_label_list_size = 0; } - vr_free(req); + vr_free(req, VR_NEXTHOP_REQ_OBJECT); return; } @@ -2584,7 +2589,7 @@ nh_table_exit(struct vrouter *router, bool soft_reset) static int nh_allocate_discard(void) { - ip4_default_nh = vr_zalloc(sizeof(struct vr_nexthop)); + ip4_default_nh = vr_zalloc(sizeof(struct vr_nexthop), VR_NEXTHOP_OBJECT); if (!ip4_default_nh) return -ENOMEM; diff --git a/dp-core/vr_route.c b/dp-core/vr_route.c index 34dc734a7..a0cdbd17c 100644 --- a/dp-core/vr_route.c +++ b/dp-core/vr_route.c @@ -428,7 +428,7 @@ inet_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, if (router->vr_inet_rtable) { fs->algo_deinit(router->vr_inet_rtable, fs, soft_reset); if (!soft_reset) { - vr_free(router->vr_inet_rtable); + vr_free(router->vr_inet_rtable, VR_ROUTE_TABLE_OBJECT); router->vr_inet_rtable = NULL; } } @@ -445,7 +445,8 @@ inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) return 1; if (!router->vr_inet_rtable) { - router->vr_inet_rtable = vr_zalloc(sizeof(struct vr_rtable)); + router->vr_inet_rtable = vr_zalloc(sizeof(struct vr_rtable), + VR_ROUTE_TABLE_OBJECT); if (!router->vr_inet_rtable) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0); } @@ -504,7 +505,7 @@ bridge_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) return 0; if (fs->algo_init) { - table = vr_zalloc(sizeof(struct vr_rtable)); + table = vr_zalloc(sizeof(struct vr_rtable), VR_ROUTE_TABLE_OBJECT); if (!table) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0); @@ -528,7 +529,7 @@ bridge_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, fs->algo_deinit(router->vr_bridge_rtable, fs, soft_reset); if (!soft_reset) { - vr_free(router->vr_bridge_rtable); + vr_free(router->vr_bridge_rtable, VR_ROUTE_TABLE_OBJECT); router->vr_bridge_rtable = NULL; } } diff --git a/dp-core/vr_sandesh.c b/dp-core/vr_sandesh.c index af72f5846..6ec20cd52 100644 --- a/dp-core/vr_sandesh.c +++ b/dp-core/vr_sandesh.c @@ -67,6 +67,10 @@ struct sandesh_object_md sandesh_md[] = { (VR_FLOW_MAX_CPUS * sizeof(unsigned int))), .obj_type_string = "vr_flow_req", }, + [VR_MEM_STATS_OBJECT_ID] = { + .obj_len = 4 * sizeof(vr_mem_stats_req), + .obj_type_string = "vr_mem_stats_req", + }, }; static unsigned int diff --git a/dp-core/vr_stats.c b/dp-core/vr_stats.c index 14018a791..e665654c2 100644 --- a/dp-core/vr_stats.c +++ b/dp-core/vr_stats.c @@ -81,11 +81,11 @@ vr_drop_stats_get(unsigned int core) if (!router && (ret = -ENOENT)) goto exit_get; - stats = vr_zalloc(sizeof(*stats)); + stats = vr_zalloc(sizeof(*stats), VR_DROP_STATS_REQ_OBJECT); if (!stats && (ret = -ENOMEM)) goto exit_get; - response = vr_zalloc(sizeof(*response)); + response = vr_zalloc(sizeof(*response), VR_DROP_STATS_REQ_OBJECT); if (!response && (ret = -ENOMEM)) goto exit_get; @@ -211,10 +211,10 @@ vr_drop_stats_get(unsigned int core) exit_get: vr_message_response(VR_DROP_STATS_OBJECT_ID, ret ? NULL : response, ret); if (stats != NULL) - vr_free(stats); + vr_free(stats, VR_DROP_STATS_REQ_OBJECT); if (response != NULL) - vr_free(response); + vr_free(response, VR_DROP_STATS_REQ_OBJECT); return; } @@ -243,6 +243,253 @@ vr_drop_stats_req_process(void *s_req) return; } +static void +vr_mem_stats_get(void) +{ + int ret = 0; + unsigned int cpu, i; + int64_t alloced = 0, freed = 0; + + struct vrouter *router = vrouter_get(0); + struct vr_malloc_stats *stats_block; + vr_mem_stats_req *response = NULL; + + if (!router && (ret = -ENOENT)) + goto exit_get; + + response = vr_zalloc(sizeof(*response), VR_MEM_STATS_REQ_OBJECT); + if (!response && (ret = -ENOMEM)) + goto exit_get; + + + for (cpu = 0; cpu < vr_num_cpus; cpu++) { + stats_block = (struct vr_malloc_stats *)router->vr_malloc_stats[cpu]; + response->vms_assembler_table_object += (stats_block[VR_ASSEMBLER_TABLE_OBJECT].ms_alloc - + stats_block[VR_ASSEMBLER_TABLE_OBJECT].ms_free); + response->vms_bridge_mac_object += (stats_block[VR_BRIDGE_MAC_OBJECT].ms_alloc - + stats_block[VR_BRIDGE_MAC_OBJECT].ms_free); + response->vms_btable_object += (stats_block[VR_BTABLE_OBJECT].ms_alloc - + stats_block[VR_BTABLE_OBJECT].ms_free); + response->vms_build_info_object += (stats_block[VR_BUILD_INFO_OBJECT].ms_alloc - + stats_block[VR_BUILD_INFO_OBJECT].ms_free); + response->vms_defer_object += (stats_block[VR_DEFER_OBJECT].ms_alloc - + stats_block[VR_DEFER_OBJECT].ms_free); + response->vms_drop_stats_object += (stats_block[VR_DROP_STATS_OBJECT].ms_alloc - + stats_block[VR_DROP_STATS_OBJECT].ms_free); + response->vms_drop_stats_req_object += (stats_block[VR_DROP_STATS_REQ_OBJECT].ms_alloc - + stats_block[VR_DROP_STATS_REQ_OBJECT].ms_free); + response->vms_flow_queue_object += (stats_block[VR_FLOW_QUEUE_OBJECT].ms_alloc - + stats_block[VR_FLOW_QUEUE_OBJECT].ms_free); + response->vms_flow_req_object += (stats_block[VR_FLOW_REQ_OBJECT].ms_alloc - + stats_block[VR_FLOW_REQ_OBJECT].ms_free); + response->vms_flow_req_path_object += (stats_block[VR_FLOW_REQ_PATH_OBJECT].ms_alloc - + stats_block[VR_FLOW_REQ_PATH_OBJECT].ms_free); + response->vms_flow_hold_stat_object += (stats_block[VR_FLOW_HOLD_STAT_OBJECT].ms_alloc - + stats_block[VR_FLOW_HOLD_STAT_OBJECT].ms_free); + response->vms_flow_link_local_object += (stats_block[VR_FLOW_LINK_LOCAL_OBJECT].ms_alloc - + stats_block[VR_FLOW_LINK_LOCAL_OBJECT].ms_free); + response->vms_flow_metadata_object += (stats_block[VR_FLOW_METADATA_OBJECT].ms_alloc - + stats_block[VR_FLOW_METADATA_OBJECT].ms_free); + response->vms_flow_table_info_object += (stats_block[VR_FLOW_TABLE_INFO_OBJECT].ms_alloc - + stats_block[VR_FLOW_TABLE_INFO_OBJECT].ms_free); + response->vms_fragment_object += (stats_block[VR_FRAGMENT_OBJECT].ms_alloc - + stats_block[VR_FRAGMENT_OBJECT].ms_free); + response->vms_fragment_queue_object += (stats_block[VR_FRAGMENT_QUEUE_OBJECT].ms_alloc - + stats_block[VR_FRAGMENT_QUEUE_OBJECT].ms_free); + response->vms_fragment_queue_element_object += (stats_block[VR_FRAGMENT_QUEUE_ELEMENT_OBJECT].ms_alloc - + stats_block[VR_FRAGMENT_QUEUE_ELEMENT_OBJECT].ms_free); + response->vms_fragment_scanner_object += (stats_block[VR_FRAGMENT_SCANNER_OBJECT].ms_alloc - + stats_block[VR_FRAGMENT_SCANNER_OBJECT].ms_free); + response->vms_hpacket_pool_object += (stats_block[VR_HPACKET_POOL_OBJECT].ms_alloc - + stats_block[VR_HPACKET_POOL_OBJECT].ms_free); + response->vms_htable_object += (stats_block[VR_HTABLE_OBJECT].ms_alloc - + stats_block[VR_HTABLE_OBJECT].ms_free); + response->vms_interface_object += (stats_block[VR_INTERFACE_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_OBJECT].ms_free); + response->vms_interface_mac_object += (stats_block[VR_INTERFACE_MAC_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_MAC_OBJECT].ms_free); + response->vms_interface_req_object += (stats_block[VR_INTERFACE_REQ_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_REQ_OBJECT].ms_free); + response->vms_interface_req_mac_object += (stats_block[VR_INTERFACE_REQ_MAC_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_REQ_MAC_OBJECT].ms_free); + response->vms_interface_req_name_object += (stats_block[VR_INTERFACE_REQ_NAME_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_REQ_NAME_OBJECT].ms_free); + response->vms_interface_stats_object += (stats_block[VR_INTERFACE_STATS_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_STATS_OBJECT].ms_free); + response->vms_interface_table_object += (stats_block[VR_INTERFACE_TABLE_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_TABLE_OBJECT].ms_free); + response->vms_interface_vrf_table_object += (stats_block[VR_INTERFACE_VRF_TABLE_OBJECT].ms_alloc - + stats_block[VR_INTERFACE_VRF_TABLE_OBJECT].ms_free); + response->vms_itable_object += (stats_block[VR_ITABLE_OBJECT].ms_alloc - + stats_block[VR_ITABLE_OBJECT].ms_free); + response->vms_malloc_object += (stats_block[VR_MALLOC_OBJECT].ms_alloc - + stats_block[VR_MALLOC_OBJECT].ms_free); + response->vms_message_object += (stats_block[VR_MESSAGE_OBJECT].ms_alloc - + stats_block[VR_MESSAGE_OBJECT].ms_free); + response->vms_message_response_object += (stats_block[VR_MESSAGE_RESPONSE_OBJECT].ms_alloc - + stats_block[VR_MESSAGE_RESPONSE_OBJECT].ms_free); + response->vms_message_dump_object += (stats_block[VR_MESSAGE_DUMP_OBJECT].ms_alloc - + stats_block[VR_MESSAGE_DUMP_OBJECT].ms_free); + response->vms_mem_stats_req_object += (stats_block[VR_MEM_STATS_REQ_OBJECT].ms_alloc - + stats_block[VR_MEM_STATS_REQ_OBJECT].ms_free); + response->vms_mirror_object += (stats_block[VR_MIRROR_OBJECT].ms_alloc - + stats_block[VR_MIRROR_OBJECT].ms_free); + response->vms_mirror_table_object += (stats_block[VR_MIRROR_TABLE_OBJECT].ms_alloc - + stats_block[VR_MIRROR_TABLE_OBJECT].ms_free); + response->vms_mirror_meta_object += (stats_block[VR_MIRROR_META_OBJECT].ms_alloc - + stats_block[VR_MIRROR_META_OBJECT].ms_free); + response->vms_mtrie_object += (stats_block[VR_MTRIE_OBJECT].ms_alloc - + stats_block[VR_MTRIE_OBJECT].ms_free); + response->vms_mtrie_bucket_object += (stats_block[VR_MTRIE_BUCKET_OBJECT].ms_alloc - + stats_block[VR_MTRIE_BUCKET_OBJECT].ms_free); + response->vms_mtrie_stats_object += (stats_block[VR_MTRIE_STATS_OBJECT].ms_alloc - + stats_block[VR_MTRIE_STATS_OBJECT].ms_free); + response->vms_mtrie_table_object += (stats_block[VR_MTRIE_TABLE_OBJECT].ms_alloc - + stats_block[VR_MTRIE_TABLE_OBJECT].ms_free); + response->vms_nexthop_object += (stats_block[VR_NEXTHOP_OBJECT].ms_alloc - + stats_block[VR_NEXTHOP_OBJECT].ms_free); + response->vms_nexthop_component_object += (stats_block[VR_NEXTHOP_COMPONENT_OBJECT].ms_alloc - + stats_block[VR_NEXTHOP_COMPONENT_OBJECT].ms_free); + response->vms_nexthop_req_list_object += (stats_block[VR_NEXTHOP_REQ_LIST_OBJECT].ms_alloc - + stats_block[VR_NEXTHOP_REQ_LIST_OBJECT].ms_free); + response->vms_nexthop_req_encap_object += (stats_block[VR_NEXTHOP_REQ_ENCAP_OBJECT].ms_alloc - + stats_block[VR_NEXTHOP_REQ_ENCAP_OBJECT].ms_free); + response->vms_nexthop_req_object += (stats_block[VR_NEXTHOP_REQ_OBJECT].ms_alloc - + stats_block[VR_NEXTHOP_REQ_OBJECT].ms_free); + response->vms_route_table_object += (stats_block[VR_ROUTE_TABLE_OBJECT].ms_alloc - + stats_block[VR_ROUTE_TABLE_OBJECT].ms_free); + response->vms_route_req_mac_object += (stats_block[VR_ROUTE_REQ_MAC_OBJECT].ms_alloc - + stats_block[VR_ROUTE_REQ_MAC_OBJECT].ms_free); + response->vms_timer_object += (stats_block[VR_TIMER_OBJECT].ms_alloc - + stats_block[VR_TIMER_OBJECT].ms_free); + response->vms_usock_object += (stats_block[VR_USOCK_OBJECT].ms_alloc - + stats_block[VR_USOCK_OBJECT].ms_free); + response->vms_usock_poll_object += (stats_block[VR_USOCK_POLL_OBJECT].ms_alloc - + stats_block[VR_USOCK_POLL_OBJECT].ms_free); + response->vms_usock_buf_object += (stats_block[VR_USOCK_BUF_OBJECT].ms_alloc - + stats_block[VR_USOCK_BUF_OBJECT].ms_free); + response->vms_usock_iovec_object += (stats_block[VR_USOCK_IOVEC_OBJECT].ms_alloc - + stats_block[VR_USOCK_IOVEC_OBJECT].ms_free); + response->vms_vrouter_req_object += (stats_block[VR_VROUTER_REQ_OBJECT].ms_alloc - + stats_block[VR_VROUTER_REQ_OBJECT].ms_free); + for (i = 0; i < VR_VROUTER_MAX_OBJECT; i++) { + alloced += stats_block[i].ms_alloc; + freed += stats_block[i].ms_free; + } + } + + + response->vms_alloced = alloced; + response->vms_freed = freed; + +exit_get: + vr_message_response(VR_MEM_STATS_OBJECT_ID, ret ? NULL : response, ret); + if (response != NULL) + vr_free(response, VR_MEM_STATS_REQ_OBJECT); + + return; +} + +void +vr_mem_stats_req_process(void *s_req) +{ + int ret; + vr_mem_stats_req *req = (vr_mem_stats_req *)s_req; + + if ((req->h_op != SANDESH_OP_GET) && (ret = -EOPNOTSUPP)) + vr_send_response(ret); + + vr_mem_stats_get(); + return; +} + +void +vr_free_stats(unsigned int object) +{ + struct vrouter *router = vrouter_get(0); + unsigned int cpu; + + cpu = vr_get_cpu(); + if (router->vr_malloc_stats && router->vr_malloc_stats[cpu]) + router->vr_malloc_stats[cpu][object].ms_free++; + + return; +} + +void +vr_malloc_stats(unsigned int size, unsigned int object) +{ + struct vrouter *router = vrouter_get(0); + unsigned int cpu; + + cpu = vr_get_cpu(); + if (router->vr_malloc_stats) { + if (router->vr_malloc_stats[cpu]) { + router->vr_malloc_stats[cpu][object].ms_size += size; + router->vr_malloc_stats[cpu][object].ms_alloc++; + } + } + + return; +} + +static void +vr_malloc_stats_exit(struct vrouter *router) +{ + unsigned int i; + + if (!router->vr_malloc_stats) + return; + + for (i = 0; i < vr_num_cpus; i++) { + if (router->vr_malloc_stats[i]) { + vr_free(router->vr_malloc_stats[i], VR_MALLOC_OBJECT); + router->vr_malloc_stats[i] = NULL; + } + } + + vr_free(router->vr_malloc_stats, VR_MALLOC_OBJECT); + + return; +} + +static int +vr_malloc_stats_init(struct vrouter *router) +{ + unsigned int i, size, cpu, total_size = 0; + + if (router->vr_malloc_stats) + return 0; + + size = vr_num_cpus * sizeof(void *); + router->vr_malloc_stats = vr_zalloc(size, VR_MALLOC_OBJECT); + if (!router->vr_malloc_stats) + return -ENOMEM; + total_size += size; + + size = VR_VROUTER_MAX_OBJECT * sizeof(struct vr_malloc_stats); + /* + * align the allocation to cache line size so that per-cpu variable + * do not result in cache thrashing + */ + if (size % 64) { + size = size + (64 - (size % 64)); + } + + for (i = 0; i < vr_num_cpus; i++) { + router->vr_malloc_stats[i] = vr_zalloc(size, VR_MALLOC_OBJECT); + if (!router->vr_malloc_stats) + return -ENOMEM; + total_size += size; + } + + cpu = vr_get_cpu(); + router->vr_malloc_stats[cpu][VR_MALLOC_OBJECT].ms_alloc = vr_num_cpus + 1; + router->vr_malloc_stats[cpu][VR_MALLOC_OBJECT].ms_size = total_size; + + return 0; +} + static void vr_pkt_drop_stats_exit(struct vrouter *router) { @@ -254,11 +501,11 @@ vr_pkt_drop_stats_exit(struct vrouter *router) for (i = 0; i < vr_num_cpus; i++) { if (!router->vr_pdrop_stats[i]) break; - vr_free(router->vr_pdrop_stats[i]); + vr_free(router->vr_pdrop_stats[i], VR_DROP_STATS_OBJECT); router->vr_pdrop_stats[i] = NULL; } - vr_free(router->vr_pdrop_stats); + vr_free(router->vr_pdrop_stats, VR_DROP_STATS_OBJECT); router->vr_pdrop_stats = NULL; return; @@ -274,7 +521,7 @@ vr_pkt_drop_stats_init(struct vrouter *router) return 0; size = sizeof(void *) * vr_num_cpus; - router->vr_pdrop_stats = vr_zalloc(size); + router->vr_pdrop_stats = vr_zalloc(size, VR_DROP_STATS_OBJECT); if (!router->vr_pdrop_stats) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); @@ -283,7 +530,7 @@ vr_pkt_drop_stats_init(struct vrouter *router) size = VP_DROP_MAX * sizeof(uint64_t); for (i = 0; i < vr_num_cpus; i++) { - router->vr_pdrop_stats[i] = vr_zalloc(size); + router->vr_pdrop_stats[i] = vr_zalloc(size, VR_DROP_STATS_OBJECT); if (!router->vr_pdrop_stats[i]) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, i); @@ -322,6 +569,7 @@ vr_stats_exit(struct vrouter *router, bool soft_reset) return; } + vr_malloc_stats_exit(router); vr_pkt_drop_stats_exit(router); return; } @@ -329,5 +577,11 @@ vr_stats_exit(struct vrouter *router, bool soft_reset) int vr_stats_init(struct vrouter *router) { + int ret; + + ret = vr_malloc_stats_init(router); + if (ret) + return ret; + return vr_pkt_drop_stats_init(router); } diff --git a/dp-core/vrouter.c b/dp-core/vrouter.c index 22b3d7ac3..4bfaf6912 100644 --- a/dp-core/vrouter.c +++ b/dp-core/vrouter.c @@ -252,12 +252,10 @@ vrouter_ops_destroy(vrouter_ops *req) return; if (req->vo_build_info) { - vr_free(req->vo_build_info); + vr_free(req->vo_build_info, VR_BUILD_INFO_OBJECT); req->vo_build_info = NULL; } - vr_free(req->vo_build_info); - return; } @@ -266,13 +264,14 @@ vrouter_ops_get(void) { vrouter_ops *req; - req = vr_malloc(sizeof(*req)); + req = vr_malloc(sizeof(*req), VR_VROUTER_REQ_OBJECT); if (!req) return NULL; - req->vo_build_info = vr_zalloc(strlen(ContrailBuildInfo)); + req->vo_build_info = vr_zalloc(strlen(ContrailBuildInfo), + VR_BUILD_INFO_OBJECT); if (!req->vo_build_info) { - vr_free(req); + vr_free(req, VR_VROUTER_REQ_OBJECT); return NULL; } diff --git a/dpdk/vr_dpdk_host.c b/dpdk/vr_dpdk_host.c index e3cae5d6f..bad6e2f26 100644 --- a/dpdk/vr_dpdk_host.c +++ b/dpdk/vr_dpdk_host.c @@ -47,6 +47,9 @@ struct rcu_cb_data { unsigned char rcd_user_data[0]; }; +extern void vr_malloc_stats(unsigned int, unsigned int); +extern void vr_free_stats(unsigned int); + static void * dpdk_page_alloc(unsigned int size) { @@ -79,21 +82,28 @@ dpdk_printf(const char *format, ...) } static void * -dpdk_malloc(unsigned int size) +dpdk_malloc(unsigned int size, unsigned int object) { + vr_malloc_stats(size, object); return rte_malloc(NULL, size, 0); } static void * -dpdk_zalloc(unsigned int size) +dpdk_zalloc(unsigned int size, unsigned int object) { + vr_malloc_stats(size, object); return rte_calloc(NULL, size, 1, 0); } static void -dpdk_free(void *mem) +dpdk_free(void *mem, unsigned int object) { - rte_free(mem); + if (mem) { + vr_free_stats(object); + rte_free(mem); + } + + return; } static uint64_t @@ -499,7 +509,7 @@ dpdk_work_timer(struct rte_timer *timer, void *arg) dpdk_timer(timer, arg); dpdk_delete_timer(vtimer); - dpdk_free(vtimer); + dpdk_free(vtimer, VR_TIMER_OBJECT); return; } @@ -510,15 +520,15 @@ dpdk_schedule_work(unsigned int cpu, void (*fn)(void *), void *arg) struct rte_timer *timer; struct vr_timer *vtimer; - timer = dpdk_malloc(sizeof(struct rte_timer)); + timer = dpdk_malloc(sizeof(struct rte_timer), VR_TIMER_OBJECT); if (!timer) { RTE_LOG(ERR, VROUTER, "Error allocating RTE timer\n"); return; } - vtimer = dpdk_malloc(sizeof(*vtimer)); + vtimer = dpdk_malloc(sizeof(*vtimer), VR_TIMER_OBJECT); if (!vtimer) { - dpdk_free(timer); + dpdk_free(timer, VR_TIMER_OBJECT); RTE_LOG(ERR, VROUTER, "Error allocating VR timer for work\n"); return; } @@ -561,7 +571,7 @@ rcu_cb(struct rcu_head *rh) /* Call the user call back */ cb_data->rcd_user_cb(cb_data->rcd_router, cb_data->rcd_user_data); - dpdk_free(cb_data); + dpdk_free(cb_data, VR_DEFER_OBJECT); return; } @@ -587,7 +597,7 @@ dpdk_get_defer_data(unsigned int len) if (!len) return NULL; - cb_data = dpdk_malloc(sizeof(*cb_data) + len); + cb_data = dpdk_malloc(sizeof(*cb_data) + len, VR_DEFER_OBJECT); if (!cb_data) { return NULL; } @@ -604,7 +614,7 @@ dpdk_put_defer_data(void *data) return; cb_data = CONTAINER_OF(rcd_user_data, struct rcu_cb_data, data); - dpdk_free(cb_data); + dpdk_free(cb_data, VR_DEFER_OBJECT); return; } diff --git a/dpdk/vr_dpdk_netlink.c b/dpdk/vr_dpdk_netlink.c index c4456c3ad..09036836c 100644 --- a/dpdk/vr_dpdk_netlink.c +++ b/dpdk/vr_dpdk_netlink.c @@ -113,7 +113,7 @@ static void dpdk_nl_trans_free(char *buf) { buf -= HDR_LEN; - vr_free(buf); + vr_free(buf, VR_MESSAGE_OBJECT); return; } @@ -123,7 +123,7 @@ dpdk_nl_trans_alloc(unsigned int size) { char *buf; - buf = vr_malloc(size + HDR_LEN); + buf = vr_malloc(size + HDR_LEN, VR_MESSAGE_OBJECT); if (!buf) return NULL; diff --git a/dpdk/vr_dpdk_usocket.c b/dpdk/vr_dpdk_usocket.c index 2efae6ec8..af41d81dd 100644 --- a/dpdk/vr_dpdk_usocket.c +++ b/dpdk/vr_dpdk_usocket.c @@ -63,7 +63,7 @@ usock_deinit_poll(struct vr_usocket *usockp) RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd); if (usockp->usock_pfds) { - vr_free(usockp->usock_pfds); + vr_free(usockp->usock_pfds, VR_USOCK_POLL_OBJECT); usockp->usock_pfds = NULL; } @@ -103,7 +103,7 @@ usock_init_poll(struct vr_usocket *usockp) if (!usockp->usock_pfds) { usockp->usock_pfds = vr_zalloc(sizeof(struct pollfd) * - usockp->usock_max_cfds + 1); + usockp->usock_max_cfds + 1, VR_USOCK_POLL_OBJECT); if (!usockp->usock_pfds) { usock_set_error(usockp, -ENOMEM); goto error_return; @@ -161,7 +161,7 @@ usock_bind_usockets(struct vr_usocket *parent, struct vr_usocket *child) if (!parent->usock_children) { parent->usock_children = vr_zalloc(sizeof(struct vr_usocket *) * - USOCK_MAX_CHILD_FDS + 1); + USOCK_MAX_CHILD_FDS + 1, VR_USOCK_OBJECT); if (!parent->usock_children) { usock_set_error(parent, -ENOMEM); return -ENOMEM; @@ -209,13 +209,13 @@ usock_clone(struct vr_usocket *parent, int cfd) RTE_LOG(DEBUG, USOCK, "%s[%lx]: parent FD %d cfd %d\n", __func__, pthread_self(), parent->usock_fd, cfd); - child = vr_zalloc(sizeof(struct vr_usocket)); + child = vr_zalloc(sizeof(struct vr_usocket), VR_USOCK_OBJECT); if (!child) { usock_set_error(parent, -ENOMEM); goto error_return; } - child->usock_rx_buf = vr_malloc(USOCK_RX_BUF_LEN); + child->usock_rx_buf = vr_malloc(USOCK_RX_BUF_LEN, VR_USOCK_BUF_OBJECT); if (!child->usock_rx_buf) { usock_set_error(parent, -ENOMEM); goto error_return; @@ -234,8 +234,8 @@ usock_clone(struct vr_usocket *parent, int cfd) error_return: if (child) { if (child->usock_rx_buf) - vr_free(child->usock_rx_buf); - vr_free(child); + vr_free(child->usock_rx_buf, VR_USOCK_BUF_OBJECT); + vr_free(child, VR_USOCK_OBJECT); } return parent->usock_error; @@ -291,12 +291,12 @@ usock_close(struct vr_usocket *usockp) close(usockp->usock_fd); if (!usockp->usock_mbuf_pool && usockp->usock_rx_buf) { - vr_free(usockp->usock_rx_buf); + vr_free(usockp->usock_rx_buf, VR_USOCK_BUF_OBJECT); usockp->usock_rx_buf = NULL; } if (usockp->usock_iovec) { - vr_free(usockp->usock_iovec); + vr_free(usockp->usock_iovec, VR_USOCK_IOVEC_OBJECT); usockp->usock_iovec = NULL; } @@ -312,7 +312,7 @@ usock_close(struct vr_usocket *usockp) usockp->usock_io_in_progress = 0; - vr_free(usockp); + vr_free(usockp, VR_USOCK_OBJECT); return; } @@ -667,7 +667,8 @@ __usock_read(struct vr_usocket *usockp) } if (usockp->usock_buf_len < usockp->usock_read_len) { - usockp->usock_rx_buf = vr_malloc(usockp->usock_read_len); + usockp->usock_rx_buf = vr_malloc(usockp->usock_read_len, + VR_USOCK_BUF_OBJECT); if (!usockp->usock_rx_buf) { /* bad, but let's recover */ usockp->usock_rx_buf = buf; @@ -676,7 +677,7 @@ __usock_read(struct vr_usocket *usockp) usockp->usock_state = READING_FAULTY_DATA; } else { memcpy(usockp->usock_rx_buf, buf, usockp->usock_read_offset); - vr_free(buf); + vr_free(buf, VR_USOCK_BUF_OBJECT); usockp->usock_buf_len = usockp->usock_read_len; buf = usockp->usock_rx_buf; } @@ -736,7 +737,7 @@ usock_alloc(unsigned short proto, unsigned short type) return NULL; } - usockp = vr_zalloc(sizeof(*usockp)); + usockp = vr_zalloc(sizeof(*usockp), VR_USOCK_OBJECT); if (!usockp) goto error_exit; @@ -779,7 +780,7 @@ usock_alloc(unsigned short proto, unsigned short type) } if (buf_len) { - usockp->usock_rx_buf = vr_zalloc(buf_len); + usockp->usock_rx_buf = vr_zalloc(buf_len, VR_USOCK_BUF_OBJECT); if (!usockp->usock_rx_buf) goto error_exit; @@ -800,7 +801,7 @@ usock_alloc(unsigned short proto, unsigned short type) } usockp->usock_iovec = vr_zalloc(sizeof(struct iovec) * - PKT0_MAX_IOV_LEN); + PKT0_MAX_IOV_LEN, VR_USOCK_IOVEC_OBJECT); if (!usockp->usock_iovec) goto error_exit; diff --git a/freebsd/vrouter_mod.c b/freebsd/vrouter_mod.c index d3b24e165..259c591b8 100644 --- a/freebsd/vrouter_mod.c +++ b/freebsd/vrouter_mod.c @@ -412,7 +412,7 @@ fh_delete_timer(struct vr_timer *vtimer) vr_log(VR_DEBUG, "stop timer %p\n", callout); if (callout) { callout_drain(callout); - vr_free(vtimer->vt_os_arg); + vr_free(vtimer->vt_os_arg, VR_TIMER_OBJECT); vtimer->vt_os_arg = NULL; } @@ -424,7 +424,7 @@ fh_create_timer(struct vr_timer *vtimer) { struct callout *callout; - callout = vr_zalloc(sizeof(*callout)); + callout = vr_zalloc(sizeof(*callout), VR_TIMER_OBJECT); if (!callout) { vr_log(VR_ERR, "Failed to alloc callout\n"); return (-1); diff --git a/host/vr_host_packet.c b/host/vr_host_packet.c index 190c6018d..a23da6079 100644 --- a/host/vr_host_packet.c +++ b/host/vr_host_packet.c @@ -175,7 +175,7 @@ vr_hpacket_pool_destroy(struct vr_hpacket_pool *pool) vr_hpacket_free(hpkt); hpkt = n_hpkt; } - vr_free(pool); + vr_free(pool, VR_HPACKET_POOL_OBJECT); return; } @@ -190,7 +190,7 @@ vr_hpacket_pool_create(unsigned int pool_size, unsigned int psize) if (!pool_size) return NULL; - pool = vr_zalloc(sizeof(*pool)); + pool = vr_zalloc(sizeof(*pool), VR_HPACKET_POOL_OBJECT); if (!pool) goto cleanup; diff --git a/host/vrouter_host_mod.c b/host/vrouter_host_mod.c index e7c59a9d2..4161b0f91 100644 --- a/host/vrouter_host_mod.c +++ b/host/vrouter_host_mod.c @@ -29,7 +29,7 @@ vr_lib_create_timer(struct vr_timer *vtimer) { struct dummy_timer_list *timer; - timer = vr_zalloc(sizeof(*timer)); + timer = vr_zalloc(sizeof(*timer), VR_TIMER_OBJECT); if (!timer) return -1; init_timer(timer); @@ -46,7 +46,7 @@ vr_lib_create_timer(struct vr_timer *vtimer) static void vr_lib_delete_timer(struct vr_timer *vtimer) { - vr_free(vtimer->vt_os_arg); + vr_free(vtimer->vt_os_arg, VR_TIMER_OBJECT); } static void * @@ -82,19 +82,19 @@ vr_lib_printf(const char *format, ...) } static void * -vr_lib_malloc(unsigned int size) +vr_lib_malloc(unsigned int size, unsigned int object) { return malloc(size); } static void * -vr_lib_zalloc(unsigned int size) +vr_lib_zalloc(unsigned int size, unsigned int object) { return calloc(size, 1); } static void -vr_lib_free(void *mem) +vr_lib_free(void *mem, unsigned int object) { if (mem) free(mem); diff --git a/include/vr_message.h b/include/vr_message.h index 476394e1e..911bb9333 100644 --- a/include/vr_message.h +++ b/include/vr_message.h @@ -29,6 +29,7 @@ #define VR_VXLAN_OBJECT_ID 11 #define VR_VROUTER_OPS_OBJECT_ID 12 #define VR_FLOW_INFO_OBJECT_ID 13 +#define VR_MEM_STATS_OBJECT_ID 14 #define VR_MESSAGE_PAGE_SIZE (4096 - 128) diff --git a/include/vrouter.h b/include/vrouter.h index 627e701c1..4d02728e9 100644 --- a/include/vrouter.h +++ b/include/vrouter.h @@ -26,6 +26,64 @@ extern "C" { #define VR_CPU_MASK 0xff extern unsigned int vr_num_cpus; +enum vr_malloc_objects_t { + VR_ASSEMBLER_TABLE_OBJECT, + VR_BRIDGE_MAC_OBJECT, + VR_BTABLE_OBJECT, + VR_BUILD_INFO_OBJECT, + VR_DEFER_OBJECT, + VR_DROP_STATS_OBJECT, + VR_DROP_STATS_REQ_OBJECT, + VR_FLOW_QUEUE_OBJECT, + VR_FLOW_REQ_OBJECT, + VR_FLOW_REQ_PATH_OBJECT, + VR_FLOW_HOLD_STAT_OBJECT, + VR_FLOW_LINK_LOCAL_OBJECT, + VR_FLOW_METADATA_OBJECT, + VR_FLOW_TABLE_INFO_OBJECT, + VR_FRAGMENT_OBJECT, + VR_FRAGMENT_QUEUE_OBJECT, + VR_FRAGMENT_QUEUE_ELEMENT_OBJECT, + VR_FRAGMENT_SCANNER_OBJECT, + VR_HPACKET_POOL_OBJECT, + VR_HTABLE_OBJECT, + VR_INTERFACE_OBJECT, + VR_INTERFACE_MAC_OBJECT, + VR_INTERFACE_REQ_OBJECT, + VR_INTERFACE_REQ_MAC_OBJECT, + VR_INTERFACE_REQ_NAME_OBJECT, + VR_INTERFACE_STATS_OBJECT, + VR_INTERFACE_TABLE_OBJECT, + VR_INTERFACE_VRF_TABLE_OBJECT, + VR_ITABLE_OBJECT, + VR_MALLOC_OBJECT, + VR_MESSAGE_OBJECT, + VR_MESSAGE_RESPONSE_OBJECT, + VR_MESSAGE_DUMP_OBJECT, + VR_MEM_STATS_REQ_OBJECT, + VR_MIRROR_OBJECT, + VR_MIRROR_TABLE_OBJECT, + VR_MIRROR_META_OBJECT, + VR_MTRIE_OBJECT, + VR_MTRIE_BUCKET_OBJECT, + VR_MTRIE_STATS_OBJECT, + VR_MTRIE_TABLE_OBJECT, + VR_NEXTHOP_OBJECT, + VR_NEXTHOP_COMPONENT_OBJECT, + VR_NEXTHOP_REQ_LIST_OBJECT, + VR_NEXTHOP_REQ_ENCAP_OBJECT, + VR_NEXTHOP_REQ_OBJECT, + VR_ROUTE_TABLE_OBJECT, + VR_ROUTE_REQ_MAC_OBJECT, + VR_TIMER_OBJECT, + VR_USOCK_OBJECT, + VR_USOCK_POLL_OBJECT, + VR_USOCK_BUF_OBJECT, + VR_USOCK_IOVEC_OBJECT, + VR_VROUTER_REQ_OBJECT, + VR_VROUTER_MAX_OBJECT, +}; + extern int vr_perfr; extern int vr_mudp; extern int vr_perfs; @@ -58,9 +116,9 @@ struct vr_timer { struct host_os { int (*hos_printf)(const char *, ...); - void *(*hos_malloc)(unsigned int); - void *(*hos_zalloc)(unsigned int); - void (*hos_free)(void *); + void *(*hos_malloc)(unsigned int, unsigned int); + void *(*hos_zalloc)(unsigned int, unsigned int); + void (*hos_free)(void *, unsigned int); uint64_t (*hos_vtop)(void *); void *(*hos_page_alloc)(unsigned int); void (*hos_page_free)(void *, unsigned int); @@ -157,6 +215,12 @@ struct host_os { #define vr_gro_process vrouter_host->hos_gro_process #define vr_enqueue_to_assembler vrouter_host->hos_enqueue_to_assembler +struct vr_malloc_stats { + int64_t ms_size; + int64_t ms_alloc; + int64_t ms_free; +}; + struct vrouter { unsigned char vr_vrrp_mac[VR_ETHER_ALEN]; unsigned char vr_mac[VR_ETHER_ALEN]; @@ -192,6 +256,7 @@ struct vrouter { struct vr_timer *vr_fragment_otable_scanner; uint64_t **vr_pdrop_stats; + struct vr_malloc_stats **vr_malloc_stats; uint16_t vr_link_local_ports_size; unsigned char *vr_link_local_ports; diff --git a/linux/vr_fragment_assembler.c b/linux/vr_fragment_assembler.c index 93ded4877..f920afd0b 100644 --- a/linux/vr_fragment_assembler.c +++ b/linux/vr_fragment_assembler.c @@ -42,7 +42,7 @@ vr_linux_fragment_queue_free(struct vr_linux_fragment_queue *vlfq) if (vfqe->fqe_pnode.pl_packet) vr_pfree(vfqe->fqe_pnode.pl_packet, VP_DROP_MISC); vfqe->fqe_pnode.pl_packet = NULL; - vr_free(vfqe); + vr_free(vfqe, VR_FRAGMENT_QUEUE_ELEMENT_OBJECT); vfqe = next; } @@ -153,7 +153,7 @@ vr_linux_assembler_table_exit(void) vr_assembler_table_scan_exit(); if (vr_linux_assembler_table) { - vr_free(vr_linux_assembler_table); + vr_free(vr_linux_assembler_table, VR_ASSEMBLER_TABLE_OBJECT); vr_linux_assembler_table = NULL; } @@ -166,7 +166,7 @@ vr_linux_assembler_table_init(void) unsigned int i, size; size = sizeof(struct vr_linux_fragment_bucket) * VR_LINUX_ASSEMBLER_BUCKETS; - vr_linux_assembler_table = vr_zalloc(size); + vr_linux_assembler_table = vr_zalloc(size, VR_ASSEMBLER_TABLE_OBJECT); if (!vr_linux_assembler_table) { printk("%s:%d Allocation for %u failed\n", __FUNCTION__, __LINE__, size); @@ -200,7 +200,7 @@ vr_linux_fragment_queue_exit(void) for (i = 0; i < vr_num_cpus; i++) vr_linux_fragment_queue_free(&vr_lfq_pcpu_queues[i]); - vr_free(vr_lfq_pcpu_queues); + vr_free(vr_lfq_pcpu_queues, VR_FRAGMENT_QUEUE_OBJECT); vr_lfq_pcpu_queues = NULL; } @@ -213,7 +213,7 @@ vr_linux_fragment_queue_init(void) unsigned int i, size; size = sizeof(struct vr_linux_fragment_queue) * vr_num_cpus; - vr_lfq_pcpu_queues = vr_zalloc(size); + vr_lfq_pcpu_queues = vr_zalloc(size, VR_FRAGMENT_QUEUE_OBJECT); if (!vr_lfq_pcpu_queues) { printk("%s:%d Allocation for %u failed\n", __FUNCTION__, __LINE__, size); diff --git a/linux/vrouter_mod.c b/linux/vrouter_mod.c index ce7f4a0cf..b1931dad7 100644 --- a/linux/vrouter_mod.c +++ b/linux/vrouter_mod.c @@ -71,6 +71,8 @@ extern int vr_genetlink_init(void); extern void vr_genetlink_exit(void); extern int vr_mem_init(void); extern void vr_mem_exit(void); +extern void vr_malloc_stats(unsigned int, unsigned int); +extern void vr_free_stats(unsigned int); extern void vhost_exit(void); extern int lh_gro_process(struct vr_packet *, struct vr_interface *, bool); @@ -91,22 +93,26 @@ lh_printk(const char *format, ...) } static void * -lh_malloc(unsigned int size) +lh_malloc(unsigned int size, unsigned int object) { + vr_malloc_stats(size, object); return kmalloc(size, GFP_ATOMIC); } static void * -lh_zalloc(unsigned int size) +lh_zalloc(unsigned int size, unsigned int object) { + vr_malloc_stats(size, object); return kzalloc(size, GFP_ATOMIC); } static void -lh_free(void *mem) +lh_free(void *mem, unsigned int object) { - if (mem) + if (mem) { + vr_free_stats(object); kfree(mem); + } return; } @@ -465,7 +471,7 @@ rcu_cb(struct rcu_head *rh) /* Call the user call back */ cb_data->rcd_user_cb(cb_data->rcd_router, cb_data->rcd_user_data); - lh_free(cb_data); + lh_free(cb_data, VR_DEFER_OBJECT); return; } @@ -491,7 +497,7 @@ lh_get_defer_data(unsigned int len) if (!len) return NULL; - cb_data = lh_malloc(sizeof(*cb_data) + len); + cb_data = lh_malloc(sizeof(*cb_data) + len, VR_DEFER_OBJECT); if (!cb_data) { return NULL; } @@ -508,7 +514,7 @@ lh_put_defer_data(void *data) return; cb_data = container_of(data, struct rcu_cb_data, rcd_user_data); - lh_free(cb_data); + lh_free(cb_data, VR_DEFER_OBJECT); return; } @@ -2331,7 +2337,7 @@ lh_delete_timer(struct vr_timer *vtimer) if (timer) { del_timer_sync(timer); - vr_free(vtimer->vt_os_arg); + vr_free(vtimer->vt_os_arg, VR_TIMER_OBJECT); vtimer->vt_os_arg = NULL; } @@ -2343,7 +2349,7 @@ lh_create_timer(struct vr_timer *vtimer) { struct timer_list *timer; - timer = vr_zalloc(sizeof(*timer)); + timer = vr_zalloc(sizeof(*timer), VR_TIMER_OBJECT); if (!timer) return -ENOMEM; init_timer(timer); diff --git a/sandesh/vr.sandesh b/sandesh/vr.sandesh index d2a5ead00..c1f814455 100644 --- a/sandesh/vr.sandesh +++ b/sandesh/vr.sandesh @@ -231,6 +231,67 @@ buffer sandesh vrouter_ops { 12: string vo_build_info; } +buffer sandesh vr_mem_stats_req { + 1: sandesh_op h_op; + 2: i16 vms_rid; + 3: i64 vms_alloced; + 4: i64 vms_freed; + 5: i64 vms_assembler_table_object; + 6: i64 vms_bridge_mac_object; + 7: i64 vms_btable_object; + 8: i64 vms_build_info_object; + 9: i64 vms_defer_object; + 10: i64 vms_drop_stats_object; + 11: i64 vms_drop_stats_req_object; + 12: i64 vms_flow_queue_object; + 13: i64 vms_flow_req_object; + 14: i64 vms_flow_req_path_object; + 15: i64 vms_flow_hold_stat_object; + 16: i64 vms_flow_link_local_object; + 17: i64 vms_flow_metadata_object; + 18: i64 vms_flow_table_info_object; + 19: i64 vms_fragment_object; + 20: i64 vms_fragment_queue_object; + 21: i64 vms_fragment_queue_element_object; + 22: i64 vms_fragment_scanner_object; + 23: i64 vms_hpacket_pool_object; + 24: i64 vms_htable_object; + 25: i64 vms_interface_object; + 26: i64 vms_interface_mac_object; + 27: i64 vms_interface_req_object; + 28: i64 vms_interface_req_mac_object; + 29: i64 vms_interface_req_name_object; + 30: i64 vms_interface_stats_object; + 31: i64 vms_interface_table_object; + 32: i64 vms_interface_vrf_table_object; + 33: i64 vms_itable_object; + 34: i64 vms_malloc_object; + 35: i64 vms_message_object; + 36: i64 vms_message_response_object; + 37: i64 vms_message_dump_object; + 38: i64 vms_mem_stats_req_object; + 39: i64 vms_mirror_object; + 40: i64 vms_mirror_table_object; + 41: i64 vms_mirror_meta_object; + 42: i64 vms_mtrie_object; + 43: i64 vms_mtrie_bucket_object; + 44: i64 vms_mtrie_stats_object; + 45: i64 vms_mtrie_table_object; + 46: i64 vms_nexthop_object; + 47: i64 vms_nexthop_component_object; + 48: i64 vms_nexthop_req_list_object; + 49: i64 vms_nexthop_req_encap_object; + 50: i64 vms_nexthop_req_object; + 51: i64 vms_route_table_object; + 52: i64 vms_route_req_mac_object; + 53: i64 vms_timer_object; + 54: i64 vms_usock_object; + 55: i64 vms_usock_poll_object; + 56: i64 vms_usock_buf_object; + 57: i64 vms_usock_iovec_object; + 58: i64 vms_vrouter_req_object; +} + buffer sandesh vr_drop_stats_req { 1: sandesh_op h_op; 2: u32 vds_core; diff --git a/utils/SConscript b/utils/SConscript index 2c4e42f67..2a2ad93a6 100644 --- a/utils/SConscript +++ b/utils/SConscript @@ -65,8 +65,12 @@ vxlan = env.Program(target = 'vxlan', source = vxlan_sources) vrouter_sources = ['vrouter.c'] vrouter = env.Program(target = 'vrouter', source = vrouter_sources) +vrmemstats_sources = ['vrmemstats.c'] +vrmemstats = env.Program(target = 'vrmemstats', source = vrmemstats_sources) + # to make sure that all are built when you do 'scons' @ the top level -binaries = [vif, rt, nh, mirror, mpls, flow, vrfstats, dropstats, vxlan, vrouter] +binaries = [vif, rt, nh, mirror, mpls, flow, vrfstats, dropstats, + vxlan, vrouter, vrmemstats] scripts = ['vifdump'] env.Default(binaries) env.Alias('install', env.Install(env['INSTALL_BIN'], binaries + scripts)) diff --git a/utils/nl_util.c b/utils/nl_util.c index 2266a6cd6..569f65fb2 100644 --- a/utils/nl_util.c +++ b/utils/nl_util.c @@ -47,6 +47,7 @@ extern void vr_vrf_assign_req_process(void *s_req) __attribute__((weak)); extern void vr_vrf_stats_req_process(void *s_req) __attribute__((weak)); extern void vr_drop_stats_req_process(void *s_req) __attribute__((weak)); extern void vr_vxlan_req_process(void *s_req) __attribute__((weak)); +extern void vr_mem_stats_req_process(void *s_req) __attribute__((weak)); void vrouter_ops_process(void *s_req) @@ -122,6 +123,12 @@ vr_vxlan_req_process(void *s_req) return; } +void +vr_mem_stats_req_process(void *s_req) +{ + return; +} + struct nl_response * nl_parse_gen_ctrl(struct nl_client *cl) { diff --git a/utils/vrmemstats.c b/utils/vrmemstats.c new file mode 100644 index 000000000..3e77d8231 --- /dev/null +++ b/utils/vrmemstats.c @@ -0,0 +1,324 @@ +/* + * vrmemstats.c - vrouter memory statistics + * + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#if defined(__linux__) +#include + +#include +#include +#include + +#include +#include +#elif defined(__FreeBSD__) +#include +#include +#endif + +#include "vr_types.h" +#include "vr_message.h" +#include "vr_nexthop.h" +#include "vr_genetlink.h" +#include "nl_util.h" +#include "vr_os.h" +#include "ini_parser.h" + +static struct nl_client *cl; +static int resp_code; +static vr_mem_stats_req stats_req; +static int help_set; + +void +vr_mem_stats_req_process(void *s_req) +{ + vr_mem_stats_req *stats = (vr_mem_stats_req *)s_req; + + + printf("vRouter memory usage statistics\n\n"); + + printf("Alloced %lu Freed %lu\n", stats->vms_alloced, stats->vms_freed); + printf("Outstanding memory/object:\n\n"); + + printf("Assembler Table %" PRIu64 "\n", + stats->vms_assembler_table_object); + printf("Bridge MAC %" PRIu64 "\n", + stats->vms_bridge_mac_object); + printf("Btable %" PRIu64 "\n", + stats->vms_btable_object); + printf("Build Info %" PRIu64 "\n", + stats->vms_build_info_object); + printf("Defer %" PRIu64 "\n", + stats->vms_defer_object); + printf("Drop Stats %" PRIu64 "\n", + stats->vms_drop_stats_object); + printf("Drop Stats Request %" PRIu64 "\n", + stats->vms_drop_stats_req_object); + printf("Flow queue %" PRIu64 "\n", + stats->vms_flow_queue_object); + printf("Flow Request %" PRIu64 "\n", + stats->vms_flow_req_object); + printf("Flow Request Path %" PRIu64 "\n", + stats->vms_flow_req_path_object); + printf("Flow Hold Stat %" PRIu64 "\n", + stats->vms_flow_hold_stat_object); + printf("Flow Link Local %" PRIu64 "\n", + stats->vms_flow_link_local_object); + printf("Flow Metadata %" PRIu64 "\n", + stats->vms_flow_metadata_object); + printf("Flow Table Info %" PRIu64 "\n", + stats->vms_flow_table_info_object); + printf("Fragment %" PRIu64 "\n", + stats->vms_fragment_object); + printf("Fragment Queue %" PRIu64 "\n", + stats->vms_fragment_queue_object); + printf("Fragment Queue Element %" PRIu64 "\n", + stats->vms_fragment_queue_element_object); + printf("Fragment Scanner %" PRIu64 "\n", + stats->vms_fragment_scanner_object); + printf("Host Packet Pool %" PRIu64 "\n", + stats->vms_hpacket_pool_object); + printf("Hash Table %" PRIu64 "\n", + stats->vms_htable_object); + printf("Interface %" PRIu64 "\n", + stats->vms_interface_object); + printf("Interface MAC %" PRIu64 "\n", + stats->vms_interface_mac_object); + printf("Interface Request %" PRIu64 "\n", + stats->vms_interface_req_object); + printf("Interface Request MAC %" PRIu64 "\n", + stats->vms_interface_req_mac_object); + printf("Interface Request Name %" PRIu64 "\n", + stats->vms_interface_req_name_object); + printf("Interface Stats %" PRIu64 "\n", + stats->vms_interface_stats_object); + printf("Interface Table %" PRIu64 "\n", + stats->vms_interface_table_object); + printf("VRF Table %" PRIu64 "\n", + stats->vms_interface_vrf_table_object); + printf("Index Table %" PRIu64 "\n", + stats->vms_itable_object); + printf("Malloc %" PRIu64 "\n", + stats->vms_malloc_object); + printf("Message %" PRIu64 "\n", + stats->vms_message_object); + printf("Message Response %" PRIu64 "\n", + stats->vms_message_response_object); + printf("Message Dump %" PRIu64 "\n", + stats->vms_message_dump_object); + printf("Memory Stats Request %" PRIu64 "\n", + stats->vms_mem_stats_req_object); + printf("Mirror %" PRIu64 "\n", + stats->vms_mirror_object); + printf("Mirror Table %" PRIu64 "\n", + stats->vms_mirror_table_object); + printf("Mirror MetMirror Meta %" PRIu64 "\n", + stats->vms_mirror_meta_object); + printf("MTRIE %" PRIu64 "\n", + stats->vms_mtrie_object); + printf("Mtrie Bucket %" PRIu64 "\n", + stats->vms_mtrie_bucket_object); + printf("Mtrie Stats %" PRIu64 "\n", + stats->vms_mtrie_stats_object); + printf("Mtrie Table %" PRIu64 "\n", + stats->vms_mtrie_table_object); + printf("Nexthop %" PRIu64 "\n", + stats->vms_nexthop_object); + printf("NextHop Component %" PRIu64 "\n", + stats->vms_nexthop_component_object); + printf("NextHop Request List %" PRIu64 "\n", + stats->vms_nexthop_req_list_object); + printf("NextHop Request Encap %" PRIu64 "\n", + stats->vms_nexthop_req_encap_object); + printf("NextHop Request %" PRIu64 "\n", + stats->vms_nexthop_req_object); + printf("Route Table %" PRIu64 "\n", + stats->vms_route_table_object); + printf("Timer %" PRIu64 "\n", + stats->vms_timer_object); + printf("Usock %" PRIu64 "\n", + stats->vms_usock_object); + printf("Usock Poll %" PRIu64 "\n", + stats->vms_usock_poll_object); + printf("Usock Buf %" PRIu64 "\n", + stats->vms_usock_buf_object); + printf("Usock Iovec %" PRIu64 "\n", + stats->vms_usock_iovec_object); + printf("Vrouter Request %" PRIu64 "\n", + stats->vms_vrouter_req_object); + return; +} + +void +vr_response_process(void *s) +{ + vr_response *stats_resp; + + stats_resp = (vr_response *)s; + resp_code = stats_resp->resp_code; + + if (stats_resp->resp_code < 0) { + printf("Error %s in kernel operation\n", strerror(stats_resp->resp_code)); + exit(-1); + } + + return; +} + + +static vr_mem_stats_req * +vr_build_mem_stats_request(void) +{ + stats_req.h_op = SANDESH_OP_GET; + stats_req.vms_rid = 0; + + return &stats_req; +} + +static int +vr_build_netlink_request(vr_mem_stats_req *req) +{ + int ret, error = 0, attr_len; + + /* nlmsg header */ + ret = nl_build_nlh(cl, cl->cl_genl_family_id, NLM_F_REQUEST); + if (ret) + return ret; + + /* Generic nlmsg header */ + ret = nl_build_genlh(cl, SANDESH_REQUEST, 0); + if (ret) + return ret; + + attr_len = nl_get_attr_hdr_size(); + ret = sandesh_encode(req, "vr_mem_stats_req", vr_find_sandesh_info, + (nl_get_buf_ptr(cl) + attr_len), + (nl_get_buf_len(cl) - attr_len), &error); + + if ((ret <= 0) || error) + return -1; + + /* Add sandesh attribute */ + nl_build_attr(cl, ret, NL_ATTR_VR_MESSAGE_PROTOCOL); + nl_update_nlh(cl); + + return 0; +} + +static int +vr_send_one_message(void) +{ + int ret; + struct nl_response *resp; + + ret = nl_sendmsg(cl); + if (ret <= 0) + return 0; + + if((ret = nl_recvmsg(cl)) > 0) { + resp = nl_parse_reply(cl); + if (resp->nl_op == SANDESH_REQUEST) + sandesh_decode(resp->nl_data, resp->nl_len, vr_find_sandesh_info, &ret); + } + + return resp_code; +} + +static void +vr_mem_stats_op(void) +{ + vr_send_one_message(); + return; +} + +static int +vr_get_mem_stats(void) +{ + int ret; + vr_mem_stats_req *req; + + req = vr_build_mem_stats_request(); + if (!req) + return -errno; + + ret = vr_build_netlink_request(req); + if (ret < 0) + return ret; + + vr_mem_stats_op(); + + return 0; +} + +enum opt_index { + HELP_OPT_INDEX, + MAX_OPT_INDEX, +}; + +static struct option long_options[] = { + [HELP_OPT_INDEX] = {"help", no_argument, &help_set, 1}, + [MAX_OPT_INDEX] = {"NULL", 0, 0, 0}, +}; + +static void +Usage() +{ + printf("Usage: memstats [--help]\n"); + exit(-EINVAL); +} + +int +main(int argc, char *argv[]) +{ + char opt; + int ret, option_index; + + while (((opt = getopt_long(argc, argv, "", + long_options, &option_index)) >= 0)) { + switch (opt) { + case 0: + break; + + default: + Usage(); + } + } + + cl = nl_register_client(); + if (!cl) { + exit(1); + } + + parse_ini_file(); + + ret = nl_socket(cl, get_domain(), get_type(), get_protocol()); + if (ret <= 0) { + exit(1); + } + + ret = nl_connect(cl, get_ip(), get_port()); + if (ret < 0) { + exit(1); + } + + if (vrouter_get_family_id(cl) <= 0) { + return -1; + } + + vr_get_mem_stats(); + + return 0; +}