docs: cleanup and update

This commit is contained in:
Vivek Kumar Dutta 2024-07-08 11:55:18 +05:30
parent 6730d2784b
commit 7cdea20a2d
32 changed files with 4406 additions and 4746 deletions

5
.gitignore vendored
View file

@ -1,12 +1,7 @@
CMakeFiles
CMakeCache.txt
Makefile
install_manifest.txt install_manifest.txt
*.cmake
*.o *.o
*.so *.so
bbfdmd/ubus/bbfdmd bbfdmd/ubus/bbfdmd
docs/index.md
__pycache__ __pycache__
out out
/datamodel /datamodel

158
README.md
View file

@ -1,14 +1,14 @@
# BroadBand Forum Data Models (BBFDM) # BroadBand Forum Data Models (BBFDM)
`bbfdm` is a datamodel backend for Higher layer management protocols like [TR-069/CWMP](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/). It is designed in a hardware agnostic way and provides the available datamodel parameters over ubus on the northbound interface and creates the datamodel mapping based on uci and ubus on southbound interface. `bbfdm` is a suite to provide TR181 datamodel backend for Higher layer management protocols like [TR-069/CWMP](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/). It is designed in a hardware agnostic way and provides the available datamodel parameters over ubus on the northbound interface and creates the datamodel mapping based on uci and ubus on southbound interface.
`bbfdm` has three main components: `bbfdm` has three main components:
| Component | Description | | Component | Description |
| ---------- | ------------------------------------------------- | | ------------ | ------------------------------------------------- |
| bbfdmd | A daemon to expose data model objects over ubus in pretty and raw format | | bbfdmd | A daemon to expose data model objects over ubus |
| libbbfdm-api | A shared library which provides API to build and parse datamodel tree, it also provides API to create datamodel extensions using shared DotSo plugin, or with JSON Plugin. | | libbbfdm-api | API library to create and parse datamodel tree |
| libbbfdm | A datamodel tree/library build with libbbfdm-api, it includes core TR181 and related datamodel | | libbbfdm | Minimal TR181 datamodel definition |
## Directory Structure ## Directory Structure
@ -16,101 +16,67 @@
`bbfdm` package is structured as follow: `bbfdm` package is structured as follow:
```bash ```bash
├── bbfdmd ├── bbfdmd -- This directory contains daemon code to expose the datamodel tree on northbound
├── docs │   └── ubus - Daemon to expose datamodel over ubus
├── libbbfdm-api ├── docs -- More detailed explanation of datamodel and user guide
├── libbbfdm ├── gitlab-ci -- Used for CI/CD pipeline test
│   ├── dmtree ├── libbbfdm -- Minimal TR181 datamodel implementation
│   │   ├── json ├── libbbfdm-api -- API library to create datamodel definition and parse the datamodel definition to form a datamodel tree
│   │   ├── tr181 ├── tools -- Tools to convert xml datamodel definition to json, generate c code and many more
│   │   ├── vendor └── utilities -- Small helper utilities to complete/optimize the datamodel deployment
│   ├── scripts
└── tools
``` ```
- `bbfdmd` folder which contains the source code of bbfdm deamon.
More explanation on how this daemon works and all supported methods are presented in this file [BBFDMD](./docs/guide/bbfdmd.md)
- `libbbfdm` folder which contains the different data models supported by iopsys
- `dmtree` folder which includes all supported Data Models and vendor extension objects. It contains 6 folders:
- `tr181` folder : TR-181 Data Model files
- `vendor` folder : Vendor Data Model files
- `json` folder : Data Model JSON file
- `scripts` folder which contains bbf APIs used to run the different diagnostics scripts.
- `libbbfdm-api` folder which contains the source code of all API functions (UCI, Ubus, JSON, CLI and memory management). These API are used for GET/SET/ADD/Delete/Operate calls which can be called in internal or external packages.
All APIs exposed by libbbfdm-api are presented in this header file [libbbfdm_api.h](./libbbfdm-api/include/libbbfdm_api.h).
- `tools` folder which contains some tools to generate Data Model in C, JSON, XML and Excel format.
All supported tools are presented in this file[BBFDM Tools](./tools/README.md)
- `docs` folder which contains all documentation files.
## Design
* [BBFDMD Design](./docs/guide/bbfdmd.md)
* [Datamodel extension using JSON plugin](./docs/guide/libbbfdm-api_json_plugin_v1.md)
* [Datamodel Plugins and Microservice](./docs/guide/libbbfdm-api_datamodel_as_microservice.md)
* [BBFDM Tools](./tools/README.md)
## Important Topics ## Important Topics
* [Add support of a new Object/Parameter](./docs/guide/libbbfdm-api_obj_param_extension.md)
* [How to add new vendor](./docs/guide/libbbfdm-api_vendor.md) * [BBFDMD Design](./docs/guide/bbfdmd.md)
* [Dynamic Object/Parameter/Operate/Event](./docs/guide/libbbfdm-api_dynamic_dm.md) * [API Documentation](./docs/guide/libbbfdm-api.md)
* [Tools](./tools/README.md)
* [Utilities](./utilities/README.md)
* [How to extend datamodel with C Code](./docs/guide/How_to_extend_datamodel_with_C_Code.md)
* [How to extend datamodel with JSON](./docs/guide/How_to_extend_datamodel_with_JSON.md)
### Datamodel related topics
* [Design for firmware activation](./docs/guide/libbbfdm_DeviceInfo_FirmwareImage.md) * [Design for firmware activation](./docs/guide/libbbfdm_DeviceInfo_FirmwareImage.md)
* [Explain the different Network Deployment Scenarios](./docs/guide/network_depoyment_scenarios.md) * [Different Network Deployment Scenarios using Datamodels](./docs/guide/network_depoyment_scenarios.md)
* [Explain Policy Based Routing Management](./docs/guide/libbbfdm_Routing.md) * [GRE datamodel details ](./docs/guide/libbbfdm_GRE.md)
* [IP datamodel details](./docs/guide/libbbfdm_IP_Interface.md)
### Compilation helper utilities
* [Readme](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/bbfdm/README.md)
* [Compilation Helper utility](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/bbfdm/bbfdm.mk)
* [JSON Plugin Validator](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/bbfdm/tools/validate_plugins.py)
## Additional datamodel objects ## Additional datamodel objects
| Datamodel | Package | Link | This repository has bare minimal TR181 datamodel integrated, each service has their own datamodel additions, which they expose using plugins and micro-services.
| ---------------------------------------- | -------------- | -------------------------------------------- | List of IOWRT provided service datamodel set available in [tools_input.json](./tools/tools_input.json)
| Device.BulkData. | bulkdata | https://dev.iopsys.eu/bbf/bulkdata.git |
| Device.ManagementServer. | icwmp | https://dev.iopsys.eu/bbf/icwmp.git | ## Dependencies
| Device.CWMPManagementServer. | icwmp | https://dev.iopsys.eu/bbf/icwmp.git |
| Device.IP.Diagnostics.UDPEchoConfig. | udpecho-server | https://dev.iopsys.eu/bbf/udpecho.git | ### Build-Time Dependencies
| Device.IP.Diagnostics.UDPEchoDiagnostics.| udpecho-client | https://dev.iopsys.eu/bbf/udpecho.git |
| Device.IP.Interface.{i}.TWAMPReflector. | twamp | https://dev.iopsys.eu/bbf/twamp-light.git | To successfully build bbfdmd, following libraries are needed:
| Device.XMPP. | xmppc | https://dev.iopsys.eu/bbf/xmppc.git |
| Device.USPAgent. | obuspa | https://dev.iopsys.eu/bbf/obuspa.git | | Dependency | Link | License |
| STUN parameters | stunc | https://dev.iopsys.eu/bbf/stunc.git | | ------------ | ------------------------------------------- | -------- |
| Device.XPON. | ponmngr | https://dev.iopsys.eu/hal/ponmngr.git | | libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 |
| Device.UPNP. | ssdpd | https://github.com/miniupnp/miniupnp.git | | libubox | https://git.openwrt.org/project/libubox.git | BSD |
| Device.Users. | usermngr | https://dev.iopsys.eu/bbf/usermngr.git | | libubus | https://git.openwrt.org/project/ubus.git | LGPL 2.1 |
| Device.PeriodicStatistics. | periodicstats | https://dev.iopsys.eu/bbf/periodicstats.git | | libjson-c | https://s3.amazonaws.com/json-c_releases | MIT |
| Device.SoftwareModules. | swmodd | https://dev.iopsys.eu/lcm/swmodd.git | | libbbfdm-api | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
| Device.Time. | timemngr | https://dev.iopsys.eu/bbf/timemngr.git | | libbbfdm | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
| Device.DynamicDNS. | ddnsmngr | https://dev.iopsys.eu/bbf/ddnsmngr.git | | jq | https://github.com/stedolan/jq.git | BSD |
| Device.Hosts. | hostmngr | https://dev.iopsys.eu/iopsys/hostmngr.git |
| Device.Services.VoiceService. | tr104 | https://dev.iopsys.eu/voice/tr104.git |
| Device.Firewall. | firewallmngr | https://dev.iopsys.eu/network/firewallmngr | ### Run-Time Dependencies
| Device.NAT. | firewallmngr | https://dev.iopsys.eu/network/firewallmngr |
| Device.NAT.PortTrigger. | port-trigger | https://dev.iopsys.eu/network/port-trigger.git | In order to run the `bbfdmd`, following dependencies are needed to be running/available before `bbfdmd`.
| Device.DNS. | dnsmngr | https://dev.iopsys.eu/network/dnsmngr.git |
| Device.DHCPv4. | dhcpmngr | https://dev.iopsys.eu/network/dhcpmngr.git | | Dependency | Link | License |
| Device.DHCPv6. | dhcpmngr | https://dev.iopsys.eu/network/dhcpmngr.git | | ------------ | ---------------------------------------- | -------- |
| Device.DSL. | dslmngr | https://dev.iopsys.eu/hal/dslmngr.git | | ubusd | https://git.openwrt.org/project/ubus.git | LGPL 2.1 |
| Device.FAST. | dslmngr | https://dev.iopsys.eu/hal/dslmngr.git | | libbbfdm-api | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
| Device.ATM. | dslmngr | https://dev.iopsys.eu/hal/dslmngr.git | | libbbfdm | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
| Device.PTM. | dslmngr | https://dev.iopsys.eu/hal/dslmngr.git | | jq | https://github.com/stedolan/jq.git | BSD |
| Device.Ethernet. | ethmngr | https://dev.iopsys.eu/hal/ethmngr.git |
| Device.QoS. | qosmngr | https://dev.iopsys.eu/hal/qosmngr.git |
| Device.SSH. | sshmngr | https://dev.iopsys.eu/network/sshmngr.git |
| Device.WiFi. | wifidmd | https://dev.iopsys.eu/bbf/wifidmd.git |
| Device.USB. | usbmngr | https://dev.iopsys.eu/system/usbmngr.git |
| Device.Bridging. | bridgemngr | https://dev.iopsys.eu/network/bridgemngr.git |
| Device.IP.Diagnostics. | tr143 | https://dev.iopsys.eu/bbf/tr143d.git |
| Device.IP.Diagnostics.IPLayerCapacityMetrics. | tr471 | https://dev.iopsys.eu/bbf/tr471d.git |
| Device.X_IOPSYS_EU_IGMP. | mcastmngr | https://dev.iopsys.eu/hal/mcastmngr.git |
| Device.X_IOPSYS_EU_MLD. | mcastmngr | https://dev.iopsys.eu/hal/mcastmngr.git |
| Device.PacketCaptureDiagnostics. | packet-capture-diagnostics | https://dev.iopsys.eu/bbf/packet-capture-diagnostics.git |
| Device.SelfTestDiagnostics. | self-diagnostics | https://dev.iopsys.eu/feed/iopsys.git |
| Device.UPnP. | ssdpd | https://dev.iopsys.eu/feed/iopsys.git |
| Device.IEEE1905. | ieee1905 | https://dev.iopsys.eu/multi-ap/ieee1905.git |
| Device.MQTT.Broker. | mosquitto | https://dev.iopsys.eu/feed/openwrt-packages.git |
| Device.X_IOPSYS_EU_OpenVPN. | openvpn | https://dev.iopsys.eu/feed/openwrt-packages.git |

View file

@ -1,4 +0,0 @@
title: "BBFDM"
nav:
- "..."

View file

