diff --git a/examples/example_config.json b/examples/example_config.json index 2191bb1c1..5c1302a41 100644 --- a/examples/example_config.json +++ b/examples/example_config.json @@ -4,10 +4,9 @@ "memory_channels": 3, "portmask": 2 }, - "onvm": { "output": "stdout", "serviceid": 1, "instanceid": 3 } -} +} \ No newline at end of file diff --git a/examples/start_nf.sh b/examples/start_nf.sh index 85078392a..f1a9cf840 100755 --- a/examples/start_nf.sh +++ b/examples/start_nf.sh @@ -45,6 +45,7 @@ then config=$2 shift 2 exec sudo "$BINARY" -F "$config" "$@" + exit 0 fi # Check if -- is present, if so parse dpdk/onvm specific args diff --git a/onvm/onvm_mgr/onvm_nf.c b/onvm/onvm_mgr/onvm_nf.c index 674424ed0..aad5f291f 100644 --- a/onvm/onvm_mgr/onvm_nf.c +++ b/onvm/onvm_mgr/onvm_nf.c @@ -117,6 +117,16 @@ onvm_nf_init_lpm_region(struct lpm_request *req_lpm); static void onvm_nf_init_ft(struct ft_request *ft); +/* + * Function that clears the tx, rx, & msg_q rings + * in case an NF uses this iid in the future + * + * Input : An nf struct + * Output : none + */ +static void +onvm_nf_clear_rings(struct onvm_nf *nf); + /* * Set up the DPDK rings which will be used to pass packets, via * pointers, between the multi-process server and NF processes. @@ -192,7 +202,7 @@ onvm_nf_check_status(void) { onvm_nf_init_lpm_region(req_lpm); break; case MSG_REQUEST_FT: - ft = (struct ft_request *) msg->msg_data; + ft = (struct ft_request *)msg->msg_data; onvm_nf_init_ft(ft); break; case MSG_NF_STARTING: @@ -370,8 +380,8 @@ onvm_nf_stop(struct onvm_nf *nf) { rte_pktmbuf_free(pkts[i]); } nf_msg_pool = rte_mempool_lookup(_NF_MSG_POOL_NAME); - while (rte_ring_dequeue(nfs[nf_id].msg_q, (void**)(&msg)) == 0) { - rte_mempool_put(nf_msg_pool, (void*)msg); + while (rte_ring_dequeue(nfs[nf_id].msg_q, (void **)(&msg)) == 0) { + rte_mempool_put(nf_msg_pool, (void *)msg); } /* Free info struct */ @@ -380,7 +390,7 @@ onvm_nf_stop(struct onvm_nf *nf) { if (nf_info_mp == NULL) return 1; - rte_mempool_put(nf_info_mp, (void*)nf); + rte_mempool_put(nf_info_mp, (void *)nf); /* Further cleanup is only required if NF was succesfully started */ if (nf_status != NF_RUNNING && nf_status != NF_PAUSED) @@ -392,6 +402,9 @@ onvm_nf_stop(struct onvm_nf *nf) { /* Reset stats */ onvm_stats_clear_nf(nf_id); + /* Free rings if another NF uses this instance id */ + onvm_nf_clear_rings(&nfs[nf_id]); + /* Remove this NF from the service map. * Need to shift all elements past it in the array left to avoid gaps */ nf_per_service_count[service_id]--; @@ -429,7 +442,7 @@ onvm_nf_stop(struct onvm_nf *nf) { static void onvm_nf_init_lpm_region(struct lpm_request *req_lpm) { struct rte_lpm_config conf; - struct rte_lpm* lpm_region; + struct rte_lpm *lpm_region; conf.max_rules = req_lpm->max_num_rules; conf.number_tbl8s = req_lpm->num_tbl8s; @@ -474,6 +487,13 @@ onvm_nf_relocate_nf(uint16_t dest, uint16_t new_core) { return 0; } +static void +onvm_nf_clear_rings(struct onvm_nf *nf) { + rte_ring_free(nf->rx_q); + rte_ring_free(nf->tx_q); + rte_ring_free(nf->msg_q); +} + static void onvm_nf_init_rings(struct onvm_nf *nf) { unsigned instance_id; @@ -489,20 +509,16 @@ onvm_nf_init_rings(struct onvm_nf *nf) { rq_name = get_rx_queue_name(instance_id); tq_name = get_tx_queue_name(instance_id); msg_q_name = get_msg_queue_name(instance_id); - nf->rx_q = - rte_ring_create(rq_name, ringsize, socket_id, RING_F_SC_DEQ); /* multi prod, single cons */ - nf->tx_q = - rte_ring_create(tq_name, ringsize, socket_id, RING_F_SC_DEQ); /* multi prod, single cons */ - nf->msg_q = - rte_ring_create(msg_q_name, msgringsize, socket_id, - RING_F_SC_DEQ); /* multi prod, single cons */ + nf->rx_q = rte_ring_create(rq_name, ringsize, socket_id, RING_F_SC_DEQ); /* multi prod, single cons */ if (nf->rx_q == NULL) rte_exit(EXIT_FAILURE, "Cannot create rx ring queue for NF %u\n", instance_id); + nf->tx_q = rte_ring_create(tq_name, ringsize, socket_id, RING_F_SC_DEQ); /* multi prod, single cons */ if (nf->tx_q == NULL) rte_exit(EXIT_FAILURE, "Cannot create tx ring queue for NF %u\n", instance_id); + nf->msg_q = rte_ring_create(msg_q_name, msgringsize, socket_id, RING_F_SC_DEQ); /* multi prod, single cons */ if (nf->msg_q == NULL) rte_exit(EXIT_FAILURE, "Cannot create msg queue for NF %u\n", instance_id); } diff --git a/onvm/onvm_mgr/onvm_stats.c b/onvm/onvm_mgr/onvm_stats.c index 6f0e370f8..8d0863d55 100644 --- a/onvm/onvm_mgr/onvm_stats.c +++ b/onvm/onvm_mgr/onvm_stats.c @@ -455,10 +455,21 @@ onvm_stats_display_nfs(unsigned difftime, uint8_t verbosity_level) { const uint64_t act_next = nfs[i].stats.act_next; const uint64_t act_buffer = nfs[i].stats.tx_buffer; const uint64_t act_returned = nfs[i].stats.tx_returned; + + /* On onvm_stats_clear_nf, subtraction causes underflow */ + if (unlikely(rx == 0)) + nf_rx_last[i] = 0; const uint64_t rx_pps = (rx - nf_rx_last[i]) / difftime; + if (unlikely(tx == 0)) + nf_tx_last[i] = 0; const uint64_t tx_pps = (tx - nf_tx_last[i]) / difftime; - const uint64_t tx_drop_rate = (tx_drop - nf_tx_drop_last[i]) / difftime; + if (unlikely(rx_drop == 0)) + nf_rx_drop_last[i] = 0; const uint64_t rx_drop_rate = (rx_drop - nf_rx_drop_last[i]) / difftime; + if (unlikely(tx_drop == 0)) + nf_tx_drop_last[i] = 0; + const uint64_t tx_drop_rate = (tx_drop - nf_tx_drop_last[i]) / difftime; + const uint64_t num_wakeups = nf_wakeup_infos[i].num_wakeups; const uint64_t prev_num_wakeups = nf_wakeup_infos[i].prev_num_wakeups; const uint64_t wakeup_rate = (num_wakeups - prev_num_wakeups) / difftime; @@ -571,7 +582,6 @@ onvm_stats_display_nfs(unsigned difftime, uint8_t verbosity_level) { fprintf(stats_out, "-----------------\n"); onvm_stats_display_client_wakeup_thread_context(difftime); } - } /***************************Helper functions**********************************/ diff --git a/onvm/onvm_nflib/onvm_config_common.c b/onvm/onvm_nflib/onvm_config_common.c index ed72fd75b..6fbccfd94 100644 --- a/onvm/onvm_nflib/onvm_config_common.c +++ b/onvm/onvm_nflib/onvm_config_common.c @@ -49,6 +49,11 @@ #define IS_NULL_OR_EMPTY_STRING(s) ((s) == NULL || strncmp(s, "", 1) == 0 ? 1 : 0) +size_t +strlenn(const char* __s) { + return strlen(__s) + 1; +} + cJSON* onvm_config_parse_file(const char* filename) { if (IS_NULL_OR_EMPTY_STRING(filename)) { @@ -420,7 +425,7 @@ onvm_config_create_onvm_args(cJSON* onvm_config, int* onvm_argc, char** onvm_arg return -1; } - (*onvm_argv)[0] = malloc(sizeof(char) * strlen(FLAG_R)); + (*onvm_argv)[0] = malloc(sizeof(char) * strlenn(FLAG_R)); if ((*onvm_argv)[0] == NULL) { printf("Unable to allocate space for onvm_argv[0]\n"); free(service_id_string); @@ -428,7 +433,7 @@ onvm_config_create_onvm_args(cJSON* onvm_config, int* onvm_argc, char** onvm_arg return -1; } - memcpy((*onvm_argv)[0], FLAG_R, strlen(FLAG_R)); + memcpy((*onvm_argv)[0], FLAG_R, strlenn(FLAG_R)); snprintf(service_id_string, sizeof(char) * MAX_SERVICE_ID_SIZE, "%d", service_id); (*onvm_argv)[1] = service_id_string; @@ -443,7 +448,7 @@ onvm_config_create_onvm_args(cJSON* onvm_config, int* onvm_argc, char** onvm_arg return -1; } - (*onvm_argv)[2] = malloc(sizeof(char) * strlen(FLAG_N)); + (*onvm_argv)[2] = malloc(sizeof(char) * strlenn(FLAG_N)); if ((*onvm_argv)[2] == NULL) { printf("Could not allocate space for instance id in argv\n"); free(instance_id_string); @@ -452,7 +457,7 @@ onvm_config_create_onvm_args(cJSON* onvm_config, int* onvm_argc, char** onvm_arg free((*onvm_argv)[0]); return -1; } - memcpy((*onvm_argv)[2], FLAG_N, strlen(FLAG_N)); + memcpy((*onvm_argv)[2], FLAG_N, strlenn(FLAG_N)); snprintf(instance_id_string, sizeof(char) * MAX_SERVICE_ID_SIZE, "%d", instance_id); (*onvm_argv)[3] = instance_id_string; } @@ -491,7 +496,7 @@ onvm_config_create_dpdk_args(cJSON* dpdk_config, int* dpdk_argc, char** dpdk_arg return -1; } - core_string = (char*)malloc(sizeof(char) * strlen(cJSON_GetObjectItem(dpdk_config, "corelist")->valuestring)); + core_string = (char*)malloc(sizeof(char) * strlenn(cJSON_GetObjectItem(dpdk_config, "corelist")->valuestring)); if (core_string == NULL) { printf("Unable to allocate space for core string\n"); free(*dpdk_argv); @@ -500,7 +505,7 @@ onvm_config_create_dpdk_args(cJSON* dpdk_config, int* dpdk_argc, char** dpdk_arg } core_string = strncpy(core_string, cJSON_GetObjectItem(dpdk_config, "corelist")->valuestring, - strlen(cJSON_GetObjectItem(dpdk_config, "corelist")->valuestring)); + strlenn(cJSON_GetObjectItem(dpdk_config, "corelist")->valuestring)); if (onvm_config_extract_memory_channels(dpdk_config, &mem_channels) < 0) { printf("Unable to extract memory channels\n"); @@ -522,12 +527,12 @@ onvm_config_create_dpdk_args(cJSON* dpdk_config, int* dpdk_argc, char** dpdk_arg snprintf(mem_channels_string, mem_channels_string_size, "%d", mem_channels); - arg_size[0] = strlen(FLAG_L); - arg_size[1] = strlen(core_string); - arg_size[2] = strlen(FLAG_N); - arg_size[3] = strlen(mem_channels_string); - arg_size[4] = strlen(PROC_TYPE_SECONDARY); - arg_size[5] = strlen(FLAG_DASH); + arg_size[0] = strlenn(FLAG_L); + arg_size[1] = strlenn(core_string); + arg_size[2] = strlenn(FLAG_N); + arg_size[3] = strlenn(mem_channels_string); + arg_size[4] = strlenn(PROC_TYPE_SECONDARY); + arg_size[5] = strlenn(FLAG_DASH); for (i = 0; i < *dpdk_argc; ++i) { (*dpdk_argv)[i] = (char*)malloc(arg_size[i]); diff --git a/onvm/onvm_nflib/onvm_config_common.h b/onvm/onvm_nflib/onvm_config_common.h index f4de86aec..45d9e5a9f 100644 --- a/onvm/onvm_nflib/onvm_config_common.h +++ b/onvm/onvm_nflib/onvm_config_common.h @@ -55,6 +55,18 @@ /*****************************API************************************/ +/* + * Uses strlen to get string length *including* + * null terminator '\0' + * + * @param __s + * String to measure + * @return + * Size of the string including null terminator + */ +size_t +strlenn(const char* __s); + /** * Parses a config file into a cJSON struct. * This struct contains all information stored within the config file