mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
BBF: Library to expose dynamic DM over ubus
This commit is contained in:
parent
947ecd0bea
commit
8a1c125ddb
18 changed files with 4055 additions and 12 deletions
|
|
@ -6,6 +6,7 @@ stages:
|
||||||
- static_code_analysis
|
- static_code_analysis
|
||||||
- unit_test
|
- unit_test
|
||||||
- functional_test
|
- functional_test
|
||||||
|
- libbbf_ubus_test
|
||||||
- memory_test
|
- memory_test
|
||||||
- uspd
|
- uspd
|
||||||
|
|
||||||
|
|
@ -55,6 +56,23 @@ run_functional_api_test:
|
||||||
- timestamp.log
|
- timestamp.log
|
||||||
- functional-api-test-coverage.xml
|
- functional-api-test-coverage.xml
|
||||||
|
|
||||||
|
run_libbbf_ubus_test:
|
||||||
|
stage: libbbf_ubus_test
|
||||||
|
image: iopsys/code-analysis:latest
|
||||||
|
allow_failure: false
|
||||||
|
script:
|
||||||
|
- "./gitlab-ci/setup.sh"
|
||||||
|
- "./gitlab-ci/libbbf_ubus_api_test.sh"
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
junit: ./report/tap.xml
|
||||||
|
paths:
|
||||||
|
- timestamp.log
|
||||||
|
- memory-report.xml
|
||||||
|
- api-result.log
|
||||||
|
|
||||||
run_tools_test:
|
run_tools_test:
|
||||||
stage: unit_test
|
stage: unit_test
|
||||||
image: iopsys/code-analysis:latest
|
image: iopsys/code-analysis:latest
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
|
||||||
libbbfdm_includedir = $(includedir)/libbbfdm
|
libbbfdm_includedir = $(includedir)/libbbfdm
|
||||||
libbbf_api_includedir = $(includedir)/libbbf_api
|
libbbf_api_includedir = $(includedir)/libbbf_api
|
||||||
|
libbbf_ubus_includedir = $(includedir)/libbbf_ubus
|
||||||
|
|
||||||
libbbfdm_tr181_includedir = $(libbbfdm_includedir)
|
libbbfdm_tr181_includedir = $(libbbfdm_includedir)
|
||||||
libbbfdm_include_HEADERS = *.h
|
libbbfdm_include_HEADERS = *.h
|
||||||
libbbf_api_include_HEADERS = libbbf_api/*.h
|
libbbf_api_include_HEADERS = libbbf_api/*.h
|
||||||
|
libbbf_ubus_include_HEADERS = include/*.h
|
||||||
|
|
||||||
SUBDIRS = bin
|
SUBDIRS = bin libbbf_ubus
|
||||||
|
|
|
||||||
29
README.md
29
README.md
|
|
@ -1,6 +1,15 @@
|
||||||
# BroadBand Forum Data Models (BBFDM)
|
# BroadBand Forum Data Models (BBFDM)
|
||||||
|
|
||||||
`bbfdm` is a data model library implementation which includes a list of objects, parameters and operates used for CPE management through remote control protocols such as [TR-069/CWMP](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/).
|
`bbfdm` is a data model library implementation which includes a list of objects, parameters and operates used for CPE management through remote control protocols such as [TR-069/CWMP](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/).
|
||||||
|
This package comprises of the below libraries:
|
||||||
|
|
||||||
|
| Library | Description |
|
||||||
|
| ------- | ------------------------------------------------- |
|
||||||
|
| libbbfdm | This provides the mechanism to add new parameters or extend the existing DM tree using json plugin or shared library plugin. |
|
||||||
|
| libbbf_api | This provides the APIs for UCI, Ubus, JSON, CLI and memory management. |
|
||||||
|
| libbbf_ubus | This library helps to expose the datamodel directly over ubus. Application can expose any datamodel(need not be part of "Device."/TR-181) using this library. |
|
||||||
|
|
||||||
|
Note: Applications that use libbbf_ubus to expose datamodel, not required to use libbbfdm.
|
||||||
|
|
||||||
## Design of bbfdm
|
## Design of bbfdm
|
||||||
|
|
||||||
|
|
@ -19,6 +28,7 @@
|
||||||
│ ├── openwrt
|
│ ├── openwrt
|
||||||
│ └── vendor.h
|
│ └── vendor.h
|
||||||
├── libbbf_api
|
├── libbbf_api
|
||||||
|
├── libbbf_ubus
|
||||||
├── scripts
|
├── scripts
|
||||||
└── tools
|
└── tools
|
||||||
```
|
```
|
||||||
|
|
@ -37,6 +47,8 @@
|
||||||
|
|
||||||
- `libbbf_api` folder which contains the source code of all API functions (UCI, Ubus, JSON, CLI and memory management)
|
- `libbbf_api` folder which contains the source code of all API functions (UCI, Ubus, JSON, CLI and memory management)
|
||||||
|
|
||||||
|
- `libbbf_ubus` folder which contains the source code of all API functions helps in exposing datamodel directly over ubus
|
||||||
|
|
||||||
- `scripts` folder which contains the Diagnostics scripts
|
- `scripts` folder which contains the Diagnostics scripts
|
||||||
|
|
||||||
- `tools` folder which contains some tools to generate Data Model in C, JSON, XML and Excel format
|
- `tools` folder which contains some tools to generate Data Model in C, JSON, XML and Excel format
|
||||||
|
|
@ -1034,9 +1046,21 @@ The input json file should be defined as follow:
|
||||||
|
|
||||||
- For more examples of tools input json file, you can see this link: [tools_input.json](./devel/tools/tools_input.json)
|
- For more examples of tools input json file, you can see this link: [tools_input.json](./devel/tools/tools_input.json)
|
||||||
|
|
||||||
## Dependencies
|
# How to expose datamodel over ubus directly with the help of libbbf APIs
|
||||||
|
|
||||||
To successfully build libbbfdm, the following libraries are needed:
|
`Libbbf_ubus` is the library that helps in exposing the datamodel over ubus directly using libbbf_api.
|
||||||
|
Application using `libbbf_ubus`, shall not use the `libbbfdm` library because all needed operations from `libbbfdm` library has been internally handled in `libbbf_ubus`.
|
||||||
|
|
||||||
|
To identify the mechanism of exposing datamodel directly over ubus please refer to the sample code [dmtest.c](./test/dynamicdm_ubus_test/bbf_ubus.c)
|
||||||
|
|
||||||
|
For more info you can see the schemas at:
|
||||||
|
|
||||||
|
- Raw schema [link](./schemas/dmtest.json)
|
||||||
|
- Markdown schema [link](./docs/api/dmtest.md)
|
||||||
|
|
||||||
|
## Dependencies of of libbbfdm and libbbf_ubus
|
||||||
|
|
||||||
|
To successfully build libbbfdm or libbbf_ubus, the following libraries are needed:
|
||||||
|
|
||||||
| Dependency | Link | License |
|
| Dependency | Link | License |
|
||||||
| ----------- | ------------------------------------------- | -------------- |
|
| ----------- | ------------------------------------------- | -------------- |
|
||||||
|
|
@ -1047,3 +1071,4 @@ To successfully build libbbfdm, the following libraries are needed:
|
||||||
| libcurl | https://dl.uxnr.de/mirror/curl | MIT |
|
| libcurl | https://dl.uxnr.de/mirror/curl | MIT |
|
||||||
| libtrace | https://github.com/apietila/libtrace.git | GPLv2 |
|
| libtrace | https://github.com/apietila/libtrace.git | GPLv2 |
|
||||||
| libbbf_api | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 |
|
| libbbf_api | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
AC_INIT([libbbfdm], [0.1], [mohamed.kallel@pivasoftware.com])
|
AC_INIT([libbbfdm], [0.1], [mohamed.kallel@pivasoftware.com])
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||||
|
|
||||||
|
AC_CONFIG_SUBDIRS([libbbf_ubus])
|
||||||
|
|
||||||
AC_ARG_ENABLE(tr181, [AS_HELP_STRING([--enable-tr181], [enable tr181 device feature])], AC_DEFINE(BBF_TR181),)
|
AC_ARG_ENABLE(tr181, [AS_HELP_STRING([--enable-tr181], [enable tr181 device feature])], AC_DEFINE(BBF_TR181),)
|
||||||
AM_CONDITIONAL([BBF_TR181],[test "x$enable_tr181" = "xyes"])
|
AM_CONDITIONAL([BBF_TR181],[test "x$enable_tr181" = "xyes"])
|
||||||
|
|
||||||
|
|
|
||||||
43
dmentry.c
43
dmentry.c
|
|
@ -16,7 +16,11 @@
|
||||||
#include "dmdynamicjson.h"
|
#include "dmdynamicjson.h"
|
||||||
#include "dmdynamiclibrary.h"
|
#include "dmdynamiclibrary.h"
|
||||||
#include "dmdynamicvendor.h"
|
#include "dmdynamicvendor.h"
|
||||||
|
|
||||||
|
#ifdef BBF_TR181
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#endif /* BBF_TR181 */
|
||||||
|
|
||||||
#include "dmbbfcommon.h"
|
#include "dmbbfcommon.h"
|
||||||
|
|
||||||
LIST_HEAD(head_package_change);
|
LIST_HEAD(head_package_change);
|
||||||
|
|
@ -129,7 +133,7 @@ int usp_fault_map(int fault)
|
||||||
return out_fault;
|
return out_fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_ctx_init_custom(struct dmctx *ctx, unsigned int instance_mode, int custom)
|
static int dm_ctx_init_custom(struct dmctx *ctx, unsigned int instance_mode, DMOBJ *tEntryObj, int custom)
|
||||||
{
|
{
|
||||||
if (custom == CTX_INIT_ALL)
|
if (custom == CTX_INIT_ALL)
|
||||||
bbf_uci_init();
|
bbf_uci_init();
|
||||||
|
|
@ -138,7 +142,7 @@ static int dm_ctx_init_custom(struct dmctx *ctx, unsigned int instance_mode, int
|
||||||
INIT_LIST_HEAD(&ctx->set_list_tmp);
|
INIT_LIST_HEAD(&ctx->set_list_tmp);
|
||||||
INIT_LIST_HEAD(&ctx->list_fault_param);
|
INIT_LIST_HEAD(&ctx->list_fault_param);
|
||||||
ctx->instance_mode = instance_mode;
|
ctx->instance_mode = instance_mode;
|
||||||
ctx->dm_entryobj = tEntry181Obj;
|
ctx->dm_entryobj = tEntryObj;
|
||||||
ctx->dm_version = DEFAULT_DMVERSION;
|
ctx->dm_version = DEFAULT_DMVERSION;
|
||||||
ctx->end_session_flag = 0;
|
ctx->end_session_flag = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -162,10 +166,19 @@ void dm_config_ubus(struct ubus_context *ctx)
|
||||||
dmubus_configure(ctx);
|
dmubus_configure(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dm_ctx_init_entry(struct dmctx *ctx, DMOBJ *tEntryObj, unsigned int instance_mode)
|
||||||
|
{
|
||||||
|
return dm_ctx_init_custom(ctx, instance_mode, tEntryObj, CTX_INIT_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
int dm_ctx_init(struct dmctx *ctx, unsigned int instance_mode)
|
int dm_ctx_init(struct dmctx *ctx, unsigned int instance_mode)
|
||||||
{
|
{
|
||||||
|
#ifdef BBF_TR181
|
||||||
dmubus_clean_endlife_entries();
|
dmubus_clean_endlife_entries();
|
||||||
return dm_ctx_init_custom(ctx, instance_mode, CTX_INIT_ALL);
|
return dm_ctx_init_custom(ctx, instance_mode, tEntry181Obj, CTX_INIT_ALL);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* BBF_TR181 */
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_ctx_clean(struct dmctx *ctx)
|
int dm_ctx_clean(struct dmctx *ctx)
|
||||||
|
|
@ -182,7 +195,11 @@ int dm_ctx_init_cache(int time)
|
||||||
|
|
||||||
int dm_ctx_init_sub(struct dmctx *ctx, unsigned int instance_mode)
|
int dm_ctx_init_sub(struct dmctx *ctx, unsigned int instance_mode)
|
||||||
{
|
{
|
||||||
return dm_ctx_init_custom(ctx, instance_mode, CTX_INIT_SUB);
|
#ifdef BBF_TR181
|
||||||
|
return dm_ctx_init_custom(ctx, instance_mode, tEntry181Obj, CTX_INIT_SUB);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* BBF_TR181 */
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_ctx_clean_sub(struct dmctx *ctx)
|
int dm_ctx_clean_sub(struct dmctx *ctx)
|
||||||
|
|
@ -197,11 +214,12 @@ int dm_get_supported_dm(struct dmctx *ctx, char *path, bool first_level, schema_
|
||||||
// Load dynamic objects and parameters
|
// Load dynamic objects and parameters
|
||||||
load_dynamic_arrays(ctx);
|
load_dynamic_arrays(ctx);
|
||||||
|
|
||||||
if (strlen(path) == 0)
|
if (strlen(path) == 0) {
|
||||||
path = "Device.";
|
path = "";
|
||||||
|
} else {
|
||||||
if (path[strlen(path) - 1] != '.')
|
if (path[strlen(path) - 1] != '.')
|
||||||
return usp_fault_map(USP_FAULT_INVALID_PATH);
|
return usp_fault_map(USP_FAULT_INVALID_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
ctx->in_param = path;
|
ctx->in_param = path;
|
||||||
|
|
||||||
|
|
@ -545,7 +563,9 @@ static void load_dynamic_arrays(struct dmctx *ctx)
|
||||||
|
|
||||||
static void free_dynamic_arrays(void)
|
static void free_dynamic_arrays(void)
|
||||||
{
|
{
|
||||||
|
#ifdef BBF_TR181
|
||||||
DMOBJ *root = tEntry181Obj;
|
DMOBJ *root = tEntry181Obj;
|
||||||
|
|
||||||
DMNODE node = {.current_object = ""};
|
DMNODE node = {.current_object = ""};
|
||||||
|
|
||||||
#ifdef BBFDM_ENABLE_JSON_PLUGIN
|
#ifdef BBFDM_ENABLE_JSON_PLUGIN
|
||||||
|
|
@ -560,6 +580,7 @@ static void free_dynamic_arrays(void)
|
||||||
free_vendor_dynamic_arrays(tEntry181Obj);
|
free_vendor_dynamic_arrays(tEntry181Obj);
|
||||||
#endif
|
#endif
|
||||||
free_dm_browse_node_dynamic_object_tree(&node, root);
|
free_dm_browse_node_dynamic_object_tree(&node, root);
|
||||||
|
#endif /* BBF_TR181 */
|
||||||
}
|
}
|
||||||
|
|
||||||
void bbf_dm_cleanup(void)
|
void bbf_dm_cleanup(void)
|
||||||
|
|
@ -568,3 +589,11 @@ void bbf_dm_cleanup(void)
|
||||||
dm_dynamic_cleanmem(&main_memhead);
|
dm_dynamic_cleanmem(&main_memhead);
|
||||||
free_dynamic_arrays();
|
free_dynamic_arrays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dm_cleanup_dynamic_entry(DMOBJ *root)
|
||||||
|
{
|
||||||
|
DMNODE node = {.current_object = ""};
|
||||||
|
|
||||||
|
dm_dynamic_cleanmem(&main_memhead);
|
||||||
|
free_dm_browse_node_dynamic_object_tree(&node, root);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ typedef enum {
|
||||||
|
|
||||||
int dm_ctx_init(struct dmctx *ctx, unsigned int instance_mode);
|
int dm_ctx_init(struct dmctx *ctx, unsigned int instance_mode);
|
||||||
int dm_ctx_init_sub(struct dmctx *ctx, unsigned int instance_mode);
|
int dm_ctx_init_sub(struct dmctx *ctx, unsigned int instance_mode);
|
||||||
|
int dm_ctx_init_entry(struct dmctx *ctx, DMOBJ tEntryObj[], unsigned int instance_mode);
|
||||||
int dm_entry_param_method(struct dmctx *ctx, int cmd, char *inparam, char *arg1, char *arg2);
|
int dm_entry_param_method(struct dmctx *ctx, int cmd, char *inparam, char *arg1, char *arg2);
|
||||||
int dm_entry_apply(struct dmctx *ctx, int cmd, char *arg1);
|
int dm_entry_apply(struct dmctx *ctx, int cmd, char *arg1);
|
||||||
int dm_entry_restart_services(void);
|
int dm_entry_restart_services(void);
|
||||||
|
|
@ -62,5 +63,6 @@ void bbf_dm_cleanup(void);
|
||||||
* object illegal access.
|
* object illegal access.
|
||||||
*/
|
*/
|
||||||
int dm_debug_browse_path(char *buff, size_t len);
|
int dm_debug_browse_path(char *buff, size_t len);
|
||||||
|
void dm_cleanup_dynamic_entry(DMOBJ *root);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
1937
docs/api/dmtest.md
Normal file
1937
docs/api/dmtest.md
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -9,3 +9,9 @@ autorestart=false
|
||||||
startretries=0
|
startretries=0
|
||||||
priority=2
|
priority=2
|
||||||
command=/bin/bash -c "/usr/sbin/rpcd"
|
command=/bin/bash -c "/usr/sbin/rpcd"
|
||||||
|
|
||||||
|
[program:bbf_ubus]
|
||||||
|
autorestart=false
|
||||||
|
priority=3
|
||||||
|
stdout_logfile=/builds/iopsys/bbf/log_file
|
||||||
|
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/builds/iopsys/bbf/memory-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /builds/iopsys/bbf/test/dynamicdm_ubus_test/bbf_ubus"
|
||||||
|
|
|
||||||
52
gitlab-ci/libbbf_ubus_api_test.sh
Executable file
52
gitlab-ci/libbbf_ubus_api_test.sh
Executable file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "$0 preparation script"
|
||||||
|
pwd
|
||||||
|
|
||||||
|
source ./gitlab-ci/shared.sh
|
||||||
|
|
||||||
|
# clean and make
|
||||||
|
# compile and install libbbf
|
||||||
|
install_libbbf
|
||||||
|
|
||||||
|
#compile and install libbbf_test dynamic extension library
|
||||||
|
install_libbbf_test
|
||||||
|
|
||||||
|
supervisorctl update
|
||||||
|
supervisorctl restart all
|
||||||
|
supervisorctl status all
|
||||||
|
exec_cmd ubus wait_for dmtest
|
||||||
|
supervisorctl status all
|
||||||
|
|
||||||
|
# debug logging
|
||||||
|
echo "Checking ubus status [$(date '+%d/%m/%Y %H:%M:%S')]"
|
||||||
|
ubus list
|
||||||
|
ubus -v list dmtest
|
||||||
|
|
||||||
|
echo "Checking system resources"
|
||||||
|
free -h
|
||||||
|
df -h
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# run functional on dmtest object validation
|
||||||
|
if [ -f "/usr/share/rpcd/schemas/dmtest.json" ]; then
|
||||||
|
rm /usr/share/rpcd/schemas/dmtest.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp -r ./schemas/dmtest.json /usr/share/rpcd/schemas
|
||||||
|
ubus-api-validator -t 5 -f ./test/api/json/dmtest.validation.json >> ./api-result.log
|
||||||
|
check_ret $?
|
||||||
|
|
||||||
|
supervisorctl status all
|
||||||
|
supervisorctl stop all
|
||||||
|
supervisorctl status
|
||||||
|
|
||||||
|
#report part
|
||||||
|
date +%s > timestamp.log
|
||||||
|
exec_cmd tap-junit --input ./api-result.log --output report
|
||||||
|
|
||||||
|
echo "Checking memory leaks..."
|
||||||
|
grep -q "Leak" memory-report.xml
|
||||||
|
error_on_zero $?
|
||||||
|
|
||||||
|
echo "Functional libbbf_ubus API test :: PASS"
|
||||||
|
|
@ -74,6 +74,15 @@ function install_libbbf_test()
|
||||||
|
|
||||||
echo "installing libbbf_test"
|
echo "installing libbbf_test"
|
||||||
cp -f test/bbf_test/libbbf_test.so /usr/lib/bbfdm
|
cp -f test/bbf_test/libbbf_test.so /usr/lib/bbfdm
|
||||||
|
|
||||||
|
echo "pre-installation for libbbf_ubus_test"
|
||||||
|
cp -f test/bbf_test/libbbf_test.so /usr/local/lib
|
||||||
|
ldconfig
|
||||||
|
|
||||||
|
# compile and install libbbf_ubus_test
|
||||||
|
echo "Compiling libbbf_ubus_test"
|
||||||
|
make clean -C test/dynamicdm_ubus_test/
|
||||||
|
make -C test/dynamicdm_ubus_test/
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_libbulkdata()
|
function install_libbulkdata()
|
||||||
|
|
@ -101,3 +110,14 @@ function install_libperiodicstats()
|
||||||
echo "installing libperiodicstats"
|
echo "installing libperiodicstats"
|
||||||
cp -f /opt/dev/periodicstats/libperiodicstats.so /usr/lib/bbfdm
|
cp -f /opt/dev/periodicstats/libperiodicstats.so /usr/lib/bbfdm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function error_on_zero()
|
||||||
|
{
|
||||||
|
ret=$1
|
||||||
|
if [ "$ret" -eq 0 ]; then
|
||||||
|
echo "Validation of last command failed, ret(${ret})"
|
||||||
|
exit $ret
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
118
include/libbbf_ubus.h
Normal file
118
include/libbbf_ubus.h
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Iopsys Software Solutions AB
|
||||||
|
*
|
||||||
|
* Author: Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License version 2.1
|
||||||
|
* as published by the Free Software Foundation
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file libbbf_ubus.h
|
||||||
|
*
|
||||||
|
* This Library provides APIs to expose the datamodel constructed with the help
|
||||||
|
* of libbbf API over the ubus directly.
|
||||||
|
* This library has an external dependency on libbbf_api
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBBBF_UBUS_H__
|
||||||
|
#define __LIBBBF_UBUS_H__
|
||||||
|
|
||||||
|
#include <libubus.h>
|
||||||
|
#include "libbbf_api/dmbbf.h"
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
**
|
||||||
|
** dynamicdm_init
|
||||||
|
**
|
||||||
|
** This API is to register the predefined ubus methods to work on provided
|
||||||
|
** `DMOBJ` tree.
|
||||||
|
**
|
||||||
|
** NOTE: dynamicdm_free should be called to deregister and free the allocated
|
||||||
|
** resources used in this API.
|
||||||
|
**
|
||||||
|
** \param ctx - pre-allocated ubus context, should not be NULL
|
||||||
|
** \param ubus_name - name of the ubus object on which pre-defined usus methods will be registered.
|
||||||
|
** It should not be NULL or Empty
|
||||||
|
** \param entry - Object which points to the root node of the tree. More details available in
|
||||||
|
** libbbf_api documentation.
|
||||||
|
**
|
||||||
|
** \return 0 if ubus methods are registered with the given tree, -1 otherwise
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
int dynamicdm_init(struct ubus_context *ctx, char *ubus_name, DMOBJ *entry);
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
**
|
||||||
|
** dynamicdm_init_plugin_object
|
||||||
|
**
|
||||||
|
** This API is to register the predefined ubus methods to work on provided
|
||||||
|
** `DM_MAP_OBJ` tree.
|
||||||
|
**
|
||||||
|
** NOTE: dynamicdm_free_plugin_object should be called to deregister and free
|
||||||
|
** the allocated resources used in this API.
|
||||||
|
** This API is for developer purpose and can register a tree with intermediate
|
||||||
|
** node.
|
||||||
|
**
|
||||||
|
** \param ctx - pre-allocated ubus context, should not be NULL
|
||||||
|
** \param ubus_name - name of the ubus object on which pre-defined usus methods will be registered.
|
||||||
|
** It should not be NULL or Empty
|
||||||
|
** \param entry - Object which points to the root node of the tree. More details available in
|
||||||
|
** libbbf_api documentation.
|
||||||
|
**
|
||||||
|
** \return 0 if ubus methods are registered with the given tree, -1 otherwise
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
int dynamicdm_init_plugin_object(struct ubus_context *ctx, char *ubus_name, DM_MAP_OBJ *entry);
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
**
|
||||||
|
** dynamicdm_free
|
||||||
|
**
|
||||||
|
** This is the API responsible to deregister/remove the allocated resources
|
||||||
|
** used in dynamicdm_init
|
||||||
|
**
|
||||||
|
** NOTE: It's the responsibility of the application to call this API before
|
||||||
|
** termination in order to free the resources if dynamicdm_init has been used.
|
||||||
|
**
|
||||||
|
** \param ctx - pre-allocated ubus context, should not be NULL
|
||||||
|
** \param ubus_name - name of the ubus object on which pre-defined usus methods are registered.
|
||||||
|
** It should not be NULL or Empty
|
||||||
|
**
|
||||||
|
** \return None
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
void dynamicdm_free(struct ubus_context *ctx, const char *ubus_name);
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
**
|
||||||
|
** dynamicdm_free
|
||||||
|
**
|
||||||
|
** This is the API responsible to deregister/remove the allocated resources
|
||||||
|
** used in dynamicdm_init_plugin_object
|
||||||
|
**
|
||||||
|
** NOTE: It's the responsibility of the application to call this API before
|
||||||
|
** termination in order to free the resources if dynamicdm_init_plugin_object
|
||||||
|
** has been used.
|
||||||
|
**
|
||||||
|
** \param ctx - pre-allocated ubus context, should not be NULL
|
||||||
|
** \param ubus_name - name of the ubus object on which pre-defined usus methods are registered.
|
||||||
|
** It should not be NULL or Empty
|
||||||
|
**
|
||||||
|
** \return None
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
void dynamicdm_free_plugin_object(struct ubus_context *ctx, const char *ubus_name);
|
||||||
|
|
||||||
|
#endif //__LIBBBF_UBUS_H__
|
||||||
38
libbbf_ubus/Makefile.am
Normal file
38
libbbf_ubus/Makefile.am
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libbbf_ubus.la
|
||||||
|
|
||||||
|
libbbf_ubus_la_SOURCES = \
|
||||||
|
../dmentry.c \
|
||||||
|
../dmbbfcommon.c \
|
||||||
|
libbbf_ubus.c
|
||||||
|
|
||||||
|
libbbf_ubus_la_CFLAGS = \
|
||||||
|
$(AM_CFLAGS) \
|
||||||
|
$(LIBUCI_CFLAGS) \
|
||||||
|
$(LIBUBOX_CFLAGS) \
|
||||||
|
$(LIBUBUS_CFLAGS)
|
||||||
|
|
||||||
|
libbbf_ubus_la_LDFLAGS = \
|
||||||
|
$(AM_LDFLAGS) \
|
||||||
|
$(LIBUCI_LDFLAGS) \
|
||||||
|
$(LIBUBOX_LDFLAGS) \
|
||||||
|
$(LIBUBUS_LDFLAGS)
|
||||||
|
|
||||||
|
libbbf_ubus_la_LIBADD = \
|
||||||
|
$(AM_LIBS) \
|
||||||
|
$(LIBUCI_LIBS) \
|
||||||
|
$(LIBUBOX_LIBS) \
|
||||||
|
$(LIBUBUS_LIBS) \
|
||||||
|
$(LIBJSON_LIBS) \
|
||||||
|
$(LIBTRACE_LIBS) \
|
||||||
|
$(LBLOBMSG_LIBS) \
|
||||||
|
$(LIBDLOPEN_LIBS) \
|
||||||
|
$(LIBCURL_LIBS) \
|
||||||
|
$(LIBOPENSSL_LIBS) \
|
||||||
|
$(LIBCRYPTO_LIBS) \
|
||||||
|
-L../bin/ -lbbf_api
|
||||||
|
|
||||||
|
libbbf_ubus_la_CFLAGS+=-I../
|
||||||
|
libbbf_ubus_la_CFLAGS+=-I../include
|
||||||
71
libbbf_ubus/configure.ac
Normal file
71
libbbf_ubus/configure.ac
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
AC_INIT([libbbf_ubus], [0.1], [suvendhu.hansa@iopsys.eu])
|
||||||
|
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_CC_C_O
|
||||||
|
AC_ENABLE_SHARED
|
||||||
|
LT_INIT
|
||||||
|
|
||||||
|
LIBJSON_LIBS='-ljson-c'
|
||||||
|
AC_SUBST([LIBJSON_LIBS])
|
||||||
|
|
||||||
|
AC_ARG_WITH([uci-include-path],
|
||||||
|
[AS_HELP_STRING([--with-uci-include-path],
|
||||||
|
[location of the uci library headers])],
|
||||||
|
[LIBUCI_CFLAGS="-I$withval"])
|
||||||
|
AC_SUBST([LIBUCI_CFLAGS])
|
||||||
|
|
||||||
|
AC_ARG_WITH([uci-lib-path],
|
||||||
|
[AS_HELP_STRING([--with-uci-lib-path], [location of the uci library])], [LIBUCI_LDFLAGS="-L$withval"])
|
||||||
|
AC_SUBST([LIBUCI_LDFLAGS])
|
||||||
|
|
||||||
|
LIBUCI_LIBS='-luci'
|
||||||
|
AC_SUBST([LIBUCI_LIBS])
|
||||||
|
|
||||||
|
LIBTRACE_LIBS='-ltrace'
|
||||||
|
AC_SUBST([LIBTRACE_LIBS])
|
||||||
|
|
||||||
|
AC_ARG_WITH([libubox-include-path],
|
||||||
|
[AS_HELP_STRING([--with-libubox-include-path],
|
||||||
|
[location of the libubox library headers])],
|
||||||
|
[LIBUBOX_CFLAGS="-I$withval"])
|
||||||
|
AC_SUBST([LIBUBOX_CFLAGS])
|
||||||
|
|
||||||
|
AC_ARG_WITH([libubox-lib-path],
|
||||||
|
[AS_HELP_STRING([--with-libubox-lib-path], [location of the libubox library])], [LIBUBOX_LDFLAGS="-L$withval"])
|
||||||
|
AC_SUBST([LIBUBOX_LDFLAGS])
|
||||||
|
|
||||||
|
LIBUBOX_LIBS='-lubox'
|
||||||
|
AC_SUBST([LIBUBOX_LIBS])
|
||||||
|
|
||||||
|
AC_ARG_WITH([libubus-include-path],
|
||||||
|
[AS_HELP_STRING([--with-libubus-include-path],
|
||||||
|
[location of the libubus library headers])],
|
||||||
|
[LIBUBUS_CFLAGS="-I$withval"])
|
||||||
|
AC_SUBST([LIBUBUS_CFLAGS])
|
||||||
|
|
||||||
|
AC_ARG_WITH([libubus-lib-path],
|
||||||
|
[AS_HELP_STRING([--with-libubus-lib-path], [location of the libubus library])], [LIBUBOX_LDFLAGS="-L$withval"])
|
||||||
|
AC_SUBST([LIBUBUS_LDFLAGS])
|
||||||
|
|
||||||
|
LIBUBUS_LIBS='-lubus'
|
||||||
|
AC_SUBST([LIBUBUS_LIBS])
|
||||||
|
|
||||||
|
LBLOBMSG_LIBS='-lblobmsg_json'
|
||||||
|
AC_SUBST([LBLOBMSG_LIBS])
|
||||||
|
|
||||||
|
LIBDLOPEN_LIBS='-ldl'
|
||||||
|
AC_SUBST([LIBDLOPEN_LIBS])
|
||||||
|
|
||||||
|
LIBCURL_LIBS='-lcurl'
|
||||||
|
AC_SUBST([LIBCURL_LIBS])
|
||||||
|
|
||||||
|
# checks for header files
|
||||||
|
AC_CHECK_HEADERS([stdlib.h string.h])
|
||||||
|
|
||||||
|
# checks for typedefs, structures, and compiler characteristics
|
||||||
|
AC_TYPE_UINT8_T
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
946
libbbf_ubus/libbbf_ubus.c
Normal file
946
libbbf_ubus/libbbf_ubus.c
Normal file
|
|
@ -0,0 +1,946 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Iopsys Software Solutions AB
|
||||||
|
*
|
||||||
|
* Author: Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License version 2.1
|
||||||
|
* as published by the Free Software Foundation
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <libubox/blobmsg.h>
|
||||||
|
#include "dmentry.h"
|
||||||
|
#include "dmbbfcommon.h"
|
||||||
|
#include "libbbf_ubus.h"
|
||||||
|
|
||||||
|
#define PATH_MAX 4096
|
||||||
|
|
||||||
|
struct obj_node {
|
||||||
|
struct ubus_object *ob;
|
||||||
|
struct ubus_object_type *ob_type;
|
||||||
|
char *obj_name;
|
||||||
|
DMOBJ *tUsrObj;
|
||||||
|
struct obj_node *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LIBBBF_UBUS_GET_PATH,
|
||||||
|
LIBBBF_UBUS_GET_PROTO,
|
||||||
|
__LIBBBF_UBUS_GET_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LIBBBF_UBUS_SET_PATH,
|
||||||
|
LIBBBF_UBUS_SET_VALUE,
|
||||||
|
LIBBBF_UBUS_SET_PROTO,
|
||||||
|
__LIBBBF_UBUS_SET_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LIBBBF_UBUS_OPERATE_PATH,
|
||||||
|
LIBBBF_UBUS_OPERATE_INPUT,
|
||||||
|
__LIBBBF_UBUS_OPERATE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LIBBBF_UBUS_SUPPORTED_PATH,
|
||||||
|
LIBBBF_UBUS_SUPPORTED_PROTO,
|
||||||
|
LIBBBF_UBUS_SUPPORTED_NXT_LEVEL,
|
||||||
|
LIBBBF_UBUS_SUPPORTED_SCHEMA_TYPE,
|
||||||
|
__LIBBBF_UBUS_SUPPORTED_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LIBBBF_UBUS_ADD_DEL_PATH,
|
||||||
|
LIBBBF_UBUS_ADD_DEL_PROTO,
|
||||||
|
__LIBBBF_UBUS_ADD_DEL_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool g_dynamicdm_transaction_start = false;
|
||||||
|
static struct obj_node *g_dynamicdm_head = NULL;
|
||||||
|
|
||||||
|
static int libbbf_ubus_supported_dm(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static int libbbf_ubus_get_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static int libbbf_ubus_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static int libbbf_ubus_operate(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static int libbbf_ubus_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static int libbbf_ubus_transaction_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static const struct blobmsg_policy libbbf_ubus_supported_dm_policy[] = {
|
||||||
|
[LIBBBF_UBUS_SUPPORTED_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_SUPPORTED_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_SUPPORTED_NXT_LEVEL] = { .name = "next-level", .type = BLOBMSG_TYPE_INT8},
|
||||||
|
[LIBBBF_UBUS_SUPPORTED_SCHEMA_TYPE] = { .name = "schema_type", .type = BLOBMSG_TYPE_INT32},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct blobmsg_policy libbbf_ubus_get_policy[] = {
|
||||||
|
[LIBBBF_UBUS_GET_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_GET_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct blobmsg_policy libbbf_ubus_set_policy[] = {
|
||||||
|
[LIBBBF_UBUS_SET_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_SET_VALUE] = { .name = "value", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_SET_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct blobmsg_policy libbbf_ubus_operate_policy[] = {
|
||||||
|
[LIBBBF_UBUS_OPERATE_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_OPERATE_INPUT] = { .name = "input", .type = BLOBMSG_TYPE_TABLE }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct blobmsg_policy libbbf_ubus_add_del_policy[] = {
|
||||||
|
[LIBBBF_UBUS_ADD_DEL_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[LIBBBF_UBUS_ADD_DEL_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ubus_method libbbf_ubus_methods[] = {
|
||||||
|
UBUS_METHOD("get_supported_dm", libbbf_ubus_supported_dm, libbbf_ubus_supported_dm_policy),
|
||||||
|
UBUS_METHOD("get", libbbf_ubus_get_handler, libbbf_ubus_get_policy),
|
||||||
|
UBUS_METHOD("set", libbbf_ubus_set_handler, libbbf_ubus_set_policy),
|
||||||
|
UBUS_METHOD("operate", libbbf_ubus_operate, libbbf_ubus_operate_policy),
|
||||||
|
UBUS_METHOD("add_object", libbbf_ubus_add_del_handler, libbbf_ubus_add_del_policy),
|
||||||
|
UBUS_METHOD("del_object", libbbf_ubus_add_del_handler, libbbf_ubus_add_del_policy),
|
||||||
|
UBUS_METHOD_NOARG("transaction_start", libbbf_ubus_transaction_handler),
|
||||||
|
UBUS_METHOD_NOARG("transaction_abort", libbbf_ubus_transaction_handler),
|
||||||
|
UBUS_METHOD_NOARG("transaction_commit", libbbf_ubus_transaction_handler),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_protocol(const char *val)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
|
||||||
|
if (strcmp("cwmp", val) == 0)
|
||||||
|
type = BBFDM_CWMP;
|
||||||
|
else if (strcmp("usp", val) == 0)
|
||||||
|
type = BBFDM_USP;
|
||||||
|
else
|
||||||
|
type = BBFDM_BOTH;
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_bbf_proto_type(struct blob_attr *proto)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
|
||||||
|
if (proto) {
|
||||||
|
const char *val = blobmsg_get_string(proto);
|
||||||
|
type = get_protocol(val);
|
||||||
|
} else {
|
||||||
|
type = BBFDM_BOTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bb_add_string(struct blob_buf *bb, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
blobmsg_add_string(bb, name, value);
|
||||||
|
else
|
||||||
|
blobmsg_add_string(bb, name, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct obj_node* find_obj_node(const char *ubus_name)
|
||||||
|
{
|
||||||
|
struct obj_node *temp = g_dynamicdm_head;
|
||||||
|
if (temp == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (strcmp(ubus_name, temp->obj_name) != 0) {
|
||||||
|
if (temp->next == NULL) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DMOBJ* get_entry_object(const char *name)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct obj_node *ob_node = find_obj_node(name);
|
||||||
|
if (!ob_node)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ob_node->tUsrObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_operate_schema(struct blob_buf *bb, struct dm_parameter *param)
|
||||||
|
{
|
||||||
|
blobmsg_add_string(bb, "parameter",param->name);
|
||||||
|
blobmsg_add_string(bb,"type",param->type);
|
||||||
|
blobmsg_add_string(bb,"cmd_type",param->additional_data);
|
||||||
|
|
||||||
|
if(param->data) {
|
||||||
|
const char **in, **out = NULL;
|
||||||
|
operation_args *args = NULL;
|
||||||
|
void *array = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
args = (operation_args *) param->data;
|
||||||
|
in = args->in;
|
||||||
|
if (in) {
|
||||||
|
array = blobmsg_open_array(bb, "in");
|
||||||
|
for (i = 0; in[i] != NULL; i++)
|
||||||
|
blobmsg_add_string(bb, NULL, in[i]);
|
||||||
|
|
||||||
|
blobmsg_close_array(bb, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
out = args->out;
|
||||||
|
if (out) {
|
||||||
|
array = blobmsg_open_array(bb, "out");
|
||||||
|
for (i = 0; out[i] != NULL; i++)
|
||||||
|
blobmsg_add_string(bb, NULL, out[i]);
|
||||||
|
|
||||||
|
blobmsg_close_array(bb, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_event_schema(struct blob_buf *bb, struct dm_parameter *param)
|
||||||
|
{
|
||||||
|
blobmsg_add_string(bb, "parameter",param->name);
|
||||||
|
blobmsg_add_string(bb,"type",param->type);
|
||||||
|
|
||||||
|
if(param->data) {
|
||||||
|
event_args *ev = NULL;
|
||||||
|
|
||||||
|
ev = (event_args *)param->data;
|
||||||
|
|
||||||
|
if (ev->param) {
|
||||||
|
const char **in = NULL;
|
||||||
|
void *key = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
in = ev->param;
|
||||||
|
key = blobmsg_open_array(bb, "in");
|
||||||
|
for (i = 0; in[i] != NULL; i++)
|
||||||
|
blobmsg_add_string(bb, NULL, in[i]);
|
||||||
|
blobmsg_close_array(bb, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_param_schema(struct blob_buf *bb, struct dm_parameter *param)
|
||||||
|
{
|
||||||
|
blobmsg_add_string(bb, "parameter", param->name);
|
||||||
|
blobmsg_add_string(bb, "writable", param->data ? param->data : "0");
|
||||||
|
blobmsg_add_string(bb, "type", param->type);
|
||||||
|
|
||||||
|
if (param->additional_data) {
|
||||||
|
const char **uniq_keys = NULL;
|
||||||
|
void *key = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
uniq_keys = (const char **)param->additional_data;
|
||||||
|
key = blobmsg_open_array(bb, "unique_keys");
|
||||||
|
for (i = 0; uniq_keys[i] != NULL; i++)
|
||||||
|
blobmsg_add_string(bb, NULL, uniq_keys[i]);
|
||||||
|
|
||||||
|
blobmsg_close_array(bb, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_add_del_req(struct ubus_context *ctx, const char *ubus_name, struct ubus_request_data *req,
|
||||||
|
char *path, const char *method, int proto)
|
||||||
|
{
|
||||||
|
int fault = 0;
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
struct blob_buf bb;
|
||||||
|
char *pkey = "true";
|
||||||
|
|
||||||
|
DMOBJ *tEntryObj = get_entry_object(ubus_name);
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("Failed to get DM entry obj\n\r");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
if (!g_dynamicdm_transaction_start) {
|
||||||
|
printf("Transaction not started\n\r");
|
||||||
|
blobmsg_add_u32(&bb, "fault", usp_fault_map(USP_FAULT_INTERNAL_ERROR));
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
set_bbfdatamodel_type(proto);
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
|
||||||
|
if (strcmp(method, "add_object") == 0) {
|
||||||
|
fault = dm_entry_param_method(&bbf_ctx, CMD_ADD_OBJECT, path, pkey, NULL);
|
||||||
|
} else {
|
||||||
|
fault = dm_entry_param_method(&bbf_ctx, CMD_DEL_OBJECT, path, pkey, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *array = blobmsg_open_array(&bb, "parameters");
|
||||||
|
void *table = blobmsg_open_table(&bb, NULL);
|
||||||
|
|
||||||
|
bb_add_string(&bb, "parameter", path);
|
||||||
|
if (fault) {
|
||||||
|
blobmsg_add_u32(&bb, "fault", fault);
|
||||||
|
blobmsg_add_u8(&bb, "status", 0);
|
||||||
|
} else {
|
||||||
|
if (strcmp(method, "add_object") == 0) {
|
||||||
|
if (bbf_ctx.addobj_instance) {
|
||||||
|
blobmsg_add_u8(&bb, "status", 1);
|
||||||
|
bb_add_string(&bb, "instance", bbf_ctx.addobj_instance);
|
||||||
|
} else {
|
||||||
|
blobmsg_add_u8(&bb, "status", 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
blobmsg_add_u8(&bb, "status", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blobmsg_close_table(&bb, table);
|
||||||
|
blobmsg_close_array(&bb, array);
|
||||||
|
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void libbbf_ubus_obj_node_free(struct obj_node *obj)
|
||||||
|
{
|
||||||
|
if (!obj)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obj->ob_type)
|
||||||
|
FREE(obj->ob_type);
|
||||||
|
|
||||||
|
if (obj->ob)
|
||||||
|
FREE(obj->ob);
|
||||||
|
|
||||||
|
if (obj->obj_name)
|
||||||
|
FREE(obj->obj_name);
|
||||||
|
|
||||||
|
FREE(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libbbf_ubus_supported_dm(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct blob_attr *tb[__LIBBBF_UBUS_SUPPORTED_MAX];
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
bool nxt_lvl = false;
|
||||||
|
uint32_t schema_type = 0;
|
||||||
|
struct blob_buf bb;
|
||||||
|
int fault = 0, proto;
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
|
||||||
|
if (blobmsg_parse(libbbf_ubus_supported_dm_policy, __LIBBBF_UBUS_SUPPORTED_MAX, tb, blob_data(msg), blob_len(msg)) == 0) {
|
||||||
|
if (tb[LIBBBF_UBUS_SUPPORTED_PATH])
|
||||||
|
snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[LIBBBF_UBUS_SUPPORTED_PATH]));
|
||||||
|
|
||||||
|
if (tb[LIBBBF_UBUS_SUPPORTED_NXT_LEVEL])
|
||||||
|
nxt_lvl = blobmsg_get_bool(tb[LIBBBF_UBUS_SUPPORTED_NXT_LEVEL]);
|
||||||
|
|
||||||
|
if (tb[LIBBBF_UBUS_SUPPORTED_SCHEMA_TYPE])
|
||||||
|
schema_type = blobmsg_get_u32(tb[LIBBBF_UBUS_SUPPORTED_SCHEMA_TYPE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DMOBJ *tEntryObj = get_entry_object(obj->name);
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("Failed to get DM entry obj\n\r");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
proto = get_bbf_proto_type(tb[LIBBBF_UBUS_SUPPORTED_PROTO]);
|
||||||
|
set_bbfdatamodel_type(proto);
|
||||||
|
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
|
||||||
|
fault = dm_get_supported_dm(&bbf_ctx, path, nxt_lvl, schema_type);
|
||||||
|
if(fault) {
|
||||||
|
blobmsg_add_u32(&bb, "fault", fault);
|
||||||
|
} else {
|
||||||
|
struct dm_parameter *param = NULL;
|
||||||
|
void *array = NULL, *table = NULL;
|
||||||
|
|
||||||
|
array = blobmsg_open_array(&bb,"parameters");
|
||||||
|
list_for_each_entry(param, &bbf_ctx.list_parameter, list) {
|
||||||
|
int cmd = get_dm_type(param->type);
|
||||||
|
|
||||||
|
table = blobmsg_open_table(&bb, NULL);
|
||||||
|
if (cmd == DMT_COMMAND) {
|
||||||
|
fill_operate_schema(&bb, param);
|
||||||
|
} else if (cmd == DMT_EVENT) {
|
||||||
|
fill_event_schema(&bb, param);
|
||||||
|
} else {
|
||||||
|
fill_param_schema(&bb, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
blobmsg_close_table(&bb, table);
|
||||||
|
}
|
||||||
|
blobmsg_close_array(&bb, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_dm_path(DMOBJ *tEntryObj)
|
||||||
|
{
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
|
||||||
|
set_bbfdatamodel_type(BBFDM_BOTH);
|
||||||
|
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
|
||||||
|
dm_entry_param_method(&bbf_ctx, CMD_GET_VALUE, "", NULL, NULL);
|
||||||
|
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libbbf_ubus_get_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct blob_attr *tb[__LIBBBF_UBUS_GET_MAX] = {NULL};
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
struct blob_buf bb;
|
||||||
|
int fault = 0, proto;
|
||||||
|
|
||||||
|
if (blobmsg_parse(libbbf_ubus_get_policy, __LIBBBF_UBUS_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
|
||||||
|
printf("Failed to parse blob\n");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tb[LIBBBF_UBUS_GET_PATH]))
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
DMOBJ *tEntryObj = get_entry_object(obj->name);
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("Failed to get DM entry obj\n\r");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[LIBBBF_UBUS_GET_PATH]));
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
proto = get_bbf_proto_type(tb[LIBBBF_UBUS_GET_PROTO]);
|
||||||
|
set_bbfdatamodel_type(proto);
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
|
||||||
|
fault = dm_entry_param_method(&bbf_ctx, CMD_GET_VALUE, path, NULL, NULL);
|
||||||
|
|
||||||
|
if (!fault) {
|
||||||
|
struct dm_parameter *n = NULL;
|
||||||
|
|
||||||
|
void *array = blobmsg_open_array(&bb, "parameters");
|
||||||
|
list_for_each_entry(n, &bbf_ctx.list_parameter, list) {
|
||||||
|
void *table = blobmsg_open_table(&bb, NULL);
|
||||||
|
bb_add_string(&bb, "parameter", n->name);
|
||||||
|
bb_add_string(&bb, "value", n->data);
|
||||||
|
bb_add_string(&bb, "type", n->type);
|
||||||
|
blobmsg_close_table(&bb, table);
|
||||||
|
}
|
||||||
|
blobmsg_close_array(&bb, array);
|
||||||
|
} else {
|
||||||
|
blobmsg_add_u32(&bb, "fault", fault);
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libbbf_ubus_operate(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)),
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct blob_attr *tb[__LIBBBF_UBUS_OPERATE_MAX] = {NULL};
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
char *input = NULL;
|
||||||
|
struct blob_buf bb;
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
int fault = 0, len;
|
||||||
|
|
||||||
|
if (blobmsg_parse(libbbf_ubus_operate_policy, __LIBBBF_UBUS_OPERATE_MAX, tb, blob_data(msg), blob_len(msg))) {
|
||||||
|
printf("Failed to parse blob\n\r");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tb[LIBBBF_UBUS_OPERATE_PATH]))
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if (tb[LIBBBF_UBUS_OPERATE_INPUT])
|
||||||
|
input = blobmsg_format_json(tb[LIBBBF_UBUS_OPERATE_INPUT], true);
|
||||||
|
|
||||||
|
DMOBJ *tEntryObj = get_entry_object(obj->name);
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("Failed to get DM entry obj\n\r");
|
||||||
|
if (input)
|
||||||
|
free(input);
|
||||||
|
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[LIBBBF_UBUS_OPERATE_PATH]));
|
||||||
|
|
||||||
|
len = strlen(path);
|
||||||
|
if (path[len - 1] == '.') {
|
||||||
|
printf("path can't end with (.)\n\r");
|
||||||
|
if (input)
|
||||||
|
free(input);
|
||||||
|
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
set_bbfdatamodel_type(BBFDM_USP);
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
|
||||||
|
fault = dm_entry_param_method(&bbf_ctx, CMD_USP_OPERATE, path, input, NULL);
|
||||||
|
|
||||||
|
switch (fault) {
|
||||||
|
case CMD_NOT_FOUND:
|
||||||
|
fault = USP_FAULT_INVALID_PATH;
|
||||||
|
break;
|
||||||
|
case CMD_INVALID_ARGUMENTS:
|
||||||
|
fault = USP_FAULT_INVALID_ARGUMENT;
|
||||||
|
break;
|
||||||
|
case CMD_FAIL:
|
||||||
|
fault = USP_FAULT_COMMAND_FAILURE;
|
||||||
|
break;
|
||||||
|
case CMD_SUCCESS:
|
||||||
|
fault = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Case(%d) not found\n\r", fault);
|
||||||
|
fault = USP_FAULT_INVALID_PATH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *array = blobmsg_open_array(&bb, "Results");
|
||||||
|
void *table = blobmsg_open_table(&bb, NULL);
|
||||||
|
blobmsg_add_string(&bb, "path", path);
|
||||||
|
|
||||||
|
if (fault == 0) {
|
||||||
|
struct dm_parameter *n = NULL;
|
||||||
|
|
||||||
|
void *array_in = blobmsg_open_array(&bb, "parameters");
|
||||||
|
list_for_each_entry(n, &bbf_ctx.list_parameter, list) {
|
||||||
|
void *table_in = blobmsg_open_table(&bb, NULL);
|
||||||
|
bb_add_string(&bb, "parameter", n->name);
|
||||||
|
bb_add_string(&bb, "value", n->data);
|
||||||
|
bb_add_string(&bb, "type", n->type);
|
||||||
|
blobmsg_close_table(&bb, table_in);
|
||||||
|
}
|
||||||
|
blobmsg_close_array(&bb, array_in);
|
||||||
|
} else {
|
||||||
|
fault = usp_fault_map(fault);
|
||||||
|
blobmsg_add_u32(&bb, "fault", fault);
|
||||||
|
}
|
||||||
|
|
||||||
|
blobmsg_close_table(&bb, table);
|
||||||
|
blobmsg_close_array(&bb, array);
|
||||||
|
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
free(input);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libbbf_ubus_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method,
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct blob_attr *tb[__LIBBBF_UBUS_ADD_DEL_MAX] = {NULL};
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
int plen, proto;
|
||||||
|
|
||||||
|
if (blobmsg_parse(libbbf_ubus_add_del_policy, __LIBBBF_UBUS_ADD_DEL_MAX, tb, blob_data(msg), blob_len(msg))) {
|
||||||
|
printf("Failed to parse blob");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tb[LIBBBF_UBUS_ADD_DEL_PATH])
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[LIBBBF_UBUS_ADD_DEL_PATH]));
|
||||||
|
|
||||||
|
plen = strlen(path);
|
||||||
|
if (path[plen - 1] != '.') {
|
||||||
|
if (plen > PATH_MAX - 2) {
|
||||||
|
printf("path too long(%d) can't append (.)\n\r", plen);
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
strcat(path, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
proto = get_bbf_proto_type(tb[LIBBBF_UBUS_ADD_DEL_PROTO]);
|
||||||
|
return handle_add_del_req(ctx, obj->name, req, path, method, proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libbbf_ubus_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method,
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct blob_buf bb;
|
||||||
|
struct blob_attr *tb[__LIBBBF_UBUS_SET_MAX] = {NULL};
|
||||||
|
char path[PATH_MAX] = {'\0'}, value[PATH_MAX] = {'\0'};
|
||||||
|
int fault = 0, proto;
|
||||||
|
void *array = NULL, *table = NULL;
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
bool fault_occured = false;
|
||||||
|
|
||||||
|
if (blobmsg_parse(libbbf_ubus_set_policy, __LIBBBF_UBUS_SET_MAX, tb, blob_data(msg), blob_len(msg))) {
|
||||||
|
printf("Failed to parse blob");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tb[LIBBBF_UBUS_SET_PATH])
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if (!tb[LIBBBF_UBUS_SET_VALUE])
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
DMOBJ *tEntryObj = get_entry_object(obj->name);
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("Failed to get DM entry obj\n\r");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[LIBBBF_UBUS_SET_PATH]));
|
||||||
|
snprintf(value, PATH_MAX, "%s", (char *)blobmsg_data(tb[LIBBBF_UBUS_SET_VALUE]));
|
||||||
|
|
||||||
|
int plen = strlen(path);
|
||||||
|
if (path[plen - 1] == '.') {
|
||||||
|
printf("path can't end with (.)\n\r");
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
if (!g_dynamicdm_transaction_start) {
|
||||||
|
printf("Transaction not started\n\r");
|
||||||
|
blobmsg_add_u32(&bb, "fault", usp_fault_map(USP_FAULT_INTERNAL_ERROR));
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
proto = get_bbf_proto_type(tb[LIBBBF_UBUS_SET_PROTO]);
|
||||||
|
set_bbfdatamodel_type(proto);
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
|
||||||
|
fault = dm_entry_param_method(&bbf_ctx, CMD_SET_VALUE, path, value, NULL);
|
||||||
|
if (fault) {
|
||||||
|
if (fault_occured == false) {
|
||||||
|
fault_occured = true;
|
||||||
|
array = blobmsg_open_array(&bb, "parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bbf_ctx.list_fault_param.next != &bbf_ctx.list_fault_param) {
|
||||||
|
struct param_fault *p = list_entry(bbf_ctx.list_fault_param.next, struct param_fault, list);
|
||||||
|
table = blobmsg_open_table(&bb, NULL);
|
||||||
|
bb_add_string(&bb, "path", p->name);
|
||||||
|
blobmsg_add_u8(&bb, "status", false);
|
||||||
|
blobmsg_add_u32(&bb, "fault", (uint32_t)p->fault);
|
||||||
|
blobmsg_close_table(&bb, table);
|
||||||
|
del_list_fault_param(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Apply the parameter
|
||||||
|
fault = dm_entry_apply(&bbf_ctx, CMD_SET_VALUE, NULL);
|
||||||
|
if (fault == 0 && fault_occured == false) {
|
||||||
|
blobmsg_add_u8(&bb, "status", true);
|
||||||
|
if (get_bbfdatamodel_type() == BBFDM_CWMP)
|
||||||
|
blobmsg_add_u64(&bb, "flag", bbf_ctx.end_session_flag);
|
||||||
|
} else {
|
||||||
|
if (!array)
|
||||||
|
array = blobmsg_open_array(&bb, "parameters");
|
||||||
|
|
||||||
|
while (bbf_ctx.list_fault_param.next != &bbf_ctx.list_fault_param) {
|
||||||
|
struct param_fault *p = list_entry(bbf_ctx.list_fault_param.next, struct param_fault, list);
|
||||||
|
table = blobmsg_open_table(&bb, NULL);
|
||||||
|
bb_add_string(&bb, "path", p->name);
|
||||||
|
blobmsg_add_u8(&bb, "status", false);
|
||||||
|
blobmsg_add_u32(&bb, "fault", (uint32_t)p->fault);
|
||||||
|
blobmsg_close_table(&bb, table);
|
||||||
|
del_list_fault_param(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array)
|
||||||
|
blobmsg_close_array(&bb, array);
|
||||||
|
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
|
||||||
|
// free
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libbbf_ubus_transaction_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct dmctx bbf_ctx;
|
||||||
|
struct blob_buf bb;
|
||||||
|
|
||||||
|
DMOBJ *tEntryObj = get_entry_object(obj->name);
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("Failed to get DM entry obj\n\r");
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
if (strcmp(method, "transaction_start") == 0) {
|
||||||
|
if (!g_dynamicdm_transaction_start) {
|
||||||
|
g_dynamicdm_transaction_start = true;
|
||||||
|
blobmsg_add_u8(&bb, "status", true);
|
||||||
|
} else {
|
||||||
|
printf("Transaction already in process\n");
|
||||||
|
blobmsg_add_u8(&bb, "status", false);
|
||||||
|
}
|
||||||
|
} else if(strcmp(method, "transaction_abort") == 0) {
|
||||||
|
if (g_dynamicdm_transaction_start) {
|
||||||
|
g_dynamicdm_transaction_start = false;
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
dm_entry_revert_changes();
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
blobmsg_add_u8(&bb, "status", true);
|
||||||
|
} else {
|
||||||
|
printf("Transaction still not started\n\r");
|
||||||
|
blobmsg_add_u8(&bb, "status", false);
|
||||||
|
}
|
||||||
|
} else if (strcmp(method, "transaction_commit") == 0) {
|
||||||
|
if (g_dynamicdm_transaction_start) {
|
||||||
|
g_dynamicdm_transaction_start = false;
|
||||||
|
dm_ctx_init_entry(&bbf_ctx, tEntryObj, 0);
|
||||||
|
dm_entry_manage_services(&bb, true);
|
||||||
|
dm_entry_restart_services();
|
||||||
|
dm_ctx_clean(&bbf_ctx);
|
||||||
|
blobmsg_add_u8(&bb, "status", true);
|
||||||
|
} else {
|
||||||
|
printf("Transaction still not started\n\r");
|
||||||
|
blobmsg_add_u8(&bb, "status", false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Unsupported method %s\n\r", method);
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
|
blob_buf_free(&bb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dynamicdm_init(struct ubus_context *ctx, char *ubus_name, DMOBJ *entry)
|
||||||
|
{
|
||||||
|
if (!ctx || !ubus_name || ubus_name[0] == '\0' || !entry)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct obj_node *new = (struct obj_node *)malloc(sizeof(struct obj_node));
|
||||||
|
if (!new)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memset(new, 0, sizeof(struct obj_node));
|
||||||
|
new->ob = (struct ubus_object *) calloc(1, sizeof(struct ubus_object));
|
||||||
|
if (!new->ob) {
|
||||||
|
printf("Out of memory!!\n\r");
|
||||||
|
libbbf_ubus_obj_node_free(new);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new->ob_type = (struct ubus_object_type *) calloc(1, sizeof(struct ubus_object_type));
|
||||||
|
if (!new->ob_type) {
|
||||||
|
printf("Out of memory!!\n\r");
|
||||||
|
libbbf_ubus_obj_node_free(new);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new->obj_name = strdup(ubus_name);
|
||||||
|
|
||||||
|
new->ob_type->name = new->obj_name;
|
||||||
|
new->ob_type->id = 0;
|
||||||
|
new->ob_type->methods = libbbf_ubus_methods;
|
||||||
|
new->ob_type->n_methods = ARRAY_SIZE(libbbf_ubus_methods);
|
||||||
|
|
||||||
|
new->ob->name = new->obj_name;
|
||||||
|
new->ob->type = new->ob_type;
|
||||||
|
new->ob->methods = libbbf_ubus_methods;
|
||||||
|
new->ob->n_methods = ARRAY_SIZE(libbbf_ubus_methods);
|
||||||
|
|
||||||
|
if (ubus_add_object(ctx, new->ob)) {
|
||||||
|
printf("Failed to add object.\n\r");
|
||||||
|
libbbf_ubus_obj_node_free(new);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new->tUsrObj = entry;
|
||||||
|
|
||||||
|
new->next = g_dynamicdm_head;
|
||||||
|
g_dynamicdm_head = new;
|
||||||
|
|
||||||
|
init_dm_path(entry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dynamicdm_init_plugin_object(struct ubus_context *ctx, char *ubus_name, DM_MAP_OBJ *entry)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DMOBJ *tEntryObj = NULL;
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0; entry[i].path != NULL; i++) {
|
||||||
|
tEntryObj = (DMOBJ*)realloc(tEntryObj, sizeof(DMOBJ) * (i+1));
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("No Memory exists\n\r");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&tEntryObj[i], 0, sizeof(DMOBJ));
|
||||||
|
|
||||||
|
tEntryObj[i].obj = entry[i].path;
|
||||||
|
tEntryObj[i].permission = &DMREAD;
|
||||||
|
tEntryObj[i].nextobj = entry[i].root_obj;
|
||||||
|
tEntryObj[i].leaf = entry[i].root_leaf;
|
||||||
|
tEntryObj[i].bbfdm_type = BBFDM_BOTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the last empty entry */
|
||||||
|
tEntryObj = (DMOBJ*)realloc(tEntryObj, sizeof(DMOBJ) * (i+1));
|
||||||
|
if (!tEntryObj) {
|
||||||
|
printf("No Memory exists\n\r");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&tEntryObj[i], 0, sizeof(DMOBJ));
|
||||||
|
|
||||||
|
if (0 != dynamicdm_init(ctx, ubus_name, tEntryObj)) {
|
||||||
|
FREE(tEntryObj);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dynamicdm_free(struct ubus_context *ctx, const char *ubus_name)
|
||||||
|
{
|
||||||
|
struct obj_node *curr = g_dynamicdm_head, *prev = NULL;
|
||||||
|
|
||||||
|
if (!ctx|| !ubus_name || ubus_name[0] == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (curr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (strcmp(ubus_name, curr->obj_name) != 0) {
|
||||||
|
if (curr->next == NULL) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
prev = curr;
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr == g_dynamicdm_head) {
|
||||||
|
g_dynamicdm_head = g_dynamicdm_head->next;
|
||||||
|
} else {
|
||||||
|
prev->next = curr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr->tUsrObj)
|
||||||
|
dm_cleanup_dynamic_entry(curr->tUsrObj);
|
||||||
|
|
||||||
|
ubus_remove_object(ctx, curr->ob);
|
||||||
|
|
||||||
|
libbbf_ubus_obj_node_free(curr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dynamicdm_free_plugin_object(struct ubus_context *ctx, const char *ubus_name)
|
||||||
|
{
|
||||||
|
if (!ctx || !ubus_name || ubus_name[0] == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct obj_node *ob_node = find_obj_node(ubus_name);
|
||||||
|
if (!ob_node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dm_cleanup_dynamic_entry(ob_node->tUsrObj);
|
||||||
|
FREE(ob_node->tUsrObj);
|
||||||
|
|
||||||
|
dynamicdm_free(ctx, ubus_name);
|
||||||
|
}
|
||||||
621
schemas/dmtest.json
Normal file
621
schemas/dmtest.json
Normal file
|
|
@ -0,0 +1,621 @@
|
||||||
|
{
|
||||||
|
"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.DHCPv4.Client.{i}.Renew()",
|
||||||
|
"Device.FactoryReset()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operate_type_t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"async",
|
||||||
|
"sync"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/dmtest.json",
|
||||||
|
"type": "object",
|
||||||
|
"title": "dmtest",
|
||||||
|
"object": "user defined dynamic DM exposed on ubus",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"get_supported_dm": {
|
||||||
|
"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/path_t"
|
||||||
|
},
|
||||||
|
"proto": {
|
||||||
|
"$ref": "#/definitions/proto_t"
|
||||||
|
},
|
||||||
|
"next-level": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "gets only next level objects if true"
|
||||||
|
},
|
||||||
|
"schema_type": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 3,
|
||||||
|
"description": "0-All, 1-Parameter only 2- Event only 3- operate only"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"oneof": [
|
||||||
|
{
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t",
|
||||||
|
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"parameters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"parameter": {
|
||||||
|
"$ref": "#/definitions/schema_path_t"
|
||||||
|
},
|
||||||
|
"writable": {
|
||||||
|
"$ref": "#/definitions/boolean_t"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/type_t"
|
||||||
|
},
|
||||||
|
"cmd_type": {
|
||||||
|
"$ref": "#/definitions/operate_type_t"
|
||||||
|
},
|
||||||
|
"in": {
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"out": {
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"parameter",
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"title": "Get handler",
|
||||||
|
"description": "Query the datamodel object",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"input",
|
||||||
|
"output"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"proto": {
|
||||||
|
"$ref": "#/definitions/proto_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"oneof": [
|
||||||
|
{
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t",
|
||||||
|
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"parameters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameter",
|
||||||
|
"value",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameter": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/type_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add_object": {
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"proto": {
|
||||||
|
"$ref": "#/definitions/proto_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"oneof": [
|
||||||
|
{
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t",
|
||||||
|
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameters"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameter",
|
||||||
|
"status"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameter": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t",
|
||||||
|
"Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code"
|
||||||
|
},
|
||||||
|
"instance": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"del_object": {
|
||||||
|
"title": "Delete object instance",
|
||||||
|
"description": "Delete a object instance from multi instance object",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"input",
|
||||||
|
"output"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"proto": {
|
||||||
|
"$ref": "#/definitions/proto_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"oneof": [
|
||||||
|
{
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t",
|
||||||
|
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameters"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameter",
|
||||||
|
"status"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameter": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"set": {
|
||||||
|
"title": "Set handler",
|
||||||
|
"description": "Set values of datamodel object element",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"input",
|
||||||
|
"output"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"path",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"proto": {
|
||||||
|
"$ref": "#/definitions/proto_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\"}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"oneof": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t",
|
||||||
|
"Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameters"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"parameter"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"parameter": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"operate": {
|
||||||
|
"title": "Operate handler",
|
||||||
|
"description": "Operate on object element provided in path",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"input",
|
||||||
|
"output"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/operate_path_t"
|
||||||
|
},
|
||||||
|
"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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"Results"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"Results": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/path_t"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13",
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"parameter": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/type_t"
|
||||||
|
},
|
||||||
|
"fault": {
|
||||||
|
"$ref": "#/definitions/fault_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"{\n\t\"status\": true}",
|
||||||
|
"{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transaction_start": {
|
||||||
|
"title": "Start a transaction before set/add/del operations",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"status"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"output"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"transaction_abort": {
|
||||||
|
"title": "Aborts an on-going transaction",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"status"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"output"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"transaction_commit": {
|
||||||
|
"title": "Commits an on-going transaction",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"input": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"status"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"output"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
test/api/json/dmtest.validation.json
Normal file
104
test/api/json/dmtest.validation.json
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
"object": "dmtest",
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"method": "get",
|
||||||
|
"args": {
|
||||||
|
"path": "Device.",
|
||||||
|
"proto": "usp"
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "transaction_start",
|
||||||
|
"args": {},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "set",
|
||||||
|
"args": {
|
||||||
|
"path": "Device..X_IOPSYS_EU_Syslog.ConsoleLogLevel",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "transaction_abort",
|
||||||
|
"args": {},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "add_object",
|
||||||
|
"args": {
|
||||||
|
"path": "Device.ManagementServer..InformParameter.",
|
||||||
|
"proto": "cwmp"
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "get_supported_dm",
|
||||||
|
"args": {
|
||||||
|
"path":"Device.",
|
||||||
|
"next-level":false,
|
||||||
|
"schema_type":1
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "get_supported_dm",
|
||||||
|
"args": {
|
||||||
|
"path":"Device."
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "get_supported_dm",
|
||||||
|
"args": {
|
||||||
|
"path":"Device.",
|
||||||
|
"next-level":false,
|
||||||
|
"schema_type":2
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "get_supported_dm",
|
||||||
|
"args": {
|
||||||
|
"path":"Device.",
|
||||||
|
"next-level":false,
|
||||||
|
"schema_type":3
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "get_supported_dm",
|
||||||
|
"args": {
|
||||||
|
"path":"Device.",
|
||||||
|
"schema_type":1
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "get_supported_dm",
|
||||||
|
"args": {},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "transaction_start",
|
||||||
|
"args": {},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "transaction_commit",
|
||||||
|
"args": {},
|
||||||
|
"rc": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "del_object",
|
||||||
|
"args": {
|
||||||
|
"path": "Device.ManagementServer..InformParameter.2",
|
||||||
|
"proto": "cwmp"
|
||||||
|
},
|
||||||
|
"rc": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
test/dynamicdm_ubus_test/Makefile
Normal file
16
test/dynamicdm_ubus_test/Makefile
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
BIN = bbf_ubus
|
||||||
|
|
||||||
|
BIN_OBJ = bbf_ubus.o
|
||||||
|
BIN_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC -I /usr/local/include/
|
||||||
|
BIN_LDFLAGS = $(LDFLAGS) -lbbf_ubus -lubus -lubox -lbbf_test
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(BIN_CFLAGS) $(FPIC) -c -o $@ $<
|
||||||
|
|
||||||
|
all: $(BIN)
|
||||||
|
|
||||||
|
$(BIN): $(BIN_OBJ)
|
||||||
|
$(CC) -o $@ $^ $(BIN_LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -fv *.o $(BIN)
|
||||||
34
test/dynamicdm_ubus_test/bbf_ubus.c
Normal file
34
test/dynamicdm_ubus_test/bbf_ubus.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <libbbf_ubus/libbbf_ubus.h>
|
||||||
|
#include <libbbf_api/dmbbf.h>
|
||||||
|
#include <libubox/uloop.h>
|
||||||
|
|
||||||
|
extern DM_MAP_OBJ tDynamicObj[];
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct ubus_context *ctx = ubus_connect(NULL);
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
printf("Failed to connect to ubus\n\r");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Sending entry obj: (%s)\n\r", tDynamicObj[0].path);
|
||||||
|
|
||||||
|
ubus_add_uloop(ctx);
|
||||||
|
|
||||||
|
if (-1 == dynamicdm_init_plugin_object(ctx, "dmtest", tDynamicObj)) {
|
||||||
|
printf("Failed to create ubus object\n\r");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uloop_run();
|
||||||
|
|
||||||
|
dynamicdm_free_plugin_object(ctx, "dmtest");
|
||||||
|
ubus_free(ctx);
|
||||||
|
uloop_done();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue