T#13540: Support Overwriting/Disabling/Extending core datamodel using JSON Plugins

This commit is contained in:
Amin Ben Romdhane 2024-02-06 06:20:59 +00:00 committed by Vivek Kumar Dutta
parent b1be97457c
commit 379f492041
7 changed files with 243 additions and 70 deletions

View file

@ -53,7 +53,8 @@ In the [test/vendor_test/](../../test/vendor_test) directory, you'll find an exa
- Add support for [Device.Firewall.Chain.{i}.Rule.{i}.X_TEST_COM_ICMPType](../../test/vendor_test/firewall.c#L178) parameter
- using JSON Plugin:
- Add support for [Device.PD2.{i}.](../../test/vendor_test/test_extend.json) object
- Add support for [Device.PD2.{i}.](../../test/vendor_test/test_extend.json#L59) object
- Add support for [Device.WiFi.X_IOPSYS_EU_TEST1](../../test/vendor_test/test_extend.json#L10) parameter
### 2. Overwrite Data Model
@ -62,7 +63,8 @@ In the [test/vendor_test/](../../test/vendor_test) directory, you'll find an exa
- Overwrite [Device.DeviceInfo.Manufacturer](../../test/vendor_test/deviceinfo.c#L29) parameter in the core tree
- using JSON Plugin:
- Overwrite [Device.DeviceInfo.Processor.](../../test/vendor_test/test_overwrite.json) object in the core tree
- Overwrite [Device.DeviceInfo.Processor.](../../test/vendor_test/test_overwrite.json#L10) object in the core tree
- Overwrite [Device.DeviceInfo.ProcessorNumberOfEntries](../../test/vendor_test/test_overwrite.json#L29) parameter in the core tree
### 3. Exclude Data Model
@ -71,11 +73,10 @@ In the [test/vendor_test/](../../test/vendor_test) directory, you'll find an exa
- Exclude [Device.Ethernet.RMONStats.{i}.Packets1024to1518Bytes](../../test/vendor_test/extension.c#L37) parameter from the core tree
- using JSON Plugin:
- Exclude [Device.X_IOPSYS_EU_IGMP.](../../test/vendor_test/test_exclude.json) object from the core tree
- Exclude [Device.X_IOPSYS_EU_IGMP.](../../test/vendor_test/test_exclude.json#L27) object from the core tree
- Exclude [Device.InterfaceStackNumberOfEntries](../../test/vendor_test/test_exclude.json#L51) parameter from the core tree
> Note1: The `libbbfdm` vendor list can support multiple vendors, separated by commas.
> Note2: If multi vendors are supported and there is an objects/parameters/operates/events implemented differently by different vendors, the implementation of the **last vendor name** in **BBF_VENDOR_LIST** will be considered.
> Note3: In the JSON plugin, there is no way to extend, overwrite and exclude parameters/operates/events that have an existing object in the core tree.

View file

@ -49,7 +49,7 @@ static bool add_service_to_main_tree(DMOBJ *main_dm, char *srv_name, char *srv_p
((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).obj = dm_dynamic_strdup(&global_memhead, srv_obj);
((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).checkdep = dm_dynamic_strdup(&global_memhead, srv_name);
} else {
int idx = get_entry_idx(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0]);
int idx = get_entry_obj_idx(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0]);
dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_realloc(&global_memhead, dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s));
memset(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s));
((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).obj = dm_dynamic_strdup(&global_memhead, srv_obj);
@ -335,12 +335,17 @@ void disable_entry_obj(DMOBJ *entryobj, char *obj_path, const char *parent_obj,
if (!entryobj || !plugin_path || DM_STRLEN(obj_path) == 0)
return;
char obj_name[256] = {0};
replace_str(obj_path, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, obj_name, sizeof(obj_name));
if (strlen(obj_name) == 0)
return;
DMOBJ *nextobj = entryobj->nextobj;
for (; (nextobj && nextobj->obj); nextobj++) {
if (DM_STRCMP(nextobj->obj, obj_path) == 0) {
BBF_INFO("## Excluding [%s%s.] from the core tree and the same object will be exposed again using (%s) ##", parent_obj, obj_path, plugin_path);
if (DM_STRCMP(nextobj->obj, obj_name) == 0) {
BBF_INFO("## Excluding [%s%s.] from the core tree and the same object will be exposed again using (%s) ##", parent_obj, obj_name, plugin_path);
nextobj->bbfdm_type = BBFDM_NONE;
return;
}
@ -354,8 +359,8 @@ void disable_entry_obj(DMOBJ *entryobj, char *obj_path, const char *parent_obj,
DMOBJ *jentryobj = next_dyn_array->nextobj[j];
for (; (jentryobj && jentryobj->obj); jentryobj++) {
if (DM_STRCMP(jentryobj->obj, obj_path) == 0) {
TRACE("## Excluding [%s%s.] from the core tree and the same object will be exposed again using (%s) ##", parent_obj, obj_path, plugin_path);
if (DM_STRCMP(jentryobj->obj, obj_name) == 0) {
BBF_INFO("## Excluding [%s%s.] from the core tree and the same object will be exposed again using (%s) ##", parent_obj, obj_name, plugin_path);
jentryobj->bbfdm_type = BBFDM_NONE;
return;
}
@ -371,12 +376,17 @@ void disable_entry_leaf(DMOBJ *entryobj, char *leaf_path, const char *parent_obj
if (!entryobj || !plugin_path || DM_STRLEN(leaf_path) == 0)
return;
char leaf_name[256] = {0};
replace_str(leaf_path, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, leaf_name, sizeof(leaf_name));
if (strlen(leaf_name) == 0)
return;
DMLEAF *leaf = entryobj->leaf;
for (; (leaf && leaf->parameter); leaf++) {
if (DM_STRCMP(leaf->parameter, leaf_path) == 0) {
BBF_INFO("## Excluding [%s%s] from the core tree and the same parameter will be exposed again using (%s) ##", parent_obj, leaf_path, plugin_path);
if (DM_STRCMP(leaf->parameter, leaf_name) == 0) {
BBF_INFO("## Excluding [%s%s] from the core tree and the same parameter will be exposed again using (%s) ##", parent_obj, leaf_name, plugin_path);
leaf->bbfdm_type = BBFDM_NONE;
return;
}
@ -390,8 +400,8 @@ void disable_entry_leaf(DMOBJ *entryobj, char *leaf_path, const char *parent_obj
DMLEAF *jleaf = next_dyn_array->nextleaf[j];
for (; (jleaf && jleaf->parameter); jleaf++) {
if (DM_STRCMP(jleaf->parameter, leaf_path) == 0) {
TRACE("## Excluding [%s%s] from the core tree and the same parameter will be exposed again using (%s) ##", parent_obj, leaf_path, plugin_path);
if (DM_STRCMP(jleaf->parameter, leaf_name) == 0) {
BBF_INFO("## Excluding [%s%s] from the core tree and the same parameter will be exposed again using (%s) ##", parent_obj, leaf_name, plugin_path);
jleaf->bbfdm_type = BBFDM_NONE;
return;
}
@ -402,7 +412,7 @@ void disable_entry_leaf(DMOBJ *entryobj, char *leaf_path, const char *parent_obj
}
}
int get_entry_idx(DMOBJ *entryobj)
int get_entry_obj_idx(DMOBJ *entryobj)
{
int idx = 0;
@ -412,6 +422,16 @@ int get_entry_idx(DMOBJ *entryobj)
return idx;
}
int get_entry_leaf_idx(DMLEAF *entryleaf)
{
int idx = 0;
for (; (entryleaf && entryleaf->parameter); entryleaf++)
idx++;
return idx;
}
int get_obj_idx(DMOBJ **entryobj)
{
int idx = 0;

View file

@ -16,7 +16,8 @@ DMOBJ *find_entry_obj(DMOBJ *entryobj, char *obj_path);
void disable_entry_obj(DMOBJ *entryobj, char *obj_path, const char *parent_obj, const char *plugin_path);
void disable_entry_leaf(DMOBJ *entryobj, char *leaf_path, const char *parent_obj, const char *plugin_path);
int get_entry_idx(DMOBJ *entryobj);
int get_entry_obj_idx(DMOBJ *entryobj);
int get_entry_leaf_idx(DMLEAF *entryleaf);
int get_obj_idx(DMOBJ **entryobj);
int get_leaf_idx(DMLEAF **entryleaf);

View file

@ -1863,6 +1863,54 @@ void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json
}
}
static void create_parse_obj(DMOBJ *dm_entryobj, char *obj_path, json_object *jobj, int json_plugin_version)
{
if (dm_entryobj->nextdynamicobj == NULL) {
dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj));
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT;
dm_entryobj->nextdynamicobj[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT;
dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT;
}
if (dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj == NULL) {
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj = calloc(2, sizeof(struct dm_obj_s *));
}
if (dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] == NULL) {
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] = dm_dynamic_calloc(&json_memhead, 2, sizeof(struct dm_obj_s));
parse_obj(obj_path, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], 0, json_plugin_version, &json_list);
} else {
int idx = get_entry_obj_idx(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0]);
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] = dm_dynamic_realloc(&json_memhead, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s));
memset(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s));
parse_obj(obj_path, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], idx, json_plugin_version, &json_list);
}
}
static void create_parse_param(DMOBJ *dm_entryobj, char *obj_path, char *param, json_object *jobj, int json_plugin_version)
{
if (dm_entryobj->dynamicleaf == NULL) {
dm_entryobj->dynamicleaf = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj));
dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT;
dm_entryobj->dynamicleaf[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT;
dm_entryobj->dynamicleaf[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT;
}
if (dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf == NULL) {
dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf = calloc(2, sizeof(struct dm_leaf_s *));
}
if (dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0] == NULL) {
dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0] = dm_dynamic_calloc(&json_memhead, 2, sizeof(struct dm_leaf_s));
parse_param(obj_path, param, jobj, dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0], 0, json_plugin_version, &json_list);
} else {
int idx = get_entry_leaf_idx(dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0]);
dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0] = dm_dynamic_realloc(&json_memhead, dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0], (idx + 2) * sizeof(struct dm_leaf_s));
memset(dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0] + (idx + 1), 0, sizeof(struct dm_leaf_s));
parse_param(obj_path, param, jobj, dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf[0], idx, json_plugin_version, &json_list);
}
}
int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
{
int json_plugin_version = JSON_VERSION_0;
@ -1892,47 +1940,40 @@ int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
continue;
}
char obj_prefix[MAX_DM_LENGTH] = {0};
json_plugin_find_prefix_obj(obj_path, obj_prefix, MAX_DM_LENGTH);
if (strlen(obj_prefix) == 0) {
BBF_DEBUG("ERROR: Obj prefix is empty for (%s) Object", obj_path);
continue;
}
DMOBJ *dm_entryobj = find_entry_obj(entryobj, obj_path);
if (dm_entryobj) { // The object is already in the core tree, should check the next level
char curr_obj[128] = {0};
json_plugin_find_current_obj(obj_path, curr_obj, sizeof(curr_obj));
if (strlen(curr_obj) == 0) {
BBF_DEBUG("ERROR: Can't get the current object from (%s) parent object", obj_path);
continue;
}
json_object_object_foreach(jobj, opt, json_obj) {
DMOBJ *dm_entryobj = find_entry_obj(entryobj, obj_prefix);
if (!dm_entryobj) {
BBF_DEBUG("ERROR: entry obj doesn't exist for (%s) Object", obj_prefix);
continue;
}
if (json_object_get_type(json_obj) == json_type_object && is_obj(opt, json_obj)) {
char curr_obj[128] = {0};
disable_entry_obj(dm_entryobj, curr_obj, obj_prefix, plugin_path);
json_plugin_find_current_obj(opt, curr_obj, sizeof(curr_obj));
if (dm_entryobj->nextdynamicobj == NULL) {
dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj));
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT;
dm_entryobj->nextdynamicobj[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT;
dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT;
}
disable_entry_obj(dm_entryobj, curr_obj, obj_path, plugin_path);
create_parse_obj(dm_entryobj, opt, json_obj, json_plugin_version);
}
if (dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj == NULL) {
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj = calloc(2, sizeof(struct dm_obj_s *));
}
if (json_object_get_type(json_obj) == json_type_object && !is_obj(opt, json_obj) && strcmp(opt, "mapping") != 0) {
disable_entry_leaf(dm_entryobj, opt, obj_path, plugin_path);
create_parse_param(dm_entryobj, obj_path, opt, json_obj, json_plugin_version);
}
}
} else { // It's a new object
char obj_prefix[MAX_DM_LENGTH] = {0};
json_plugin_find_prefix_obj(obj_path, obj_prefix, MAX_DM_LENGTH);
if (strlen(obj_prefix) == 0) {
BBF_DEBUG("ERROR: Obj prefix is empty for (%s) Object", obj_path);
continue;
}
if (dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] == NULL) {
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] = dm_dynamic_calloc(&json_memhead, 2, sizeof(struct dm_obj_s));
parse_obj(obj_path, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], 0, json_plugin_version, &json_list);
} else {
int idx = get_entry_idx(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0]);
dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] = dm_dynamic_realloc(&json_memhead, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s));
memset(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s));
parse_obj(obj_path, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], idx, json_plugin_version, &json_list);
dm_entryobj = find_entry_obj(entryobj, obj_prefix);
if (!dm_entryobj) {
BBF_DEBUG("ERROR: entry obj doesn't exist for (%s) Object", obj_prefix);
continue;
}
create_parse_obj(dm_entryobj, obj_path, jobj, json_plugin_version);
}
}