@ -0,0 +1,793 @@
{
"definitions": {
"path_t": {
"description": "Complete object element path as per TR181",
"type": "string",
"minLength": 6,
"maxLength": 1024,
"examples": [
"Device.",
"Device.DeviceInfo.Manufacturer",
"Device.WiFi.SSID.1.",
"Device.WiFi."
]
},
"schema_path_t": {
"description": "Datamodel object schema path",
"type": "string",
"minLength": 6,
"maxLength": 1024,
"examples": [
"Device.Bridging.Bridge.{i}.",
"Device.DeviceInfo.Manufacturer",
"Device.WiFi.SSID.{i}.SSID"
]
},
"boolean_t": {
"type": "string",
"enum": [
"0",
"1"
]
},
"operate_path_t": {
"description": "Datamodel object schema path",
"type": "string",
"minLength": 6,
"maxLength": 1024,
"examples": [
"Device.IP.Diagnostics.IPPing()",
"Device.DHCPv4.Client.{i}.Renew()",
"Device.FactoryReset()"
]
},
"query_path_t": {
"description": "DM object path with search queries",
"type": "string",
"minLength": 6,
"maxLength": 1024,
"examples": [
"Device.",
"Device.DeviceInfo.Manufacturer",
"Device.WiFi.SSID.1.BSSID",
"Device.WiFi.SSID.*.BSSID",
"Device.WiFi."
]
},
"instance_t": {
"description": "Multi object instances",
"type": "string",
"minLength": 6,
"maxLength": 256
},
"proto_t": {
"type": "string",
"default": "both",
"enum": [
"usp",
"cwmp",
"both"
]
},
"type_t": {
"type": "string",
"enum": [
"xsd:string",
"xsd:unsignedInt",
"xsd:int",
"xsd:unsignedLong",
"xsd:long",
"xsd:boolean",
"xsd:dateTime",
"xsd:hexBinary",
"xsd:object",
"xsd:command",
"xsd:event"
]
},
"fault_t": {
"type": "integer",
"minimum": 7000,
"maximum": 9050
},
"trans_type_t": {
"type": "string",
"enum": [
"start",
"commit",
"abort",
"status"
]
},
"srv_type_t": {
"type": "string",
"enum": [
"register",
"list"
]
},
"format_t": {
"type": "string",
"default": "pretty",
"enum": [
"raw",
"pretty"
]
},
"instance_mode_t": {
"type": "integer",
"default": 0,
"minimum": 0,
"maximum": 1
},
"trans_id_t": {
"description": "Required for CUD operation, it shall be same number as got from transaction->start",
"type": "integer",
"minimum": 1
}
},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://dev.iopsys.eu/bbf/bbfdm/-/blob/devel/docs/api/ubus/bbfdm.md",
"type": "object",
"title": "bbf",
"object": "bbf",
"additionalProperties": false,
"properties": {
"schema": {
"title": "Get list of supported datamodel parameters",
"description": "Schema will have all the nodes/objects supported by libbbf",
"type": "object",
"required": [
"output"
],
"properties": {
"input": {
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/query_path_t"
},
"paths": {
"type": "array",
"uniqueItems": true,
"items": [
{
"$ref": "#/definitions/query_path_t"
}
]
},
"first_level": {
"type": "boolean",
"description": "gets only first level objects if true"
},
"commands": {
"type": "boolean",
"description": "includes commands in the list if true"
},
"events": {
"type": "boolean",
"description": "includes events in the list if true"
},
"params": {
"type": "boolean",
"description": "includes objs/params in the list if true"
},
"optional": {
"type": "object",
"properties": {
"proto": {
"$ref": "#/definitions/proto_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/schema_path_t"
},
"data": {
"$ref": "#/definitions/boolean_t"
},
"type": {
"$ref": "#/definitions/type_t"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"input": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/schema_path_t"
},
"data": {
"$ref": "#/definitions/boolean_t"
},
"type": {
"$ref": "#/definitions/type_t"
}
}
}
]
},
"output": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/schema_path_t"
},
"data": {
"$ref": "#/definitions/boolean_t"
},
"type": {
"$ref": "#/definitions/type_t"
}
}
}
]
}
},
"required": [
"path"
]
}
]
}
}
}
}
},
"get": {
"title": "Get handler",
"description": "Query the datamodel object",
"type": "object",
"required": [
"input",
"output"
],
"properties": {
"input": {
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"$ref": "#/definitions/query_path_t"
},
"paths": {
"type": "array",
"uniqueItems": true,
"items": [
{
"$ref": "#/definitions/query_path_t"
}
]
},
"maxdepth": {
"type": "integer",
"description": "Integer to decide the depth of data model to be parsed"
},
"optional": {
"type": "object",
"properties": {
"format": {
"$ref": "#/definitions/format_t"
},
"proto": {
"$ref": "#/definitions/proto_t"
},
"instance_mode": {
"$ref": "#/definitions/instance_mode_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"data": {
"type": "string"
},
"type": {
"$ref": "#/definitions/type_t"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
}
},
"required": [
"path"
]
}
]
}
}
}
}
},
"instances": {
"title": "Instance query handler",
"description": "Get the instances of multi object",
"type": "object",
"required": [
"input"
],
"properties": {
"input": {
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"$ref": "#/definitions/query_path_t"
},
"first_level": {
"type": "boolean",
"description": "gets only first level objects if true"
},
"optional": {
"type": "object",
"properties": {
"proto": {
"$ref": "#/definitions/proto_t"
},
"instance_mode": {
"$ref": "#/definitions/instance_mode_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
}
},
"required": [
"path"
]
}
]
}
}
}
}
},
"add": {
"title": "Add a new object instance",
"description": "Add a new object in multi instance object",
"type": "object",
"required": [
"input",
"output"
],
"properties": {
"input": {
"type": "object",
"required": [
"path",
"optional"
],
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"obj_path": {
"type": "object",
"properties": {}
},
"optional": {
"type": "object",
"properties": {
"transaction_id": {
"$ref": "#/definitions/trans_id_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"data": {
"type": "string"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
}
},
"required": [
"path"
]
}
]
}
}
}
}
},
"del": {
"title": "Delete object instance",
"description": "Delete a object instance from multi instance object",
"type": "object",
"required": [
"input",
"output"
],
"properties": {
"input": {
"type": "object",
"required": [
"path",
"transaction_id"
],
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"paths": {
"type": "array",
"uniqueItems": true,
"items": [
{
"$ref": "#/definitions/query_path_t"
}
]
},
"optional": {
"type": "object",
"properties": {
"transaction_id": {
"$ref": "#/definitions/trans_id_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"data": {
"type": "string"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
}
},
"required": [
"parameter",
"type"
]
}
]
}
}
}
}
},
"set": {
"title": "Set handler",
"description": "Set values of datamodel object element",
"type": "object",
"required": [
"input",
"output"
],
"properties": {
"input": {
"type": "object",
"required": [
"path",
"value",
"optional"
],
"properties": {
"path": {
"$ref": "#/definitions/query_path_t"
},
"value": {
"description": "value of the object element provided in path, path should contains valid writable object element",
"type": "string",
"examples": [
"{\"path\":\"Device.WiFi.SSID.1.SSID\", \"value\":\"test_ssid\"}",
"{\"path\":\"Device.WiFi.SSID.2.Enable\", \"value\":\"true\"}",
"{\"path\":\"Device.WiFi.SSID.1.Enable\", \"value\":\"0\"}"
]
},
"obj_path": {
"description": "To set multiple values at once, path should be relative to object elements",
"examples": [
"{\"path\":\"Device.WiFi.SSID.1.\", \"obj_path\":{\"SSID\":\"test_ssid\",\"Name\":\"test_name\"}}",
"{\"path\":\"Device.WiFi.SSID.2.\", \"obj_path\":{\"SSID\":\"test_ssid\"}}"
],
"type": "object",
"properties": {}
},
"optional": {
"type": "object",
"properties": {
"proto": {
"$ref": "#/definitions/proto_t"
},
"instance_mode": {
"$ref": "#/definitions/instance_mode_t"
},
"transaction_id": {
"$ref": "#/definitions/trans_id_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"data": {
"$ref": "#/definitions/boolean_t"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
}
},
"required": [
"path"
]
}
]
}
}
}
}
},
"operate": {
"title": "Operate handler",
"description": "Operate on object element provided in path",
"type": "object",
"required": [
"input",
"output"
],
"properties": {
"input": {
"type": "object",
"required": [
"command"
],
"properties": {
"command": {
"$ref": "#/definitions/operate_path_t"
},
"command_key": {
"type": "string"
},
"input": {
"description": "Input arguments for the operate command as defined in TR-181-2.13",
"examples": [
"{\"path\":\"Device.IP.Diagnostics.IPPing\\(\\)\", \"input\":{\"Host\":\"iopsys.eu\"}}"
],
"type": "object",
"properties": {}
},
"optional": {
"type": "object",
"properties": {
"format": {
"$ref": "#/definitions/format_t"
},
"proto": {
"$ref": "#/definitions/proto_t"
},
"instance_mode": {
"$ref": "#/definitions/instance_mode_t"
}
}
}
}
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"data": {
"$ref": "#/definitions/boolean_t"
},
"fault": {
"$ref": "#/definitions/fault_t",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"fault_msg": {
"type": "string",
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
},
"output": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"path": {
"$ref": "#/definitions/path_t"
},
"data": {
"$ref": "#/definitions/boolean_t"
},
"type": {
"$ref": "#/definitions/type_t"
}
}
}
]
}
},
"required": [
"path",
"data"
]
}
]
}
}
}
}
},
"transaction": {
"title": "Start/commit/abort/status a transaction before set/add/del operations",
"type": "object",
"properties": {
"input": {
"type": "object",
"properties": {
"cmd": {
"$ref": "#/definitions/trans_type_t"
},
"timeout": {
"type": "integer",
"description": "Timeout (in milliseconds) for the transaction, on timeout changes will be reverted",
"minimum":0
},
"restart_services": {
"description": "If yes, bbfdmd restart the service after CUD operation, else return list of updated uci to handler restart externally.",
"type": "boolean"
},
"optional": {
"type": "object",
"properties": {
"transaction_id": {
"$ref": "#/definitions/trans_id_t"
}
}
}
},
"required": [
"cmd"
]
},
"output": {
"type": "object",
"properties": {
"status": {
"type": "boolean"
},
"transaction_id": {
"type": "integer",
"minimum": 1
},
"error": {
"type": "string"
}
},
"required": [
"status"
]
}
},
"required": [
"input",
"output"
]
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,13 @@
"description": "BBFDM daemon Settings", "description": "BBFDM daemon Settings",
"multi": false, "multi": false,
"options": [ "options": [
{
"name": "enable",
"type": "boolean",
"required": "no",
"default": "1",
"description": "Enables bbfdmd"
},
{ {
"name": "debug", "name": "debug",
"type": "boolean", "type": "boolean",
@ -40,13 +47,6 @@
"default": "2", "default": "2",
"description": "This parameter configures when subprocess can be used for get operation. Level here denotes the Datamodel object depth up-to which subprocess will be used to collect the get data. For example, if this is configured to 1, then only get for 'Device.' shall be called within the subprocess. If configured as level 2, then all the get with up-to depth 2 like 'Device.WiFi.', 'Device.IP.' shall be called in subprocess." "description": "This parameter configures when subprocess can be used for get operation. Level here denotes the Datamodel object depth up-to which subprocess will be used to collect the get data. For example, if this is configured to 1, then only get for 'Device.' shall be called within the subprocess. If configured as level 2, then all the get with up-to depth 2 like 'Device.WiFi.', 'Device.IP.' shall be called in subprocess."
}, },
{
"name": "bbf_caching_time",
"type": "integer",
"required": "no",
"default": "0",
"description": "Max caching time in seconds for ubus output used in datamodel parameters. If not configured, output shall be cleared end the end of call."
},
{ {
"name": "refresh_time", "name": "refresh_time",
"type": "integer", "type": "integer",
@ -55,6 +55,34 @@
"description": "The time period in seconds after which bbfdmd will refresh the datamodel instances in a periodic manner. If configured to '0' then instance updater will be disabled. If not configured at all then after every 5 seconds datamodel instances will be refreshed." "description": "The time period in seconds after which bbfdmd will refresh the datamodel instances in a periodic manner. If configured to '0' then instance updater will be disabled. If not configured at all then after every 5 seconds datamodel instances will be refreshed."
} }
] ]
},
{
"section": "micro_services",
"description": "Datamodel micro-service",
"multi": false,
"options": [
{
"name": "enable",
"type": "boolean",
"required": "no",
"default": "1",
"description": "Enables bbfdmd"
},
{
"name": "enable_core",
"type": "boolean",
"required": "no",
"default": "0",
"description": "Sets core flag in procd for datamodel microservices"
},
{
"name": "enable_respawn",
"type": "boolean",
"required": "no",
"default": "0",
"description": "Enable respawning of datamodel micro-service process"
}
]
} }
] ]
} }

View file

@ -0,0 +1,281 @@
# How to Write a datamodel definition using C code
Datamodel definition can be added manually by defining the whole tree node-by-node or structure-by-structure, or can be semi-automated by using a `bbfdm` tool, which generates template C source code with all the structure definitions and dummy get/set/add/delete handlers.
## Generate datamodel source code with dummy definition using tool
```bash
./tools/convert_dm_json_to_c.py --help
Usage: ./tools/convert_dm_json_to_c.py [Object path]
Examples:
- ./tools/convert_dm_json_to_c.py
==> Generate the C code of full data model in datamodel/ folder
- ./tools/convert_dm_json_to_c.py Device.DeviceInfo.
==> Generate the C code of Device.DeviceInfo object in datamodel/ folder
- ./tools/convert_dm_json_to_c.py Device.Services.VoiceService.{i}.DECT.Base.{i}.
==> Generate the C code for a specific multi-instance object in datamodel/ folder
```
After running the tool, datamodel shall be gets generated in datamodel directory with dummy handlers with '//TODO' marker, to complete the definition, developer need to update the logic in dummy function pointers.
To know more about different type of function pointers, check below section.
## Write datamodel source code manually
To write a datamodel definition manually, one has to add the Root definition along with object and leaves.
### Root definition
As per TR181, the root of the tree is 'Device.', which can be defined by using below named structure 'tDynamicObj'
```bash
DM_MAP_OBJ tDynamicObj[] = {
{"Device.", tDeviceObj, tDeviceParams},
{0}
};
```
The “tDynamicObj” table contains entries of **DM_MAP_OBJ** structure, which contains three arguments:
| Argument | Description |
| ---------------- | ------------------------------------------------------------------------------------------------------------- |
| `parentobj` | A string of the parent object name. Example “Device.IP.Diagnostics.”, “Device.DeviceInfo”, “Device.WiFi.Radio.” |
| `nextobject` | Pointer to a **DMOBJ** array which contains a list of the child objects |
| `parameter` | Pointer to a **DMLEAF** array which contains a list of the child parameters |
> Note: This symbol needs to be defined once per module globally, and has the root definition for that module's datamodels
Datamodel can be divided in two parts,
1. Intermediate nodes or objects (defined with DMOBJ)
2. End nodes or leaf parameters (defined with DMLEAF)
### Object definition (DMOBJ)
Each object in the **DMOBJ** table contains the following arguments:
| Argument | Description |
| ------------------- | ---------------------------------------------------------------------------------------------- |
| `OBJ` | A string of the object name. Example “Bridging”, “IP”, “DeviceInfo”, “WiFi” |
| `permission` | The permission of the object. Could be **&DMREAD** or **&DMWRITE**. If it's `&DMWRITE` then we can add/delete instances of this object |
| `addobj` | The function to add new instance under this object. This function will be triggered when the ACS/Controller call AddObject of this object |
| `delobj` | The function to delete instance under this object. This function will be triggered when the ACS/Controller call DeleteObject of an instance of this object |
| `checkdep` | A string of the object dependency, it can be a file("file:/etc/config/network") or an ubus object,method("ubus:network.interface->status"). If it's `NULL` then the object has always appeared in the tree |
| `browseinstobj` | This function allow to browse all instances under this object |
| `nextdynamicobj` | Pointer to the next of **DMOBJ** which contains a list of the child objects using json files, shared libraries and vendor extension |
| `dynamicleaf` | Pointer to the next of **DMLEAF** which contains a list of the child parameters using json files, shared libraries and vendor extension |
| `nextobj` | Pointer to a **DMOBJ** array which contains a list of the child objects |
| `leaf` | Pointer to a **DMLEAF** array which contains a list of the child parameters |
| `linker` | This argument is deprecated and should be `NULL` |
| `bbfdm_type` | The bbfdm type of the object. Could be **BBFDM_CWMP**, **BBFDM_USP**, **BBFDM_BOTH** or **BBFDM_NONE**.If it's **BBFDM_BOTH** then we can see this object in all protocols (CWMP, USP,...) |
| `uniqueKeys` | This argument is deprecated and should be `NULL` |
example:
```bash
/* *** Device. *** */
DMOBJ tDeviceObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type*/
{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH, NULL},
{0}
};
```
Datamodel objects can be of two types
- Single instance object (Path which has a '.' prefix)
- Multi-instance objects (Path with has '.{i}' prefix)
Multi-instance objects means, there could be one or more such nodes available, it can be viewed as a group of things which also has a close resemblance with 'uci sections'. In datamodel definitions, this mostly depends on runtime data, and to define such object, one has to define a `browseinstobj` function pointer to dynamically gather data and create instances at the runtime.
#### Browse definition
The browse function allow to go over all instances of the current object and link them to the data model tree. So, it need to retrieve the instance number for the current instance and then create a link between current instance and existing defined tree.
To retrieve the instance, below APIs can be used
- `handle_instance`: allow to retrieve/attribute the instances number/alias from uci config sections depending of the request and the instance mode.
- `handle_instance_without_section`: allow to attribute the instances number/alias with constant values.
To link the current instance with the datamodel definition
- DM_LINK_INST_OBJ: This API needs to be called for each instance, this API also has a structure called `dm_data` which can be used to pass-on the data from current node to child objects.
> Note1: It is **mandatory** to use the generic structure `(struct dm_data *)` to pass the data to child objects/params.
> Note2: the browse function is only required for multi-instances objects.
### Leaf definition
Each leaf in the **DMLEAF** table can be a **Parameter**, **Command** or **Event**.
#### 1.Parameter definition
| Argument | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `PARAM` | A string of the parameter name. Example “Enable”, “Status”, “Name” |
| `permission` | The permission of the parameter. Could be **&DMREAD** or **&DMWRITE**.If it's `&DMWRITE` then we can set a value for this parameter |
| `type` | Type of the parameter: **DM_STRING**, **DM_BOOL**, **DM_UNINT**,... |
| `getvalue` | The function which return the value of this parameter |
| `setvalue` | The function which set the value of this parameter |
| `bbfdm_type` | The bbfdm type of the parameter. Could be **BBFDM_CWMP**, **BBFDM_USP**, **BBFDM_BOTH** or **BBFDM_NONE**.If it's **BBFDM_BOTH** then we can see this parameter in all protocols (CWMP, USP,...) |
| `dm_falgs` | An enumeration value used to specify the displayed parameter value. Could be **DM_FLAG_REFERENCE**, **DM_FLAG_UNIQUE**, **DM_FLAG_LINKER** or **DM_FLAG_SECURE**. |
#### 2.Command definition
| Argument | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `PARAM` | A string of the command name. Example “IPPing()”, “DownloadDiagnostics()”, “Renew()” |
| `permission` | The permission of the command. Could be **&DMASYNC** or **&DMSYNC**. |
| `type` | Type of the command, It should be **DMT_COMMAND** |
| `getvalue` | The function which return the input, output arguments of the command |
| `setvalue` | The function which call the operation of the command |
| `bbfdm_type` | The bbfdm type of the command. It should be **BBFDM_USP** as long as operate commands are only defined in USP protocol. |
#### 3.Event definition
| Argument | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `PARAM` | A string of the event name. Example “Boot!”, “Push!”, “Periodic!” |
| `permission` | The permission of the event. It should be **DMREAD** |
| `type` | Type of the event, It should be **DMT_EVENT** |
| `getvalue` | The function which return the parameter arguments of the event |
| `setvalue` | The function which call the operation of the event |
| `bbfdm_type` | The bbfdm type of the event. It should be **BBFDM_USP** as long as events are only defined in USP protocol. |
##### How events works
A datamodel event can be sent from external source (like: hotplug script) or it can be auto-generated based on system events. `bbfdmd` provides a methods to trigger datamodel event from ubus event.
Upon starting `bbfdmd`, it calls `bbf_entry_method` API with `BBF_SCHEMA` method to retrieve all events supported by Data Model. Subsequently, it attempts to register an event handler for each event by using the event name argument defined in each event leaf and then listens for that event name.
When the ubus event triggered in the system, `bbfdmd` calls `bbf_entry_method` API with `BBF_EVENT` method to perform the event operation. And finally, it sends `bbfdm.event` ubus event with the required input information obtained from the returned event operation.
Example:
Below is an example of `Device.WiFi.DataElements.AssociationEvent.Associated!` event implementation:
```bash
static event_args wifidataelementsassociationevent_associated_args = {
.name = "wifi.dataelements.Associated",
.param = (const char *[]) {
"type",
"version",
"protocols",
"BSSID",
"MACAddress",
"StatusCode",
"HTCapabilities",
"VHTCapabilities",
"HECapabilities",
"TimeStamp",
NULL
}
};
static int get_event_args_WiFiDataElementsAssociationEvent_Associated(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = (char *)&wifidataelementsassociationevent_associated_args;
return 0;
}
static int event_WiFiDataElementsAssociationEvent_Associated(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case EVENT_CHECK:
// Nothing to check
break;
case EVENT_RUN:
char *event_time = dmjson_get_value((json_object *)value, 1, "eventTime");
char *bssid = dmjson_get_value((json_object *)value, 3, "wfa-dataelements:AssociationEvent.AssocData", "DisassocData", "BSSID");
char *mac_addr = dmjson_get_value((json_object *)value, 3, "wfa-dataelements:AssociationEvent.AssocData", "DisassocData", "MACAddress");
add_list_parameter(ctx, dmstrdup("TimeStamp"), dmstrdup(event_time), DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(ctx, dmstrdup("BSSID"), dmstrdup(bssid), DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(ctx, dmstrdup("MACAddress"), dmstrdup(mac_addr), DMT_TYPE[DMT_STRING], NULL);
break;
}
return 0;
}
DMLEAF tWiFiDataElementsAssociationEventParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"Associated!", &DMREAD, DMT_EVENT, get_event_args_WiFiDataElementsAssociationEvent_Associated, event_WiFiDataElementsAssociationEvent_Associated, BBFDM_USP},
{0}
};
```
More leaf Example(s):
```bash
DMLEAF tDeviceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"RootDataModelVersion", &DMREAD, DMT_STRING, get_Device_RootDataModelVersion, NULL, BBFDM_BOTH},
{"Reboot()", &DMSYNC, DMT_COMMAND, NULL, operate_Device_Reboot, BBFDM_USP},
{"Boot!", &DMREAD, DMT_EVENT, NULL, NULL, BBFDM_USP},
{0}
};
```
#### Alias handling
In general datamodel parameters with multi-instance objects has a parameter named as '.Alias' to uniquely identify the instance. Below APIs can be used to get/set Aliases, provided browseinstobj has dmmap definition in dm_data.
- Alias get handler (`bbf_get_alias`)
- Alias set handler (`bbf_set_alias`)
```bash
int bbf_get_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char **value)
```
Input(s):
| Input | Description |
| ------ | ------------ |
| ctx | bbf context |
| s | Pointer to dmmap uci section from where will get Alias value |
| option_name| dmmap uci option name for alias value |
| instance | instance value |
| value | pointer to where the value will be stored |
```bash
int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char *value);
```
Input(s):
| Input | Description |
| ------ | ------------ |
| ctx | bbf context |
| s | Pointer to dmmap uci section to where will save Alias value |
| option_name | dmmap uci option name to store the alias value |
| instance | instance value |
| value | the value to be set |
Example:
```bash
static int get_WiFiEndPoint_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "endpointalias", instance, value);
}
static int set_WiFiEndPoint_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
return bbf_set_alias(ctx, ((struct dm_data *)data)->dmmap_section, "endpointalias", instance, value);
}
```
#### NumberOfEntries parameter handling
Each multi-instance object has a related LEAF entry to denote the number of instances present for that object, Since multi-instance object already has a browse function which got the runtime logic to loop through the instances, `libbbfdm-api` provides another API `get_number_of_entries` to get the number of entries.
Example:
```bash
static int get_Device_InterfaceStackNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
int cnt = get_number_of_entries(ctx, data, instance, browseInterfaceStackInst);
dmasprintf(value, "%d", cnt);
return 0;
}
```

