bbfdm/docs/guide/linker_design.md
2023-10-23 10:52:54 +02:00

7 KiB

Datamodel Linker

Aim of this document is to explain how to migrate the linker functionality to the new linker design.

As per the definition in TR-181, each multi-instance object should have at least one unique key to identify each instance that's why in the current implementation we have defined two arguments in DMOBJ structure to support that:

  • get_linker function pointer to specify the linker value
  • unique_keys array to list the unique key parameters
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"Interface", &DMWRITE, addObjIPInterface, delObjIPInterface, NULL, browseIPInterfaceInst, NULL, NULL, tIPInterfaceObj, tIPInterfaceParams, get_linker_ip_interface, BBFDM_BOTH, LIST_KEY{"Alias", "Name", NULL}},

However, this implementation caused us many issues, such as:

  • The unique key list can include parameters that are not yet supported.
  • A parameter can map to another multi-instance object that doesn't have a linker function.

To improve this requirement, we introduce a new argument dm_flags in DMLEAF structure which can play the role of defining all required information above.

The new dm_flags argument can only support for now 3 enumerations:

  • DM_FLAG_REFERENCE: parameter value should be an object reference available in the tree
  • DM_FLAG_UNIQUE: parameter value should be used to identify each instance
  • DM_FLAG_LINKER: parameter value can be used to identify each instance when calling a set method since each multi-instance object can have many unique keys

Note:

  • DM_FLAG_LINKER must be defined only once for each multi-instance object.
  • Each object can have multiple unique keys.
  • Regarding JSON plugin, we also introduce a new array option to support the same functionality. "flags": [ "Reference", "Unique", "Linker" ].

Now with the new design datamodel gives more flexibility to define any parameter as a unique key, linker and reference at the same time, and all linker functions was removed and all related APIs are deprecated.

Below the list of APIs that have been deprecated:

  • dm_entry_validate_allowed_objects
  • adm_entry_get_linker_param
  • adm_entry_get_linker_value

Below the list of new APIs that we introduced:

  • dm_validate_allowed_objects
  • adm_entry_get_reference_param
  • bbf_get_reference_param
  • bbf_get_reference_args

Actually bbfdm supports two methods to expose datamodel tree:

  • datamodel exposed via bbfdm, which includes the main tree defined in bbfdm package and datamodel registred via JSON or DotSo plugins.
  • datamodel exposed through micro-services.

In the next item, we will explain how to migrate to the new linker design based on the datamodel registration.

Migrate to the new linker design

  1. Update dm_falgs argument of DMLEAF structure
  • Parameter exposed via main tree, DotSo plugin or micro-service: add DM_FLAG_REFERENCE to all parameters that have a path reference as a value.
DMLEAF tIPInterfaceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
...
"LowerLayers", &DMWRITE, DMT_STRING, get_IPInterface_LowerLayers, set_IPInterface_LowerLayers, BBFDM_BOTH, DM_FLAG_REFERENCE},
...
}
  • Parameter exposed via JSON plugin: add Reference value to the flags option for all parameters that have a path reference as a value
"Profile": {
	"type": "string",
	"read": true,
	...
	"flags": [
		"Reference"
	],
	...
}
  1. Update Get method based on the new API

Before updating the get method, it is important to know which unique key parameter is used to identify the path reference then update the get method accordingly.

  • Parameter exposed via main tree or DotSo plugin: use adm_entry_get_reference_param API to get the path reference
static int get_MQTTBroker_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *iface = NULL;

	dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "interface", &iface);
	adm_entry_get_reference_param(ctx, "Device.IP.Interface.*.Name", iface, value);
	return 0;
}
  • Parameter exposed via micro-service: use bbf_get_reference_param API to get the path reference
static int get_client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *iface = NULL;

	dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "interface", &iface);

	return bbf_get_reference_param("Device.IP.Interface.", "Name", iface, value);

}
  • Parameter exposed via JSON plugin: update the linker_obj option with the full parameter path to obtain the path reference
"Profile": {
	"type": "string",
	"read": true,
	"write": true,
	"protocols": [
		"cwmp",
		"usp"
	],
	"flags": [
		"Reference"
	],
	"mapping": [
		{
			"type": "uci",
			"uci": {
				"file": "urlfilter",
				"section": {
					"type": "filter"
				},
				"option": {
					"name": "profile"
				}
			},
			"linker_obj": "Device.{BBF_VENDOR_PREFIX}URLFilter.Profile.*.Name"
		}
	]
}

Note:

  • All instances should be replaced with the instance wildcard '*'.
  1. Update Set method based on the new API
  • Parameter exposed via main tree, DotSo plugin or micro-service: first, add DM_FLAG_LINKER to mark that the parameter is being used as a linker for that object.
DMLEAF tIPInterfaceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
...
{"Name", &DMREAD, DMT_STRING, get_IPInterface_Name, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER},
...
}

Then, use bbf_get_reference_args to get the reference path and value in the set method.

static int set_client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbf_get_reference_args(value, &reference);

	switch (action)	{
		case VALUECHECK:
			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			break;
		case VALUESET:
			dmuci_set_value_by_section(((struct dmmap_dup *)data)->config_section, "interface", reference.value);
			break;
	}
	return 0;
}
  • Parameter exposed via JSON plugin: add Linker value to the flags array to mark that the parameter is being used as a linker for that object.
"Name": {
	"type": "string",
	"read": true,
	"write": true,
	"protocols": [
		"cwmp",
		"usp"
	],
	"flags": [
		"Unique",
		"Linker"
	],
	...
}

The following links provide more examples of how the linker was implemented.