View file

@ -1,26 +1,60 @@
{
"Device.DeviceInfo.ProcessStatus.": {
"Device.DeviceInfo.": {
"type": "object",
"protocols": [
"none"
"cwmp",
"usp"
],
"access": false,
"array": false
"array": false,
"Device.DeviceInfo.ProcessStatus.": {
"type": "object",
"protocols": [
"none"
],
"access": false,
"array": false
}
},
"Device.X_IOPSYS_EU_IGMP.": {
"Device.": {
"type": "object",
"protocols": [
"none"
"cwmp",
"usp"
],
"access": false,
"array": false
},
"Device.X_IOPSYS_EU_MLD.": {
"type": "object",
"protocols": [
"none"
],
"access": false,
"array": false
}
"array": false,
"Device.{BBF_VENDOR_PREFIX}IGMP.": {
"type": "object",
"protocols": [
"none"
],
"access": false,
"array": false
},
"Device.{BBF_VENDOR_PREFIX}MLD.": {
"type": "object",
"protocols": [
"none"
],
"access": false,
"array": false
},
"Device.InterfaceStack.": {
"type": "object",
"protocols": [
"none"
],
"access": false,
"array": false
},
"InterfaceStackNumberOfEntries": {
"type": "unsignedInt",
"protocols": [
"none"
],
"read": true,
"write": false
}
}
}

View file

@ -1,4 +1,61 @@
{
"Device.WiFi.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"access": false,
"array": false,
"{BBF_VENDOR_PREFIX}TEST1": {
"type": "boolean",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"datatype": "boolean",
"mapping": [
{
"type": "uci",
"uci": {
"file": "wireless",
"section": {
"name": "config"
},
"option": {
"name": "test1_enable"
}
}
}
]
},
"{BBF_VENDOR_PREFIX}TEST2": {
"type": "boolean",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"datatype": "boolean",
"mapping": [
{
"type": "uci",
"uci": {
"file": "wireless",
"section": {
"name": "config"
},
"option": {
"name": "test1_enable"
}
}
}
]
}
},
"Device.PD2.{i}.": {
"type": "object",
"version": "2.14",

View file

@ -1,5 +1,5 @@
{
"Device.DeviceInfo.Processor.": {
"Device.DeviceInfo.": {
"type": "object",
"protocols": [
"cwmp",
@ -7,15 +7,34 @@
],
"access": false,
"array": false,
"Architecture": {
"type": "string",
"Device.DeviceInfo.Processor.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"access": false,
"array": false,
"Architecture": {
"type": "string",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"default": "x86_64"
}
},
"ProcessorNumberOfEntries": {
"type": "unsignedInt",
"read": true,
"write": false,
"default": "x86_64"
"protocols": [
"cwmp",
"usp"
],
"default": "1"
}
}
}