View file

@ -1,13 +1,14 @@
# How to extend Datamodel parameters using Json plugins # How to extend Datamodel parameters using Json
It is often required to extend datamodel parameters of the device, extending the datamodel parameters using json plugin is the simplest way for the same. `bbfdm` provides tools to convert Broadband-forum's xml datamodel definition for cwmp and usp to a combined JSON file.
To extend the datamodel using json plugin, its required to be defined it, as it is defined in `datamodel.json` file and then place that json in '/etc/bbfdm/json/' directory of device. JSON definition of datamodel with latest release available in [datamodel.json](../../libbbfdm/dmtree/json/datamodel.json)
Now, a partial node from this file can be used to create a JSON datamodel definition, provided user adds a mapping to all LEAF parameters and multi-instance object.
It is often the case, that the supported mapping might not handle all the scenarios, and required some structural changes to fulfill the new requirements, to make these plugins backward compatible with the older mappings some kind of check was required, which is can be solved with having a "version" field in the plugin, which describes the list of supported mappings with that specific version. This can be added as below:
```json ```json
{ {
"json_plugin_version": 1, "json_plugin_version": 2,
"Device.": { "Device.": {
"type": "object", "type": "object",
"protocols": [ "protocols": [
@ -65,11 +66,490 @@ It is often the case, that the supported mapping might not handle all the scenar
} }
} }
``` ```
> Note: If the `json_plugin_version` is omitted in the json then it means, it is having legacy mapping and considered as `json_plugin_version` 0.
> Note1: `json_plugin_version` is **mandatory** in json datamodel definition.
> Note2: It is advised to use `json_plugin_version` 2 for datamodel definition, usages version 0 and 1 are deprecated.
## JSON Plugin Version 2
Earlier versions of the json_plugins where treated as separate tree, so there where no sharing of data between main tree and JSON plugin, also it was not possible to overwrite/exclude a datamodel entry from core using JSON file.
JSON Plugin Version 2 introduces enhancements to the previous versions by providing increased flexibility in extending, overwriting, and excluding objects/parameters/commands/events from the core data model.
### How It Works
To illustrate how the new features work, let's consider the following example JSON Plugin:
```json
{
"json_plugin_version": 2,
"Device.WiFi.AccessPoint.{i}.Security.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"access": false,
"array": false,
"{BBF_VENDOR_PREFIX}KeyPassphrase": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"datatype": "string",
"mapping": [
{
"data": "@Parent",
"type": "uci_sec",
"key": "key"
}
]
},
"WEPKey": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"datatype": "string",
"mapping": [
{
"data": "@Parent",
"type": "uci_sec",
"key": "wek_key"
}
]
},
"SAEPassphrase": {
"type": "string",
"read": true,
"write": false,
"protocols": [
"none"
]
}
}
}
```
The JSON Plugin V2 operates by parsing the JSON file. Then it checks the parent top object, which in this example is `Device.WiFi.AccessPoint.{i}.Security`.
- If this object exists in the core data model, the plugin proceeds to examine the next each subsequent level to determine the necessary action for each JSON object.
- If the object does not exist in the core data model, it is extended.
- If the object exists, it is either overwritten or excluded, depending on the defined protocols. If the protocols array is defined as 'none', the object is excluded.
- If the parent top object does not exist in the core data model, the plugin follows the old behavior defined in JSON Plugin V0 and V1, which is extending the core data model.
Examples
- Device.WiFi.AccessPoint.{i}.Security.X_IOPSYS_EU_KeyPassphrase: This parameter will be extended to the core data model since it does not exist.
- Device.WiFi.AccessPoint.{i}.Security.WEPKey: This parameter will be overwritten in the core data model since it already exists.
- Device.WiFi.AccessPoint.{i}.Security.SAEPassphrase: This parameter will be excluded from the core data model since it exists, but the new protocol defined is `none`.
More example(s):
- [Extend](../../test/vendor_test/test_extend.json)
- [Overwrite](../../test/vendor_test/test_overwrite.json), and
- [Exclude](../../test/vendor_test/test_exclude.json)
### Important Notes
> Note: When extending a multiple-instance object, align the passed data from the browse function to children (LEAF) by keeping it `(struct uci_section *)data` pointer in case of the `type` is `uci_sec` or `(json_object *)data` pointer in case of the `type` is `json`.
> Note: The mapping format used by JSON Plugin V2 follows the format of version 1. Ensure that all mappings are aligned with JSON Plugin V1 specifications.
> Note4: Additional examples for each feature can be found in the following links:
### Features Supported with JSON Plugin V2
- Allow extending the core tree with simple mappings based on the data passed from the parent object.
- Allow overwriting an existing object, parameter, command, or event from the core tree.
- Allow excluding an existing object, parameter, command, or event from the core tree.
#### Some examples on JSON Definition
**1. Object without instance:**
```bash
"Device.CWMP.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"access": false
}
```
**2. Object with instance:**
- **UCI command:** uci show wireless | grep wifi-device
```bash
"Device.X_IOPSYS_EU_Radio.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"access": true,
"mapping": {
"type": "uci",
"uci": {
"file": "wireless",
"section": {
"type": "wifi-device"
},
"dmmapfile": "dmmap_wireless"
}
}
}
```
- **UBUS command:** ubus call dsl status | jsonfilter -e @.line
```bash
"Device.DSL.Line.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"access": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl",
"method": "status",
"args": {},
"key": "line"
}
}
}
```
**3. Parameter under object with instance:**
- **UCI option command:** uci get wireless.@wifi-device[0].country
- **@i:** is the number of instance object
```bash
"Country": {
"type": "string",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": [
{
"type" : "uci",
"uci" : {
"file" : "wireless",
"section" : {
"type": "wifi-device",
"index": "@i-1"
},
"option" : {
"name" : "country"
}
}
}
]
}
```
- **UCI list command:** uci get urlfilter.@profile[0].whitelist_url
- **@i:** is the number of instance object
```bash
"WhitelistURL": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"list": {
"datatype": "string"
},
"mapping": [
{
"type": "uci",
"uci": {
"file": "urlfilter",
"section": {
"type": "profile",
"index": "@i-1"
},
"list": {
"name": "whitelist_url"
}
}
}
]
}
```
- **UBUS command:** ubus call wifi status | jsonfilter -e @.radios[0].noise
- **@i:** is the number of instance object
```bash
"Noise": {
"type": "int",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": [
{
"type" : "ubus",
"ubus" : {
"object" : "wifi",
"method" : "status",
"args" : {},
"key" : "radios[@i-1].noise"
}
}
]
}
```
**4. Parameter without instance:**
- **UCI option command:** uci get cwmp.cpe.userid
```bash
"Username": {
"type": "string",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": [
{
"type" : "uci",
"uci" : {
"file" : "cwmp",
"section" : {
"type": "cwmp",
"name": "cpe"
},
"option" : {
"name" : "userid"
}
}
}
]
}
```
- **UCI list command:** uci get urlfilter.globals.blacklist_url
- **@i:** is the number of instance object
```bash
"BlacklistURL": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"list": {
"datatype": "string"
},
"mapping": [
{
"type": "uci",
"uci": {
"file": "urlfilter",
"section": {
"name": "globals"
},
"list": {
"name": "blacklist_url"
}
}
}
]
}
```
- **UBUS command:** ubus call system info | jsonfilter -e @.uptime
```bash
"Uptime": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": [
{
"type" : "ubus",
"ubus" : {
"object" : "system",
"method" : "info",
"args" : {},
"key" : "uptime"
}
}
]
}
```
- **UBUS command:** ubus call system info | jsonfilter -e @.memory.total
```bash
"Total": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": [
{
"type" : "ubus",
"ubus" : {
"object" : "system",
"method" : "info",
"args" : {},
"key" : "memory.total"
}
}
]
}
```
**5. Parameter to map another data model Object:**
- **UCI option command:** uci get urlfilter.@filter[0].profile
- **linker_obj** is the path name of an object that is stacked immediately below this object
```bash
"Profile": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"mapping": [
{
"type": "uci",
"uci": {
"file": "urlfilter",
"section": {
"type": "filter",
"index": "@i-1"
},
"option": {
"name": "profile"
}
},
"linker_obj": "Device.{BBF_VENDOR_PREFIX}URLFilter.Profile.*.Name"
}
]
}
```
**6. Object with Event and Operate command:**
```bash
{
"Device.X_IOPSYS_Test.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"access": false,
"Push!": {
"type": "event",
"protocols": [
"usp"
],
"data": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"usp"
]
}
},
"Status()": {
"type": "command",
"async": true,
"protocols": [
"usp"
],
"input": {
"Option": {
"type": "string",
"read": "true",
"write": "true",
"protocols": [
"usp"
]
}
},
"output": {
"Result": {
"type": "string",
"read": "true",
"write": "false",
"protocols": [
"usp"
]
}
},
"mapping": [
{
"type": "ubus",
"ubus": {
"object": "test",
"method": "status"
}
}
]
}
}
}
```
## How to add object dependency using Json plugin ## How to add object dependency using Json plugin
In some cases we may need to set a dependency on datamodel object. In such cases the object will only populate if its dependencies are fulfilled. In some cases we may need to set a dependency on datamodel object. In such cases the object will only populate if its dependencies are fulfilled.
The json object `dependency` is used to define the same. Below is an example of how to add object dependency: The json object `dependency` is used to define the same. Below is an example of how to add object dependency:
```json ```json
{ {
"json_plugin_version": 1, "json_plugin_version": 1,
@ -142,23 +622,6 @@ mapping: [
If we consider multi-instance objects, they are kind of special because we have group of information, where one group can be visualize as one instance. Also, the parameters of multi-instance objects also shares data with there parents, apart from that, for others as well, we might require some runtime information to get some mappings, for those scenarios, mapping have some special symbol, all start with '@' symbol, some of them only applicable in case of multi-instance object. Overall all these are just for create the convention so that datamodel can easily be extended without getting into hustle of programming. Again, the plugin handler does not have any intelligence of it own and completely driven by the mapping provided by the enduser, so if mapping is in-correct it would give incorrect result or no result in the datamodel. If we consider multi-instance objects, they are kind of special because we have group of information, where one group can be visualize as one instance. Also, the parameters of multi-instance objects also shares data with there parents, apart from that, for others as well, we might require some runtime information to get some mappings, for those scenarios, mapping have some special symbol, all start with '@' symbol, some of them only applicable in case of multi-instance object. Overall all these are just for create the convention so that datamodel can easily be extended without getting into hustle of programming. Again, the plugin handler does not have any intelligence of it own and completely driven by the mapping provided by the enduser, so if mapping is in-correct it would give incorrect result or no result in the datamodel.
## Special symbols
@index => Current instance number - 1
@index - 1 => Parent instance number - 1
@index - 2 => Grand parent instance number - 1, and likewise
@Name => Section name of parent
@Parent => data passed by parent
@Count => Returns the count of instances
@Value => Replace with the value passed in set command, only used for ubus **set**
@Input.XXX => Replace with the value passed in Input 'XXX' option, only used for ubus **operate**
## How to have different mappings for get/set: ## How to have different mappings for get/set:
```json ```json
@ -472,10 +935,13 @@ This object 'Device.LMAP.MeasurementAgent.{i}.Task.{i}.Option.{i}.' maps to the
2. Task.{i}: child object of MeasurementAgent object which maps to 'task' section, it must have a 'dm_parent' option with the value 'agent' 2. Task.{i}: child object of MeasurementAgent object which maps to 'task' section, it must have a 'dm_parent' option with the value 'agent'
3. Option.{i}: child object of Task object which maps to 'task_option' section, it must have a 'dm_parent' option with the value 'http_get_mt' 3. Option.{i}: child object of Task object which maps to 'task_option' section, it must have a 'dm_parent' option with the value 'http_get_mt'
## Feature supported with this mapping ## Special symbols
- Use of `json_plugin_version` for mapping extensions
- Use different mappings for get/set | Symbols | Meaning of the symbol |
- Support for NumberOfEntries parameter | ------- | ---------------------- |
- Data sharing between parent and child node in multi-instance object | @Name | Section name of parent |
- Use of index number in mapping | @Parent | data passed by parent |
- Support for set in ubus command | @Count | Returns the count of instances |
| @Value | Replace with the value passed in set command, only used for ubus **set** |
| @Input.XXX | Replace with the value passed in Input 'XXX' option, only used for ubus **operate** |

View file

@ -1,79 +1,26 @@
# BBFDM Daemon (bbfdmd) # BBFDM Daemon (bbfdmd)
`bbfdmd` is daemon which exposes data-model objects over ubus as required by [TR-069/cwmp](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/). `bbfdmd` daemon responsible for creating a datamodel layer between system resources and exposing TR181 data-model objects over ubus for higher layer application protocols like [TR-069/cwmp](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/).
> Note 1: The command outputs shown in this readme are examples only, actual output may differ based on device and configuration. > Note 1: The command outputs shown in this document are examples only, actual output may differ based on device and configuration.
> Note 2: Long command outputs are compressed for better readability
## UCI Config
The configuration file is an `uci` file `/etc/config/bbfdm`. Sample configuration file is provided below.
```bash
config bbfdmd 'bbfdmd'
option loglevel '2'
option sock '/tmp/bbfdm.sock'
option transaction_timeout 10
option subprocess_level '1'
option refresh_time '10'
```
In the above uci, loglevel can have below value:
|loglevel | Meaning |
|---------| -----------------------------------------|
| 0 | Disabled logging |
| 1 | Only errors will be logged |
| 2 | Only errors and warnings will be logged |
| 3 | Log everything except debug |
| 4 | Everything will be logged |
For more info on the `bbfdmd` UCI configuration visit [uci documentation](../api/uci/bbfdm.md) OR [raw uci schema](../../schemas/uci/bbfdm.json)
## Concepts and Workflow ## Concepts and Workflow
`bbfdmd` internally uses both `libbbfdm-api` and `libbbfdm` to get the data-model objects. On startup it parses the uci file to check the different configurations and then based on that it registers the `bbfdm` ubus namespace. `bbfdmd` daemon gets started by `/etc/init.d/bbfdmd` service, bbfdmd init script reads the input from `bbfdm` uci file and then it generates the input for `bbfdmd` daemon in json format in `/tmp/bbfdm/input.json`
When a ubus method is called it first fills `bbfdm_data_t` structure with the necessary information, then proceeds the `Get/Set/Operate/Add/Del` operation based on that information. ```json input.json
`bbfdmd` uses `bbf_entry_method` API from `libbbfdm-api` and `tEntryRoot`, `tVendorExtension`, `tVendorExtensionOverwrite` and `tVendorExtensionExclude` global shared arrays from `libbbfdm` to get the device tree schema and its values.
In short, it covers/supports all methods introduced in `TR-069` and `TR-369` by using the `bbf_entry_method` API from `libbbfdm-api` with the different methods and the existing data-model available with `libbbfdm`.
## Debugging tools
With the advancement in the datamodel tree, it is sometime required to do some debugging at the source, to simplify that `bbfdmd` offer a command line tool, which can
- Work directly on plugins, or
- Gets the data from an ubus object
and then show it on the CLI. This command line tool is part of `bbfdmd` binary itself and can be accessed with command line argument option '-c' along with binary.
```bash
# bbfdmd -h
Usage: bbfdmd [options]
options:
-s <socket path> ubus socket
-m <json path> json input configuration for micro services
-c <command input> Run cli command
-h Displays this help
#
```
If no command line option provided along with `bbfdmd` command then it starts in daemon mode and get the default configuration from `/etc/bbfdm/input.json`
```bash
# cat /etc/bbfdm/input.json
{ {
"daemon": { "daemon": {
"config": { "config": {
"loglevel": "1", "loglevel": "1",
"refresh_time": "10", "refresh_time": "120",
"transaction_timeout": "10" "transaction_timeout": "30",
"subprocess_level": "2"
}, },
"input": { "input": {
"type": "DotSo", "type": "DotSo",
"name": "/lib/libbbfdm.so" "name": "/usr/share/bbfdm/libbbfdm.so",
"plugin_dir": "/usr/share/bbfdm/plugins"
}, },
"output": { "output": {
"type": "UBUS", "type": "UBUS",
@ -96,6 +43,313 @@ If no command line option provided along with `bbfdmd` command then it starts in
} }
``` ```
When `bbfdmd` starts it parses the `input.json` file to check the different configurations, like
- Name of the TR181 datamodel definition file (daemon.input.name)
- Location of datamodel definition loaded as plugins (daemon.input.plugin_dir
- Name of the ubus object it has to register (daemon.output.name)
`bbfdmd` daemon use `libbbfdm-api` library to traverse the datamodel tree added by 'libbbfdm' or other plugins added in predefined plugin path(daemon.input.plugin_dir).
When a ubus method is called it first fills `bbfdm_data_t` structure with the necessary information, then proceeds the `Get/Set/Operate/Add/Del` operation based on that information.
To load the datamodel definitions from a DotSO file, it looks for a 'tDynamicObj' symbol and use it to create the base entry object, for datamodel operations it rely on libbbfdm-api's `bbf_entry_method` which process the datamodel operation on input path and produces result in list/blob, which further gets responded over ubus.
In short, it covers/supports all methods introduced in `TR-069` and `TR-369` by using the `bbf_entry_method` API from `libbbfdm-api` with the different methods and the existing data-model available with `libbbfdm`.
`bbfdmd` daemon can also be used to expose a module specific datamodel or sub-tree, by using datamodel micro-services. Datamodel micro-service is nothing but another `bbfdmd` instance running with smaller data sub-set, micro-service can be identified in the runtime by running a `ps` command
```bash
# ps|grep bbf
3804 root 6968 S {dm_bridgemngr} /usr/sbin/bbfdmd -m bridgemngr
3805 root 7064 S {dm_bulkdata} /usr/sbin/bbfdmd -m bulkdata
3806 root 6900 S {dm_ddnsmngr} /usr/sbin/bbfdmd -m ddnsmngr
3807 root 6996 S {dm_dhcpmngr} /usr/sbin/bbfdmd -m dhcpmngr
```
A `bbfdmd` instance with -m input means its running a module(sub-tree) datamodel. These micro-services exposed their own ubus objects
```bash
# ubus list bbfdm.*
bbfdm.Bridging
bbfdm.BulkData
bbfdm.DHCPv4_DHCPv6
bbfdm.DNS
```
When a datamodel started as micro-service, it looks/waits for `bbfdm` ubus object(added by main bbfdmd process), once its available micro-service resister with the main `bbfdmd` process by calling it 'service' method
```bash
# ubus -v list bbfdm
'bbfdm' @e970413c
"service":{"cmd":"String","name":"String","parent_dm":"String","objects":"Array"}
```
More details about micro-services covered in a dedicated section.
> Note: In general, bbfdmd does not reload the services after updating the configs, higher layer applications (i.e. icwmp, obuspa) usages `bbf.config` to apply the configs and reloads the services, please check `bbf.config` documentation for more details.
## Input and output Schema(s)
`bbfdmd` basic configuration can be updated with uci, a guide and uci schema available in following links
- [bbfdm uci guide](../api/uci/bbfdm.md)
- [bbfdm uci schema](../api/uci/bbfdm.json)
`bbfdmd` ubus guide and schema
- [bbfdm ubus guide](../api/ubus/bbfdm.md)
- [bbfdm ubus schema](../api/ubus/bbfdm.json)
`bbfmdd` can also be used to expose sub tree using different ubus object by using datamodel micro-service, ubus guide and schema for datamodel micro-services
- [datamodel micro-service](../api/ubus/bbfdm_micro_service.md)
- [datamodel micro-service schema](../api/ubus/bbfdm_micro_service.json)
Apart from these, datamodel micro-services can also be configured by updating their input files directly at the runtime, micro-service input files present in `/etc/bbfdm/micro_services/` in CPE.
Datamodel micro-service has a similar input file as of main bbfdmd
```json
{
"daemon": {
"enable": "1",
"service_name": "sshmngr",
"config": {
"loglevel": "1"
}
}
}
```
### Ubus methods
Following are the ubus methods exposed by `bbfdmd` main process:
```bash
# ubus -v list bbfdm
'bbfdm' @9e9928ef
"get":{"path":"String","paths":"Array","maxdepth":"Integer","optional":"Table"}
"schema":{"path":"String","paths":"Array","first_level":"Boolean","optional":"Table"}
"instances":{"path":"String","paths":"Array","first_level":"Boolean","optional":"Table"}
"set":{"path":"String","value":"String","obj_path":"Table","optional":"Table"}
"operate":{"command":"String","command_key":"String","input":"Table","optional":"Table"}
"add":{"path":"String","obj_path":"Table","optional":"Table"}
"del":{"path":"String","paths":"Array","optional":"Table"}
"transaction":{"cmd":"String","timeout":"Integer","restart_services":"Boolean","optional":"Table"}
"service":{"cmd":"String","name":"String","parent_dm":"String","objects":"Array"}
"notify_event":{"name":"String","input":"Table"}
```
Each datamodel micro-service expose their own ubus object, which is slightly different from main `bbfdm` ubus object, following is an example of ubus methods exposed by datamodel micro-services.
```bash
# ubus -v list bbfdm.SSH
'bbfdm.SSH' @bb8a66da
"get":{"path":"String","paths":"Array","maxdepth":"Integer","optional":"Table"}
"schema":{"path":"String","paths":"Array","first_level":"Boolean","optional":"Table"}
"instances":{"path":"String","paths":"Array","first_level":"Boolean","optional":"Table"}
"set":{"path":"String","value":"String","obj_path":"Table","optional":"Table"}
"operate":{"command":"String","command_key":"String","input":"Table","optional":"Table"}
"add":{"path":"String","obj_path":"Table","optional":"Table"}
"del":{"path":"String","paths":"Array","optional":"Table"}
"transaction":{"cmd":"String","timeout":"Integer","restart_services":"Boolean","optional":"Table"}
```
> Note1: `optional` table are present in all methods and it supports below options:
```console
"optional":{"proto":"String", "instance_mode":"Integer", "transaction_id":"Integer", "format":"String"}
```
- `proto` in each method specify the data-model prototype('cwmp', 'usp') to use, if not provided default data-model will be used.
- `instance_mode` could be 0 or 1, for instance number, instance alias respectively.
- `transaction_id` to define the transaction id number.
- `format` could be 'raw' or 'pretty', to specify the format to use as output, if not provided 'pretty' format will be used.
> Note2: `first_level` true means only get next level objects and false means get all objects recursively
> Note3: `maxdepth` is measured on max number of .(Dot) present in object name
> Note4: Check ubus schema document for more details
### Fault handling
To indicate a fault and source of fault `bbfdmd` provides `fault` along with `fault_msg` in the response in case of faults, which then handled by higher layer applications (i.e icwmp, obuspa).
This provides a clear inside on the root cause of the fault, and based on `fault_msg` it's easily to understand what the issue is and how to fix it and find out the limitations(if there are any on the device).
#### Example(s)
1. The requested value is correct as per TR181 standard, but there is a limitation in the device.
```console
root@iopsys:~# ubus call bbfdm set '{"path":"Device.Firewall.Config", "value":"High"}'
{
"results": [
{
"path": "Device.Firewall.Config",
"fault": 9007,
"fault_msg": "The current Firewall implementation supports only 'Advanced' config."
}
]
}
```
2. The requested value is outside the allowed range.
```console
root@iopsys:~# ubus call bbfdm set '{"path":"Device.Firewall.Chain.1.Rule.9.DestPort", "value":"123456"}'
{
"results": [
{
"path": "Device.Firewall.Chain.1.Rule.9.DestPort",
"fault": 9007,
"fault_msg": "'123456' value is not within range (min: '-1' max: '65535')"
}
]
}
```
3. Some arguments should be defined to perform the requested operation.
```console
root@iopsys:~# ubus call bbfdm operate '{"command":"Device.IP.Diagnostics.IPPing()", "command_key":"ipping_test", "input":{}}'
{
"results": [
{
"path": "Device.IP.Diagnostics.IPPing()",
"data": "ipping_test",
"fault": 7004,
"fault_msg": "IPPing: 'Host' input should be defined"
}
]
}
```
4. The path parameter value must start with 'Device.'. The command below doesn't have Device before path "Users.User."
```console
root@iopsys:~# ubus call bbfdm get '{"path":"Users.User.", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Users.User.",
"fault": 7026,
"fault_msg": "Path is not present in the data model schema"
}
]
}
```
These fault messages defined in datamodel handlers, user can add such fault message using `bbfdm_set_fault_message` libbbfdm-api's API, if no specific fault message defined for particular obj/param, datamodel returns standard error messages that are defined in CWMP and USP protocols as the fault message value.
##### Errors Codes
| Error Code | Meaning |
|------------|--------------------------------------------------------------|
| 7003 | Message failed due to an internal error. |
| 7004 | Message failed due to invalid values in the request elements and/or failure to update one or more parameters during Add or Set requests. |
| 7005 | Message failed due to memory or processing limitations. |
| 7008 | Requested path was invalid or a reference was invalid. |
| 7010 | Requested Path Name associated with this ParamError did not match any instantiated parameters. |
| 7011 | Unable to convert string value to correct data type. |
| 7012 | Out of range or invalid enumeration. |
| 7022 | Command failed to operate. |
| 7026 | Path is not present in the data model schema. |
### Parallel calls over Ubus
Some datamodel operations takes less time to execute compared to other, like
- Get on sub-set of datamodel or an individual datamodel parameter takes very less, where as
- Get on complete Device. and Async operate commands takes much longer
executing/serializing operations simplifies the code from developer perspective, but its not suitable for deployments. To make it suitable `bbfdmd` support parallel calls.
- All datamodel `operate` commands are running in parallel
- `get` calls depends on uci option 'bbfdm.bbfdmd.subprocess_level' (default: 2)
example(s):
```console
root@iopsys:~# time ubus call bbfdm get '{"path":"Device."}' >/dev/null &
root@iopsys:~# time ubus call bbfdm get '{"path":"Device.Users."}' >/dev/null
real 0m 0.07s
user 0m 0.00s
sys 0m 0.00s
root@iopsys:~#
real 0m 1.86s
user 0m 0.05s
sys 0m 0.00s
[1]+ Done time ubus call bbfdm get "{\"path\":\"Device.\"}" >/dev/null
root@iopsys:~#
```
## Datamodel micro-services
Datamodel micro-service is nothing but running a partial datamodel sub-set with another instance of `bbfdmd` binary.
Benefit:
- Instead of having a huge datamodel tree, it split the tree based on modules, which reduce the cost of operation on the tree
- Resolves one point failure, if any datamodel micro-service not working correctly it only affects that specific module, not the rest of the tree
- Moving datamodel code to module repo, brings the service layer and datamodel layer closer, which lowers the possibilities of wrong mapping
- Possible to use lightweight `bbfdmd` inside containers with json plugin for Container service management
- Possible to impose CPU/Memory restrictions or even run it in a procd jail to limit the host resource access
Cons:
- It requires to execute a `bbfdmd` instance each module, so takes bit more resouces
- Resolving of complex datamodel paths, like datamodel references of external modules (ex: `bridgemngr` refers to wifi layer from `wifidmd`) cost more on IPC
When not to use micro-service:
- Its suggested not to use datamodel micro-service specially in the devices which are having very less resources(in terms of memory/cpu), or
- On devices which have high IPC cost over ubus
### How to Use micro-service
Manually configuring and starting a micro-services requires multiple steps, but its made simple by using `bbfdm.mk` compile time helper utility.
To launch a datamodel definition as a datamodel micro-service, user need to install the datamodel definition/plugin using
`BBFDM_INSTALL_MS_DM` API from `bbfdm.mk`
```bash
bulkdata/Makefile: $(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/bbf_plugin/bulkdata.json $(1) $(PKG_NAME)
ddnsmngr/Makefile: $(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/src/libddnsmngr.so $(1) $(PKG_NAME)
```
Please check [bbfdm.mk](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/bbfdm/bbfdm.mk) documentation for more details.
In Devices, datamodel micro-services started and managed by `/etc/init.d/bbfdm.services` init script, which reads the global micro-service related configuration from `bbfdm` uci file, and reads module specific configuration for each module's input file present in `/etc/bbfdm/micro_services/` directory.
> In plugins approach, the 3rd party datamodel gets attached to main bbfdm process, which further increases nodes in main datamodel tree, which overtime become a huge tree, results in slower turn around service time for the APIs. Also, any unhandled fault in plugin result in segfault in main bbfdmd process, which takes down the whole tree along with plugin, resulting in complete failure from cwmp and USP, with micro-services plugins runs as an individual processes, so impact of fault limited to its own micro-service only.
Micro-service approach, disintegrate the plugins further and run them as individual daemons with the help of "bbfdmd" "-m" command line options.
## Datamodel debugging tools
To debug the datamodel objects/parameters, `bbfdmd` provides a command line interface, which can
- Work directly on plugins, or
- Gets the data from an ubus object
and then show it on the CLI. This command line tool is part of `bbfdmd` binary itself and can be accessed with command line argument option '-c' along with binary.
```bash
# bbfdmd -h
Usage: bbfdmd [options]
options:
-s <socket path> ubus socket
-m <json path> json input configuration for micro services
-c <command input> Run cli command
-h Displays this help
#
```
If no command line option provided along with `bbfdmd` command then it starts in daemon mode.
In command (or CLI) mode, it supports interactively querying the data model and setting values in the configuration via the data model. In command (or CLI) mode, it supports interactively querying the data model and setting values in the configuration via the data model.
```bash ```bash
@ -111,90 +365,77 @@ Valid commands:
# #
``` ```
Below is another example of json input file: To debug datamodel mapping/description code, user/developer can use below API to add debug logs
```bash
BBF_ERR(MESSAGE, ...)
BBF_WARNING(MESSAGE, ...)
BBF_INFO(MESSAGE, ...)
BBF_DEBUG(MESSAGE, ...)
```
Above API logs gets logged using syslog, based on log_level defined in `bbfdm`.
To configure the log_level use `bbfdm.bbfdmd.loglevel` uci option.
To configure the log_level in micro-service, update the `loglevel` module json file,
```json ```json
# cat /etc/bbfdm/micro_services/sshmngr.json
{ {
"cli": { "daemon": {
"enable": "1",
"service_name": "sshmngr",
"config": { "config": {
"proto": "usp", // usp, cwmp "loglevel": "1"
"instance_mode": 0 // 0:number, 1:alias
},
"input": {
"type": "UBUS", // JSON, UBUS, DotSO, UNIX
"name": "bbfdm"
},
"output": {
"type": "CLI" // CLI, JSON
} }
} }
} }
``` ```
> NOTE1: `bbfdmd` CLI mode is an experimentation feature and it can be updated later. and then restart the bbfdm.services
> NOTE2: If `-m` option is not passed when starting `bbfdmd`, so configuration options will be loaded from the default [INPUT.JSON](../../test/files/tmp/bbfdm/input.json) located in '/tmp/bbfdm/input.json'. ## How to extend datamodel
* To see the currently implemented data model use: Although `bbfdm/iowrt` provides datamodels for major services, but still for deployment user might need to add some vendor extensions or needs to add the missing datamodel support. To do the same `bbfdm` or more precisely `libbfdm-api` provides the infrastructure to easily define a new datamodel tree.
```console As per TR106 description, a datamodel is, "A hierarchical set of Objects, Parameters, Commands and/or Events that define the managed Objects accessible via a particular Agent."
$ bbfdmd -c schema Device.
```
* To query the value of a parameter use: Please check [TR106](https://www.broadband-forum.org/pdfs/tr-106-1-13-0.pdf) for more details about datamodel terminology.
```console `bbfdm` provide the tools and utilities to further extend/overwrite/disable the datamodel using C-code or simply by using JSON datamodel definition.
root@iopsys:~# bbfdmd -c get Device.Time.
Device.Time.Enable => 0
root@iopsys:~#
root@iopsys:~# bbfdmd -c get Device.WiFi.SSID.1.SSID
Device.WiFi.SSID.1.SSID => test-5g
```
> Note: Wildcard (*) is valid placeholder for multi-instance object instance and partial paths are also allowed. ### JSON datamodel
Pro:
- Easy to add (compilation not required)
- Least maintenance (Change in libbbfdm-api has minimal impact)
Con:
- Can only support easy one to one mappings with uci and ubus
- Invalid plugin syntax might cause faults
### C Based datamodel
Pro:
- Support complex mapping and data sharing between nodes
- Lots of references available
- Tools available to auto-generate the template code
- All core operations supported
Con:
- Moderate maintenance (Change in libbbfdm-api requires adaptation/alignment)
* To set the value of a data model parameter use: Both ways of extending datamodel covered at length with examples in following links
* [How to extend datamodel with C Code](How_to_extend_datamodel_with_C_Code.md)
* [How to extend datamodel with JSON](How_to_extend_datamodel_with_JSON.md)
```console After creating the datamodel definition, it can be installed the help of `bbfdm.mk` APIs to run them from main `bbfdmd` instance or from micro-service instance.
$ bbfdmd -c set "parameter" "value"
```
> Note: The CLI mode also supports adding and deleting instances of data model objects and supported instances. > Note: If a datamodel object added by a micro-service, all datamodel extensions below that path needed to be hanlded in the same micro-service. Like a wifi extension needed to be installed in wifidmd micro-service as a plugin.
### How to choose C or JSON for datamodel extensions
## Important topics C/JSON both datamodel definition support defining all datamodel operations, but JSON should be used with simple datamodel deployments.
* [UBUS methods](bbfdmd_ubus_methods.md)
* [UBUS Errors](bbfdmd_ubus_errors.md)
* [Parallel UBUS call](bbfdmd_ubus_parallel_call.md)
* [Third party datamodel integration](bbfdmd_dm_integration.md)
If its requires to perform more than one step to retrieve data from lowerlayer, it is suggested to use C-Based datamodel definitions, as it gives more control over the data and its mapping, or simply put if JSON plugin does not meets the requirement of datamodel mapping use C-Based definition.
## Dependencies
### Build-Time Dependencies
To successfully build bbfdmd, following libraries are needed:
| Dependency | Link | License |
| ---------- | ------------------------------------------- | -------------- |
| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 |
| libubox | https://git.openwrt.org/project/libubox.git | BSD |
| libubus | https://git.openwrt.org/project/ubus.git | LGPL 2.1 |
| libjson-c | https://s3.amazonaws.com/json-c_releases | MIT |
| libbbfdm-api | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
| libbbfdm | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
### Run-Time Dependencies
In order to run the `bbfdmd`, following dependencies are needed to be running/available before `bbfdmd`.
| Dependency | Link | License |
| ---------- | ---------------------------------------- | -------- |
| ubusd | https://git.openwrt.org/project/ubus.git | LGPL 2.1 |
| libbbfdm-api | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
| libbbfdm | https://dev.iopsys.eu/bbf/bbfdm.git | BSD-3 |
System daemon `ubusd` is used to expose the BBFDM functionality over `ubus`.

View file

@ -1,213 +0,0 @@
# Third party data model integration
It is also possible to itegrate thrid party data model to the bbfdmd to expose it to the ubus. To do so certain APIs in libbbfdm-api needs to be implemented to make the data model compatible with bbfdmd. APIs are described below.
## List of libbbfdm-api methods used in bbfdmd to integrate third party data model
### Refernces
Deatils of libbbfdm-api can be found at [link](../../docs)
following are the libbbfdm-api methods used in bbfdmd to access the data model defined in libbbfdm
```
bbf_entry_method
bbf_ctx_init
bbf_ctx_init_sub
bbf_ctx_clean
bbf_ctx_clean_sub
bbf_entry_restart_services
bbf_entry_revert_changes
```
## Methods
Description of the methods are given below
### bbf_entry_method
used to read the data model based on the input given
```
int bbf_entry_method(struct dmctx *ctx, int cmd)
inputs
struct dmctx *ctx
pointer to struct dmctx strunture. The list of parameter will be updated in ctx.list_parameter. each node in the list is of type
struct dm_parameter which contains char *name, char *data, char *type and char *additional_data;
the content of fields are updated based on the cmd and are as follows-
cmd | Name | Type | Data | Addtional Data |
|------------- |------------- |------------- |------------ |--------------------- |
|BBF_GET_VALUE |Parameter |$ref(type) |Value | NA |
|BBF_GET_NAME |Parameter |$ref(type) |writable(0/1) | NA |
|BBF_SET_VALUE |path | NA | NA | NA |
|BBF_ADD_OBJECT |path | NA | NA | NA |
|BBF_DEL_OBJECT |path | NA | NA | NA |
|BBF_OPERATE |path | NA | NA | NA |
|BBF_SCHEMA |paramter ||$ref(type) |writable(0/1) |unique keys |
|BBF_INSTANCES |parameter | NA |NA |NA |
|BBF_EVENT |path | NA | NA | NA |
int cmd
command to API to tell how the data model is to be read, possible values are
BBF_GET_VALUE - Read the values of the parameters from data model
BBF_GET_NAME - Read the names of the parameters from data model
BBF_SET_VALUE - Set value of specified parameters in the data model
BBF_ADD_OBJECT - Add object in a multi instance parameter in the data model
BBF_DEL_OBJECT - Delete object from a multi instance parameter in the data model
BBF_OPERATE - execute the specified command
BBF_SCHEMA - Read all the parameter type parameter from data model.
BBF_INSTANCES - Read all the instance of multi instance parameter from data model.
BBF_EVENT - execute the specified event
return
int fault
contains the fault code if API is not able to read the data model. returns 0 on success.
```
### bbf_ctx_init
This method is used to initialize the dmctx structure object to read the data model.
```
void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj);
inputs
struct dmctx *ctx
pointer to struct dmctx strunture to be initialized.
return
None
```
### bbf_ctx_init_sub
This method is an extension of bbf_ctx_init method. only difference it only intializes dmctx structure object and does not intializes other resources used in reading data model
```
void bbf_ctx_init_sub(struct dmctx *ctx, DMOBJ *tEntryObj)
inputs
struct dmctx *ctx
pointer to struct dmctx strunture to be initialized.
return
None
```
### bbf_ctx_clean
This method is used to free the dmctx structure object and other resources post reading the data model.
```
void bbf_ctx_clean(struct dmctx *ctx)
input
struct dmctx *ctx
pointer to struct dmctx strunture to be freed.
return
None
```
### bbf_ctx_clean_sub
This method is an extension of bbf_ctx_clean method. only difference is it frees the dmctx structure and does not free other resources used in reading data model
```
void bbf_ctx_clean_sub(struct dmctx *ctx)
input
struct dmctx *ctx
pointer to struct dmctx strunture to be freed.
return
None
```
### bbf_entry_restart_services
This method is used to restart the state of data model whenever its state is changed
```
void bbf_entry_restart_services(struct blob_buf *bb, bool restart_services)
input
struct blob_buf *bb
pointer to the struct blob_buf object. contains all the packages updated.
bool restart_services
if true packages will be updated through ubus call.
if false packages will be updated through uci.
return
None
```
### bbf_entry_revert_changes
This method is used to revert the changes whenever its state is changed
```
void bbf_entry_revert_changes(struct blob_buf *bb)
input
struct blob_buf *bb
pointer to the struct blob_buf object. contains all the packages updated.
return
None
```
### Datamodel Tree
`libbbfdm-api` provides API to easily extend and define datamodel tree.
#### Alias handling
In general datamodel parameters with multi-instance objects has a parameter named as '.Alias' to uniquely identify the instance. libbbf-api provides two generic APIs to handle the get/set of Alias parameters.
These APIs only applicable for standard/dmmap uci mappings.
```bash
/*********************************************************************//**
**
** bbf_get_alias
**
** This API is used to get the Alias parameter value based on s and option_name
**
** \param ctx - bbf context
** \param s - uci section from where will get Alias value
** \param option_name - option name
** \param instance - instance value
** \param value - pointer to where the value will be stored
**
** \return 0 if operation is successful, -1 otherwise
**
**************************************************************************/
int bbf_get_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char **value);
/*********************************************************************//**
**
** bbf_set_alias
**
** This API is used to set the Alias parameter value
**
** \param ctx - bbf context
** \param s - uci section to where will save Alias value
** \param option_name - option name
** \param instance - instance value
** \param value - the value to be set
**
** \return 0 if operation is successful, -1 otherwise
**
**************************************************************************/
int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char *value);
```
Example:
```bash
static int get_WiFiEndPoint_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "endpointalias", instance, value);
}
static int set_WiFiEndPoint_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
return bbf_set_alias(ctx, ((struct dm_data *)data)->dmmap_section, "endpointalias", instance, value);
}
```

View file

@ -1,70 +0,0 @@
# Monitoring Events in the Data Model
`bbfdmd` now supports monitoring events directly from the Data Model, eliminating the need for internal registration and handling within `bbfdmd`.
# How to add an new event
- Insert the event into the required `DMLEAF` table
- Ensure that `leaf_type` is defined as `DMT_EVENT` and `bbfdm_type` as `BBFDM_USP`
- Implement the get/set event API
# How it works
Upon starting `bbfdmd`, it calls `bbf_entry_method` API with `BBF_SCHEMA` method to retrieve all events supported by Data Model. Subsequently, it attempts to register an event handler for each event by using the event name argument defined in each event leaf and then listens for that event name.
When the event name is triggered, `bbfdmd` calls `bbf_entry_method` API with `BBF_EVENT` method to perform the event operation. And finally, it sends `bbfdm.event` ubus event with the required input information obtained from the returned event operation.
# Event Example
Below is an example of `Device.WiFi.DataElements.AssociationEvent.Associated!` event implementation:
static event_args wifidataelementsassociationevent_associated_args = {
.name = "wifi.dataelements.Associated",
.param = (const char *[]) {
"type",
"version",
"protocols",
"BSSID",
"MACAddress",
"StatusCode",
"HTCapabilities",
"VHTCapabilities",
"HECapabilities",
"TimeStamp",
NULL
}
};
static int get_event_args_WiFiDataElementsAssociationEvent_Associated(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = (char *)&wifidataelementsassociationevent_associated_args;
return 0;
}
static int event_WiFiDataElementsAssociationEvent_Associated(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case EVENT_CHECK:
// Nothing to check
break;
case EVENT_RUN:
char *event_time = dmjson_get_value((json_object *)value, 1, "eventTime");
char *bssid = dmjson_get_value((json_object *)value, 3, "wfa-dataelements:AssociationEvent.AssocData", "DisassocData", "BSSID");
char *mac_addr = dmjson_get_value((json_object *)value, 3, "wfa-dataelements:AssociationEvent.AssocData", "DisassocData", "MACAddress");
add_list_parameter(ctx, dmstrdup("TimeStamp"), dmstrdup(event_time), DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(ctx, dmstrdup("BSSID"), dmstrdup(bssid), DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(ctx, dmstrdup("MACAddress"), dmstrdup(mac_addr), DMT_TYPE[DMT_STRING], NULL);
break;
}
return 0;
}
DMLEAF tWiFiDataElementsAssociationEventParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"Associated!", &DMREAD, DMT_EVENT, get_event_args_WiFiDataElementsAssociationEvent_Associated, event_WiFiDataElementsAssociationEvent_Associated, BBFDM_USP},
{0}
};

View file

@ -1,197 +0,0 @@
# UBUS Errors
Today, in addional to the `CWMP` and `USP` standard error messages, bbfdm has introduced a new feature to provide customers more clarification about the root cause of the fault,
and based on that it's easily to understand what the issue is and how to fix it and find out the limitations we have on the device.
Whenever you encounter an error in a specific method(GET/SET/ADD/DELETE/OPERATE), you can use the `fault_msg` option to understand the reason for the error.
## Example of fault messages
1. The requested value is correct as per TR181 standard, but there is a limitation in the device.
```console
root@iopsys:~# ubus call bbfdm set '{"path":"Device.Firewall.Config", "value":"High"}'
{
"results": [
{
"path": "Device.Firewall.Config",
"fault": 9007,
"fault_msg": "The current Firewall implementation supports only 'Advanced' config."
}
]
}
root@iopsys:~# ubus call bbfdm set '{"path":"Device.Firewall.AdvancedLevel", "value":"Device.Firewall.Level.2"}'
{
"results": [
{
"path": "Device.Firewall.AdvancedLevel",
"fault": 9007,
"fault_msg": "The current Firewall implementation supports only one Level. So the value should be 'Device.Firewall.Level.1'."
}
]
}
```
2. The requested value is outside the allowed range.
```console
root@iopsys:~# ubus call bbfdm set '{"path":"Device.Firewall.Chain.1.Rule.9.DestPort", "value":"123456"}'
{
"results": [
{
"path": "Device.Firewall.Chain.1.Rule.9.DestPort",
"fault": 9007,
"fault_msg": "'123456' value is not within range (min: '-1' max: '65535')"
}
]
}
```
3. Some arguments should be defined to perform the requested operation.
```console
root@iopsys:~# ubus call bbfdm operate '{"command":"Device.IP.Diagnostics.IPPing()", "command_key":"ipping_test", "input":{}}'
{
"results": [
{
"path": "Device.IP.Diagnostics.IPPing()",
"data": "ipping_test",
"fault": 7004,
"fault_msg": "IPPing: 'Host' input should be defined"
}
]
}
```
4. The requested method is not permitted since the instance was created by the system.
```console
root@iopsys:~# ubus call bbfdm add '{"path":"Device.Firewall.Chain.2.Rule."}'
{
"results": [
{
"path": "Device.Firewall.Chain.2.Rule.",
"fault": 9003,
"fault_msg": "This is a dynamic 'Chain' instance which is created by 'Port Mapping', so it's not permitted to add a static 'Rule'."
}
]
}
root@iopsys:~# ubus call bbfdm del '{"path":"Device.Firewall.Chain.1.Rule.1."}'
{
"results": [
{
"path": "Device.Firewall.Chain.1.Rule.1.",
"fault": 9003,
"fault_msg": "This is a dynamic 'Rule' instance, therefore it's not permitted to delete it."
}
]
}
```
> Note: If no specific fault message defined for particular obj/param, we return the standard error messages that are defined in CWMP and USP protocols as the fault message value.
## Path syntax and possible error cases
Please note some error scenerios with the bbfdm.
1. The path parameter value must start with 'Device.'. The command below doesn't have Device before path "Users.User."
```console
root@iopsys:~# ubus call bbfdm get '{"path":"Users.User.", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Users.User.",
"fault": 7026,
"fault_msg": "Path is not present in the data model schema"
}
]
}
```
2. The path parameter must end with a '.' if the path element is not a leaf element e.g.,
Note that first two commands doesn't end with a '.' while the command with Alias is correct, due to Alias
being the leaf element. To find correct schema path user can check with dump_schema option.
```console
root@iopsys:~#
root@iopsys:~# ubus call bbfdm get '{"path":"Device.Users.User.4", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Device.Users.User.4",
"fault": 7026,
"fault_msg": "Path is not present in the data model schema"
}
]
}
root@iopsys:~#
root@iopsys:~# ubus call bbfdm get '{"path":"Device.Users.User.*", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Device.Users.User.*",
"fault": 7008,
"fault_msg": "Requested path was invalid or a reference was invalid"
}
]
}
root@iopsys:~#
root@iopsys:~# ubus call bbfdm get '{"path":"Device.Users.User.4.Alias", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Device.Users.User.4.Alias",
"data": "cpe-4",
"type": "xsd:string"
}
]
}
```
3. The path parameter value must use proper '.' separated path search expression. Note that a '.' is missing between User and *
```console
root@eagle-44d43771b550:~# ubus call bbfdm get '{"path":"Device.Users.User.*", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Device.Users.User.*",
"fault": 7008,
"fault_msg": "Requested path was invalid or a reference was invalid"
}
]
}
```
4. The path parameter value must be a valid path schema, in example below SSID is used which is invalid schema element for Device.Users.User.{i}.
```console
root@iopsys:~# ubus call bbfdm get '{"path":"Device.Users.User.1.SSID", "optional": {"format":"raw", "proto":"usp"}}'
{
"results": [
{
"path": "Device.Users.User.1.SSID",
"fault": 7026,
"fault_msg": "Path is not present in the data model schema"
}
]
}
```
#### Errors Codes
| Error Code | Meaning |
|------------|--------------------------------------------------------------|
| 7003 | Message failed due to an internal error. |
| 7004 | Message failed due to invalid values in the request elements and/or failure to update one or more parameters during Add or Set requests. |
| 7005 | Message failed due to memory or processing limitations. |
| 7008 | Requested path was invalid or a reference was invalid. |
| 7010 | Requested Path Name associated with this ParamError did not match any instantiated parameters. |
| 7011 | Unable to convert string value to correct data type. |
| 7012 | Out of range or invalid enumeration. |
| 7022 | Command failed to operate. |
| 7026 | Path is not present in the data model schema. |

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
# Parallel UBUS calls
All `operate` operation and `get` operation with a depth up to 'BBF_SUBPROCESS_DEPTH(2)'
runs in a parallel subprocess to avoid blocking the next call.
```console
root@iopsys:~# time ubus call bbfdm get '{"path":"Device."}' >/dev/null &
root@iopsys:~# time ubus call bbfdm get '{"path":"Device.Users."}' >/dev/null
real 0m 0.07s
user 0m 0.00s
sys 0m 0.00s
root@iopsys:~#
real 0m 1.86s
user 0m 0.05s
sys 0m 0.00s
[1]+ Done time ubus call bbfdm get "{\"path\":\"Device.\"}" >/dev/null
root@iopsys:~#
```

196
docs/guide/libbbfdm-api.md Normal file
View file

@ -0,0 +1,196 @@
# API guide and usages
`libbbfdm-api` provides API to define datamodel objects as well as it also provides APIs to traverse the datamodel definitions.
Most used datamodel APIs described in [libbbfdm_api.h](../../libbbfdm-api/include/libbbfdm_api.h)
Following is the list of APIs used by bbfdmd for tree traversal:
### bbf_entry_method
used to read the data model based on the input given
```
int bbf_entry_method(struct dmctx *ctx, int cmd)
inputs
struct dmctx *ctx
pointer to struct dmctx strunture. The list of parameter will be updated in ctx.list_parameter. each node in the list is of type
struct dm_parameter which contains char *name, char *data, char *type and char *additional_data;
the content of fields are updated based on the cmd and are as follows-
cmd | Name | Type | Data | Addtional Data |
|------------- |------------- |------------- |------------ |--------------------- |
|BBF_GET_VALUE |Parameter |$ref(type) |Value | NA |
|BBF_GET_NAME |Parameter |$ref(type) |writable(0/1) | NA |
|BBF_SET_VALUE |path | NA | NA | NA |
|BBF_ADD_OBJECT |path | NA | NA | NA |
|BBF_DEL_OBJECT |path | NA | NA | NA |
|BBF_OPERATE |path | NA | NA | NA |
|BBF_SCHEMA |paramter ||$ref(type) |writable(0/1) |unique keys |
|BBF_INSTANCES |parameter | NA |NA |NA |
|BBF_EVENT |path | NA | NA | NA |
int cmd
command to API to tell how the data model is to be read, possible values are
BBF_GET_VALUE - Read the values of the parameters from data model
BBF_GET_NAME - Read the names of the parameters from data model
BBF_SET_VALUE - Set value of specified parameters in the data model
BBF_ADD_OBJECT - Add object in a multi instance parameter in the data model
BBF_DEL_OBJECT - Delete object from a multi instance parameter in the data model
BBF_OPERATE - execute the specified command
BBF_SCHEMA - Read all the parameter type parameter from data model.
BBF_INSTANCES - Read all the instance of multi instance parameter from data model.
BBF_EVENT - execute the specified event
return
int fault
contains the fault code if API is not able to read the data model. returns 0 on success.
```
### bbf_ctx_init
This method is used to initialize the dmctx structure object to read the data model.
```
void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj);
inputs
struct dmctx *ctx
pointer to struct dmctx strunture to be initialized.
return
None
```
### bbf_ctx_init_sub
This method is an extension of bbf_ctx_init method. only difference it only intializes dmctx structure object and does not intializes other resources used in reading data model
```
void bbf_ctx_init_sub(struct dmctx *ctx, DMOBJ *tEntryObj)
inputs
struct dmctx *ctx
pointer to struct dmctx strunture to be initialized.
return
None
```
### bbf_ctx_clean
This method is used to free the dmctx structure object and other resources post reading the data model.
```
void bbf_ctx_clean(struct dmctx *ctx)
input
struct dmctx *ctx
pointer to struct dmctx strunture to be freed.
return
None
```
### bbf_ctx_clean_sub
This method is an extension of bbf_ctx_clean method. only difference is it frees the dmctx structure and does not free other resources used in reading data model
```
void bbf_ctx_clean_sub(struct dmctx *ctx)
input
struct dmctx *ctx
pointer to struct dmctx strunture to be freed.
return
None
```
### bbf_entry_restart_services
This method is used to restart the state of data model whenever its state is changed
```
void bbf_entry_restart_services(struct blob_buf *bb, bool restart_services)
input
struct blob_buf *bb
pointer to the struct blob_buf object. contains all the packages updated.
bool restart_services
if true packages will be updated through ubus call.
if false packages will be updated through uci.
return
None
```
### bbf_entry_revert_changes
This method is used to revert the changes whenever its state is changed
```
void bbf_entry_revert_changes(struct blob_buf *bb)
input
struct blob_buf *bb
pointer to the struct blob_buf object. contains all the packages updated.
return
None
```
# Deprecated/removed APIs and user defined datatypes
To support new feature sometimes old APIs provided by libbbfdm-api library needs to be updated, this guide provides a better context to the migration.
Following table has APIs/datatypes which are now deprecated:
| Type | Deprecated API | New API | Comment |
| -------- | ------------------------- | ---------------------------- | ------- |
| function | `bbf_get_reference_param` | `bbfdm_get_references` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| function | `bbf_get_reference_args` | `bbfdm_get_reference_linker` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| stucture | `dmmap_dup` | `dm_data` | Replaced to support the extension for Obj/Param/Operate using JSON plugin |
Following table has list of APIs/datatypes which no longer exists in libbbfdm-api, along with new revised APIs replacement:
| Type | Removed API | New API | Comment |
| -------- | ---------------------------------- | ------------------------------------ | -------------------------------------- |
| function | `dm_validate_string` | `bbfdm_validate_string` | To support fault_msg in case of errors |
| function | `bbf_validate_string` | `bbfdm_validate_string` | To support fault_msg in case of errors |
| function | `bbf_validate_boolean` | `bbfdm_validate_boolean` | To support fault_msg in case of errors |
| function | `bbf_validate_unsignedInt` | `bbfdm_validate_unsignedInt` | To support fault_msg in case of errors |
| function | `bbf_validate_int` | `bbfdm_validate_int` | To support fault_msg in case of errors |
| function | `bbf_validate_unsignedLong` | `bbfdm_validate_unsignedLong` | To support fault_msg in case of errors |
| function | `bbf_validate_long` | `bbfdm_validate_long` | To support fault_msg in case of errors |
| function | `bbf_validate_dateTime` | `bbfdm_validate_dateTime` | To support fault_msg in case of errors |
| function | `bbf_validate_hexBinary` | `bbfdm_validate_hexBinary` | To support fault_msg in case of errors |
| function | `bbf_validate_string_list` | `bbfdm_validate_string_list` | To support fault_msg in case of errors |
| function | `bbf_validate_unsignedInt_list` | `bbfdm_validate_unsignedInt_list` | To support fault_msg in case of errors |
| function | `bbf_validate_int_list` | `bbfdm_validate_int_list` | To support fault_msg in case of errors |
| function | `bbf_validate_unsignedLong_list` | `bbfdm_validate_unsignedLong_list` | To support fault_msg in case of errors |
| function | `bbf_validate_long_list` | `bbfdm_validate_long_list` | To support fault_msg in case of errors |
| function | `bbf_validate_hexBinary_list` | `bbfdm_validate_hexBinary_list` | To support fault_msg in case of errors |
| function | `dm_validate_boolean` | `bbfdm_validate_boolean` | To support fault_msg in case of errors |
| function | `dm_validate_unsignedInt` | `bbfdm_validate_unsignedInt` | To support fault_msg in case of errors |
| function | `dm_validate_int` | `bbfdm_validate_int` | To support fault_msg in case of errors |
| function | `dm_validate_unsignedLong` | `bbfdm_validate_unsignedLong` | To support fault_msg in case of errors |
| function | `dm_validate_long` | `bbfdm_validate_long` | To support fault_msg in case of errors |
| function | `dm_validate_dateTime` | `bbfdm_validate_dateTime` | To support fault_msg in case of errors |
| function | `dm_validate_hexBinary` | `bbfdm_validate_hexBinary` | To support fault_msg in case of errors |
| function | `dm_validate_string_list` | `bbfdm_validate_string_list` | To support fault_msg in case of errors |
| function | `dm_validate_unsignedInt_list` | `bbfdm_validate_unsignedInt_list` | To support fault_msg in case of errors |
| function | `dm_validate_int_list` | `bbfdm_validate_int_list` | To support fault_msg in case of errors |
| function | `dm_validate_unsignedLong_list` | `bbfdm_validate_unsignedLong_list` | To support fault_msg in case of errors |
| function | `dm_validate_long_list` | `bbfdm_validate_long_list` | To support fault_msg in case of errors |
| function | `dm_validate_hexBinary_list` | `bbfdm_validate_hexBinary_list` | To support fault_msg in case of errors |
| function | `dm_entry_validate_allowed_objects`| `dm_validate_allowed_objects` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| function | `dm_entry_validate_external_linker_allowed_objects` | `dm_validate_allowed_objects` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| function | `adm_entry_get_linker_param` | | Removed, no more required |
| function | `adm_entry_get_linker_value` | | Removed, no more required |
| enum | `CMD_SUCCESS` | | Removed, no more required |
| enum | `CMD_INVALID_ARGUMENTS` | | Removed, no more required |
| enum | `CMD_FAIL` | | Removed, no more required |
| enum | `CMD_NOT_FOUND` | | Removed, no more required |
| enum | `__STATUS_MAX` | | Removed, no more required |

View file

@ -1,134 +0,0 @@
# Datamodel additions (DotSO Plugin/ JSON Plugin/ Micro-Service)
It is often required by customers to have/implement some datamodel parameters which is not available in bbfdm, `bbfdm` provides four ways to extend the existing datamodel parameters.
- Using [JSON Plugin](./json_plugin_v1.md)
- Using [DotSO Plugin](./bbfdm_dm_integration.md)
- With bbfdm micro-service
- [Individual datamodel daemon](https://dev.iopsys.eu/voice/tr104)
Out of all the supported method, each have its own pro and cons:
## JSON Plugins
Pro:
- Easy to add (compilation not required)
- Least maintenance (Change in libbbfdm-api has minimal impact)
Con:
- Can only support easy one to one mappings with uci and ubus
- In-tree datamodel references not supported
- Invalid plugin syntax might cause segfault on main bbfdmd service, result in complete cwmp/usp service down
- Make the main tree bigger, which result into slow service time
## DotSO Plugin
Pro:
- Similar to adding in the core
- Support complex mapping and data sharing between nodes
- All core operations supported
Con:
- Moderate maintenance (Change in libbbfdm-api requires adaptation/alignment)
- Any segfault on plugin might teardown main bbfdmd service, result in complete cwmp/usp service down
- Make the main tree bigger, which result into slow service time
## BBFDM micro-service
Pro:
- Creates a sub datamodel tree and registers to main datamodel tree
- Can be used with existing DotSO and JSON Plugins
- Faults in plugins only limited to micro-service, main tree won't gets affected
Con:
- Currently references to out side tree nodes not supported
- Maintenance cost depends on JSON or DotSO plugin selection
## Individual daemon to run micro-service
It has same pro and cons as of running the plugin with micro-service, with a added benefit of low maintenance as all the dependency embedded in single binary.
## Workflow of Individual daemon and micro-service
daemon started by the init script, it adds its own ubus objects based on input and wait for parent/master ubus object, once master ubus object available, it registers self with the main tree.
`icwmp` and `obuspa` gets the datamodel from main tree which is provided by `bbfdm` daemon, so no change required in either cwmp and obuspa.
## Summary
In plugins approach, the 3rd party datamodel gets attached to main bbfdm process, which further increases nodes in main datamodel tree, which overtime become a huge tree, results in slower turn around service time for the APIs.
Also with plugins, since its part of main process, any unhandled fault result in segfault in main bbfdmd process, which takes down the whole tree along with it, resulting in complete failure from cwmp and USP, with micro-services plugins runs as an individual processes, so impact of fault limited to its own process only.
Micro-service approach, disintegrate the plugins further and run them as individual daemons with the help of "bbfdmd" "-m" command line options.
## How to switch to micro-service model
It's a three step process, if DotSO or JSON plugin already present, if not refer to the plugins document.
1. Install the DotSO/JSON plugin to non-bbf plugin location
2. Create an json file with required input parameters, like below
```json
{
"daemon": {
"config": {
"loglevel": "1"
},
"input": {
"type": "JSON", // JSON or DotSO
"name": "/etc/bulkdata/bulkdata.json" // Path of the plugin
},
"output": {
"type": "UBUS",
"parent_dm": "Device.", // Parent tree to attach the plugin
"object": "BulkData", // Name of the object
"root_obj": "bbfdm" // Name of the root tree ubus object which is bbfdm
}
}
}
```
3. Place this json file in micro-service(`/etc/bbfdm/micro_services`) directory
```bash
$ cat /etc/bbfdm/micro_services/bulkdata.json
{
"daemon": {
"config": {
"loglevel": "1"
},
"input": {
"type": "JSON",
"name": "/etc/bulkdata/bulkdata.json"
},
"output": {
"type": "UBUS",
"parent_dm": "Device.",
"object": "BulkData",
"root_obj": "bbfdm"
}
}
}
```
Which then gets started by `bbfdmd` init script.
## When to switch to micro-service model
There are few parameters which can help in answer this query,
1. If a plugin add significantly huge amount of nodes to main tree
2. If the service known to miss-behave and cause faults
3. If a plugin add a service with no/less dependency on other datamodel parameters
## DotSO Plugins examples
- [STUN](https://dev.iopsys.eu/bbf/stunc.git)
- [UDPEcho](https://dev.iopsys.eu/bbf/udpecho.git)
- [SoftwareModule](https://dev.iopsys.eu/bbf/swmodd.git)
- [XMPP](https://dev.iopsys.eu/bbf/xmpp.git)
- [TWAMP](https://dev.iopsys.eu/bbf/twamp-light.git)
- [Usermngr](https://dev.iopsys.eu/bbf/usermngr.git)
- [ManagementServer](https://dev.iopsys.eu/bbf/icwmp.git)
## JSON Plugin example
- [URLFilter](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/urlfilter/files/etc/bbfdm/json/urlfilter.json)
- [XPON](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/ponmngr/files/etc/bbfdm/json/xpon.json)
## Micro service example
- [Bulkdata](https://dev.iopsys.eu/feed/iopsys/-/commit/8bdfd3ea51a81941ee9c53a46a66cf6c0f6eb88f)
- [PeriodicStats](https://dev.iopsys.eu/feed/iopsys/-/commit/66163d394586b953b8f891f91afb1677df29403a)
## Individual daemons
- [TR104](https://dev.iopsys.eu/feed/iopsys/-/commit/7160fadf5607fcc785fd13e41eac402da6164280)

View file

@ -1,425 +0,0 @@
# BBFDM Dynamic Object/Parameter/Operate/Event
`bbfdm` library allows all applications installed on the box to import its own Data Model parameters at run time in two formats:
- **Shared library**
- **JSON files**
## 1. Shared library via external package
The application should bring its shared library under **'/usr/share/bbfdm/plugins'** 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 icwmpd and bbfdmd/obuspa.
Each library should contains the Root table: **“tDynamicObj”**
### DynamicObject definition
The “tDynamicObj” table contains entries of **DM_MAP_OBJ** structure.
The **DM_MAP_OBJ** structure contains three arguments:
| Argument | Description |
| ---------------- | ------------------------------------------------------------------------------------------------------------- |
| `parentobj` | A string of the parent object name. Example “Device.IP.Diagnostics.”, “Device.DeviceInfo”, “Device.WiFi.Radio.” |
| `nextobject` | Pointer to a **DMOBJ** array which contains a list of the child objects |
| `parameter` | Pointer to a **DMLEAF** array which contains a list of the child parameters |
For the other tables, they are defined in the same way as the Object and Parameter definition described above.
> Note1: Shared library can only add vendor or standard objects that are not implemented by `libbbfdm`
> Note2: Shared library is not allowed to overwrite objects/parameters
- For more examples on the external packages, you can see these links: [BulkData](https://dev.iopsys.eu/bbf/bulkdata/-/blob/master/datamodel.c), [XMPP](https://dev.iopsys.eu/bbf/xmppc/-/blob/master/datamodel.c)
### 2. JSON File via external package
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 icwmpd and bbfdmd/obuspa.
#### Some examples on JSON Definition
**1. Object without instance:**
```bash
"Device.CWMP.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"access": false
}
```
**2. Object with instance:**
- **UCI command:** uci show wireless | grep wifi-device
```bash
"Device.X_IOPSYS_EU_Radio.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"access": true,
"mapping": {
"type": "uci",
"uci": {
"file": "wireless",
"section": {
"type": "wifi-device"
},
"dmmapfile": "dmmap_wireless"
}
}
}
```
- **UBUS command:** ubus call dsl status | jsonfilter -e @.line
```bash
"Device.DSL.Line.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"access": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl",
"method": "status",
"args": {},
"key": "line"
}
}
}
```
**3. Parameter under object with instance:**
- **UCI option command:** uci get wireless.@wifi-device[0].country
- **@i:** is the number of instance object
```bash
"Country": {
"type": "string",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": [
{
"type" : "uci",
"uci" : {
"file" : "wireless",
"section" : {
"type": "wifi-device",
"index": "@i-1"
},
"option" : {
"name" : "country"
}
}
}
]
}
```
- **UCI list command:** uci get urlfilter.@profile[0].whitelist_url
- **@i:** is the number of instance object
```bash
"WhitelistURL": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"list": {
"datatype": "string"
},
"mapping": [
{
"type": "uci",
"uci": {
"file": "urlfilter",
"section": {
"type": "profile",
"index": "@i-1"
},
"list": {
"name": "whitelist_url"
}
}
}
]
}
```
- **UBUS command:** ubus call wifi status | jsonfilter -e @.radios[0].noise
- **@i:** is the number of instance object
```bash
"Noise": {
"type": "int",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": [
{
"type" : "ubus",
"ubus" : {
"object" : "wifi",
"method" : "status",
"args" : {},
"key" : "radios[@i-1].noise"
}
}
]
}
```
**4. Parameter without instance:**
- **UCI option command:** uci get cwmp.cpe.userid
```bash
"Username": {
"type": "string",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": [
{
"type" : "uci",
"uci" : {
"file" : "cwmp",
"section" : {
"type": "cwmp",
"name": "cpe"
},
"option" : {
"name" : "userid"
}
}
}
]
}
```
- **UCI list command:** uci get urlfilter.globals.blacklist_url
- **@i:** is the number of instance object
```bash
"BlacklistURL": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"list": {
"datatype": "string"
},
"mapping": [
{
"type": "uci",
"uci": {
"file": "urlfilter",
"section": {
"name": "globals"
},
"list": {
"name": "blacklist_url"
}
}
}
]
}
```
- **UBUS command:** ubus call system info | jsonfilter -e @.uptime
```bash
"Uptime": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": [
{
"type" : "ubus",
"ubus" : {
"object" : "system",
"method" : "info",
"args" : {},
"key" : "uptime"
}
}
]
}
```
- **UBUS command:** ubus call system info | jsonfilter -e @.memory.total
```bash
"Total": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": [
{
"type" : "ubus",
"ubus" : {
"object" : "system",
"method" : "info",
"args" : {},
"key" : "memory.total"
}
}
]
}
```
**5. Parameter to map another data model Object:**
- **UCI option command:** uci get urlfilter.@filter[0].profile
- **linker_obj** is the path name of an object that is stacked immediately below this object
```bash
"Profile": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"mapping": [
{
"type": "uci",
"uci": {
"file": "urlfilter",
"section": {
"type": "filter",
"index": "@i-1"
},
"option": {
"name": "profile"
}
},
"linker_obj": "Device.{BBF_VENDOR_PREFIX}URLFilter.Profile.*.Name"
}
]
}
```
**6. Object with Event and Operate command:**
```bash
{
"Device.X_IOPSYS_Test.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"access": false,
"Push!": {
"type": "event",
"protocols": [
"usp"
],
"data": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"usp"
]
}
},
"Status()": {
"type": "command",
"async": true,
"protocols": [
"usp"
],
"input": {
"Option": {
"type": "string",
"read": "true",
"write": "true",
"protocols": [
"usp"
]
}
},
"output": {
"Result": {
"type": "string",
"read": "true",
"write": "false",
"protocols": [
"usp"
]
}
},
"mapping": [
{
"type": "ubus",
"ubus": {
"object": "test",
"method": "status"
}
}
]
}
}
}
```
> Note1: JSON File can only add vendor or standard objects that are not implemented by `libbbfdm`
> Note2: JSON File is not allowed to overwrite objects/parameters
> Note3: Set, Add, Delete methods are only allowed for uci mapping. therefore for ubus mapping, only Get method is authorized
> Note4: Each object definition in JSON file must begin with "Device." and should have the full parent path if it is under another object
- For more examples on JSON files, you can see these links: [X_IOPSYS_EU_MCPD](https://dev.iopsys.eu/feed/broadcom/-/blob/devel/mcpd/files/etc/bbfdm/json/X_IOPSYS_EU_MCPD.json), [X_IOPSYS_EU_Dropbear](../../test/files/etc/bbfdm/json/X_IOPSYS_EU_Dropbear.json), [X_IOPSYS_EU_TEST](../../test/files/etc/bbfdm/json/X_IOPSYS_EU_TEST.json)

View file

@ -1,97 +0,0 @@
# JSON Plugin Version 2
The purpose of this document is to describe the new features supported by JSON Plugin V2.
JSON Plugin Version 2 introduces enhancements to the previous versions by providing increased flexibility in extending, overwriting, and excluding objects/parameters/commands/events from the core data model.
## How It Works
To illustrate how the new features work, let's consider the following example JSON Plugin:
```json
{
"json_plugin_version": 2,
"Device.WiFi.AccessPoint.{i}.Security.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"access": false,
"array": false,
"{BBF_VENDOR_PREFIX}KeyPassphrase": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"datatype": "string",
"mapping": [
{
"data": "@Parent",
"type": "uci_sec",
"key": "key"
}
]
},
"WEPKey": {
"type": "string",
"read": true,
"write": true,
"protocols": [
"cwmp",
"usp"
],
"datatype": "string",
"mapping": [
{
"data": "@Parent",
"type": "uci_sec",
"key": "wek_key"
}
]
},
"SAEPassphrase": {
"type": "string",
"read": true,
"write": false,
"protocols": [
"none"
]
}
}
}
```
The JSON Plugin V2 operates by parsing the JSON file. Then it checks the parent top object, which in this example is `Device.WiFi.AccessPoint.{i}.Security`.
- If this object exists in the core data model, the plugin proceeds to examine the next each subsequent level to determine the necessary action for each JSON object.
- If the object does not exist in the core data model, it is extended.
- If the object exists, it is either overwritten or excluded, depending on the defined protocols. If the protocols array is defined as 'none', the object is excluded.
- If the parent top object does not exist in the core data model, the plugin follows the old behavior defined in JSON Plugin V0 and V1, which is extending the core data model.
Examples
- Device.WiFi.AccessPoint.{i}.Security.X_IOPSYS_EU_KeyPassphrase: This parameter will be extended to the core data model since it does not exist.
- Device.WiFi.AccessPoint.{i}.Security.WEPKey: This parameter will be overwritten in the core data model since it already exists.
- Device.WiFi.AccessPoint.{i}.Security.SAEPassphrase: This parameter will be excluded from the core data model since it exists, but the new protocol defined is `none`.
## Important Notes
> Note1: To utilize the functionalities described, ensure that JSON version 2 is specified in the plugin by `json_plugin_version` option.
> Note2: When extending a multiple-instance object, align the passed data from the browse function to children (LEAF) by keeping it `(struct uci_section *)data` pointer in case of the `type` is `uci_sec` or `(json_object *)data` pointer in case of the `type` is `json`.
> Note3: The mapping format used by JSON Plugin V2 follows the format of version 1. Ensure that all mappings are aligned with JSON Plugin V1 specifications.
> Note4: Additional examples for each feature can be found in the following links:[Extend](../../test/vendor_test/test_extend.json), [Overwrite](../../test/vendor_test/test_overwrite.json), and [Exclude](../../test/vendor_test/test_exclude.json).
## Features Supported with JSON Plugin V2
- Allow extending the core tree with simple mappings based on the data passed from the parent object.
- Allow overwriting an existing object, parameter, command, or event from the core tree.
- Allow excluding an existing object, parameter, command, or event from the core tree.

View file

@ -1,55 +0,0 @@
# Migration of deprecated/removed APIs and user defined datatypes
To support new feature sometimes old APIs provided by libbbfdm-api library needs to be updated, this guide provides a better context to the migration.
Following table has deprecated and new APIs, datatypes:
| Type | Deprecated API | New API | Comment |
| ---- | -------------- | ------- | ------- |
| function | `int bbf_get_reference_param(char *path, char *key_name, char *key_value, char **value)` | `int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_path, char *key_name, char *key_value, char *out, size_t out_len)` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| function | `int bbf_get_reference_args(char *value, struct dm_reference *reference_args)` | `int bbfdm_get_reference_linker(struct dmctx *ctx, char *reference_path, struct dm_reference *reference_args)` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| stucture | `struct dmmap_dup` | `structure dm_data` | Replaced to support the extension for Obj/Param/Operate using JSON plugin |
Following table has removed and new APIs, datatypes:
| Type | Removed API | New API | Comment |
| ---- | -------------- | ------- | ------- |
| function | `dm_validate_string(char *value, int min_length, int max_length, char *enumeration[], char *pattern[])` | `int bbfdm_validate_string(struct dmctx *ctx, char *value, int min_length, int max_length, char *enumeration[], char *pattern[])`| Replace to support fault_msg in case of errors |
| function | `bbf_validate_string(char *value, int min_length, int max_length, char *enumeration[], char *pattern[])` | `int bbfdm_validate_string(struct dmctx *ctx, char *value, int min_length, int max_length, char *enumeration[], char *pattern[])`| Replace to support fault_msg in case of errors |
| function | `bbf_validate_boolean(char *value)` | `int bbfdm_validate_boolean(struct dmctx *ctx, char *value)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_unsignedInt(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedInt(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_int(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_int(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_unsignedLong(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedLong(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_long(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_long(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_dateTime(char *value)` | `int bbfdm_validate_dateTime(struct dmctx *ctx, char *value)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_hexBinary(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_hexBinary(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_string_list(char *value, int min_item, int max_item, int max_size, int min, int max, char *enumeration[], char *pattern[])` | `int bbfdm_validate_string_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, int min, int max, char *enumeration[], char *pattern[])` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_unsignedInt_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedInt_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_int_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_int_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_unsignedLong_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedLong_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `bbf_validate_long_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_long_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)`| Replace to support fault_msg in case of errors |
| function | `bbf_validate_hexBinary_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_hexBinary_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_boolean(char *value)` | `int bbfdm_validate_boolean(struct dmctx *ctx, char *value)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_unsignedInt(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedInt(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_int(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_int(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_unsignedLong(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedLong(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_long(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_long(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_dateTime(char *value)` | `int bbfdm_validate_dateTime(struct dmctx *ctx, char *value)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_hexBinary(char *value, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_hexBinary(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_string_list(char *value, int min_item, int max_item, int max_size, int min, int max, char *enumeration[], char *pattern[])` | `int bbfdm_validate_string_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, int min, int max, char *enumeration[], char *pattern[])` | Replace to support fault_msg in case of errors |
| function | `dm_validate_unsignedInt_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedInt_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_int_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_int_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_unsignedLong_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_unsignedLong_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `dm_validate_long_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_long_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)`| Replace to support fault_msg in case of errors |
| function | `dm_validate_hexBinary_list(char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | `int bbfdm_validate_hexBinary_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size)` | Replace to support fault_msg in case of errors |
| function | `int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *objects[])` | `int dm_validate_allowed_objects(struct dmctx *ctx, struct dm_reference *reference, char *objects[])` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| function | `int dm_entry_validate_external_linker_allowed_objects(struct dmctx *ctx, char *value, char *objects[])` | `int dm_validate_allowed_objects(struct dmctx *ctx, struct dm_reference *reference, char *objects[])` | Replaced with a generic API that is accessible for both internal (bbfdm core) and external (microservices) data models |
| function | `int adm_entry_get_linker_param(struct dmctx *ctx, char *param, char *linker, char **value)` | | Removed, no more required |
| function | `int adm_entry_get_linker_value(struct dmctx *ctx, char *param, char **value)` | | Removed, no more required |
| enum | `CMD_SUCCESS` | | Removed, no more required |
| enum | `CMD_INVALID_ARGUMENTS` | | Removed, no more required |
| enum | `CMD_FAIL` | | Removed, no more required |
| enum | `CMD_NOT_FOUND` | | Removed, no more required |
| enum | `__STATUS_MAX` | | Removed, no more required |

View file

@ -1,167 +0,0 @@
# How to add support for a new Object/Parameter
As mentioned in README, all Data Models are stored in the **'dmtree'** folder. In order to implement a new object/parameter, you need to expand its get/set/add/delete functions and then save them in the right folder.
`bbfdm` library offers a tool to generate templates of the source code from json files placed under **'dmtree/json'**. So, any developer can fill the data model json file [data_model](../../libbbfdm/dmtree/json/datamodel.json) with mapping field according to UCI, UBUS or CLI commands then generate the source code in C.
```bash
$ ./convert_dm_json_to_c.py
Usage: ./tools/convert_dm_json_to_c.py [Object path]
Examples:
- ./tools/convert_dm_json_to_c.py
==> Generate the C code of full data model in datamodel/ folder
- ./tools/convert_dm_json_to_c.py Device.DeviceInfo.
==> Generate the C code of Device.DeviceInfo object in datamodel/ folder
```
Below some examples of **UCI**, **UBUS** or **CLI** mappings:
#### UCI command
- **@Name:** the section name of parent object
- **@i:** is the number of instance object
```bash
"mapping": [
{
"type": "uci",
"uci": {
"file": "wireless",
"section": {
"type": "wifi-device",
"name": "@Name",
"index": "@i-1"
},
"option": {
"name": "disabled"
}
}
}
]
```
#### UBUS command
- **@Name:** the section name of parent object
```bash
"mapping": [
{
"type": "ubus",
"ubus": {
"object": "network.device",
"method": "status",
"args": {
"name": "@Name"
},
"key": "statistics.rx_bytes"
}
}
]
```
#### CLI command:
- **@Name:** the section name of parent object
- **-i:** is the number of arguments command
```bash
"mapping": [
{
"type" : "cli",
"cli" : {
"command" : "wlctl",
"args" : [
"-i",
"@Name",
"bands"
]
}
}
]
```
After building the templates of C source code, a **datamodel** folder will be generated under **'tools'** folder that contains all files related to each object under root "**Device.**"
> Note: You can generate the source code without filling out the mapping field in the JSON file
### Object definition
Each object in the **DMOBJ** table contains the following arguments:
| Argument | Description |
| ------------------- | ---------------------------------------------------------------------------------------------- |
| `OBJ` | A string of the object name. Example “Bridging”, “IP”, “DeviceInfo”, “WiFi” |
| `permission` | The permission of the object. Could be **&DMREAD** or **&DMWRITE**. If it's `&DMWRITE` then we can add/delete instances of this object |
| `addobj` | The function to add new instance under this object. This function will be triggered when the ACS/Controller call AddObject of this object |
| `delobj` | The function to delete instance under this object. This function will be triggered when the ACS/Controller call DeleteObject of an instance of this object |
| `checkdep` | A string of the object dependency, it can be a file("file:/etc/config/network") or an ubus object,method("ubus:network.interface->status"). If it's `NULL` then the object has always appeared in the tree |
| `browseinstobj` | This function allow to browse all instances under this object |
| `nextdynamicobj` | Pointer to the next of **DMOBJ** which contains a list of the child objects using json files, shared libraries and vendor extension |
| `dynamicleaf` | Pointer to the next of **DMLEAF** which contains a list of the child parameters using json files, shared libraries and vendor extension |
| `nextobj` | Pointer to a **DMOBJ** array which contains a list of the child objects |
| `leaf` | Pointer to a **DMLEAF** array which contains a list of the child parameters |
| `linker` | This argument is deprecated and should be `NULL` |
| `bbfdm_type` | The bbfdm type of the object. Could be **BBFDM_CWMP**, **BBFDM_USP**, **BBFDM_BOTH** or **BBFDM_NONE**.If it's **BBFDM_BOTH** then we can see this object in all protocols (CWMP, USP,...) |
| `uniqueKeys` | This argument is deprecated and should be `NULL` |
### Leaf definition
Each leaf in the **DMLEAF** table can be a **Parameter**, **Command** or **Event**.
#### 1.Parameter definition
| Argument | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `PARAM` | A string of the parameter name. Example “Enable”, “Status”, “Name” |
| `permission` | The permission of the parameter. Could be **&DMREAD** or **&DMWRITE**.If it's `&DMWRITE` then we can set a value for this parameter |
| `type` | Type of the parameter: **DM_STRING**, **DM_BOOL**, **DM_UNINT**,... |
| `getvalue` | The function which return the value of this parameter |
| `setvalue` | The function which set the value of this parameter |
| `bbfdm_type` | The bbfdm type of the parameter. Could be **BBFDM_CWMP**, **BBFDM_USP**, **BBFDM_BOTH** or **BBFDM_NONE**.If it's **BBFDM_BOTH** then we can see this parameter in all protocols (CWMP, USP,...) |
| `dm_falgs` | An enumeration value used to specify the displayed parameter value. Could be **DM_FLAG_REFERENCE**, **DM_FLAG_UNIQUE**, **DM_FLAG_LINKER** or **DM_FLAG_SECURE**. |
#### 2.Command definition
| Argument | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `PARAM` | A string of the command name. Example “IPPing()”, “DownloadDiagnostics()”, “Renew()” |
| `permission` | The permission of the command. Could be **&DMASYNC** or **&DMSYNC**. |
| `type` | Type of the command, It should be **DMT_COMMAND** |
| `getvalue` | The function which return the input, output arguments of the command |
| `setvalue` | The function which call the operation of the command |
| `bbfdm_type` | The bbfdm type of the command. It should be **BBFDM_USP** as long as operate commands are only defined in USP protocol. |
#### 3.Event definition
| Argument | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `PARAM` | A string of the event name. Example “Boot!”, “Push!”, “Periodic!” |
| `permission` | The permission of the event. It should be **DMREAD** |
| `type` | Type of the event, It should be **DMT_EVENT** |
| `getvalue` | The function which return the parameter arguments of the event |
| `setvalue` | The function which call the operation of the event |
| `bbfdm_type` | The bbfdm type of the event. It should be **BBFDM_USP** as long as events are only defined in USP protocol. |
### Browse definition
The browse function allow to go over all instances of the current object and link them to the data model tree.
In this function, there are two functions that need to be defined:
- function to retrieve the instances: it can be:
* `handle_instance` function: allow to retrieve/attribute the instances number/alias from uci config sections depending of the request and the instance mode.
* `handle_instance_without_section` function: allow to attribute the instances number/alias with constant values.
- function to link the instances: To link each instance to the data model tree, it's necessary to call `DM_LINK_INST_OBJ()` API for every instance. Additionally, it's **mandatory** to use the generic structure `(struct dm_data *)` as passed `data` at each instance level in order to maintain the capability to extend the data model using `JSON` plugin. This structure will be utilized later in functions related to sub-objects and parameters (Get/Set/Add/Delete/Operate/Event).
> Note1: the browse function is only developed for multi-instances objects.
> Note2: you can use [bbf_test plugin](../../test/bbf_test/bbf_test.c) as a reference in order to develop any new object/leaf/browse.

View file

@ -1,82 +0,0 @@
# BBFDM Vendor
The `bbfdm` library offers functionality for vendors to define their vendor extensions. This allows them to **extend** the core Data Model by introducing new objects/parameters/operates/events, **overwrite** and **exclude** existing ones.
## How to Add a New Vendor
### 1. Create a Vendor Folder
To add a new vendor, simply create a new folder under **'dmtree/vendor/'** which contains all files related to the vendor. Ensure that the folder name matches the vendor name specified in **BBF_VENDOR_LIST** macro.
### 2. Populate the `tDynamicObj` Table
For extending, overwriting, and excluding objects/parameters/operates/events from the core tree, it's mandatory to have a `tDynamicObj` table. This table should be defined using **DM_MAP_OBJ** structure, which has three arguments:
| Argument | Description |
| ---------------- | ------------------------------------------------------------------------------------------------------------- |
| `parentobj` | A string representing the parent object name from which to extend/exclude/overwrite the required items. Example: "Device.IP.Diagnostics.", "Device.WiFi.Radio." |
| `nextobject` | Pointer to a **DMOBJ** array containing a list of child objects to extend/exclude/overwrite |
| `parameter` | Pointer to a **DMLEAF** array containing a list of child parameters to extend/exclude/overwrite |
- The `parentobj` must be a string path of an **object** available in the core tree. If it doesn't exist, it will be skipped during parsing of the `tDynamicObj` table.
- To extend the Data Model tree, fill the `nextobject` and `parameter` arguments with the required objects/parameters/operates/events not supported by the core tree.
- To overwrite existing objects/parameters/operates/events in the core tree, fill the `nextobject` and `parameter` arguments with the same items defined in the core tree, along with new **add/del/get/set/browse** APIs needed by the vendor.
- To exclude existing objects/parameters/operates/events in the core tree, fill the `nextobject` and `parameter` arguments with the same items defined in the core tree, and setting **bbfdm_type** to **BBFDM_NONE**.
### 3. Enable vendor
To enable the new vendor:
- Add the vendor to the list in **BBF_VENDOR_LIST** macro.
- Define the vendor prefix using **BBF_VENDOR_PREFIX** macro.
Example Configuration Options:
```bash
BBF_VENDOR_LIST="iopsys,xxxx"
BBF_VENDOR_PREFIX="X_IOPSYS_EU_"
```
## Example how to Extend, Overwrite and Exclude the Data Model tree
In the [test/vendor_test/](../../test/vendor_test) directory, you'll find an example implementation for **test** vendor. This implementation demonstrates how to extend, overwrite, and exclude objects/parameters/operates/events from the core tree.
### 1. Extend Data Model
- using DotSo Plugin:
- Add support for [Device.Firewall.Chain.{i}.Rule.{i}.X_TEST_COM_TimeSpan.](../../test/vendor_test/firewall.c#L172) object
- 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#L60) object
- Add support for [Device.WiFi.X_IOPSYS_EU_TEST1](../../test/vendor_test/test_extend.json#L11) parameter
### 2. Overwrite Data Model
- using DotSo Plugin:
- Overwrite [Device.X_IOPSYS_EU_Dropbear.{i}.](../../test/vendor_test/device.c#L18) object in the core tree
- 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#L11) object in the core tree
- Overwrite [Device.DeviceInfo.ProcessorNumberOfEntries](../../test/vendor_test/test_overwrite.json#L30) parameter in the core tree
### 3. Exclude Data Model
- using DotSo Plugin:
- Exclude [Device.USB.](../../test/vendor_test/device.c#L17) object from the core tree
- 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#L28) object from the core tree
- Exclude [Device.InterfaceStackNumberOfEntries](../../test/vendor_test/test_exclude.json#L52) 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.

View file

@ -43,7 +43,7 @@ echo "1..${num}" >> ./funl-result.log
generate_report python_test ./funl-result.log generate_report python_test ./funl-result.log
# run functional on bbf object validation # run functional on bbf object validation
cp -r ./schemas/ubus/bbfdm.json /usr/share/rpcd/schemas/bbf.json cp -r ./docs/api/ubus/bbfdm.json /usr/share/rpcd/schemas/bbf.json
ubus-api-validator -t 10 -f ./test/funl/validation/bbf.validation.json > ./funl-result.log ubus-api-validator -t 10 -f ./test/funl/validation/bbf.validation.json > ./funl-result.log
fault=$? fault=$?
generate_report bbf_positive ./funl-result.log generate_report bbf_positive ./funl-result.log

View file

@ -29,19 +29,12 @@ INSTALL(TARGETS bbfdm
INSTALL(DIRECTORY DESTINATION etc/bbfdm) INSTALL(DIRECTORY DESTINATION etc/bbfdm)
INSTALL(DIRECTORY DESTINATION etc/bbfdm/dmmap) INSTALL(DIRECTORY DESTINATION etc/bbfdm/dmmap)
INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/scripts)
INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/plugins) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/plugins)
INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/micro_services) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/micro_services)
INSTALL(DIRECTORY DESTINATION usr/share/bbfdm) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm)
INSTALL(DIRECTORY DESTINATION usr/libexec/rpcd) INSTALL(DIRECTORY DESTINATION usr/libexec/rpcd)
FILE(GLOB scripts scripts/*)
FOREACH(script ${scripts})
INSTALL(FILES ${script}
PERMISSIONS OWNER_EXECUTE
DESTINATION usr/share/bbfdm/scripts
)
ENDFOREACH()
string(REPLACE "," ";" VENDOR_LIST ${BBF_VENDOR_LIST}) string(REPLACE "," ";" VENDOR_LIST ${BBF_VENDOR_LIST})

File diff suppressed because it is too large Load diff

View file

@ -364,6 +364,7 @@ def download_and_build_plugins(plugins, vendor_prefix):
dm_files = get_option_value(plugin, "dm_files") dm_files = get_option_value(plugin, "dm_files")
is_microservice = get_option_value(plugin, "is_microservice") is_microservice = get_option_value(plugin, "is_microservice")
extra_dependencies = get_option_value(plugin, "extra_dependencies", []) extra_dependencies = get_option_value(plugin, "extra_dependencies", [])
dm_desc_file = get_option_value(plugin, "dm_info_file", "")
repo_path = None repo_path = None
name=os.path.basename(repo).replace('.git','') name=os.path.basename(repo).replace('.git','')
@ -394,6 +395,11 @@ def download_and_build_plugins(plugins, vendor_prefix):
BBF_ERROR_CODE += 1 BBF_ERROR_CODE += 1
continue continue
create_folder(".repo/dm_info")
if dm_desc_file.endswith('.json'):
dest_file = ".repo/dm_info/" + os.path.basename(dm_desc_file).replace('.json', f"_{plugin_index}.json")
rename_file(repo_path + "/" + dm_desc_file, dest_file)
LIST_FILES = [] LIST_FILES = []
os.chdir(repo_path) os.chdir(repo_path)
for dm_file in dm_files: for dm_file in dm_files:

View file

@ -8,6 +8,7 @@ import json
import bbf_common as bbf import bbf_common as bbf
import generate_dm_xml as bbf_xml import generate_dm_xml as bbf_xml
import generate_dm_excel as bbf_excel import generate_dm_excel as bbf_excel
import glob
def print_dm_usage(): def print_dm_usage():
@ -97,6 +98,13 @@ else:
bbf.create_folder(output_dir) bbf.create_folder(output_dir)
print("Dumping default DM_JSON_FILES")
print(DM_JSON_FILES)
DM_JSON_FILES.extend(glob.glob('.repo/dm_info/*.json'))
print("Dumping all")
print(DM_JSON_FILES)
if isinstance(file_format, list): if isinstance(file_format, list):
for _format in file_format: for _format in file_format:

View file

@ -128,7 +128,8 @@
"version": "devel", "version": "devel",
"dm_files": [ "dm_files": [
"src/times.c" "src/times.c"
] ],
"dm_info_file": "src/datamodel_description.json"
}, },
{ {
"repo": "https://dev.iopsys.eu/bbf/timemngr.git", "repo": "https://dev.iopsys.eu/bbf/timemngr.git",
@ -211,6 +212,7 @@
"repo": "https://dev.iopsys.eu/hal/ethmngr.git", "repo": "https://dev.iopsys.eu/hal/ethmngr.git",
"proto": "git", "proto": "git",
"version": "devel", "version": "devel",
"dm_info_file": "bbf_plugin/datamodel_description.json",
"dm_files": [ "dm_files": [
"bbf_plugin/ethernet.c", "bbf_plugin/ethernet.c",
"bbf_plugin/dmlayer.c" "bbf_plugin/dmlayer.c"
@ -240,6 +242,7 @@
"repo": "https://dev.iopsys.eu/network/bridgemngr.git", "repo": "https://dev.iopsys.eu/network/bridgemngr.git",
"proto": "git", "proto": "git",
"version": "devel", "version": "devel",
"dm_info_file": "src/driver_vlan_backend/datamodel_description.json",
"dm_files": [ "dm_files": [
"src/driver_vlan_backend/bridging.c", "src/driver_vlan_backend/bridging.c",
"src/driver_vlan_backend/common.c" "src/driver_vlan_backend/common.c"
@ -311,6 +314,7 @@
"repo": "https://dev.iopsys.eu/hal/mcastmngr.git", "repo": "https://dev.iopsys.eu/hal/mcastmngr.git",
"proto": "git", "proto": "git",
"version": "devel", "version": "devel",
"dm_info_file": "bbf_plugin/datamodel_description.json",
"dm_files": [ "dm_files": [
"bbf_plugin/mcast_bbf.c", "bbf_plugin/mcast_bbf.c",
"bbf_plugin/x_iopsys_eu_igmp.c", "bbf_plugin/x_iopsys_eu_igmp.c",
@ -321,6 +325,7 @@
"repo": "https://dev.iopsys.eu/voice/tr104.git", "repo": "https://dev.iopsys.eu/voice/tr104.git",
"proto": "git", "proto": "git",
"version": "devel", "version": "devel",
"dm_info_file": "libdm/extensions/iowrt/datamodel_description.json",
"dm_files": [ "dm_files": [
"libdm/tr104/*.c" "libdm/tr104/*.c"
], ],

80
utilities/README.md Normal file
View file

@ -0,0 +1,80 @@
# Utilities to support datamodel deployments
This directory has sets of small utilities to ease the datamodel deployments and integration with higher layer application protocols.
List of utilities:
1. bbf.diag
2. bbf.secure
3. bbf.config
## bbf.diag utility
`bbf.diag` is a `rpcd` libexec based utility, which is responsible for providing ubus backend to few datamodel diagnostics commands like:
- ipping
- nslookup
- serverselection
- udpecho
### How to add a new bbf.diag utility
To add a new bbf.diag utility user has to add an script with below syntax
```bash
#!/bin/sh
. /usr/share/libubox/jshn.sh
. /usr/share/bbfdm/scripts/bbf_api
__list() {
json_add_object "test"
json_add_string "host" "str"
json_close_object
}
__error() {
json_init
json_add_string "Status" "$1"
}
__launch() {
json_init
json_add_string "Status" "$1"
}
if [ "$1" = "list" ]; then
__list
elif [ -n "$1" ]; then
__launch "$1"
else
__error "Error_Internal" "1"
fi
```
User needs to install this newly added script using `BBFDM_INSTALL_SCRIPT` bbfdm.mk API.
References:
- [Diagnostics Scripts](https://dev.iopsys.eu/bbf/tr143d/-/tree/devel/scripts/bbf_diag)
- [Installation](https://dev.iopsys.eu/feed/iopsys/-/blob/devel/tr143/Makefile)
## bbf.secure utility
USP[TR369 Specifications](https://usp.technology/specification/index.html#sec:special-roles) requirement of 'SecuredRole' requires bbfdm layer to retrieve and provide the Secured(Password/key) parameter values in plain text.
But storing Secured parameters in plain text in uci/filesystem is bit of a security risk, to mitigate the risk `bbf.secure` provides way to store the Secured parameter values in hashed format.
A how to use guide for bbf.secure available [here](https://dev.iopsys.eu/feed/iopsys/-/tree/devel/bbfdm?ref_type=heads#bbf_obfuscation_key)
## bbf.config utility
OpenWRT way of reloading services with `ubus call uci commit '{"name":"<uci_name>"}` does not perfectly fits with datamodel requirements. It send a trigger via rpcd to procd by using this ubus call which returns instantly, internally procd reloads for all the services which has a reload dependency configured on that specific uci.
Sometimes, there is a good amount of delay in trigger and actual service reload.
Bbf.config solves that by adding an in-build reload monitoring functionality which get the list of impacted services and then monitor for PID change for the services with a timeout of 10 sec, with this we make sure Higher layer application(icwmp/obsupa) waits for the application before processing more command.
Currently have two variants of bbf.config, which can be enabled with below compile time configs
1. CONFIG_BBF_CONFIGMNGR_SCRIPT_BACKEND => Simple rpcd script based backend
2. CONFIG_BBF_CONFIGMNGR_C_BACKEND => C based application backend with PID monitoring (default)