From df5f58c125df84478e95513aec751756fccd7037 Mon Sep 17 00:00:00 2001 From: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu> Date: Sun, 23 Mar 2025 22:39:15 +0530 Subject: [PATCH 1/6] qosmngr: transform from dm_plugin to unified daemon for bbfdm --- Makefile | 26 ++++------------ bbf_plugin/Makefile | 26 ---------------- bbf_plugin/qos_bbf_vendor.c | 48 ------------------------------ bbf_plugin/qos_bbf_vendor.h | 20 ------------- include/qosmngr.h | 4 ++- src/main.c | 30 +++++++++++++++++-- {bbf_plugin => src}/qos_bbf.c | 56 +++++++++++++++++++++++++++++------ {bbf_plugin => src}/qos_bbf.h | 0 src/qosmngr.c | 33 ++++++++++++--------- 9 files changed, 102 insertions(+), 141 deletions(-) delete mode 100644 bbf_plugin/Makefile delete mode 100644 bbf_plugin/qos_bbf_vendor.c delete mode 100644 bbf_plugin/qos_bbf_vendor.h rename {bbf_plugin => src}/qos_bbf.c (97%) rename {bbf_plugin => src}/qos_bbf.h (100%) diff --git a/Makefile b/Makefile index d6e8359..172212b 100644 --- a/Makefile +++ b/Makefile @@ -3,19 +3,15 @@ include common.mk -include Makefile.diag.inc -QOSMNGR_LIB=libqosmngr.so -PLUGIN = bbf_plugin - GCOV=gcov SRC_DIR = src CODECOVERAGE_SRC = $(addprefix $(SRC_DIR)/, qosmngr.c ) PROG = $(PROJECT_TOPLEVEL)/qosmngr -SHARED_LIB = $(PROJECT_TOPLEVEL)/libqosmngr.so -OBJS = $(addprefix $(SRC_DIR)/, main.o qosmngr.o ) +OBJS = $(addprefix $(SRC_DIR)/, main.o qosmngr.o qos_bbf.o) PROG_CFLAGS = $(CFLAGS) -I$(INCLUDE_DIR) $(DIAG_CFLAGS) -Werror -fstrict-aliasing -PROG_LDFLAGS = $(LDFLAGS) +PROG_LDFLAGS = $(LDFLAGS) -lbbfdm-ubus -lbbfdm-api PROG_LIBS = $(COMMON_LDFLAGS) -lgcov # MUSL has the following issue in snprintf, so it is ignored: @@ -23,18 +19,10 @@ PROG_CFLAGS += -Wno-format-nonliteral .PHONY: all clean -all: version $(PLUGIN) $(PROG) - -$(PLUGIN): $(OBJS) - $(MAKE) -C ./bbf_plugin - -$(PROG): $(INCLUDE_DIR)/version.h $(OBJS) - $(CC) $(PROG_LDFLAGS) -o $@ $^ $(PROG_LIBS) +all: version $(PROG) -${QOSMNGR_LIB}: - $(CC) $(PROG_LDFLAGS) -shared -o $@ $^ $(PROG_LIBS) - -$(SHARED_LIB): $(INCLUDE_DIR)/version.h $(OBJS) +$(PROG): $(OBJS) + $(CC) -o $@ $^ $(PROG_LDFLAGS) $(PROG_LIBS) version: $(INCLUDE_DIR)/version.h @@ -47,8 +35,6 @@ $(INCLUDE_DIR)/version.h: $(PROJECT_TOPLEVEL)/VERSION echo "const char *qosmngr_xtra_version = \"$$xver$$dirty\";" >> $@; \ ) -test: ${QOSMNGR_LIB} - coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -fPIC coverage: LDFLAGS += --coverage coverage: test $(PROG) @@ -61,7 +47,7 @@ functional-test: test $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< clean: - rm -f *.o $(SHARED_LIB) $(PROG) $(INCLUDE_DIR)/version.h + rm -f *.o $(PROG) $(INCLUDE_DIR)/version.h rm -f *.xml *.html find -name '*.gcda' -exec rm {} -fv \; find -name '*.gcno' -exec rm {} -fv \; diff --git a/bbf_plugin/Makefile b/bbf_plugin/Makefile deleted file mode 100644 index e170fd1..0000000 --- a/bbf_plugin/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -LIB_QOS_BBF := libqos_bbf.so -LIB_QOS_BBF_VENDOR := libqos_vendor_bbf.so - -OBJS := qos_bbf.o -OBJS_VENDOR := qos_bbf_vendor.o - -LIB_CFLAGS = $(CFLAGS) -Wall -Werror -LIB_LDFLAGS = $(LDFLAGS) -FPIC := -fPIC - -.PHONY: all - -%.o: %.c - $(CC) $(LIB_CFLAGS) $(FPIC) -c -o $@ $< - -all: $(LIB_QOS_BBF) $(LIB_QOS_BBF_VENDOR) - -$(LIB_QOS_BBF): $(OBJS) - $(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^ - -$(LIB_QOS_BBF_VENDOR): $(OBJS_VENDOR) - $(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^ - -clean: - rm -f *.o $(LIB_QOS_BBF) $(LIB_QOS_BBF_VENDOR) - diff --git a/bbf_plugin/qos_bbf_vendor.c b/bbf_plugin/qos_bbf_vendor.c deleted file mode 100644 index 07c41e1..0000000 --- a/bbf_plugin/qos_bbf_vendor.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2024 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Rohit Topno <r.topno@gxgroup.eu> - */ - -#include "qos_bbf_vendor.h" - -/************************************************************* - * GET & SET PARAM -*************************************************************/ -static int get_QoSClassification_VLANIDMark(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "vid_mark", "-1"); - return 0; -} - -static int set_QoSClassification_VLANIDMark(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - switch (action) { - case VALUECHECK: - if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1",NULL}}, 1)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "vid_mark", value); - break; - } - return 0; -} - -/* ********** DynamicObj ********** */ -DM_MAP_OBJ tDynamicObj[] = { -/* parentobj, nextobject, parameter */ -{"Device.QoS.Classification.{i}.", NULL, tQoSClassificationParams}, -{0} -}; - -/* *** Device.QoS.Classification.{i}. *** */ -DMLEAF tQoSClassificationParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */ -{BBF_VENDOR_PREFIX"VLANIDMark", &DMWRITE, DMT_UNINT, get_QoSClassification_VLANIDMark, set_QoSClassification_VLANIDMark, BBFDM_BOTH}, -{0} -}; diff --git a/bbf_plugin/qos_bbf_vendor.h b/bbf_plugin/qos_bbf_vendor.h deleted file mode 100644 index b5eecf4..0000000 --- a/bbf_plugin/qos_bbf_vendor.h +++ /dev/null @@ -1,20 +0,0 @@ - -/* - * Copyright (C) 2024 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Rohit Topno <r.topno@gxgroup.eu> - * - */ - -#ifndef __IOPSYS_QOS_H -#define __IOPSYS_QOS_H - -#include "libbbfdm-api/dmcommon.h" - -extern DMLEAF tQoSClassificationParams[]; - -#endif //__IOPSYS_QOS_H diff --git a/include/qosmngr.h b/include/qosmngr.h index d745993..b64c21c 100644 --- a/include/qosmngr.h +++ b/include/qosmngr.h @@ -63,8 +63,10 @@ struct qos_queue { struct qos_queue_config config; }; +int init_qstat(void); int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); - +int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void *dd, + char *ifname, int qid); #endif /* QOSMNGR_H */ diff --git a/src/main.c b/src/main.c index 68ffc63..bed269a 100644 --- a/src/main.c +++ b/src/main.c @@ -2,7 +2,7 @@ /* * main.c - qosmngr's boilerplate and entry point * - * Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved. + * Copyright (C) 2020-2025 iopsys Software Solutions AB. All rights reserved. * * Author: Oskar Viljasaar <oskar.viljasaar@iopsys.eu> * @@ -25,13 +25,18 @@ #include <stdlib.h> #include <libubus.h> +#include <libbbfdm-ubus/bbfdm-ubus.h> #include "qosmngr.h" #include "version.h" +#include "qos_bbf.h" + const char *ubus_socket; struct ubus_context *ctx = NULL; +extern DM_MAP_OBJ tDynamicObj[]; +static struct bbfdm_context bbfdm_ctx = {0}; const struct blobmsg_policy get_status_policy[NUM_QOS_POLICY] = { [QOS_POLICY_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, @@ -90,12 +95,19 @@ int main(int argc, char **argv) int ret; int ch; int num_of_q = QOS_MIN_Q_NUM_PER_PORT; + int log_level = 6; // default LOG_INFO + /* Logging to syslog */ openlog("qosmngr", LOG_PID|LOG_CONS, LOG_LOCAL1); - while ((ch = getopt(argc, argv, "vsq:e:")) != -1) { + while ((ch = getopt(argc, argv, "lvsq:e:")) != -1) { switch (ch) { + case 'l': + log_level = (int)strtoul(optarg, NULL, 10); + if (log_level < 0 || log_level > 7) + log_level = 6; + break; case 'v': qosmngr_version(); exit(0); @@ -127,10 +139,22 @@ int main(int argc, char **argv) if (ret) goto out; + memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); + bbfdm_ubus_set_service_name(&bbfdm_ctx, "qosmngr"); + bbfdm_ubus_set_log_level(log_level); + bbfdm_ubus_load_data_model(tDynamicObj); + + if (bbfdm_ubus_regiter_init(&bbfdm_ctx)) { + syslog(LOG_ERR, "Failed to register ubus"); + goto out; + } + + init_qstat(); + /* Main loop of qosmngr */ uloop_run(); - out: + bbfdm_ubus_regiter_free(&bbfdm_ctx);; ubus_free(ctx); uloop_done(); diff --git a/bbf_plugin/qos_bbf.c b/src/qos_bbf.c similarity index 97% rename from bbf_plugin/qos_bbf.c rename to src/qos_bbf.c index 4b4ca12..49fad34 100644 --- a/bbf_plugin/qos_bbf.c +++ b/src/qos_bbf.c @@ -11,6 +11,8 @@ #include "qos_bbf.h" #include "libbbfdm_api.h" +#include "qosmngr.h" + #define PROTOCOLS_FILE "/etc/protocols" /************************************************************* @@ -73,7 +75,7 @@ static unsigned long qos_get_new_order(void) uci_foreach_sections("qos", "classify", s) { dmuci_get_value_by_section_string(s, "order", &order); - unsigned long order_tol = DM_STRTOL(order); + unsigned long order_tol = DM_STRTOUL(order); if (order_tol > max) max = order_tol; } @@ -99,11 +101,11 @@ static void qos_update_order(const char *order, bool is_del) { struct uci_section *classify_s = NULL; char *curr_order = NULL; - unsigned long order_tol = DM_STRTOL(order); + unsigned long order_tol = DM_STRTOUL(order); uci_foreach_sections("qos", "classify", classify_s) { dmuci_get_value_by_section_string(classify_s, "order", &curr_order); - unsigned long curr_order_tol = DM_STRTOL(curr_order); + unsigned long curr_order_tol = DM_STRTOUL(curr_order); if (curr_order_tol >= order_tol) { char new_order[16] = {0}; @@ -1347,6 +1349,26 @@ static int set_QoSClassification_Policer(char *refparam, struct dmctx *ctx, void return 0; } +static int get_QoSClassification_VLANIDMark(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + *value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "vid_mark", "-1"); + return 0; +} + +static int set_QoSClassification_VLANIDMark(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + switch (action) { + case VALUECHECK: + if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1",NULL}}, 1)) + return FAULT_9007; + break; + case VALUESET: + dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "vid_mark", value); + break; + } + return 0; +} + static int get_QoSPolicer_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enable", "1"); @@ -1846,15 +1868,30 @@ static int get_QoSQueueStats_value(void *data, char *option, char **value) dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "queue", &queue_link); dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "interface", &intf_link); - if (queue_link && *queue_link && intf_link && *intf_link) { - json_object *res = NULL; + if (queue_link && *queue_link && DM_STRLEN(queue_link) > 2 && intf_link && *intf_link) { char queue_id[8] = {0}; snprintf(queue_id, sizeof(queue_id), "%c", queue_link[2]); - dmubus_call("qos", "queue_stats", UBUS_ARGS{{"ifname", intf_link, String}, {"qid", queue_id, Integer}}, 2, &res); - DM_ASSERT(res, *value = "0"); - json_object *queue_obj = dmjson_select_obj_in_array_idx(res, 0, 1, "queues"); - *value = dmjson_get_value(queue_obj, 1, option); + int qid = (int) DM_STRTOL(queue_id); + struct qos_stats stats = {0}; + + if (!prepare_stats_blob(NULL, &stats, NULL, intf_link, qid)) { + char val_buf[65] = {0}; + + if (!DM_STRNCMP(option, "tx_packets", DM_STRLEN("tx_packets"))) { + snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_packets); + *value = dmstrdup(val_buf); + } else if (!DM_STRNCMP(option, "tx_bytes", DM_STRLEN("tx_bytes"))) { + snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_bytes); + *value = dmstrdup(val_buf); + } else if (!DM_STRNCMP(option, "tx_dropped_packets", DM_STRLEN("tx_dropped_packets"))) { + snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_dropped_packets); + *value = dmstrdup(val_buf); + } else if (!DM_STRNCMP(option, "tx_dropped_bytes", DM_STRLEN("tx_dropped_bytes"))) { + snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_dropped_bytes); + *value = dmstrdup(val_buf); + } + } } return 0; } @@ -2108,6 +2145,7 @@ DMLEAF tQoSClassificationParams[] = { {"TrafficClass", &DMWRITE, DMT_INT, get_QoSClassification_TrafficClass, set_QoSClassification_TrafficClass, BBFDM_BOTH}, {"Policer", &DMWRITE, DMT_STRING, get_QoSClassification_Policer, set_QoSClassification_Policer, BBFDM_BOTH}, //{"App", &DMWRITE, DMT_STRING, get_QoSClassification_App, set_QoSClassification_App, BBFDM_BOTH}, +{BBF_VENDOR_PREFIX"VLANIDMark", &DMWRITE, DMT_UNINT, get_QoSClassification_VLANIDMark, set_QoSClassification_VLANIDMark, BBFDM_BOTH}, {0} }; diff --git a/bbf_plugin/qos_bbf.h b/src/qos_bbf.h similarity index 100% rename from bbf_plugin/qos_bbf.h rename to src/qos_bbf.h diff --git a/src/qosmngr.c b/src/qosmngr.c index 4c05a3f..c5250fa 100644 --- a/src/qosmngr.c +++ b/src/qosmngr.c @@ -150,7 +150,7 @@ static int init_interface(const char *ifname, size_t index) * @param none * retrun integer value 0 on success and -1 on failure */ -static int init_qstat(void) +int init_qstat(void) { int ret = 0; @@ -299,6 +299,7 @@ static int init_qstat(void) ret = init_interface(json_object_get_string(wan_device), i); json_object_put(board_json); + init_flag = 0; free_and_return: free(buffer); @@ -313,9 +314,9 @@ free_and_return: * @param dd output parameter pointer to void used for blob buffer array elements * @param ifname input parameter pointer to char for which to get stats * @param qid input parameter integer queue identifier for which to get stats - * retrun integer value 0 on success and -1 on failure + * return integer value 0 on success and -1 on failure */ -static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void *dd, +int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void *dd, char *ifname, int qid) { int index; @@ -332,8 +333,8 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void index = get_interface_index(ifname); if (index < 0 || index >= interface_count) { - syslog(LOG_ERR, "Invalid interface index %d (out of %zu)", - index, interface_count); + syslog(LOG_ERR, "Invalid interface index %d (out of %zu) for interface %s", + index, interface_count, ifname); return -1; } @@ -358,19 +359,24 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void q_stat->tx_bytes += stats->tx_bytes; q_stat->tx_dropped_packets += stats->tx_dropped_packets; q_stat->tx_dropped_bytes += stats->tx_dropped_bytes; + + // update the contents so the caller gets latest data + memcpy(stats, q_stat, sizeof(struct qos_stats)); } - dd = blobmsg_open_table(b, ""); + if (b) { + dd = blobmsg_open_table(b, ""); - blobmsg_add_string(b, "iface", ifname); - blobmsg_add_u32(b, "qid", (uint32_t)qid); - blobmsg_add_u64(b, "tx_packets", (uint64_t)q_stat->tx_packets); - blobmsg_add_u64(b, "tx_bytes", (uint64_t)q_stat->tx_bytes); - blobmsg_add_u64(b, "tx_dropped_packets", (uint64_t)q_stat->tx_dropped_packets); - blobmsg_add_u64(b, "tx_dropped_bytes", (uint64_t)q_stat->tx_dropped_bytes); + blobmsg_add_string(b, "iface", ifname); + blobmsg_add_u32(b, "qid", (uint32_t)qid); + blobmsg_add_u64(b, "tx_packets", (uint64_t)q_stat->tx_packets); + blobmsg_add_u64(b, "tx_bytes", (uint64_t)q_stat->tx_bytes); + blobmsg_add_u64(b, "tx_dropped_packets", (uint64_t)q_stat->tx_dropped_packets); + blobmsg_add_u64(b, "tx_dropped_bytes", (uint64_t)q_stat->tx_dropped_bytes); - blobmsg_close_table(b, dd); + blobmsg_close_table(b, dd); + } return ret; } @@ -544,7 +550,6 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, return ret; } syslog(LOG_INFO, "Initialized gobal q_stat successfully"); - init_flag = 0; } blob_buf_init(&b, 0); -- GitLab From 441602943935a597441ee3e33da44025b992928b Mon Sep 17 00:00:00 2001 From: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu> Date: Mon, 24 Mar 2025 20:28:31 +0530 Subject: [PATCH 2/6] qosmngr: correctly process EtherType between hex and decimal --- Makefile | 6 ++++-- src/qos_bbf.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 172212b..1593044 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ PROG_CFLAGS += -Wno-format-nonliteral all: version $(PROG) -$(PROG): $(OBJS) +$(PROG): $(INCLUDE_DIR)/version.h $(OBJS) $(CC) -o $@ $^ $(PROG_LDFLAGS) $(PROG_LIBS) version: $(INCLUDE_DIR)/version.h @@ -35,7 +35,9 @@ $(INCLUDE_DIR)/version.h: $(PROJECT_TOPLEVEL)/VERSION echo "const char *qosmngr_xtra_version = \"$$xver$$dirty\";" >> $@; \ ) -coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -fPIC +test: $(PROG) + +coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -fPIC -DBBF_VENDOR_PREFIX='"X_IOWRT_EU"' coverage: LDFLAGS += --coverage coverage: test $(PROG) $(foreach testprog, $(CODECOVERAGE_SRC), $(GCOV) $(testprog);) diff --git a/src/qos_bbf.c b/src/qos_bbf.c index 49fad34..e35b4c1 100644 --- a/src/qos_bbf.c +++ b/src/qos_bbf.c @@ -948,6 +948,13 @@ static int set_QoSClassification_DestMACAddress(char *refparam, struct dmctx *ct static int get_QoSClassification_Ethertype(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "ethertype", "-1"); + // if value is not -1 + if (DM_STRNCMP(*value, "-1", DM_STRLEN("-1"))) { + char *endptr = NULL; + long ethertype = strtol(*value, &endptr, 16); + dmasprintf(value, "%ld", ethertype); + } + return 0; } @@ -959,7 +966,13 @@ static int set_QoSClassification_Ethertype(char *refparam, struct dmctx *ctx, vo return FAULT_9007; break; case VALUESET: - dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "ethertype", value); + char *hex_str = NULL; + char *endptr; + long ethertype = strtol(value, &endptr, 10); + + dmasprintf(&hex_str, "0x%04X", (unsigned int)ethertype); + + dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "ethertype", hex_str); break; } return 0; -- GitLab From bc98d77fb606f4901448b1ed1252539d880c7a30 Mon Sep 17 00:00:00 2001 From: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu> Date: Tue, 25 Mar 2025 20:00:33 +0530 Subject: [PATCH 3/6] qosmngr: make qos ubus object conditional on compilation flag --- src/main.c | 33 +++++++++++-------- src/qos_bbf.c | 89 ++++++++++++++++++++++++++++----------------------- src/qosmngr.c | 5 +-- 3 files changed, 72 insertions(+), 55 deletions(-) diff --git a/src/main.c b/src/main.c index bed269a..0d85e90 100644 --- a/src/main.c +++ b/src/main.c @@ -38,6 +38,7 @@ struct ubus_context *ctx = NULL; extern DM_MAP_OBJ tDynamicObj[]; static struct bbfdm_context bbfdm_ctx = {0}; +#ifdef UBUS_SUPPORT const struct blobmsg_policy get_status_policy[NUM_QOS_POLICY] = { [QOS_POLICY_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, [QOS_POLICY_QID] = { .name = "qid", .type = BLOBMSG_TYPE_INT32}, @@ -57,16 +58,6 @@ static struct ubus_object test_object = { .n_methods = ARRAY_SIZE(qos_methods), }; -/** - * To get the qosmngr version - * @param : none - * return : none - */ -void qosmngr_version(void) -{ - syslog(LOG_ERR, "version : %s.%s\n", qosmngr_base_version, qosmngr_xtra_version); -} - /** * To expose the qosmngr object on ubus i.e., qos with method queue_stats * @param context input parameter pointer to ubus context @@ -83,6 +74,17 @@ static int qosmngr_publish_object(struct ubus_context *context) return ret; } +#endif + +/** + * To get the qosmngr version + * @param : none + * return : none + */ +void qosmngr_version(void) +{ + syslog(LOG_ERR, "version : %s.%s\n", qosmngr_base_version, qosmngr_xtra_version); +} /** * Main function for qosmngr, everything starts here @@ -92,7 +94,6 @@ static int qosmngr_publish_object(struct ubus_context *context) */ int main(int argc, char **argv) { - int ret; int ch; int num_of_q = QOS_MIN_Q_NUM_PER_PORT; int log_level = 6; // default LOG_INFO @@ -104,7 +105,10 @@ int main(int argc, char **argv) while ((ch = getopt(argc, argv, "lvsq:e:")) != -1) { switch (ch) { case 'l': - log_level = (int)strtoul(optarg, NULL, 10); + if (optarg) { + log_level = (int)strtoul(optarg, NULL, 10); + } + if (log_level < 0 || log_level > 7) log_level = 6; break; @@ -135,9 +139,12 @@ int main(int argc, char **argv) ubus_add_uloop(ctx); +#ifdef UBUS_SUPPORT + int ret; ret = qosmngr_publish_object(ctx); if (ret) goto out; +#endif memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); bbfdm_ubus_set_service_name(&bbfdm_ctx, "qosmngr"); @@ -154,7 +161,7 @@ int main(int argc, char **argv) /* Main loop of qosmngr */ uloop_run(); out: - bbfdm_ubus_regiter_free(&bbfdm_ctx);; + bbfdm_ubus_regiter_free(&bbfdm_ctx); ubus_free(ctx); uloop_done(); diff --git a/src/qos_bbf.c b/src/qos_bbf.c index e35b4c1..e717ada 100644 --- a/src/qos_bbf.c +++ b/src/qos_bbf.c @@ -117,6 +117,22 @@ static void qos_update_order(const char *order, bool is_del) } } +static int get_QoSQueueStats_value(struct qos_stats *stats, char *intf, char *queue) +{ + char *queue_str = queue; + if (queue && *queue && DM_STRLEN(queue) > 2 && intf && *intf) { + char queue_id[8] = {0}; + + snprintf(queue_id, sizeof(queue_id), "%c", queue_str[2]); + int qid = (int) DM_STRTOL(queue_id); + + if (!prepare_stats_blob(NULL, stats, NULL, intf, qid)) { + return 0; + } + } + return 1; +} + /************************************************************* * ENTRY METHOD *************************************************************/ @@ -179,11 +195,28 @@ static int browseQoSQueueInst(struct dmctx *dmctx, DMNODE *parent_node, void *pr static int browseQoSQueueStatsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) { - struct dm_data curr_data = {0}; struct uci_section *s = NULL; char *inst = NULL; uci_path_foreach_sections(bbfdm, "dmmap_qstats", "queue_stats", s) { + struct dm_data curr_data = {0}; + + char *queue = NULL, *intf = NULL, *enabled = NULL; + struct qos_stats stats = {0}; + + enabled = dmuci_get_value_by_section_fallback_def(s, "enabled", "0"); + + // if enabled is not 0 + if (DM_STRNCMP(enabled, "0", DM_STRLEN("0"))) { + dmuci_get_value_by_section_string(s, "queue", &queue); + dmuci_get_value_by_section_string(s, "interface", &intf); + + if (!get_QoSQueueStats_value(&stats, intf, queue)) { + curr_data.additional_data = (void *)(&stats); + } else { + curr_data.additional_data = NULL; + } + } curr_data.config_section = s; @@ -1873,60 +1906,36 @@ static int set_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void * return 0; } -static int get_QoSQueueStats_value(void *data, char *option, char **value) +static int get_QoSQueueStats_OutputPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - char *queue_link = NULL, *intf_link = NULL; - - *value = "0"; - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "queue", &queue_link); - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "interface", &intf_link); - - if (queue_link && *queue_link && DM_STRLEN(queue_link) > 2 && intf_link && *intf_link) { - char queue_id[8] = {0}; - - snprintf(queue_id, sizeof(queue_id), "%c", queue_link[2]); - int qid = (int) DM_STRTOL(queue_id); - struct qos_stats stats = {0}; - - if (!prepare_stats_blob(NULL, &stats, NULL, intf_link, qid)) { - char val_buf[65] = {0}; - - if (!DM_STRNCMP(option, "tx_packets", DM_STRLEN("tx_packets"))) { - snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_packets); - *value = dmstrdup(val_buf); - } else if (!DM_STRNCMP(option, "tx_bytes", DM_STRLEN("tx_bytes"))) { - snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_bytes); - *value = dmstrdup(val_buf); - } else if (!DM_STRNCMP(option, "tx_dropped_packets", DM_STRLEN("tx_dropped_packets"))) { - snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_dropped_packets); - *value = dmstrdup(val_buf); - } else if (!DM_STRNCMP(option, "tx_dropped_bytes", DM_STRLEN("tx_dropped_bytes"))) { - snprintf(val_buf, sizeof(val_buf), "%lu", stats.tx_dropped_bytes); - *value = dmstrdup(val_buf); - } - } + if (((struct dm_data *)data)->additional_data) { + dmasprintf(value, "%llu", ((struct qos_stats *)((struct dm_data *)data)->additional_data)->tx_packets); } return 0; } -static int get_QoSQueueStats_OutputPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - return get_QoSQueueStats_value(data, "tx_packets", value); -} - static int get_QoSQueueStats_OutputBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - return get_QoSQueueStats_value(data, "tx_bytes", value); + if (((struct dm_data *)data)->additional_data) { + dmasprintf(value, "%llu", ((struct qos_stats *)((struct dm_data *)data)->additional_data)->tx_bytes); + } + return 0; } static int get_QoSQueueStats_DroppedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - return get_QoSQueueStats_value(data, "tx_dropped_packets", value); + if (((struct dm_data *)data)->additional_data) { + dmasprintf(value, "%llu", ((struct qos_stats *)((struct dm_data *)data)->additional_data)->tx_dropped_packets); + } + return 0; } static int get_QoSQueueStats_DroppedBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - return get_QoSQueueStats_value(data, "tx_dropped_bytes", value); + if (((struct dm_data *)data)->additional_data) { + dmasprintf(value, "%llu", ((struct qos_stats *)((struct dm_data *)data)->additional_data)->tx_dropped_bytes); + } + return 0; } static int get_QoSShaper_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) diff --git a/src/qosmngr.c b/src/qosmngr.c index c5250fa..7ff70dd 100644 --- a/src/qosmngr.c +++ b/src/qosmngr.c @@ -353,8 +353,7 @@ int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void *dd, q_stat->tx_bytes = stats->tx_bytes; q_stat->tx_dropped_packets = stats->tx_dropped_packets; q_stat->tx_dropped_bytes = stats->tx_dropped_bytes; - } - else { + } else { q_stat->tx_packets += stats->tx_packets; q_stat->tx_bytes += stats->tx_bytes; q_stat->tx_dropped_packets += stats->tx_dropped_packets; @@ -381,6 +380,7 @@ int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void *dd, return ret; } +#ifdef UBUS_SUPPORT /** * get_stats_by_ifname function for getting specific interface stats * @param b output parameter pointer to blob_buf @@ -578,3 +578,4 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, blob_buf_free(&b); return ret; } +#endif -- GitLab From ad1e84553fecf0e7dbde9c4f347424ec85116863 Mon Sep 17 00:00:00 2001 From: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu> Date: Mon, 7 Apr 2025 21:10:32 +0530 Subject: [PATCH 4/6] qosmngr: use BBF api for logging, instead of syslog --- include/qosmngr.h | 2 +- src/main.c | 10 ++++----- src/qos_bbf.c | 4 ++++ src/qosmngr.c | 52 +++++++++++++++++++++++------------------------ 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/include/qosmngr.h b/include/qosmngr.h index b64c21c..e846b1a 100644 --- a/include/qosmngr.h +++ b/include/qosmngr.h @@ -30,7 +30,7 @@ #include <qos.h> /* logging though syslog */ -#include <syslog.h> +#include <libbbfdm-api/dmcommon.h> /* UCI definitions, used to parse the config files at their right location */ #define UCI_CONFIG_QOS "qos" diff --git a/src/main.c b/src/main.c index 0d85e90..17235e4 100644 --- a/src/main.c +++ b/src/main.c @@ -68,7 +68,7 @@ static int qosmngr_publish_object(struct ubus_context *context) int ret; ret = ubus_add_object(context, &test_object); if (ret) { - syslog(LOG_ERR, "Failed to add 'qos' ubus object: %s\n", + BBF_ERR("Failed to add 'qos' ubus object: %s\n", ubus_strerror(ret)); } @@ -83,7 +83,7 @@ static int qosmngr_publish_object(struct ubus_context *context) */ void qosmngr_version(void) { - syslog(LOG_ERR, "version : %s.%s\n", qosmngr_base_version, qosmngr_xtra_version); + BBF_ERR("version : %s.%s\n", qosmngr_base_version, qosmngr_xtra_version); } /** @@ -96,7 +96,7 @@ int main(int argc, char **argv) { int ch; int num_of_q = QOS_MIN_Q_NUM_PER_PORT; - int log_level = 6; // default LOG_INFO + int log_level = 7; // default LOG_DEBUG /* Logging to syslog */ @@ -133,7 +133,7 @@ int main(int argc, char **argv) uloop_init(); ctx = ubus_connect(ubus_socket); if (!ctx) { - syslog(LOG_ERR, "Failed to connect to ubus\n"); + BBF_ERR("Failed to connect to ubus\n"); return -1; } @@ -152,7 +152,7 @@ int main(int argc, char **argv) bbfdm_ubus_load_data_model(tDynamicObj); if (bbfdm_ubus_regiter_init(&bbfdm_ctx)) { - syslog(LOG_ERR, "Failed to register ubus"); + BBF_ERR("Failed to register ubus"); goto out; } diff --git a/src/qos_bbf.c b/src/qos_bbf.c index e717ada..67fcb1f 100644 --- a/src/qos_bbf.c +++ b/src/qos_bbf.c @@ -126,6 +126,10 @@ static int get_QoSQueueStats_value(struct qos_stats *stats, char *intf, char *qu snprintf(queue_id, sizeof(queue_id), "%c", queue_str[2]); int qid = (int) DM_STRTOL(queue_id); + // the function name is prepare_stats_blob + // but when the first argument is NULL + // it does not populate the blob + // and only the stats are updated if (!prepare_stats_blob(NULL, stats, NULL, intf, qid)) { return 0; } diff --git a/src/qosmngr.c b/src/qosmngr.c index 7ff70dd..fa4a174 100644 --- a/src/qosmngr.c +++ b/src/qosmngr.c @@ -71,7 +71,7 @@ static int get_no_queues(const char *ifname) uci_load(uci_ctx, "qos", &uci_pkg); if (!uci_pkg) { - syslog(LOG_ERR, "Failed to load configuration\n"); + BBF_ERR("Failed to load configuration\n"); queues = -1; goto done; } @@ -138,7 +138,7 @@ static int init_interface(const char *ifname, size_t index) 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"); + BBF_ERR("Initialization failed during memory allocation.\n"); free(interfaces); return -1; } @@ -154,7 +154,7 @@ int init_qstat(void) { int ret = 0; - syslog(LOG_ERR, "Initializing global stat structure.\n"); + BBF_ERR("Initializing global stat structure.\n"); interface_count = 0; long int size; @@ -172,7 +172,7 @@ int init_qstat(void) unsigned int buffer_size = 0; /* Allocate memory for entire content */ if (size < 0) { - syslog(LOG_ERR, "file read size < 0"); + BBF_ERR("file read size < 0"); fclose(fp); return -1; } else { @@ -181,14 +181,14 @@ int init_qstat(void) buffer = calloc(1, buffer_size + 1); if (buffer == NULL) { - syslog(LOG_ERR, "memory allocation to read buffer failed"); + BBF_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"); + BBF_ERR("read from board.json file failed"); free(buffer); fclose(fp); return -1; @@ -196,7 +196,7 @@ int init_qstat(void) struct json_object *board_json = json_tokener_parse(buffer); if (board_json == NULL) { - syslog(LOG_ERR, "failed to read board.json as json"); + BBF_ERR("failed to read board.json as json"); free(buffer); fclose(fp); return -1; @@ -204,7 +204,7 @@ int init_qstat(void) 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"); + BBF_ERR("network object not found in board.json"); ret = -1; json_object_put(board_json); goto free_and_return; @@ -212,7 +212,7 @@ int init_qstat(void) struct json_object *lan = NULL; if (!json_object_object_get_ex(network, "lan", &lan)) { - syslog(LOG_ERR, "lan object not found in board.json"); + BBF_ERR("lan object not found in board.json"); json_object_put(board_json); ret = -1; goto free_and_return; @@ -225,7 +225,7 @@ int init_qstat(void) // its not necessary that board.json has wan section at all if (json_object_object_get_ex(network, "wan", &wan)) { if (!json_object_object_get_ex(wan, "device", &wan_device)) { - syslog(LOG_ERR, "wan device object not found in board.json"); + BBF_ERR("wan device object not found in board.json"); ret = -1; json_object_put(board_json); goto free_and_return; @@ -236,9 +236,9 @@ int init_qstat(void) struct json_object *lan_ports = NULL; if (!json_object_object_get_ex(lan, "ports", &lan_ports)) { - syslog(LOG_INFO, "lan ports object not found in board.json"); + BBF_INFO("lan ports object not found in board.json"); if (!json_object_object_get_ex(lan, "device", &lan_ports)) { - syslog(LOG_INFO, "lan device object not found in board.json"); + BBF_INFO("lan device object not found in board.json"); ret = -1; json_object_put(board_json); goto free_and_return; @@ -256,7 +256,7 @@ int init_qstat(void) interfaces = (qos_interface_data *)calloc(interface_count, sizeof(qos_interface_data)); if (interfaces == NULL) { - syslog(LOG_ERR, "Initialization failed during memory allocation."); + BBF_ERR("Initialization failed during memory allocation."); ret = -1; json_object_put(board_json); goto free_and_return; @@ -267,7 +267,7 @@ int init_qstat(void) 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"); + BBF_ERR("cannot read lan ports array"); ret = -1; json_object_put(board_json); free(interfaces); @@ -277,7 +277,7 @@ int init_qstat(void) ret = init_interface(json_object_get_string(l_port_name), i); if (ret < 0) { - syslog(LOG_ERR, "cannot int lan ports qos"); + BBF_ERR("cannot int lan ports qos"); json_object_put(board_json); free(interfaces); goto free_and_return; @@ -287,7 +287,7 @@ int init_qstat(void) } else { ret = init_interface(json_object_get_string(lan_ports), i); if (ret < 0) { - syslog(LOG_ERR, "cannot int lan device qos"); + BBF_ERR("cannot int lan device qos"); json_object_put(board_json); free(interfaces); goto free_and_return; @@ -327,20 +327,20 @@ int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void *dd, ret = qos_get_stats(ifname, qid, stats, &is_read_and_reset); if (ret != 0) { - syslog(LOG_ERR, "blob_get_status: ret %d\n", ret); + BBF_ERR("blob_get_status: ret %d\n", ret); return ret; } index = get_interface_index(ifname); if (index < 0 || index >= interface_count) { - syslog(LOG_ERR, "Invalid interface index %d (out of %zu) for interface %s", + BBF_ERR("Invalid interface index %d (out of %zu) for interface %s", index, interface_count, ifname); return -1; } iface = &interfaces[index]; if (qid < 0 || qid >= iface->q_count) { - syslog(LOG_ERR, "Invalid queue index %d (out of %zu)", + BBF_ERR("Invalid queue index %d (out of %zu)", qid, iface->q_count); return -1; } @@ -433,7 +433,7 @@ static int get_stats_for_all_intf(struct blob_buf *b, struct qos_stats *stats, v cur->if_name, QOS_QUEUE_ANY); if (ret != 0) { - syslog(LOG_ERR, "get_stats_by_ifname failed: ret %d", ret); + BBF_ERR("get_stats_by_ifname failed: ret %d", ret); continue; } } @@ -471,7 +471,7 @@ static int validate_keys(char *req_json) if (!(!strncmp(key, PARAM1, strlen(PARAM1)) || !strncmp(key, PARAM2, strlen(PARAM2)))) { - syslog(LOG_ERR, "ERROR :: unknown parameter : %s\n", key); + BBF_ERR("ERROR :: unknown parameter : %s\n", key); return -1; } } @@ -521,7 +521,7 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, /* Validate requested parameters, i.e., ifname and qid */ ret = validate_request(msg); if (ret) { - syslog(LOG_ERR, "validate_request failed : ret %d\n", ret); + BBF_ERR("validate_request failed : ret %d\n", ret); return UBUS_STATUS_INVALID_ARGUMENT; } @@ -546,10 +546,10 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, if (init_flag) { ret = init_qstat(); if (ret) { - syslog(LOG_ERR, "Failed to initialize gobal q_stat"); + BBF_ERR("Failed to initialize gobal q_stat"); return ret; } - syslog(LOG_INFO, "Initialized gobal q_stat successfully"); + BBF_INFO("Initialized gobal q_stat successfully"); } blob_buf_init(&b, 0); @@ -559,13 +559,13 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, if (tb[QOS_POLICY_IFNAME]) { ret = get_stats_by_ifname(&b, &stats, &dd, ifname, qid); if (ret != 0) { - syslog(LOG_ERR, "get_stats_by_ifname : ret %d\n", ret); + BBF_ERR("get_stats_by_ifname : ret %d\n", ret); goto fail_get_status; } } else { ret = get_stats_for_all_intf(&b, &stats, &dd); if (ret != 0) { - syslog(LOG_ERR, "get_stats_for_all_intf : ret %d\n", ret); + BBF_ERR("get_stats_for_all_intf : ret %d\n", ret); goto fail_get_status; } } -- GitLab From 12ab6e2a4549accc5b81b076a5fa7473c094155e Mon Sep 17 00:00:00 2001 From: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu> Date: Tue, 8 Apr 2025 05:29:59 +0530 Subject: [PATCH 5/6] qosmngr: add deprecation warning for ubus call --- src/qosmngr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qosmngr.c b/src/qosmngr.c index fa4a174..7f4c1ef 100644 --- a/src/qosmngr.c +++ b/src/qosmngr.c @@ -510,6 +510,8 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { + BBF_ERR("Warning: qos ubus object has been deprecated, please use bbfdm to fetch the stats!\n"); + int ret = 0; int qid = QOS_QUEUE_ANY; char ifname[IFNAMSIZ] = {0}; -- GitLab From 83aa4a3a355700ea86490941ea9b244c39fb9519 Mon Sep 17 00:00:00 2001 From: Vivek Kumar Dutta <vivek.dutta@iopsys.eu> Date: Fri, 11 Apr 2025 10:50:28 +0530 Subject: [PATCH 6/6] cleanup --- .gitlab-ci.yml | 34 +---- Makefile | 58 -------- Makefile.diag.inc | 1 - common.mk | 10 -- gitlab-ci/build.sh | 2 +- gitlab-ci/functional-test.sh | 23 --- src/Makefile | 28 ++++ src/main.c | 117 ++++++++------- src/qos_bbf.c | 25 +--- src/qosmngr.c | 89 +++-------- {include => src}/qosmngr.h | 8 +- test/cmocka/Makefile | 26 ---- test/cmocka/functional_test_qos.c | 240 ------------------------------ 13 files changed, 128 insertions(+), 533 deletions(-) delete mode 100644 Makefile delete mode 100644 Makefile.diag.inc delete mode 100644 common.mk delete mode 100755 gitlab-ci/functional-test.sh create mode 100644 src/Makefile rename {include => src}/qosmngr.h (94%) delete mode 100644 test/cmocka/Makefile delete mode 100644 test/cmocka/functional_test_qos.c diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c92acc..a1b0995 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,24 +1,21 @@ include: - project: 'iopsys/gitlab-ci-pipeline' file: '/static-code-analysis.yml' - ref: '0.31' + ref: '1.2' + +variables: + DEBUG: 'TRUE' + SOURCE_FOLDER: "src" + CPPCHECK_OPTIONS: "--suppress=cert-STR05-C" stages: - static_code_analysis - compile_test - - unit_test - - functional_test - api_test -variables: - COMMON_IMAGE: "dev.iopsys.eu:5050/iopsys/gitlab-ci-pipeline/code-analysis:0.31" - DEBUG: 'TRUE' - SOURCE_FOLDER: "src" - RUN_CPPCHECK: "cppcheck --enable=all --error-exitcode=1 --suppress=missingInclude --suppress=unusedFunction --suppress=unreadVariable --suppress=variableScope --suppress=redundantInitialization --suppress=unusedLabel --suppress=unusedStructMember --suppress=knownConditionTrueFalse --suppress=unmatchedSuppression --force" - run_compile_test: stage: compile_test - image: dev.iopsys.eu:5050/iopsys/gitlab-ci-pipeline/code-analysis:latest + image: ${COMMON_IMAGE} allow_failure: false script: - "./gitlab-ci/install-dependencies.sh" @@ -26,7 +23,7 @@ run_compile_test: run_api_test: stage: api_test - image: dev.iopsys.eu:5050/iopsys/gitlab-ci-pipeline/code-analysis:latest + image: ${COMMON_IMAGE} allow_failure: false script: - "./gitlab-ci/install-dependencies.sh" @@ -41,18 +38,3 @@ run_api_test: - api-test-coverage.xml - api-test-memory-report.xml - timestamp.log - -run_functional_test: - stage: functional_test - image: dev.iopsys.eu:5050/iopsys/gitlab-ci-pipeline/code-analysis:latest - allow_failure: false - script: - - "./gitlab-ci/install-dependencies.sh" - - "./gitlab-ci/setup.sh" - - "./gitlab-ci/functional-test.sh" - - artifacts: - when: always - paths: - - functional-test-coverage.xml - - timestamp.log diff --git a/Makefile b/Makefile deleted file mode 100644 index 1593044..0000000 --- a/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# Makefile for qosmngr -include common.mk - --include Makefile.diag.inc - -GCOV=gcov -SRC_DIR = src - -CODECOVERAGE_SRC = $(addprefix $(SRC_DIR)/, qosmngr.c ) -PROG = $(PROJECT_TOPLEVEL)/qosmngr -OBJS = $(addprefix $(SRC_DIR)/, main.o qosmngr.o qos_bbf.o) - -PROG_CFLAGS = $(CFLAGS) -I$(INCLUDE_DIR) $(DIAG_CFLAGS) -Werror -fstrict-aliasing -PROG_LDFLAGS = $(LDFLAGS) -lbbfdm-ubus -lbbfdm-api -PROG_LIBS = $(COMMON_LDFLAGS) -lgcov - -# MUSL has the following issue in snprintf, so it is ignored: -PROG_CFLAGS += -Wno-format-nonliteral - -.PHONY: all clean - -all: version $(PROG) - -$(PROG): $(INCLUDE_DIR)/version.h $(OBJS) - $(CC) -o $@ $^ $(PROG_LDFLAGS) $(PROG_LIBS) - -version: $(INCLUDE_DIR)/version.h - -$(INCLUDE_DIR)/version.h: $(PROJECT_TOPLEVEL)/VERSION - @(dirty=$(shell (git status --porcelain | grep -q .) && echo -dirty); \ - [ -f $(PROJECT_TOPLEVEL)/VERSION ] && basever=$(shell cat $(PROJECT_TOPLEVEL)/VERSION) || \ - basever=Unknown; \ - xver=$(shell date +'%y%V%u-%H%M'); \ - echo "const char *qosmngr_base_version = \"$$basever\";" > $@; \ - echo "const char *qosmngr_xtra_version = \"$$xver$$dirty\";" >> $@; \ - ) - -test: $(PROG) - -coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -fPIC -DBBF_VENDOR_PREFIX='"X_IOWRT_EU"' -coverage: LDFLAGS += --coverage -coverage: test $(PROG) - $(foreach testprog, $(CODECOVERAGE_SRC), $(GCOV) $(testprog);) - -functional-test: test - $(MAKE) -C test/cmocka functional-test - -%.o: %.c - $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< - -clean: - rm -f *.o $(PROG) $(INCLUDE_DIR)/version.h - rm -f *.xml *.html - find -name '*.gcda' -exec rm {} -fv \; - find -name '*.gcno' -exec rm {} -fv \; - find -name '*.gcov' -exec rm {} -fv \; - make -C test/cmocka clean - diff --git a/Makefile.diag.inc b/Makefile.diag.inc deleted file mode 100644 index 7729cbb..0000000 --- a/Makefile.diag.inc +++ /dev/null @@ -1 +0,0 @@ -DIAG_CFLAGS = -Wall -Wshadow -Wdouble-promotion -Wformat=2 -Wundef -fno-common -Wconversion -Wstrict-prototypes -Wno-declaration-after-statement diff --git a/common.mk b/common.mk deleted file mode 100644 index 2069d99..0000000 --- a/common.mk +++ /dev/null @@ -1,10 +0,0 @@ -# Useful to refer to headers not located in the same directory as the source files being compiled -PROJECT_TOPLEVEL := $(dir $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) -INCLUDE_DIR = $(PROJECT_TOPLEVEL)/include - -# Common compiler options -CC=gcc # gcc || clang - -COMMON_LDFLAGS = -luci -lubus -lubox -ljson-c -lblobmsg_json -lnl-genl-3 -lnl-3 -lqos -QOSMNGR_LIB_DIR ?= $(shell dirname $(PWD)) -QOSMNGR_LDFLAGS = -lqosmngr -L$(QOSMNGR_LIB_DIR) diff --git a/gitlab-ci/build.sh b/gitlab-ci/build.sh index aa28e04..20d23f4 100755 --- a/gitlab-ci/build.sh +++ b/gitlab-ci/build.sh @@ -2,4 +2,4 @@ set -e echo "build stage" pwd -make CFLAGS='-DBBF_VENDOR_PREFIX=\"X_IOPSYS_EU_\"' +make -C ./src CFLAGS='-DBBF_VENDOR_PREFIX=\"X_IOPSYS_EU_\"' diff --git a/gitlab-ci/functional-test.sh b/gitlab-ci/functional-test.sh deleted file mode 100755 index f5231f6..0000000 --- a/gitlab-ci/functional-test.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -echo "Functional Test" -pwd - -make coverage -C ./ -supervisorctl status all -supervisorctl update -sleep 3 -supervisorctl status all - -make functional-test -C ./ - -supervisorctl stop all -supervisorctl status - -#report part -#GitLab-CI output -gcovr -r . -# Artefact -gcovr -r . --xml -o ./functional-test-coverage.xml -date +%s > timestamp.log - diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ef3e7b7 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,28 @@ +PROG = qosmngr +OBJS = main.o qosmngr.o qos_bbf.o + +PROG_CFLAGS = $(CFLAGS) -Wall -Werror +PROG_LDFLAGS = $(LDFLAGS) -lbbfdm-ubus -lbbfdm-api -luci -lubus -lubox -ljson-c +PROG_LDFLAGS += -lblobmsg_json -lnl-genl-3 -lnl-3 -lqos + +ifeq ($(filter -DBBF_VENDOR_PREFIX=%,$(PROG_CFLAGS)),) +PROG_CFLAGS += -DBBF_VENDOR_PREFIX=\"X_IOWRT_EU_\" +endif + +.PHONY: all clean + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) -o $@ $^ $(PROG_LDFLAGS) + +%.o: %.c + $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< + +clean: + rm -f *.o $(PROG) + rm -f *.xml *.html + find -name '*.gcda' -exec rm {} -fv \; + find -name '*.gcno' -exec rm {} -fv \; + find -name '*.gcov' -exec rm {} -fv \; + diff --git a/src/main.c b/src/main.c index 17235e4..625523e 100644 --- a/src/main.c +++ b/src/main.c @@ -28,15 +28,13 @@ #include <libbbfdm-ubus/bbfdm-ubus.h> #include "qosmngr.h" -#include "version.h" - #include "qos_bbf.h" -const char *ubus_socket; +#define PROTOCOLS_FILE "/etc/protocols" + +protocol_list_t g_protocol_maps; -struct ubus_context *ctx = NULL; extern DM_MAP_OBJ tDynamicObj[]; -static struct bbfdm_context bbfdm_ctx = {0}; #ifdef UBUS_SUPPORT const struct blobmsg_policy get_status_policy[NUM_QOS_POLICY] = { @@ -76,33 +74,56 @@ static int qosmngr_publish_object(struct ubus_context *context) } #endif -/** - * To get the qosmngr version - * @param : none - * return : none - */ -void qosmngr_version(void) +static int init_protocol_numbers() { - BBF_ERR("version : %s.%s\n", qosmngr_base_version, qosmngr_xtra_version); + char line[256] = {0}; + protocol_list_t *pentry; + + INIT_LIST_HEAD(&g_protocol_maps.list); + + // cppcheck-suppress cert-MSC24-C + FILE *file = fopen(PROTOCOLS_FILE, "r"); + if (!file) + return -1; + + while (fgets(line, sizeof(line), file)) { + if (line[0] == '#' || line[0] == '\n') + continue; + + char name[32] = {0}; + int number = 0; + if (sscanf(line, "%31s %d", name, &number) == 2) { + pentry = (protocol_list_t *) calloc(1, sizeof(protocol_list_t)); + if (pentry) { + pentry->proto_num = number; + snprintf(pentry->proto_name, sizeof(name), "%s", name); + list_add_tail(&pentry->list, &g_protocol_maps.list); + } + } + } + + fclose(file); + return 0; } -/** - * Main function for qosmngr, everything starts here - * @param argc input number of input arguments - * @param argv input double pointer array of optional command line arguments - * retrun integer value 0 on success and -1 on failure - */ -int main(int argc, char **argv) +int cleanup() { - int ch; - int num_of_q = QOS_MIN_Q_NUM_PER_PORT; - int log_level = 7; // default LOG_DEBUG + protocol_list_t *entry = NULL, *tmp = NULL; + list_for_each_entry_safe(entry, tmp, &g_protocol_maps.list, list) { + list_del(&entry->list); + free(entry); + } + return 0; +} - /* Logging to syslog */ - openlog("qosmngr", LOG_PID|LOG_CONS, LOG_LOCAL1); +int main(int argc, char **argv) +{ + int ch; + int log_level = 7; + struct bbfdm_context bbfdm_ctx = {0}; - while ((ch = getopt(argc, argv, "lvsq:e:")) != -1) { + while ((ch = getopt(argc, argv, "l:q:")) != -1) { switch (ch) { case 'l': if (optarg) { @@ -110,16 +131,10 @@ int main(int argc, char **argv) } if (log_level < 0 || log_level > 7) - log_level = 6; - break; - case 'v': - qosmngr_version(); - exit(0); - case 's': - ubus_socket = optarg; + log_level = 7; break; case 'q': - num_of_q = get_no_of_q_per_port(argv[argc-1]); + int num_of_q = get_no_of_q_per_port(argv[argc-1]); printf("%d", num_of_q); exit(0); default: @@ -127,43 +142,31 @@ int main(int argc, char **argv) } } - argc -= optind; - argv += optind; - - uloop_init(); - ctx = ubus_connect(ubus_socket); - if (!ctx) { - BBF_ERR("Failed to connect to ubus\n"); - return -1; - } - - ubus_add_uloop(ctx); - -#ifdef UBUS_SUPPORT - int ret; - ret = qosmngr_publish_object(ctx); - if (ret) - goto out; -#endif - memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); bbfdm_ubus_set_service_name(&bbfdm_ctx, "qosmngr"); bbfdm_ubus_set_log_level(log_level); bbfdm_ubus_load_data_model(tDynamicObj); + openlog("qosmngr", LOG_PID|LOG_CONS, LOG_LOCAL1); + if (bbfdm_ubus_regiter_init(&bbfdm_ctx)) { - BBF_ERR("Failed to register ubus"); + BBF_ERR("Failed to register bbfdm.qosmngr ubus"); goto out; } +#ifdef UBUS_SUPPORT + if (qosmngr_publish_object(&bbfdm_ctx.ubus_ctx)) { + BBF_ERR("Failed to register qos object"); + goto out; + } +#endif + init_qstat(); + init_protocol_numbers(); - /* Main loop of qosmngr */ uloop_run(); out: bbfdm_ubus_regiter_free(&bbfdm_ctx); - ubus_free(ctx); - uloop_done(); - + cleanup(); return 0; } diff --git a/src/qos_bbf.c b/src/qos_bbf.c index 67fcb1f..6e40051 100644 --- a/src/qos_bbf.c +++ b/src/qos_bbf.c @@ -13,7 +13,7 @@ #include "libbbfdm_api.h" #include "qosmngr.h" -#define PROTOCOLS_FILE "/etc/protocols" +extern protocol_list_t g_protocol_maps; /************************************************************* * COMMON FUNCTIONS @@ -31,26 +31,13 @@ static int is_numeric(const char *str) static int lookup_protocol_number(const char *protocol) { - FILE *file = fopen(PROTOCOLS_FILE, "r"); - if (!file) - return -1; - - char line[256]; - while (fgets(line, sizeof(line), file)) { - if (line[0] == '#' || line[0] == '\n') - continue; - - char name[32] = {0}; - int number = 0; - if (sscanf(line, "%31s %d", name, &number) == 2) { - if (strcasecmp(name, protocol) == 0) { - fclose(file); - return number; - } + protocol_list_t *entry = NULL; + + list_for_each_entry(entry, &g_protocol_maps.list, list) { + if (strcasecmp(entry->proto_name, protocol) == 0) { + return entry->proto_num; } } - - fclose(file); return -1; } diff --git a/src/qosmngr.c b/src/qosmngr.c index 7f4c1ef..498b1f4 100644 --- a/src/qosmngr.c +++ b/src/qosmngr.c @@ -42,15 +42,15 @@ #define PARAM1 "ifname" #define PARAM2 "qid" +#define BOARD_JSON_FILE "/etc/board.json" + /** Container for single interface data (with multiple queues) */ typedef struct qos_interface_data { - char if_name[IFNAMSIZ]; /**< Cached interface name */ size_t q_count; /**< Cached number of queues */ struct qos_stats *q_stat; /**< Cached queue statistics */ + char if_name[IFNAMSIZ]; /**< Cached interface name */ } qos_interface_data; -static int init_flag = 1; - /** Number of interfaces currently cached by qosmngr */ static size_t interface_count = 0; /** Array of interfaces cached by qosmngr */ @@ -127,21 +127,23 @@ static int get_interface_index(const char *ifname) return -1; } -static int init_interface(const char *ifname, size_t index) +static int init_interface_queues(const char *ifname, qos_interface_data *data) { - qos_interface_data *data = &interfaces[index]; - size_t queues = (size_t)get_no_queues(ifname); + if (data == NULL) { + BBF_ERR("Null interface entry"); + return -1; + } + strncpy(data->if_name, ifname, IFNAMSIZ); data->q_count = queues; - data->q_stat = (struct qos_stats *)calloc(queues, - sizeof(struct qos_stats)); + data->q_stat = (struct qos_stats *)calloc(queues, sizeof(struct qos_stats)); if (data->q_stat == NULL) { BBF_ERR("Initialization failed during memory allocation.\n"); - free(interfaces); return -1; } + return 0; } @@ -154,51 +156,10 @@ int init_qstat(void) { int ret = 0; - BBF_ERR("Initializing global stat structure.\n"); - interface_count = 0; - long int size; - FILE *fp = NULL; - char *buffer = NULL; - - fp = fopen("/etc/board.json","r"); - if (fp == NULL) - return -1; - - fseek(fp, 0L, SEEK_END); - size = ftell(fp); - rewind(fp); - - unsigned int buffer_size = 0; - /* Allocate memory for entire content */ - if (size < 0) { - BBF_ERR("file read size < 0"); - fclose(fp); - return -1; - } else { - buffer_size = (unsigned int)size; - } - - buffer = calloc(1, buffer_size + 1); - if (buffer == NULL) { - BBF_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) { - BBF_ERR("read from board.json file failed"); - free(buffer); - fclose(fp); - return -1; - } - - struct json_object *board_json = json_tokener_parse(buffer); + struct json_object *board_json = json_object_from_file(BOARD_JSON_FILE); if (board_json == NULL) { BBF_ERR("failed to read board.json as json"); - free(buffer); - fclose(fp); return -1; } @@ -274,8 +235,7 @@ int init_qstat(void) goto free_and_return; } - ret = init_interface(json_object_get_string(l_port_name), i); - + ret = init_interface_queues(json_object_get_string(l_port_name), &interfaces[i]); if (ret < 0) { BBF_ERR("cannot int lan ports qos"); json_object_put(board_json); @@ -285,7 +245,7 @@ int init_qstat(void) } } else { - ret = init_interface(json_object_get_string(lan_ports), i); + ret = init_interface_queues(json_object_get_string(lan_ports), &interfaces[i]); if (ret < 0) { BBF_ERR("cannot int lan device qos"); json_object_put(board_json); @@ -295,15 +255,13 @@ int init_qstat(void) i++; } - if (wan_device) - ret = init_interface(json_object_get_string(wan_device), i); + if (wan_device) { + ret = init_interface_queues(json_object_get_string(wan_device), &interfaces[i]); + } json_object_put(board_json); - init_flag = 0; free_and_return: - free(buffer); - fclose(fp); return ret; } @@ -510,8 +468,6 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { - BBF_ERR("Warning: qos ubus object has been deprecated, please use bbfdm to fetch the stats!\n"); - int ret = 0; int qid = QOS_QUEUE_ANY; char ifname[IFNAMSIZ] = {0}; @@ -520,6 +476,7 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, struct blob_buf b = {0}; struct qos_stats stats = {0}; + BBF_WARNING("Warning: qos ubus object has been deprecated, please use bbfdm to fetch the stats!\n"); /* Validate requested parameters, i.e., ifname and qid */ ret = validate_request(msg); if (ret) { @@ -544,16 +501,6 @@ 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) { - BBF_ERR("Failed to initialize gobal q_stat"); - return ret; - } - BBF_INFO("Initialized gobal q_stat successfully"); - } - blob_buf_init(&b, 0); d = blobmsg_open_array(&b, "queues"); diff --git a/include/qosmngr.h b/src/qosmngr.h similarity index 94% rename from include/qosmngr.h rename to src/qosmngr.h index e846b1a..9784af2 100644 --- a/include/qosmngr.h +++ b/src/qosmngr.h @@ -58,11 +58,17 @@ extern const struct blobmsg_policy get_status_policy[NUM_QOS_POLICY]; /* A QoS queue. */ struct qos_queue { - char name[IFNAMSIZ]; bool enable; struct qos_queue_config config; + char name[IFNAMSIZ]; }; +typedef struct protocol_list { + struct list_head list; + int proto_num; + char proto_name[32]; +} protocol_list_t; + int init_qstat(void); int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile deleted file mode 100644 index 0051154..0000000 --- a/test/cmocka/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../../common.mk - -QOSMNGR_LIB_DIR = $(PROJECT_TOPLEVEL) -CMOCKA_LIB = -lcmocka -LIBS = $(QOSMNGR_LDFLAGS) $(CMOCKA_LIB) -lpthread $(COMMON_LDFLAGS) -ljson-validator -ljson-schema-validator -ljson-editor -CFLAGS = -g -Wall -O0 -fPIC -I$(INCLUDE_DIR) -LDFLAGS = $(LIBS) -Wl,-rpath=$(QOSMNGR_LIB_DIR) -I$(QOSMNGR_LIB_DIR) --coverage -FUNCTIONAL_TESTS = functional_test_qos - -VALGRIND = valgrind --leak-check=full --show-reachable=no \ - --show-leak-kinds=all --errors-for-leak-kinds=all \ - --error-exitcode=1 --track-origins=yes - -%.o: %.c - $(CC) $(CFLAGS) $(FPIC) -c -o $@ $< - -functional_test_qos: functional_test_qos.o - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -functional-test: $(FUNCTIONAL_TESTS) - $(foreach testprog, $(FUNCTIONAL_TESTS), sudo $(VALGRIND) ./$(testprog);) - -.PHONY: clean - -clean: - rm $(FUNCTIONAL_TESTS) *.o *.gcno *.gcda -fv diff --git a/test/cmocka/functional_test_qos.c b/test/cmocka/functional_test_qos.c deleted file mode 100644 index 2f15f64..0000000 --- a/test/cmocka/functional_test_qos.c +++ /dev/null @@ -1,240 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <errno.h> -#include <cmocka.h> - -#include <libubus.h> -#include <libubox/blobmsg_json.h> -#include <libubox/blobmsg.h> - -#include <json-validator.h> -#include <json-c/json.h> -#include <json-editor.h> -#include <json-c/json_tokener.h> - -#include "qosmngr.h" - -#define UBUS_OUTPUT_FILE "/tmp/qosmngr_ubus_output.txt" - -struct json_object *json_output = NULL; - -/** - * group_setup function to setup the test modules - * @param state input parameter pointer to a pointer to test state - */ -static int group_setup(void **state) -{ - // Start ubusd if it is not running - system("pidof ubusd || ubusd &"); - - // Restart qosmngr - system("kill $(pidof qosmngr) 2>/dev/null; ../../qosmngr &"); - - return 0; -} - -/** - * group_teardown function to cleanup the test modules - * @param state input parameter pointer to a pointer to test state - */ -static int group_teardown(void **state) -{ - // Stop qosmngr - system("kill $(pidof qosmngr) 2>/dev/null"); - - // Delete test logs - unlink(UBUS_OUTPUT_FILE); - - return 0; -} - -/** - * teardown function to cleanup the test modules - * @param state input parameter pointer to a pointer to test state - */ -static int teardown(void **state) -{ - if (json_output) { - json_object_put(json_output); // Free the output JSON object - json_output = NULL; - } - - return 0; -} - -/** - * validate_queues function to validate all queues received under queues - * @param queues input parameter pointer to json_object containg all queues to - * be validated - */ -static void validate_queues(struct json_object *queues) -{ - int i; - int len; - - assert_non_null(queues); - len = json_object_array_length(queues); - - // Assert on length as well, should be greater than 0 - assert_true(len >= 0); - - for (i = 0; i < len; i++) { - struct json_object *queue = json_object_array_get_idx(queues, i); - json_object_object_foreach(queue, key, val) { - int val_type = json_object_get_type(val); - switch(val_type) { - case json_type_int: - assert_true(json_object_get_int(val) >= 0); - break; - case json_type_string: - assert_true(!strncmp(json_object_get_string(val), - "eth", strlen("eth"))); - break; - } - } - } -} - -/** - * validate_stats function to validate json_object received under json_obj - * @param json_obj input parameter pointer to json_object containg ubus output - */ -static void validate_stats(struct json_object *json_obj) -{ - assert_non_null(json_obj); - - json_object_object_foreach(json_obj, key, val) { - int val_type = json_object_get_type(val); - - if (val_type == json_type_array) { - switch (val_type) { - case json_type_array: - validate_queues(val); - break; - } - } - } -} - -/** - * get_ubus_call_output function to fill global json output variable with ubus call output - * @param ubus_cmd input parameter pointer to char string containg ubus call - * @param negative_case input parameter of type bool to identify negative scenarios - */ -static void get_ubus_call_output(const char *ubus_cmd, bool negative_case) -{ - char cmd[256]; - int fd = -1; - char *str = NULL; - - // Put the output of ubus call into a string - snprintf(cmd, sizeof(cmd), "%s > %s", ubus_cmd, UBUS_OUTPUT_FILE); - int rc = system(cmd); - assert_return_code(rc, errno); - - fd = open(UBUS_OUTPUT_FILE, O_RDONLY); - assert_return_code(fd, errno); - - struct stat st; - rc = fstat(fd, &st); - - if(negative_case) { - assert_false(rc == 0 && st.st_size > 0); - return; - } else - assert_true(rc == 0 && st.st_size > 0); - - str = calloc(1, (size_t)st.st_size + 1); - assert_non_null(str); - - ssize_t read_len = read(fd, str, (size_t)st.st_size); - assert_int_equal((int)read_len, (int)st.st_size); - - // Parse the string to a json_object - //printf("JSON_OBJECT GET : %s\n", str); - json_output = json_tokener_parse(str); - - if (fd >= 0) - close(fd); - if (str) - free(str); -} - -/** - * test_qos_stats_no_param function to test qos_stats without any parameter - * @param state input parameter pointer to a pointer to test state - */ -static void test_qos_stats_no_param(void **state) -{ - get_ubus_call_output("ubus call qos queue_stats", false); - validate_stats(json_output); -} - -/** - * test_qos_stats_one_param function to test qos_stats with just ifname - * @param state input parameter pointer to a pointer to test state - */ -static void test_qos_stats_one_param(void **state) -{ - get_ubus_call_output("ubus call qos queue_stats '{\"ifname\":\"eth0\"}'", false); - validate_stats(json_output); -} - -/** - * test_qos_stats_all_param function to test qos_stats with all valid params - * @param state input parameter pointer to a pointer to test state - */ -static void test_qos_stats_all_param(void **state) -{ - get_ubus_call_output("ubus call qos queue_stats '{\"ifname\":\"eth0\", \"qid\":0}'", false); - validate_stats(json_output); -} - -/** - * test_qos_stats_missing_param_ifname function to test missing parameter i.e., ifname - * @param state input parameter pointer to a pointer to test state - */ -static void test_qos_stats_missing_param_ifname(void **state) -{ - get_ubus_call_output("ubus call qos queue_stats '{\"qid\":0}'", true); -} - -/** - * test_qos_stats_invalid_param_port function to test invalid parameter as port - * @param state input parameter pointer to a pointer to test state - */ -static void test_qos_stats_invalid_param_port(void **state) -{ - get_ubus_call_output("ubus call qos queue_stats '{\"port\":\"eth0\"}'", true); -} - -/** - * test_qos_stats_invalid_param_pid function to test invalid parameter as pid - * @param state input parameter pointer to a pointer to test state - */ -static void test_qos_stats_invalid_param_pid(void **state) -{ - get_ubus_call_output("ubus call qos queue_stats '{\"ifname\":\"eth0\", \"pid\":0}'", true); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test_teardown(test_qos_stats_no_param, teardown), - cmocka_unit_test_teardown(test_qos_stats_one_param, teardown), - cmocka_unit_test_teardown(test_qos_stats_all_param, teardown), - - // -ve scenarios - cmocka_unit_test_teardown(test_qos_stats_missing_param_ifname, teardown), - cmocka_unit_test_teardown(test_qos_stats_invalid_param_port, teardown), - cmocka_unit_test_teardown(test_qos_stats_invalid_param_pid, teardown), - }; - - return cmocka_run_group_tests(tests, group_setup, group_teardown); -} -- GitLab