README
uspd
is a TR-369/USP backend ubus daemon process to understand USP syntax defined in R-ARC.7 - R-ARC.12 and provide details.
Note 1: The command outputs shown in this readme are examples only, actual output may differ based on device and configuration. Note 2: Long command outputs are compressed for better readability
Project Components
Project consists of following components:
- Application itself written in C programming language
- Documentation in a Markdown format
Build Instructions
uspd
is written using C programming language and depends on a number of components found in OpenWrt for building and running.
UCI Config
uspd requires a configuration file to provide more granular objects over ubus. Granularity is an optional feature of uspd, it can be skipped or set to level 0. The configuration file is an uci file /etc/config/uspd
. Sample configuration file is provided below.
config uspd 'usp'
option granularitylevel '0'
option loglevel '2'
In the above uci, log_level can have below value:
log_level | Meaning |
---|---|
0 | Uspd will not log anything |
1 | Only errors will be loged |
2 | Only errors and warnings will be loged |
3 | Log everything except debug |
4 | Everything will be loged |
For more info on the UCI uspd configuration see link
Ubus API
uspd
needs to be started on startup after ubusd
, as it exposes the USP functionality over ubus. By default(when granularity is not set in uci), uspd registers below two namespaces with ubus.
root@iopsys:~# ubus list |grep usp
usp
usp.raw
Each namespace provide the similar result but in different formats. usp
namespace is to provide the output as required by USP
or End User
or in pretty format, whereas usp.raw
namespace is to provide output in raw format, which can be used by other USP frontend applications(like: obuspa). Each namespace has below functionalities.
root@iopsys:~# ubus -v list usp
'usp' @deb5f751
"dump_schema":{}
"list_operate":{}
"get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"set":{"path":"String","value":"String","values":"Table","proto":"String","key":"String"}
"operate":{"path":"String","action":"String","input":"Table","proto":"String"}
"add_object":{"path":"String","proto":"String","key":"String"}
"del_object":{"path":"String","proto":"String","key":"String"}
"getm_values":{"paths":"Array","proto":"String","next-level":"Boolean"}
"getm_names":{"paths":"Array","proto":"String","next-level":"Boolean"}
"getm_attributes":{"paths":"Array","proto":"String","next-level":"Boolean"}
"setm_attributes":{"paths":"Array","proto":"String"}
root@iopsys:~#
root@iopsys:~# ubus -v list usp.raw
'usp.raw' @ff9d104b
"dump_schema":{}
"list_operate":{}
"get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"set":{"path":"String","value":"String","values":"Table","proto":"String","key":"String"}
"operate":{"path":"String","action":"String","input":"Table","proto":"String"}
"add_object":{"path":"String","proto":"String","key":"String"}
"del_object":{"path":"String","proto":"String","key":"String"}
"getm_values":{"paths":"Array","proto":"String","next-level":"Boolean"}
"getm_names":{"paths":"Array","proto":"String","next-level":"Boolean"}
"getm_attributes":{"paths":"Array","proto":"String","next-level":"Boolean"}
"setm_attributes":{"paths":"Array","proto":"String"}
root@iopsys:~#
Note:
proto
in each method specify the datamodel prototype('cwmp', 'usp') to use, if not provided default datamodel will be used.
The objects registered with the above namespaces can be called with appropriate parameters to perform a USP Get/Set/Operate/Add Object/Delete Object
operation as below.
Overview
uspd provides below commands in pretty(usp) or raw(usp.raw) formats:
- Get
- Get multiple values
- Get multiple names
- Get multiple attributes
- Set
- Set multiple attributes
- Operate
- Add object
- Delete object
- Object names
- Instances
- Validate
- Dump schema
- List operate
It also provide a granularity layer which can be configured using uci parameter and provide additional ubus objects.
Granularity
Granularity feature is basically exposes the same USP functionality by registering additinal ubus namespaces to reduce the path
length in ubus parameter. It is the number of levels upto which we want to shorten the length.
Ex:
- When Granularity is set to 1, exposed ubus namespaces are
root@iopsys:~# ubus list|grep usp
usp
usp.Device.
usp.raw
- When Granularity is set to 2, exposed ubus namespaces are
root@iopsys:~# ubus list|grep usp
usp
usp.Device.
usp.Device.Bridging.
usp.Device.DHCPv4.
usp.Device.DHCPv6.
usp.Device.DNS.
usp.Device.DeviceInfo.
usp.Device.DynamicDNS.
usp.Device.Ethernet.
usp.Device.Firewall.
usp.Device.Hosts.
usp.Device.IP.
usp.raw
root@iopsys:~#
These granular ubus objects provides the same functionality as of usp
ubus namespace
root@iopsys:~# ubus -v list usp.Device.WiFi.
'usp.Device.WiFi.' @6fd43aca
"dump_schema":{}
"list_operate":{}
"get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
"set":{"path":"String","value":"String","values":"Table","proto":"String","key":"String"}
"operate":{"path":"String","action":"String","input":"Table","proto":"String"}
"add_object":{"path":"String","proto":"String","key":"String"}
"del_object":{"path":"String","proto":"String","key":"String"}
"getm_values":{"paths":"Array","proto":"String","next-level":"Boolean"}
"getm_attributes":{"paths":"Array","proto":"String","next-level":"Boolean"}
"getm_names":{"paths":"Array","proto":"String","next-level":"Boolean"}
"setm_attributes":{"paths":"Array","proto":"String"}
root@iopsys:~#
Registered method can be called with appropriate parameters, like:
root@iopsys:~# ubus call usp.Device. get '{"path":"Users."}'
{
"Users": {
"User": [
{
"Alias": "cpe-1",
"Enable": true,
"Language": "",
"Password": "",
"RemoteAccessCapable": true,
"Username": "user"
},
{
"Alias": "cpe-2",
"Enable": true,
"Language": "",
"Password": "",
"RemoteAccessCapable": true,
"Username": "support"
},
{
"Alias": "cpe-3",
"Enable": true,
"Language": "",
"Password": "",
"RemoteAccessCapable": true,
"Username": "admin"
}
],
"UserNumberOfEntries": 3
}
}
root@iopsys:~#
root@iopsys:~# ubus call usp.Device. getm_values '{"paths":["Device.Users.User.1.Username","Device.Users.User.2.Username"]}'
{
"Device.Users.User.1.Username": "user",
"Device.Users.User.2.Username": "support"
}
root@iopsys:~#
Get
API to query the value of a specific object.
usp
ubus namespace:
To get the output in pretty format use root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"usp"}'
{
"Diagnostics": {
"IPv4DownloadDiagnosticsSupported": true,
"IPv4PingSupported": true,
"IPv4ServerSelectionDiagnosticsSupported": true,
"IPv4TraceRouteSupported": true,
"IPv6UploadDiagnosticsSupported": true,
"UDPEchoConfig": {
"BytesReceived": 0,
"BytesResponded": 0,
"TimeFirstPacketReceived": "0",
"TimeLastPacketReceived": "0",
"UDPPort": 0
}
}
}
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"cwmp"}'
{
"Diagnostics": {
"DownloadDiagnostics": {
"BOMTime": "0",
"DSCP": 0,
"DiagnosticsState": "None",
"DownloadDiagnosticMaxConnections": 1,
"TotalBytesSent": 0,
"TotalBytesSentUnderFullLoading": 0
},
"IPPing": {
"AverageResponseTime": 0,
"AverageResponseTimeDetailed": 0,
"DSCP": 0,
"DataBlockSize": 64,
"ProtocolVersion": "Any",
"SuccessCount": 0,
"Timeout": 1000
},
"IPv4DownloadDiagnosticsSupported": true,
"IPv4PingSupported": true,
"IPv4ServerSelectionDiagnosticsSupported": true,
"IPv6UDPEchoDiagnosticsSupported": true,
"IPv6UploadDiagnosticsSupported": true,
}
}
}
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.Users."}'
{
"Users": {
"User": [
{
"Alias": "cpe-1",
"Enable": true,
"Language": "",
"Password": "",
"RemoteAccessCapable": true,
"Username": "user"
},
{
"Alias": "cpe-2",
"Enable": true,
"Language": "",
"Password": "",
"RemoteAccessCapable": true,
"Username": "support"
},
{
"Alias": "cpe-3",
"Enable": true,
"Language": "",
"Password": "",
"RemoteAccessCapable": true,
"Username": "admin"
}
],
"UserNumberOfEntries": 3
}
}
usp.raw
ubus namespace:
To get the output in raw format use root@iopsys:~# ubus call usp.raw get '{"path":"Device.Users."}'
{
"parameters": [
{
"parameter": "Device.Users.User.1.Alias",
"value": "cpe-1",
"type": "xsd:string"
},
{
"parameter": "Device.Users.User.1.Enable",
"value": "1",
"type": "xsd:boolean"
},
{
"parameter": "Device.Users.User.1.Language",
"value": "",
"type": "xsd:string"
},
{
"parameter": "Device.Users.User.1.Password",
"value": "",
"type": "xsd:string"
},
{
Get multiple values
API to get values to specific object, object name must be provided in paths
paratermer array.
root@iopsys:~# ubus call usp getm_values '{"paths":["Device.Users.Us
er.1.","Device.Users.User.2."]}'
{
"Device.Users.User.1.": {
"Alias": "cpe-1",
"Enable": "1",
"Language": "",
"Password": "",
"RemoteAccessCapable": "1",
"Username": "user"
},
"Device.Users.User.2.": {
"Alias": "cpe-2",
"Enable": "1",
"Language": "",
"Password": "",
"RemoteAccessCapable": "1",
"Username": "support"
}
}
Get multiple attributes
API to get attributes to specific object, object name must be provided in paths
paratermer array.
root@iopsys:~# ubus call usp getm_attributes '{"paths":["Device.Users.User.1.","Device.Users.User.2."]}'
{
"Device.Users.User.1.": {
"Alias": "0",
"Enable": "0",
"Language": "0",
"Password": "0",
"RemoteAccessCapable": "0",
"Username": "0"
},
"Device.Users.User.2.": {
"Alias": "0",
"Enable": "0",
"Language": "0",
"Password": "0",
"RemoteAccessCapable": "0",
"Username": "0"
}
}
Set
API to set value to specific object, object name must be provided in path
parameter and vlaue in value
paratermer.
root@iopsys:~# ubus call usp set '{"path":"Device.WiFi.SSID.[BSSID==\"34:E3:80:76:01:22\"].SSID", "value":"test-2g"}'
{
"parameters": [
{
"status": true,
"path": "Device.WiFi.SSID.1.SSID"
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.[BSSID==\"34:E3:80:76:01:22\"].SSID"}'?
{
"SSID": [
{
"SSID": "test-2g"
}
]
}
Set multiple attributes
API to set multiple attributes to specific object, object name must be provided in paths
paratermer array.
root@iopsys:~# ubus call usp setm_attributes '{"paths":[{"path":"Device.DeviceIn
fo.SerialNumber","notify-type":"1","notify":"1"}]}'
{
"parameters": [
{
"path": "Device.DeviceInfo.SerialNumber"
}
]
}
Add object
API to add new objects in multi-instance object
root@iopsys:~# ubus call usp add_object '{"path":"Device.Users.User"}'
{
"status": true,
"instance": "4"
}
Delete object
API to delete an existing object from multi-instance object
root@iopsys:~# ubus call usp del_object '{"path":"Device.Users.User.[Username==\"user_2\"]."}'
{
"parameters": [
{
"parameter": "Device.Users.User.2.",
"status": true
}
]
}
Operate
API to run operate/diagnostics commands as defined in TR-369
root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Diagnostics.", "action":"IPPing","input":{"Host":"iopsys.eu"}}'
{
"Results": [
{
"path": "Device.IP.Diagnostics.IPPing",
"result": [
{
"AverageResponseTime": 0,
"AverageResponseTimeDetailed": 0,
"FailureCount": 3,
"MaximumResponseTime": 0,
"MaximumResponseTimeDetailed": 0,
"MinimumResponseTime": 9999,
"MinimumResponseTimeDetailed": 999999999,
"SuccessCount": 0
}
]
}
]
}
root@iopsys:~# ubus call usp.raw operate '{"path":"Device.IP.Diagnostics.", "action":"IPPing","input":{"Host":"iopsys.eu"}}'
{
"Results": [
{
"path": "Device.IP.Diagnostics.IPPing",
"parameters": [
{
"parameter": "AverageResponseTime",
"value": "0",
"type": "xsd:unsignedInt"
},
{
"parameter": "AverageResponseTimeDetailed",
"value": "0",
"type": "xsd:unsignedInt"
},
{
"parameter": "FailureCount",
"value": "3",
"type": "xsd:unsignedInt"
},
{
}
]
}
root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Interface.[Name==\"wan\"].", "action":"Reset"}'
{
"Results": [
{
"path": "Device.IP.Interface.2.Reset",
"result": [
{
}
]
}
]
}
root@iopsys:~# ubus call usp.raw operate '{"path":"Device.IP.Interface.[Name==\"wan\"].", "action":"Reset"}'
{
"Results": [
{
"path": "Device.IP.Interface.2.Reset",
"parameters": [
]
}
]
}
Instances
API to get the available instances of an multi-instance object. USP Instances method returns the registered instances.
root@iopsys:~# ubus call usp instances '{"path":"Device.IP.Interface.", "proto":"usp"}'
{
"parameters": [
{
"parameter": "Device.IP.Interface.1."
},
{
"parameter": "Device.IP.Interface.1.IPv4Address.1."
},
{
"parameter": "Device.IP.Interface.2."
},
{
"parameter": "Device.IP.Interface.3."
},
{
"parameter": "Device.IP.Interface.3.IPv4Address.1."
},
{
"parameter": "Device.IP.Interface.3.IPv6Address.1."
},
{
"parameter": "Device.IP.Interface.3.IPv6Prefix.1."
}
]
}
List Operate
API to list all operate command objects
root@iopsys:~# ubus call usp list_operate
{
"parameters": [
{
"parameter": "Device.DHCPv4.Client.{i}.Renew()",
"type": "sync"
},
{
"parameter": "Device.DNS.Diagnostics.NSLookupDiagnostics()",
"type": "async"
},
{
{
"parameter": "Device.IP.Diagnostics.IPPing()",
"type": "async"
},
{
"parameter": "Device.IP.Diagnostics.TraceRoute()",
"type": "async"
},
{
"parameter": "Device.IP.Diagnostics.UDPEchoDiagnostics()",
"type": "async"
},
{
"parameter": "Device.IP.Interface.{i}.Reset()",
"type": "sync"
},
{
"parameter": "Device.Reboot()",
"type": "sync"
},
{
Dump schema
API to dump all registered schema paths,
{
"parameters": [
{
"parameter": "Device.ATM.Link.{i}.",
"writable": "1",
"type": "xsd:object"
},
{
"parameter": "Device.ATM.Link.{i}.Alias",
"writable": "1",
"type": "xsd:string"
},
{
"parameter": "Device.ATM.Link.{i}.DestinationAddress",
"writable": "1",
"type": "xsd:string"
},
{
"parameter": "Device.ATM.Link.{i}.Enable",
"writable": "1",
"type": "xsd:boolean"
},
{
Path syntax and possible error cases
Please note some error scenerios with the uspd.
- The path parameter value must start with 'Device.'. The command below doesn't have Device before path "Users.User."
root@iopsys:~# ubus call usp.raw get '{"path":"Users.User."}'
{
"fault": 7026
}
- 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.
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.4"}'
{
"fault": 7026
}
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User"}'
{
"fault": 9005
}
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.*"}'
{
"fault": 7026
}
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.4.Alias"}'
{
"Alias": "cpe-4"
}
- In path parameter value below, note that, the first search expression 'Type==Normal' is string which should be used as : Type=="Normal"
root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==Normal].IPv4Address.[AddressingType==\"Static\"].IPAddress"}'
{
"fault": 7008
}
root@iopsys:~#
root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==\"Normal\"].IPv4Address.[AddressingType==\"Static\"].IPAddress"}'
{
"Interface": [
{
"IPv4Address": [
{
"IPAddress": "2.0.0.3"
}
]
}
]
}
- The path parameter value must not have an empty search expression
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.[]."}'
{
"fault": 9005
}
- The path parameter value must use proper '.' seperated path search expression. Note that a '.' is missing between User and *
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User*."}'
{
"fault": 7026
}
- 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}.
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.1.SSID"}'
{
"fault": 7026
}
- Please note that in search expression, string comparison only work with "==" or "!=". Whereas in command below its =
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.[Username=\"user\"].Alias"}'
{
"fault": 7008
}
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
Uspd can also handle parallel object calls, e.g.,
root@iopsys:~# time ubus call usp.raw get '{"path":"Device."}' >/dev/null &
root@iopsys:~# time ubus call usp.raw 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 usp.raw get "{\"path\":\"Device.\"}" >/dev/null
root@iopsys:~#
More example
root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.SSID"}'
{
"SSID": [
{
"SSID": "NORRLAND-34E380760120"
},
{
"SSID": "NORRLAND-34E380760120"
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.BSSID"}'
{
"SSID": [
{
"BSSID": "34:E3:80:76:01:22"
},
{
"BSSID": "34:E3:80:76:01:23"
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.[BSSID==\"34:E3:80:76:01:22\"].SSID"}'
{
"SSID": [
{
"SSID": "NORRLAND-34E380760120"
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Status==\"Up\"].IPv4Address.[AddressingType==\"DHCP\"].IPAddress"}'
{
"Interface": [
{
"IPv4Address": [
{
"IPAddress": "192.168.0.96"
}
]
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Status==\"Up\"].IPv4Address.[AddressingType==\"DHCP\"&&Status==\"Up\"]."}'
{
"Interface": [
{
"IPv4Address": [
{
"AddressingType": "DHCP",
"Alias": "cpe-2",
"Enable": true,
"IPAddress": "192.168.0.96",
"Status": "Up",
"SubnetMask": "255.255.255.0",
"X_IOPSYS_EU_FirewallEnabled": true
}
]
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==\"Normal\"&&Stats.PacketsSent<=500].IPv4Address.[AddressingType==\"Static\"].IPAddress"}'
{
"Interface": [
{
"IPv4Address": [
{
"IPAddress": "192.168.1.1"
}
]
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.AccessPoint.[SSIDReference+.SSID==\"NORRLAND-34E380760120\"].AssociatedDevice.[Noise>15].SignalStrength"}
'
{
"AccessPoint": [
{
"AssociatedDevice": [
{
"SignalStrength": -31
}
]
}
]
}
root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.LowerLayers#1+.Name"}'
{
{
"Name": "wlan0",
"Name": "wlan2"
}
}
root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.*.Username"}'
{
"User": [
{
"Username": "user"
},
{
"Username": "support"
},
{
"Username": "admin"
}
]
}
root@iopsys:~# ubus call usp.raw set '{"path":"Device.IP.Diagnostics.IPPing.DiagnosticsState", "value":"Requested", "proto":"cwmp"}'
{
"parameters": [
{
"path": "Device.IP.Diagnostics.IPPing.DiagnosticsState",
"status": true,
"flag": 16
}
]
}
root@iopsys:~# ubus call usp.raw set '{"path":"Device.Users.User.2.Username", "value":"abc", "proto":"cwmp"}'
{
"parameters": [
{
"path": "Device.Users.User.2.Username",
"status": true,
"flag": 0
}
]
}
root@iopsys:~# ubus call usp.raw set '{"path":"Device.Users.User.2.Username", "value":"abc"}'
{
"parameters": [
{
"path": "Device.Users.User.2.Username",
"status": true
}
]
}
root@iopsys:~# ubus call usp.raw list_inform
{
"parameters": [
{
"parameter": "Device.DeviceInfo.ActiveFirmwareImage",
"value": "Device.DeviceInfo.FirmwareImage.1",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.Description",
"value": "Iopsys code analysis test simulator",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.HardwareVersion",
"value": "1.0",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.Manufacturer",
"value": "iopsys",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.ManufacturerOUI",
"value": "XXX",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.ModelName",
"value": "ModelName",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.ProductClass",
"value": "FirstClass",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.ProvisioningCode",
"value": "",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.SerialNumber",
"value": "000000001",
"type": "xsd:string"
},
{
"parameter": "Device.DeviceInfo.SoftwareVersion",
"value": "IOPSYS-CODE-ANALYSIS",
"type": "xsd:string"
},
{
"parameter": "Device.ManagementServer.AliasBasedAddressing",
"value": "true",
"type": "xsd:boolean"
},
{
"parameter": "Device.ManagementServer.ConnReqJabberID",
"value": "",
"type": "xsd:string"
},
{
"parameter": "Device.ManagementServer.ConnReqXMPPConnection",
"value": "",
"type": "xsd:string"
},
{
"parameter": "Device.ManagementServer.ConnectionRequestURL",
"value": "",
"type": "xsd:string"
},
{
"parameter": "Device.ManagementServer.ParameterKey",
"value": "",
"type": "xsd:string"
}
]
}
root@iopsys:~# ubus call usp.raw init_notify '{"proto":"cwmp", "amd_version":5, "instance_mode": 0}'
root@iopsys:~#
Concepts and Workflow
uspd internally uses libbbfdm to get the datamodel objects. On startup it parses the uci file to check if the granularity is set and then as per the granularity value it registers the required ubus namespaces.
When a ubus method is called it first checks the path
parameter to identify if it has special USP syntax, if present it parses and determine the correct objects from libbbfdm, then proceeds with the Get/Set/Operate/Add/Del
operation on the quilified objects.
So, uspd
search for [[+*]+
in path expression, if it matches then segments the path and get the schema from libbbfdm
and store it in a link-list, then it proceeds with the next segment to filter out the unneeded schema paths. It keeps on doing so till all the expressions are solved and it finally left with qualified objects.
Once all the expressions are solved, it starts getting the values for qualified objects and store it in a stack
to print the output in pretty format.
For operate command, it solve the path expression and then call bbf_operate
from libbbfdm
to execute the operate command.
uspd
uses dm_entry_param_method
API from libbbfdm
to get the device tree schema and it's values.
In short, it covers/supports the new syntax introduced in TR-369
by using the existing datamodel available with libbbfdm.
Dependencies
Build-Time Dependencies
To successfully build uspd, 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 | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 |
Run-Time Dependencies
In order to run the uspd, following dependencies are needed to be running/available before uspd.
Dependency | Link | License |
---|---|---|
ubusd | https://git.openwrt.org/project/ubus.git | LGPL 2.1 |
libbbfdm | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 |
System daemon ubusd is used to expose the USP functionality over ubus.