From 1a15f1da7a1474d29aad77b8ad3272fcf4b4f6d1 Mon Sep 17 00:00:00 2001
From: Mohd Mehdi <husaam.mehdi@iopsys.eu>
Date: Fri, 11 Apr 2025 14:23:36 +0000
Subject: [PATCH] Unified service & datamodel daemon

---
 .gitlab-ci.yml                    |  34 +----
 Makefile                          |  70 ---------
 Makefile.diag.inc                 |   1 -
 bbf_plugin/Makefile               |  26 ----
 bbf_plugin/qos_bbf_vendor.c       |  48 ------
 bbf_plugin/qos_bbf_vendor.h       |  20 ---
 common.mk                         |  10 --
 gitlab-ci/build.sh                |   2 +-
 gitlab-ci/functional-test.sh      |  23 ---
 src/Makefile                      |  28 ++++
 src/main.c                        | 132 ++++++++++------
 {bbf_plugin => src}/qos_bbf.c     | 147 ++++++++++++------
 {bbf_plugin => src}/qos_bbf.h     |   0
 src/qosmngr.c                     | 161 ++++++++------------
 {include => src}/qosmngr.h        |  14 +-
 test/cmocka/Makefile              |  26 ----
 test/cmocka/functional_test_qos.c | 240 ------------------------------
 17 files changed, 288 insertions(+), 694 deletions(-)
 delete mode 100644 Makefile
 delete mode 100644 Makefile.diag.inc
 delete mode 100644 bbf_plugin/Makefile
 delete mode 100644 bbf_plugin/qos_bbf_vendor.c
 delete mode 100644 bbf_plugin/qos_bbf_vendor.h
 delete mode 100644 common.mk
 delete mode 100755 gitlab-ci/functional-test.sh
 create mode 100644 src/Makefile
 rename {bbf_plugin => src}/qos_bbf.c (96%)
 rename {bbf_plugin => src}/qos_bbf.h (100%)
 rename {include => src}/qosmngr.h (87%)
 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 d6e8359..0000000
--- a/Makefile
+++ /dev/null
@@ -1,70 +0,0 @@
-# Makefile for qosmngr
-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 )
-
-PROG_CFLAGS = $(CFLAGS) -I$(INCLUDE_DIR) $(DIAG_CFLAGS) -Werror -fstrict-aliasing
-PROG_LDFLAGS = $(LDFLAGS)
-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 $(PLUGIN) $(PROG)
-
-$(PLUGIN): $(OBJS)
-	$(MAKE) -C ./bbf_plugin
-
-$(PROG): $(INCLUDE_DIR)/version.h $(OBJS)
-	$(CC) $(PROG_LDFLAGS) -o $@ $^ $(PROG_LIBS)
-
-${QOSMNGR_LIB}:
-	$(CC) $(PROG_LDFLAGS) -shared -o $@ $^ $(PROG_LIBS)
-
-$(SHARED_LIB): $(INCLUDE_DIR)/version.h $(OBJS)
-
-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: ${QOSMNGR_LIB}
-
-coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -fPIC
-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 $(SHARED_LIB) $(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/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/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 68ffc63..625523e 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,14 +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;
+#define PROTOCOLS_FILE "/etc/protocols"
 
-struct ubus_context *ctx = NULL;
+protocol_list_t g_protocol_maps;
 
+extern DM_MAP_OBJ tDynamicObj[];
+
+#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},
@@ -52,16 +56,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
@@ -72,38 +66,75 @@ 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));
 	}
 
 	return ret;
 }
+#endif
+
+static int init_protocol_numbers()
+{
+	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;
+}
+
+int cleanup()
+{
+	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;
+}
 
-/**
- *  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 ret;
 	int ch;
-	int num_of_q = QOS_MIN_Q_NUM_PER_PORT;
+        int log_level = 7;
+	struct bbfdm_context bbfdm_ctx = {0};
 
-	/* Logging to syslog */
-	openlog("qosmngr", LOG_PID|LOG_CONS, LOG_LOCAL1);
-
-	while ((ch = getopt(argc, argv, "vsq:e:")) != -1) {
+	while ((ch = getopt(argc, argv, "l:q:")) != -1) {
 		switch (ch) {
-		case 'v':
-			qosmngr_version();
-			exit(0);
-		case 's':
-			ubus_socket = optarg;
+		case 'l':
+			if (optarg) {
+				log_level = (int)strtoul(optarg, NULL, 10);
+			}
+
+			if (log_level < 0 || log_level > 7)
+				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:
@@ -111,28 +142,31 @@ int main(int argc, char **argv)
 		}
 	}
 
-	argc -= optind;
-	argv += optind;
+        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);
 
-	uloop_init();
-	ctx = ubus_connect(ubus_socket);
-	if (!ctx) {
-		syslog(LOG_ERR, "Failed to connect to ubus\n");
-		return -1;
-	}
+	openlog("qosmngr", LOG_PID|LOG_CONS, LOG_LOCAL1);
 
