From 68e2d7b99e008a8a0d1a22d95249e034d0726b0b Mon Sep 17 00:00:00 2001 From: jjoseph Date: Mon, 4 Jan 2021 16:56:27 +0530 Subject: [PATCH] bbf : Feature #716 : TR-181: Device.QoS object - Added support for Device.QoS.QueueStats object from TR181. - The values are fetched from the below ubus call: ubus call qos queue_stats '{"ifname":"eth0","qid":"0"}' - Tested add/delete for QueueStats object via usp. - Tested set/get for the QueueStats params via usp. --- dmtree/tr181/os.h | 7 +- dmtree/tr181/qos-iopsyswrt.c | 190 ++++++++++++++++++++++++++++++++--- dmtree/tr181/qos.c | 8 +- 3 files changed, 186 insertions(+), 19 deletions(-) diff --git a/dmtree/tr181/os.h b/dmtree/tr181/os.h index 2d37b1ce..3dc14825 100644 --- a/dmtree/tr181/os.h +++ b/dmtree/tr181/os.h @@ -320,15 +320,20 @@ int os_get_QoSClassification_SourceUserClassID(char *refparam, struct dmctx *ctx int os_set_QoSClassification_SourceUserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); int os_get_QoSClassification_DestUserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_set_QoSClassification_DestUserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); +int os_get_QoSQueueStats_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); +int os_set_QoSQueueStats_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); +int os_get_QoSQueueStats_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_get_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_set_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); +int os_get_QoSQueueStats_Queue(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); +int os_set_QoSQueueStats_Queue(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); int os_get_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_set_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); int os_get_QoSQueueStats_OutputPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_get_QoSQueueStats_OutputBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_get_QoSQueueStats_DroppedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_get_QoSQueueStats_DroppedBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); -int os_get_QoSQueueStats_QueueOccupancyPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); +//int os_get_QoSQueueStats_QueueOccupancyPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int os_browseQoSQueueInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance); int os_browseQoSShaperInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance); int os_addObjQoSQueue(char *refparam, struct dmctx *ctx, void *data, char **instance); diff --git a/dmtree/tr181/qos-iopsyswrt.c b/dmtree/tr181/qos-iopsyswrt.c index 2a4011a7..80603c7d 100644 --- a/dmtree/tr181/qos-iopsyswrt.c +++ b/dmtree/tr181/qos-iopsyswrt.c @@ -17,7 +17,9 @@ *************************************************************/ int os_get_linker_qos_queue(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) { - *linker = ""; + char sec_name[100] = {0}; + strncpy(sec_name, section_name((struct uci_section *)data), sizeof(sec_name)); + *linker = sec_name; return 0; } @@ -140,6 +142,17 @@ int os_browseQoSQueueInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_d int os_browseQoSQueueStatsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) { + struct uci_section *s = NULL; + char *inst = NULL, *max_inst = NULL; + + uci_path_foreach_sections(bbfdm, "dmmap_qstats", "queue_stats", s) { + inst = handle_update_instance(1, dmctx, &max_inst, update_instance_alias, 3, + s, "q_instance", "q_alias"); + + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP) + break; + } + return 0; } @@ -355,18 +368,49 @@ int os_delObjQoSQueue(char *refparam, struct dmctx *ctx, void *data, char *insta int os_addObjQoSQueueStats(char *refparam, struct dmctx *ctx, void *data, char **instance) { - //TODO + struct uci_section *qstats_sec = NULL; + + char *inst = get_last_instance_bbfdm("dmmap_qstats", "queue_stats", "q_instance"); + + dmuci_add_section_bbfdm("dmmap_qstats", "queue_stats", &qstats_sec); + *instance = update_instance(inst, 2, qstats_sec, "q_instance"); + return 0; } int os_delObjQoSQueueStats(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) { + struct uci_section *qstats_sec = NULL, *dmmap_section = NULL; + char *inst = NULL; + int i = 0; + switch (del_action) { case DEL_INST: - //TODO + // Remove device section in dmmap_qstats file + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmmap_section = qstats_sec; + } + dmuci_delete_by_section(dmmap_section, NULL, NULL); break; case DEL_ALL: - //TODO + inst = get_last_instance_bbfdm("dmmap_qstats", "queue_stats", "q_instance"); + + uci_path_foreach_sections(bbfdm, "dmmap_qstats", "queue_stats", qstats_sec) { + if (atoi(inst) == i) { + break; + } + + if (dmmap_section != NULL) { + dmuci_delete_by_section(dmmap_section, NULL, NULL); + } + + dmmap_section = qstats_sec; + i++; + } + + if (dmmap_section != NULL) { + dmuci_delete_by_section(dmmap_section, NULL, NULL); + } break; } return 0; @@ -577,6 +621,12 @@ int os_get_QoS_QueueNumberOfEntries(char *refparam, struct dmctx *ctx, void *dat int os_get_QoS_QueueStatsNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = "0"; + int cnt = 0; + struct uci_section *s = NULL; + uci_path_foreach_sections(bbfdm, "dmmap_qstats", "queue_stats", s) { + cnt++; + } + dmasprintf(value, "%d", cnt); return 0; } @@ -3451,17 +3501,30 @@ int os_set_QoSQueue_ShapingBurstSize(char *refparam, struct dmctx *ctx, void *da int os_get_QoSQueueStats_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = "1"; + *value = "0"; + struct uci_section *qstats_sec = NULL; + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + *value = dmuci_get_value_by_section_fallback_def(qstats_sec, "enabled", "0"); + break; + } return 0; } int os_set_QoSQueueStats_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { + bool b; + struct uci_section *qstats_sec = NULL; + switch (action) { case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; break; case VALUESET: - //TODO + string_to_bool(value, &b); + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_set_value_by_section(qstats_sec, "enabled", b ? "1" : "0"); + } break; } return 0; @@ -3469,23 +3532,35 @@ int os_set_QoSQueueStats_Enable(char *refparam, struct dmctx *ctx, void *data, c int os_get_QoSQueueStats_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = ""; + os_get_QoSQueueStats_Enable(refparam, ctx, data, instance, value); + *value = (strcmp(*value, "1") == 0) ? "Enabled" : "Disabled"; return 0; + } int os_get_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = ""; + struct uci_section *qstats_sec = NULL; + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_get_value_by_section_string(qstats_sec, "alias", value); + break; + } return 0; } int os_set_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { + struct uci_section *qstats_sec = NULL; switch (action) { case VALUECHECK: + if (dm_validate_string(value, -1, 64, NULL, 0, NULL, 0)) + return FAULT_9007; break; case VALUESET: - //TODO + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_set_value_by_section(qstats_sec, "alias", value); + } break; } return 0; @@ -3494,16 +3569,26 @@ int os_set_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, ch int os_get_QoSQueueStats_Queue(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = ""; + struct uci_section *qstats_sec = NULL; + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_get_value_by_section_string(qstats_sec, "queue", value); + break; + } return 0; } int os_set_QoSQueueStats_Queue(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { + struct uci_section *qstats_sec = NULL; switch (action) { case VALUECHECK: + if (dm_validate_string(value, -1, 256, NULL, 0, NULL, 0)) + return FAULT_9007; break; case VALUESET: - //TODO + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_set_value_by_section(qstats_sec, "queue", value); + } break; } return 0; @@ -3512,42 +3597,119 @@ int os_set_QoSQueueStats_Queue(char *refparam, struct dmctx *ctx, void *data, ch int os_get_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value=""; + struct uci_section *qstats_sec = NULL; + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_get_value_by_section_string(qstats_sec, "interface", value); + break; + } return 0; } int os_set_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { + struct uci_section *qstats_sec = NULL; switch (action) { case VALUECHECK: + if (dm_validate_string(value, -1, 256, NULL, 0, NULL, 0)) + return FAULT_9007; break; case VALUESET: - //TODO + uci_path_foreach_option_eq(bbfdm, "dmmap_qstats", "queue_stats", "q_instance", instance, qstats_sec) { + dmuci_set_value_by_section(qstats_sec, "interface", value); + } break; } return 0; } +static int get_json_object (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value, json_object **res) +{ + char *qid_linker = NULL, *linker = NULL, *find = NULL; + + // get the ifname corresponding to the instance + os_get_QoSQueueStats_Interface(refparam, ctx, data, instance, value); + adm_entry_get_linker_value(ctx, *value, &linker); + if (linker == NULL) + return 0; + + // get the qid corresponding to the instance + os_get_QoSQueueStats_Queue(refparam, ctx, data, instance, value); + adm_entry_get_linker_value(ctx, *value, &qid_linker); + + if (qid_linker != NULL && qid_linker[0] != '\0') { + char queue_id[50] = {0}; + snprintf(queue_id, sizeof(queue_id), "%c", qid_linker[2]); + dmubus_call("qos", "queue_stats", UBUS_ARGS{{"ifname", linker, String}, {"qid", queue_id, String}}, 2, res); + } + + return 0; +} + int os_get_QoSQueueStats_OutputPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = "0"; + json_object *res = NULL, *queue_obj = NULL, *arrobj = NULL;; + int i = 0; + + get_json_object(refparam, ctx, data, instance, value, &res); + dmjson_foreach_obj_in_array(res, arrobj, queue_obj, i, 1, "queues") { + *value = dmjson_get_value(queue_obj, 1, "tx_packets"); + } + + if (value == NULL) { + *value = "0"; + } + return 0; } int os_get_QoSQueueStats_OutputBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = "0"; + json_object *res = NULL, *queue_obj = NULL, *arrobj = NULL;; + int i = 0; + + get_json_object(refparam, ctx, data, instance, value, &res); + dmjson_foreach_obj_in_array(res, arrobj, queue_obj, i, 1, "queues") { + *value = dmjson_get_value(queue_obj, 1, "tx_bytes"); + } + + if (value == NULL) { + *value = "0"; + } + return 0; } int os_get_QoSQueueStats_DroppedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = "0"; + json_object *res = NULL, *queue_obj = NULL, *arrobj = NULL;; + int i = 0; + + get_json_object(refparam, ctx, data, instance, value, &res); + dmjson_foreach_obj_in_array(res, arrobj, queue_obj, i, 1, "queues") { + *value = dmjson_get_value(queue_obj, 1, "tx_dropped_packets"); + } + + if (value == NULL) { + *value = "0"; + } + return 0; } int os_get_QoSQueueStats_DroppedBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = "0"; + json_object *res = NULL, *queue_obj = NULL, *arrobj = NULL;; + int i = 0; + + get_json_object(refparam, ctx, data, instance, value, &res); + dmjson_foreach_obj_in_array(res, arrobj, queue_obj, i, 1, "queues") { + *value = dmjson_get_value(queue_obj, 1, "tx_dropped_bytes"); + } + + if (value == NULL) { + *value = "0"; + } + return 0; } diff --git a/dmtree/tr181/qos.c b/dmtree/tr181/qos.c index 9cc39d2f..83565ca5 100644 --- a/dmtree/tr181/qos.c +++ b/dmtree/tr181/qos.c @@ -228,16 +228,16 @@ DMLEAF tQoSQueueParams[] = { /* *** Device.QoS.QueueStats.{i}. *** */ DMLEAF tQoSQueueStatsParams[] = { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -//{"Enable", &DMWRITE, DMT_BOOL, get_QoSQueueStats_Enable, set_QoSQueueStats_Enable, BBFDM_BOTH}, -//{"Status", &DMREAD, DMT_STRING, get_QoSQueueStats_Status, NULL, BBFDM_BOTH}, +{"Enable", &DMWRITE, DMT_BOOL, os_get_QoSQueueStats_Enable, os_set_QoSQueueStats_Enable, BBFDM_BOTH}, +{"Status", &DMREAD, DMT_STRING, os_get_QoSQueueStats_Status, NULL, BBFDM_BOTH}, {"Alias", &DMWRITE, DMT_STRING, os_get_QoSQueueStats_Alias, os_set_QoSQueueStats_Alias, BBFDM_BOTH}, -//{"Queue", &DMWRITE, DMT_STRING, get_QoSQueueStats_Queue, set_QoSQueueStats_Queue, BBFDM_BOTH}, +{"Queue", &DMWRITE, DMT_STRING, os_get_QoSQueueStats_Queue, os_set_QoSQueueStats_Queue, BBFDM_BOTH}, {"Interface", &DMWRITE, DMT_STRING, os_get_QoSQueueStats_Interface, os_set_QoSQueueStats_Interface, BBFDM_BOTH}, {"OutputPackets", &DMREAD, DMT_UNINT, os_get_QoSQueueStats_OutputPackets, NULL, BBFDM_BOTH}, {"OutputBytes", &DMREAD, DMT_UNINT, os_get_QoSQueueStats_OutputBytes, NULL, BBFDM_BOTH}, {"DroppedPackets", &DMREAD, DMT_UNINT, os_get_QoSQueueStats_DroppedPackets, NULL, BBFDM_BOTH}, {"DroppedBytes", &DMREAD, DMT_UNINT, os_get_QoSQueueStats_DroppedBytes, NULL, BBFDM_BOTH}, -{"QueueOccupancyPackets", &DMREAD, DMT_UNINT, os_get_QoSQueueStats_QueueOccupancyPackets, NULL, BBFDM_BOTH}, +//{"QueueOccupancyPackets", &DMREAD, DMT_UNINT, os_get_QoSQueueStats_QueueOccupancyPackets, NULL, BBFDM_BOTH}, //{"QueueOccupancyPercentage", &DMREAD, DMT_UNINT, get_QoSQueueStats_QueueOccupancyPercentage, NULL, BBFDM_BOTH}, {0} };