From 3bfe603839ce6fa6e399b31df4c8b58cb1f3ace1 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Fri, 9 Sep 2016 19:20:27 +0530 Subject: [PATCH] Fix memory allocation for interface request In order to pass per lcore queue input error statistics to the application that does vif query, we allocate only VR_MAX_CPUS worth of memory, but we try to copy vr_num_cpus worth of data. In the case of vr_num_cpus > VR_MAX_CPUS (64), we will hit a snag. As a fix, allocate memory for vr_num_cpus. Change-Id: Ifb1060aac20011b8d51e1b31063a363fe268fd3d Closes-Bug: #1621816 --- dp-core/vr_interface.c | 16 ++++++++++++++-- dp-core/vr_sandesh.c | 1 + include/vr_interface.h | 1 + include/vrouter.h | 1 + utils/vif.c | 21 +++++++++------------ 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/dp-core/vr_interface.c b/dp-core/vr_interface.c index 8dc8ad41e..5880f8a99 100644 --- a/dp-core/vr_interface.c +++ b/dp-core/vr_interface.c @@ -1996,7 +1996,7 @@ __vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf, req->vifr_oerrors = 0; /* queue counters */ req->vifr_queue_ipackets = 0; - for (i = 0; i < VR_MAX_CPUS; i++) + for (i = 0; i < vr_num_cpus; i++) req->vifr_queue_ierrors_to_lcore[i] = 0; req->vifr_queue_ierrors = 0; req->vifr_queue_opackets = 0; @@ -2081,6 +2081,18 @@ __vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf, return; } +unsigned int +vr_interface_req_get_size(void *req_p) +{ + unsigned int size = 4 * sizeof(vr_interface_req); + vr_interface_req *req = (vr_interface_req *)req_p; + + if (req->vifr_queue_ierrors_to_lcore) + size += (vr_num_cpus * sizeof(int64_t)); + + return size; +} + static int vr_interface_make_req(vr_interface_req *req, struct vr_interface *vif, unsigned int core) @@ -2125,7 +2137,7 @@ vr_interface_req_get(void) req->vifr_name = vr_zalloc(VR_INTERFACE_NAME_LEN, VR_INTERFACE_REQ_NAME_OBJECT); - req->vifr_queue_ierrors_to_lcore = vr_zalloc(VR_MAX_CPUS * sizeof(uint64_t), + req->vifr_queue_ierrors_to_lcore = vr_zalloc(vr_num_cpus * sizeof(uint64_t), VR_INTERFACE_REQ_TO_LCORE_ERRORS_OBJECT); if (req->vifr_queue_ierrors_to_lcore) req->vifr_queue_ierrors_to_lcore_size = 0; diff --git a/dp-core/vr_sandesh.c b/dp-core/vr_sandesh.c index 80f5948dd..c42cf196c 100644 --- a/dp-core/vr_sandesh.c +++ b/dp-core/vr_sandesh.c @@ -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] = { diff --git a/include/vr_interface.h b/include/vr_interface.h index c839e7596..181548134 100644 --- a/include/vr_interface.h +++ b/include/vr_interface.h @@ -322,4 +322,5 @@ extern void vr_set_vif_ptr(struct net_device *dev, void *vif); #endif extern fat_flow_port_mask_t vif_fat_flow_lookup(struct vr_interface *, uint8_t, uint16_t, uint16_t); +extern unsigned int vr_interface_req_get_size(void *); #endif /* __VR_INTERFACE_H__ */ diff --git a/include/vrouter.h b/include/vrouter.h index d5b5d3078..b46569e6e 100644 --- a/include/vrouter.h +++ b/include/vrouter.h @@ -14,6 +14,7 @@ extern "C" { #include "vr_types.h" #include "vr_qos.h" #include "vr_flow.h" +#include "vr_interface.h" #include "vr_nexthop.h" #include "vr_route.h" #include "vr_response.h" diff --git a/utils/vif.c b/utils/vif.c index 8461a234c..62dd0247b 100644 --- a/utils/vif.c +++ b/utils/vif.c @@ -633,6 +633,13 @@ rate_process(vr_interface_req *req, vr_interface_req *prev_req) temp_prev_req_ptr = prev_req->vifr_queue_ierrors_to_lcore; *prev_req = *req; prev_req->vifr_queue_ierrors_to_lcore = temp_prev_req_ptr; + if (!prev_req->vifr_queue_ierrors_to_lcore) { + prev_req->vifr_queue_ierrors_to_lcore = + malloc(req->vifr_queue_ierrors_to_lcore_size * sizeof(uint64_t)); + if (!prev_req->vifr_queue_ierrors_to_lcore) + return; + } + memcpy(prev_req->vifr_queue_ierrors_to_lcore, req->vifr_queue_ierrors_to_lcore, req->vifr_queue_ierrors_to_lcore_size * sizeof(uint64_t)); @@ -641,7 +648,8 @@ rate_process(vr_interface_req *req, vr_interface_req *prev_req) } rate_req_temp = *req; - rate_req_temp.vifr_queue_ierrors_to_lcore = calloc(VR_MAX_CPUS, sizeof(uint64_t)); + rate_req_temp.vifr_queue_ierrors_to_lcore = + calloc(req->vifr_queue_ierrors_to_lcore_size, sizeof(uint64_t)); if (!rate_req_temp.vifr_queue_ierrors_to_lcore) { fprintf(stderr, "Fail, memory allocation. (%s:%d).", __FILE__ , __LINE__); @@ -1519,17 +1527,6 @@ main(int argc, char *argv[]) vr_intf_op(cl, vr_op); } else { - for (i = 0; i < VR_MAX_INTERFACES; i++) { - - prev_req[i].vifr_queue_ierrors_to_lcore = - (calloc(VR_MAX_CPUS, sizeof(uint64_t))); - - if (!(prev_req[i].vifr_queue_ierrors_to_lcore)) { - fprintf(stderr, "Fail, memory allocation. (%s:%d).", __FILE__ , __LINE__); - exit(1); - } - } - fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK); /* * tc[get/set]attr functions are for changing terminal behavior.