-	ubus_add_uloop(ctx);
+	if (bbfdm_ubus_regiter_init(&bbfdm_ctx)) {
+		BBF_ERR("Failed to register bbfdm.qosmngr ubus");
+		goto out;
+	}
 
-	ret = qosmngr_publish_object(ctx);
-	if (ret)
+#ifdef UBUS_SUPPORT
+	if (qosmngr_publish_object(&bbfdm_ctx.ubus_ctx)) {
+		BBF_ERR("Failed to register qos object");
 		goto out;
+	}
+#endif
 
-	/* Main loop of qosmngr */
-	uloop_run();
+	init_qstat();
+	init_protocol_numbers();
 
+	uloop_run();
  out:
-	ubus_free(ctx);
-	uloop_done();
-
+	bbfdm_ubus_regiter_free(&bbfdm_ctx);
+	cleanup();
 	return 0;
 }
diff --git a/bbf_plugin/qos_bbf.c b/src/qos_bbf.c
similarity index 96%
rename from bbf_plugin/qos_bbf.c
rename to src/qos_bbf.c
index 4b4ca12..6e40051 100644
--- a/bbf_plugin/qos_bbf.c
+++ b/src/qos_bbf.c
@@ -11,7 +11,9 @@
 
 #include "qos_bbf.h"
 #include "libbbfdm_api.h"
-#define PROTOCOLS_FILE "/etc/protocols"
+#include "qosmngr.h"
+
+extern protocol_list_t g_protocol_maps;
 
 /*************************************************************
 * COMMON FUNCTIONS
@@ -29,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;
 }
 
@@ -73,7 +62,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 +88,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};
 
@@ -115,6 +104,26 @@ 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);
+
+		// 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;
+		}
+	}
+	return 1;
+}
+
 /*************************************************************
  * ENTRY METHOD
 *************************************************************/
@@ -177,11 +186,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;
 
@@ -946,6 +972,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;
 }
 
@@ -957,7 +990,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;
@@ -1347,6 +1386,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");
@@ -1838,45 +1897,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 && intf_link && *intf_link) {
-		json_object *res = NULL;
-		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);
+	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)
@@ -2108,6 +2158,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..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 */
@@ -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;
        }
@@ -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) {
-		syslog(LOG_ERR, "Initialization failed during memory allocation.\n");
-		free(interfaces);
+		BBF_ERR("Initialization failed during memory allocation.\n");
 		return -1;
 	}
+
 	return 0;
 }
 
@@ -150,61 +152,20 @@ 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;
 
-	syslog(LOG_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) {
-		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);
+	struct json_object *board_json = json_object_from_file(BOARD_JSON_FILE);
 	if (board_json == NULL) {
-		syslog(LOG_ERR, "failed to read board.json as json");
-		free(buffer);
-		fclose(fp);
+		BBF_ERR("failed to read board.json as json");
 		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");
+		BBF_ERR("network object not found in board.json");
 		ret = -1;
 		json_object_put(board_json);
 		goto free_and_return;
@@ -212,7 +173,7 @@ static 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 +186,7 @@ static 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 +197,9 @@ static 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 +217,7 @@ static 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,17 +228,16 @@ static 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);
 				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) {
-				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;
@@ -285,9 +245,9 @@ static 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) {
-			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;
@@ -295,14 +255,13 @@ static 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);
 
 free_and_return:
-	free(buffer);
-	fclose(fp);
 	return ret;
 }
 
@@ -313,9 +272,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;
@@ -326,20 +285,20 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void
 
 	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)",
-		       index, interface_count);
+		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;
 	}
@@ -352,29 +311,34 @@ 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;
-	}
-	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;
 		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;
 }
 
+#ifdef UBUS_SUPPORT
 /**
  *  get_stats_by_ifname function for getting specific interface stats
  *  @param b output parameter pointer to blob_buf
@@ -427,7 +391,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;
 		}
 	}
@@ -465,7 +429,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;
 			}
 		}
@@ -512,10 +476,11 @@ 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) {
-		syslog(LOG_ERR, "validate_request failed : ret %d\n", ret);
+		BBF_ERR("validate_request failed : ret %d\n", ret);
 		return UBUS_STATUS_INVALID_ARGUMENT;
 	}
 
@@ -536,17 +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) {
-			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");
@@ -554,13 +508,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;
 		}
 	}
@@ -573,3 +527,4 @@ int qosmngr_get_stats(struct ubus_context *ctx, struct ubus_object *obj,
 	blob_buf_free(&b);
 	return ret;
 }
+#endif
diff --git a/include/qosmngr.h b/src/qosmngr.h
similarity index 87%
rename from include/qosmngr.h
rename to src/qosmngr.h
index d745993..9784af2 100644
--- a/include/qosmngr.h
+++ b/src/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"
@@ -58,13 +58,21 @@ 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,
 		       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/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