diff --git a/src/qosmngr.c b/src/qosmngr.c index 702421393c0bd41d62726ca2dcfff525c6d1dc72..90173f3058f447d25b583ce40367ea5c34e60301 100644 --- a/src/qosmngr.c +++ b/src/qosmngr.c @@ -24,6 +24,7 @@ #include <libubox/blobmsg_json.h> #include <libubus.h> #include <uci.h> +#include <json-c/json.h> /* Needed to get the IFNAMSIZ define */ #include <net/if.h> @@ -55,7 +56,6 @@ static size_t interface_count = 0; /** Array of interfaces cached by qosmngr */ static qos_interface_data *interfaces = NULL; - /** * get_no_queues function for getting number of queues on device by calling uci qos config * @param ifname input parameter pointer to char for which number of queues needed @@ -123,6 +123,24 @@ static int get_interface_index(const char *ifname) return -1; } +static int init_interface(const char *ifname, size_t index) +{ + qos_interface_data *data = &interfaces[index]; + + size_t queues = (size_t)get_no_queues(ifname); + + strncpy(data->if_name, ifname, IFNAMSIZ); + data->q_count = queues; + data->q_stat = (struct qos_stats *)calloc(queues, + sizeof(struct qos_stats)); + if (data->q_stat == NULL) { + syslog(LOG_ERR, "Initialization failed during memory allocation.\n"); + free(interfaces); + return -1; + } + return 0; +} + /** * init_qstat function for initializing global q_stat structure for sustainable stats * @param none @@ -131,65 +149,166 @@ static int get_interface_index(const char *ifname) static int init_qstat(void) { int ret = 0; - int index = 0; syslog(LOG_ERR, "Initializing global stat structure.\n"); - struct uci_package *uci_pkg = NULL; - struct uci_element *uci_elmnt = NULL; - struct uci_context *uci_ctx = uci_alloc_context(); - interface_count = 0; + long int size; + FILE *fp = NULL; + char *buffer = NULL; + + fp = fopen("/etc/board.json","r"); + if (fp == NULL) + return -1; - uci_load(uci_ctx, "ports", &uci_pkg); - if (!uci_pkg) { - syslog(LOG_ERR, "Failed to load configuration\n"); + fseek(fp, 0L, SEEK_END); + size = ftell(fp); + rewind(fp); + + unsigned int buffer_size = 0; + /* Allocate memory for entire content */ + if (size < 0) { + syslog(LOG_ERR, "file read size < 0"); + fclose(fp); + return -1; + } else { + buffer_size = (unsigned int)size; + } + + buffer = calloc(1, buffer_size + 1); + if (buffer == NULL) { + syslog(LOG_ERR, "memory allocation to read buffer failed"); + fclose(fp); + return -1; + } + + /* Copy the file into the buffer */ + if (fread(buffer, buffer_size, 1, fp) != 1) { + syslog(LOG_ERR, "read from board.json file failed"); + free(buffer); + fclose(fp); + return -1; + } + + struct json_object *board_json = json_tokener_parse(buffer); + if (board_json == NULL) { + syslog(LOG_ERR, "failed to read board.json as json"); + free(buffer); + fclose(fp); + return -1; + } + + struct json_object *network = NULL; + if (!json_object_object_get_ex(board_json, "network", &network)) { + syslog(LOG_ERR, "network object not found in board.json"); ret = -1; - goto done; + json_object_put(board_json); + goto free_and_return; } - interface_count = 0; + struct json_object *lan = NULL; + if (!json_object_object_get_ex(network, "lan", &lan)) { + syslog(LOG_ERR, "lan object not found in board.json"); + json_object_put(network); + json_object_put(board_json); + ret = -1; + goto free_and_return; + } + + struct json_object *wan = NULL; + if (!json_object_object_get_ex(network, "wan", &wan)) { + syslog(LOG_ERR, "wan object not found in board.json"); + ret = -1; + json_object_put(lan); + json_object_put(network); + json_object_put(board_json); + goto free_and_return; + } + + struct json_object *lan_ports = NULL; + if (!json_object_object_get_ex(lan, "ports", &lan_ports)) { + syslog(LOG_ERR, "ports object not found in board.json"); + ret = -1; + json_object_put(lan); + json_object_put(wan); + json_object_put(network); + json_object_put(board_json); + goto free_and_return; + } - uci_foreach_element(&uci_pkg->sections, uci_elmnt) { - struct uci_section *uci_sec = uci_to_section(uci_elmnt); - if (uci_sec) - interface_count++; - } + struct json_object *wan_device = NULL; + if (!json_object_object_get_ex(wan, "device", &wan_device)) { + syslog(LOG_ERR, "device object not found in board.json"); + ret = -1; + json_object_put(lan_ports); + json_object_put(lan); + json_object_put(wan); + json_object_put(network); + json_object_put(board_json); + goto free_and_return; + } + // create json object for all ports by reading from lan ports and wan device + interface_count = json_object_array_length(lan_ports) + 1; // +1 for wan device interfaces = (qos_interface_data *)calloc(interface_count, sizeof(qos_interface_data)); if (interfaces == NULL) { - syslog(LOG_ERR, "Initialization failed during memory allocation.\n"); + syslog(LOG_ERR, "Initialization failed during memory allocation."); ret = -1; - goto done_unload; + json_object_put(lan_ports); + json_object_put(wan_device); + json_object_put(lan); + json_object_put(wan); + json_object_put(network); + json_object_put(board_json); + goto free_and_return; } - uci_foreach_element(&uci_pkg->sections, uci_elmnt) { - struct uci_section *uci_sec = uci_to_section(uci_elmnt); - if (uci_sec) { - qos_interface_data *data = &interfaces[index]; - struct uci_option *uci_opn = uci_lookup_option(uci_ctx, uci_sec, "ifname"); - size_t queues; - - queues = (size_t)get_no_queues(uci_opn->v.string); - strcpy(data->if_name, uci_opn->v.string); - data->q_count = queues; - data->q_stat = (struct qos_stats *)calloc(queues, - sizeof(struct qos_stats)); - if (data->q_stat == NULL) { - syslog(LOG_ERR, "Initialization failed during memory allocation.\n"); - ret = -1; - goto done_unload; - } + size_t i = 0; + for (i = 0; i < json_object_array_length(lan_ports); i++) { + struct json_object *l_port_name = json_object_array_get_idx(lan_ports, i); + if (!l_port_name) { + syslog(LOG_ERR, "cannot read lan ports array"); + ret = -1; + json_object_put(lan_ports); + json_object_put(wan_device); + json_object_put(lan); + json_object_put(wan); + json_object_put(network); + json_object_put(board_json); + free(interfaces); + goto free_and_return; + } - index++; + ret = init_interface(json_object_get_string(l_port_name), i); + + if (ret < 0) { + json_object_put(l_port_name); + json_object_put(lan_ports); + json_object_put(wan_device); + json_object_put(lan); + json_object_put(wan); + json_object_put(network); + json_object_put(board_json); + free(interfaces); + goto free_and_return; } - } -done_unload: - uci_unload(uci_ctx, uci_pkg); -done: - uci_free_context(uci_ctx); + json_object_put(l_port_name); + } + + ret = init_interface(json_object_get_string(wan_device), i); + + json_object_put(lan_ports); + json_object_put(wan_device); + json_object_put(lan); + json_object_put(wan); + json_object_put(network); + json_object_put(board_json); + +free_and_return: + free(buffer); + fclose(fp); return ret; } @@ -211,16 +330,6 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void qos_interface_data *iface; struct qos_stats *q_stat; - // Initialize global q_stat global struct - if (init_flag) { - ret = init_qstat(); - if (ret) { - syslog(LOG_ERR, "Failed to initialize gobal q_stat.\n"); - } - syslog(LOG_ERR, "Initialized gobal q_stat successfully.\n"); - init_flag = 0; - } - ret = qos_get_stats(ifname, qid, stats, &is_read_and_reset); if (ret != 0) { syslog(LOG_ERR, "blob_get_status: ret %d\n", ret); @@ -312,31 +421,17 @@ static int get_stats_by_ifname(struct blob_buf *b, struct qos_stats *stats, void static int get_stats_for_all_intf(struct blob_buf *b, struct qos_stats *stats, void *dd) { int ret = 0; - char ifname[IFNAMSIZ] = {0}; - - struct uci_package *uci_pkg = NULL; - struct uci_element *uci_elmnt = NULL; - struct uci_context *uci_ctx = uci_alloc_context(); + size_t i = 0; + for (i = 0; i < interface_count; i++) { + qos_interface_data *cur = &interfaces[i]; + ret = get_stats_by_ifname(b, stats, dd, + cur->if_name, QOS_QUEUE_ANY); - uci_load(uci_ctx, "ports", &uci_pkg); - if (!uci_pkg) { - syslog(LOG_ERR, "Failed to load configuration\n"); - ret = -1; - return ret; - } - - uci_foreach_element(&uci_pkg->sections, uci_elmnt) { - struct uci_section *uci_sec = uci_to_section(uci_elmnt); - if (uci_sec) { - struct uci_option *uci_opn = uci_lookup_option(uci_ctx, uci_sec, "ifname"); - strncpy(ifname, uci_opn->v.string, sizeof(ifname) - 1); - ret = get_stats_by_ifname(b, stats, dd, ifname, QOS_QUEUE_ANY); - if (ret != 0) { - syslog(LOG_ERR, "get_stats_by_ifname : ret %d\n", ret); - return ret; - } + if (ret != 0) { + syslog(LOG_ERR, "get_stats_by_ifname failed: ret %d", ret); + continue; } - } + } return ret; } @@ -379,7 +474,6 @@ static int validate_keys(char *req_json) return ret; } - /** * validate_request function to validate requested blob message * @param msg parameter pointer to blob_attr containing blob request @@ -443,6 +537,17 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, if (tb[QOS_POLICY_QID] && !tb[QOS_POLICY_IFNAME]) return UBUS_STATUS_INVALID_ARGUMENT; + // Initialize global q_stat global struct + if (init_flag) { + ret = init_qstat(); + if (ret) { + syslog(LOG_ERR, "Failed to initialize gobal q_stat"); + return ret; + } + syslog(LOG_INFO, "Initialized gobal q_stat successfully"); + init_flag = 0; + } + blob_buf_init(&b, 0); d = blobmsg_open_array(&b, "queues");