From 63d449df132f2682fe0c824b17eab78424424611 Mon Sep 17 00:00:00 2001 From: Amin Ben Ramdhane Date: Thu, 9 Apr 2020 16:48:34 +0100 Subject: [PATCH] Added support for ubus array in dynamic addition parameters using JSON file + example of JSON file --- README.md | 29 +- dmentryjson.c | 92 ++++-- dynamic_parameters/json/example.json | 298 ++++++++++++++++++ .../library}/example.json | 0 .../library}/example/example.c | 0 .../library}/example/example.h | 0 .../library}/generate_library.py | 0 library/example/Makefile | 23 -- 8 files changed, 394 insertions(+), 48 deletions(-) create mode 100644 dynamic_parameters/json/example.json rename {library => dynamic_parameters/library}/example.json (100%) rename {library => dynamic_parameters/library}/example/example.c (100%) rename {library => dynamic_parameters/library}/example/example.h (100%) rename {library => dynamic_parameters/library}/generate_library.py (100%) delete mode 100644 library/example/Makefile diff --git a/README.md b/README.md index 77864752..20312aed 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,8 @@ The bbfdm library allows all applications installed on the box to import its own The application should bring its JSON file under **'/etc/bbfdm/json/'** path with **UCI** and **UBUS** mappings. The new added parameters will be automatically shown by icwmp and uspd/obuspa. +To build a new JSON file, you can use **example.json file** under **dynamic_parameters/json** folder to help you build it. + **1. Object without instance:** ```plain "Device.CWMP.": { @@ -273,9 +275,32 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit } ``` +- **UBUS command:** ubus call dsl status | jsonfilter -e @.line +```plain +"Device.DSL.Line.{i}.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": true, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl", + "method": "status", + "args": {}, + "key": "line" + } + } +} +``` + **3. Parameter under object with instance:** -- **UCI command:** uci get wireless.@wifi-device[0].country
+- **UCI command:** uci get wireless.@wifi-device[0].country + - **@i:** is the number of instance object + ```plain "Country": { "type": "string", @@ -420,7 +445,7 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit The application should bring its plugin(library) file under **'/usr/lib/bbfdm/'** path that contains the sub tree of **Objects/Parameters** and the related functions **Get/Set/Add/Delete/Operate**. The new added objects, parameters and operates will be automatically shown by icwmp and uspd/obuspa. -To build a new library, you can use **example source code** under **library** folder to help you build it. +To build a new library, you can use **example source code** under **dynamic_parameters/library** folder to help you build it. Each library should contains two Root table named **“tRootDynamicObj”** and **“tRootDynamicOperate”** to define the parant path for each new object and operate. diff --git a/dmentryjson.c b/dmentryjson.c index 4bf756d1..33de285a 100644 --- a/dmentryjson.c +++ b/dmentryjson.c @@ -256,39 +256,39 @@ static int check_json_root_obj(struct dmctx *ctx, char *in_param_json, DMOBJ **r int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) { - //UCI: arg1=type :: arg2=uci_file :: arg3=uci_section_type :: arg4=uci_dmmap_file :: arg5="" :: arg6="" - - char *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL, *prefix_obj = NULL, *object = NULL; - char buf_instance[64] = "", buf_alias[64] = ""; struct dm_json_parameter *pleaf; + char *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL, *arg5 = NULL, *arg6 = NULL; char *obj = generate_obj_without_instance(parent_node->current_object, true); - generate_prefixobj_and_obj_full_obj(parent_node->current_object, &prefix_obj, &object); - - snprintf(buf_instance, sizeof(buf_instance), "%s_instance", object); - snprintf(buf_alias, sizeof(buf_alias), "%s_alias", object); - for (int i = 0; buf_instance[i]; i++) { - buf_instance[i] = tolower(buf_instance[i]); - } - for (int i = 0; buf_alias[i]; i++) { - buf_alias[i] = tolower(buf_alias[i]); - } - list_for_each_entry(pleaf, &json_list, list) { if (strcmp(pleaf->name, obj) == 0) { arg1 = pleaf->arg1; arg2 = pleaf->arg2; arg3 = pleaf->arg3; arg4 = pleaf->arg4; + arg5 = pleaf->arg5; + arg6 = pleaf->arg6; break; } } if (arg1 && strcmp(arg1, "uci") == 0) { + //UCI: arg1=type :: arg2=uci_file :: arg3=uci_section_type :: arg4=uci_dmmap_file :: arg5="" :: arg6="" + + char buf_instance[64] = "", buf_alias[64] = "", *prefix_obj = NULL, *object = NULL; char *instance = NULL, *instnbr = NULL; struct dmmap_dup *p; LIST_HEAD(dup_list); + generate_prefixobj_and_obj_full_obj(parent_node->current_object, &prefix_obj, &object); + snprintf(buf_instance, sizeof(buf_instance), "%s_instance", object); + snprintf(buf_alias, sizeof(buf_alias), "%s_alias", object); + for (int i = 0; buf_instance[i]; i++) + buf_instance[i] = tolower(buf_instance[i]); + + for (int i = 0; buf_alias[i]; i++) + buf_alias[i] = tolower(buf_alias[i]); + if(arg2 && arg3 && arg4) { synchronize_specific_config_sections_with_dmmap(arg2, arg3, arg4, &dup_list); list_for_each_entry(p, &dup_list, list) { @@ -299,6 +299,25 @@ int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char * } free_dmmap_config_dup_list(&dup_list); } + else if (arg1 && strcmp(arg1, "ubus") == 0) { + //UBUS: arg1=type :: arg2=ubus_object :: arg3=ubus_method :: arg4=ubus_args1 :: arg5=ubus_args2 :: arg6=ubus_key + + json_object *res = NULL, *dyn_obj = NULL, *arrobj = NULL; + char *idx, *idx_last = NULL; + int id = 0, j = 0; + + if (arg2 && arg3 && arg4 && arg5) + dmubus_call(arg2, arg3, UBUS_ARGS{{arg4, arg5, String}}, 1, &res); + else + dmubus_call(arg2, arg3, UBUS_ARGS{{}}, 0, &res); + if (res && arg6) { + dmjson_foreach_obj_in_array(res, arrobj, dyn_obj, j, 1, arg6) { + idx = handle_update_instance(1, dmctx, &idx_last, update_instance_without_section, 1, ++id); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)dyn_obj, idx) == DM_STOP) + break; + } + } + } return 0; } @@ -431,20 +450,30 @@ static int getvalue_param(char *refparam, struct dmctx *ctx, void *data, char *i //UBUS: arg1=type :: arg2=ubus_object :: arg3=ubus_method :: arg4=ubus_args1 :: arg5=ubus_args2 :: arg6=ubus_key json_object *res = NULL; - if (arg2 && arg3 && arg4 && arg5) { - if (data && (strcmp(arg5, "@Name") == 0)) - dmubus_call(arg2, arg3, UBUS_ARGS{{arg4, section_name((struct uci_section *)data), String}}, 1, &res); - else - dmubus_call(arg2, arg3, UBUS_ARGS{{arg4, arg5, String}}, 1, &res); + char arg2_1[128] = {0}, *opt = NULL; + if ((opt = strstr(arg2, "@Name"))) { + *opt = '\0'; + snprintf(arg2_1, sizeof(arg2_1), "%s%s", arg2, section_name((struct uci_section *)data)); + } else if ((opt = strstr(arg2, "@i-1"))) { + *opt = '\0'; + snprintf(arg2_1, sizeof(arg2_1), "%s%d", arg2, atoi(instance) - 1); + } else { + strncpy(arg2_1, arg2, sizeof(arg2_1) - 1); + } - } else if (arg2 && arg3) { - dmubus_call(arg2, arg3, UBUS_ARGS{{}}, 0, &res); + if (arg4 && arg5) { + if (data && (strcmp(arg5, "@Name") == 0)) + dmubus_call(arg2_1, arg3, UBUS_ARGS{{arg4, section_name((struct uci_section *)data), String}}, 1, &res); + else + dmubus_call(arg2_1, arg3, UBUS_ARGS{{arg4, arg5, String}}, 1, &res); + } else { + dmubus_call(arg2_1, arg3, UBUS_ARGS{{}}, 0, &res); } DM_ASSERT(res, *value = ""); if (arg6) { - char arg6_1[32] = ""; + char arg6_1[128] = ""; strcpy(arg6_1, arg6); char *opt = strchr(arg6_1, '.'); if (opt) { @@ -529,6 +558,23 @@ static void parse_mapping_obj(char *object, json_object *mapping, struct list_he //Add to list add_json_data_to_list(list, object, "uci", json_object_get_string(file), json_object_get_string(section_type), json_object_get_string(dmmap_file), "", ""); } + else if (strcmp(json_object_get_string(type), "ubus") == 0) { + //UBUS: arg1=type :: arg2=ubus_object :: arg3=ubus_method :: arg4=ubus_args1 :: arg5=ubus_args2 :: arg6=ubus_key + + struct json_object *obj1, *method, *key, *args; + char *args1 = NULL; + json_object_object_get_ex(mapping, "ubus", &obj); + json_object_object_get_ex(obj, "object", &obj1); + json_object_object_get_ex(obj, "method", &method); + json_object_object_get_ex(obj, "args", &args); + json_object_object_foreach(args, arg1, args2) { + args1 = arg1; + } + json_object_object_get_ex(obj, "key", &key); + + //Add to list + add_json_data_to_list(list, object, "ubus", json_object_get_string(obj1), json_object_get_string(method), args1, json_object_get_string(args2), json_object_get_string(key)); + } else { //Add to list add_json_data_to_list(list, object, "", "", "", "", "", ""); diff --git a/dynamic_parameters/json/example.json b/dynamic_parameters/json/example.json new file mode 100644 index 00000000..df68a0aa --- /dev/null +++ b/dynamic_parameters/json/example.json @@ -0,0 +1,298 @@ +{ + "Device.DSL.Line.{i}.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": true, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl", + "method": "status", + "args": {}, + "key": "line" + } + }, + "FirmwareVersion": { + "type": "string­", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "status", + "args": {}, + "key": "firmware_version" + } + } + }, + "UpstreamMaxBitRate": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "status", + "args": {}, + "key": "max_bit_rate.us" + } + } + }, + "Device.DSL.Line.{i}.Stats.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": false, + "TotalStart": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "total_start" + } + } + }, + "ShowtimeStart": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "showtime_start" + } + } + }, + "QuarterHourStart": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "quarter_hour_start" + } + } + }, + "Device.DSL.Line.{i}.Stats.Total.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": false, + "ErroredSecs": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "total.errored_secs" + } + } + }, + "SeverelyErroredSecs": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "total.severely_errored_secs" + } + } + } + }, + "Device.DSL.Line.{i}.Stats.LastShowtime.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": false, + "ErroredSecs": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "lastshowtime.errored_secs" + } + } + }, + "SeverelyErroredSecs": { + "type": "unsignedInt", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": false, + "mapping": { + "type": "ubus", + "ubus": { + "object": "dsl.line.@i-1", + "method": "stats", + "args": {}, + "key": "lastshowtime.severely_errored_secs" + } + } + } + } + } + }, + "Device.X_IOPSYS_EU_WiFiLife.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": false, + "Enable": { + "type": "boolean", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": true, + "mapping": { + "type": "uci", + "uci": { + "file": "wifilife", + "section": { + "type": "wifilife", + "name": "@wifilife[0]" + }, + "option": { + "name": "enabled" + } + } + } + }, + "Device.X_IOPSYS_EU_WiFiLife.Steering.{i}.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "array": true, + "mapping": { + "type": "uci", + "uci": { + "file": "wifilife", + "section": { + "type": "steer" + }, + "dmmapfile": "dmmap_wifilife" + } + }, + "Enable": { + "type": "boolean", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": true, + "mapping": { + "type": "uci", + "uci": { + "file": "wifilife", + "section": { + "type": "steer", + "index": "@i-1" + }, + "option": { + "name": "enabled" + } + } + } + }, + "LegacyFallback": { + "type": "boolean", + "protocols": [ + "cwmp", + "usp" + ], + "read": true, + "write": true, + "mapping": { + "type": "uci", + "uci": { + "file": "wifilife", + "section": { + "type": "steer", + "index": "@i-1" + }, + "option": { + "name": "fallback_legacy" + } + } + } + } + } + } +} + diff --git a/library/example.json b/dynamic_parameters/library/example.json similarity index 100% rename from library/example.json rename to dynamic_parameters/library/example.json diff --git a/library/example/example.c b/dynamic_parameters/library/example/example.c similarity index 100% rename from library/example/example.c rename to dynamic_parameters/library/example/example.c diff --git a/library/example/example.h b/dynamic_parameters/library/example/example.h similarity index 100% rename from library/example/example.h rename to dynamic_parameters/library/example/example.h diff --git a/library/generate_library.py b/dynamic_parameters/library/generate_library.py similarity index 100% rename from library/generate_library.py rename to dynamic_parameters/library/generate_library.py diff --git a/library/example/Makefile b/library/example/Makefile deleted file mode 100644 index e61c1eec..00000000 --- a/library/example/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -LIB_EXAMPLE := lib/libexample.so - -OBJS := example.o - -PROG_CFLAGS = $(CFLAGS) -fstrict-aliasing -PROG_LDFLAGS = $(LDFLAGS) -lbbfdm -FPIC := -fPIC - -.PHONY: all - -%.o: %.c - $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< - -all: $(LIB_EXAMPLE) - -$(LIB_EXAMPLE): $(OBJS) - $(shell mkdir -p lib) - $(CC) -shared -Wl,-soname,libexample.so $^ -o $@ - -clean: - rm -f *.o - rm -f $(LIB_EXAMPLE) -