diff --git a/README.md b/README.md index 8ff44e3e2b09f2a3b863dab03adc3adde242528b..a48901e188db4225f6cfc0ef49362827c5bc3f5e 100644 --- a/README.md +++ b/README.md @@ -65,15 +65,25 @@ config ptm-device 'ptm0' This is a verbose print of all methods published to ubus on a device. ```bash -'dsl' @d35e2f41 - "status":{} - "stats":{} -'dsl.channel.0' @9f3ca1b2 - "status":{} - "stats":{"interval":"String"} -'dsl.line.0' @c01eec72 - "status":{} - "stats":{"interval":"String"} +'atm.link.0' @607d41d6 + "status":{} + "stats":{} + "configure":{"link_type":"String","vpi":"Integer","vci":"Integer","encapsulation":"String","qos_class":"String","peak_cell_rate":"Integer","max_burst_size":"Integer","sustainable_cell_rate":"Integer"} +'dsl' @8e73ca86 + "status":{} + "stats":{} +'dsl.channel.0' @e76e0883 + "status":{} + "stats":{"interval":"String"} +'dsl.line.0' @3a06e2d2 + "status":{} + "stats":{"interval":"String"} + "configure":{"xtse":"String","vdsl2_profiles":"String","fast_profiles":"String","data_gathering":"Boolean","limit_mask":"Integer","us0_mask":"Integer"} +'fast.line.0' @bc51c0a7 + "status":{} + "stats":{"interval":"String"} +'ptm.link.0' @35822197 + "status":{} ``` For more info on the Ubus API see [link](./docs/ubus.splash.md) diff --git a/docs/api/atm.link.md b/docs/api/atm.link.md new file mode 100644 index 0000000000000000000000000000000000000000..1266d323ba7892ebadc6a3f935e80c05c5bbc28c --- /dev/null +++ b/docs/api/atm.link.md @@ -0,0 +1,157 @@ +# atm.link.<number> + +| List of Methods | +| --- | +| [status](#status) | +| [stats](#stats) | +| [configure](#configure) | + +## status + +`status` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call atm.link.0 status +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "atm.link.0", "status"] +} +``` + +### Input + +None + +### Output + +- type: `object` +- Example as below +```json +{ + "status": "up", + "link_type": "eoa", + "auto_config": true, + "dest_addr": { + "vpi": 8, + "vci": 35 + }, + "encapsulation": "llc", + "fcs_preserved": true, + "vc_search_list": [ + { + "vpi": 8, + "vci": 36 + }, + { + "vpi": 8, + "vci": 37 + } + ], + "aal": "aal5", + "qos": { + "qos_class": "ubr", + "peak_cell_rate": 18867, + "max_burst_size": 22640, + "sustainable_cell_rate": 15093 + } +} +``` + +## stats + +`stats` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call atm.link.0 stats +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "atm.link.0", "stats"] +} +``` + +### Input + +None + +### Output + +- type: `object` +- Example as below +```json +{ + "transmitted_blocks": 12345678, + "received_blocks": 87654321, + "crc_errors": 12 +} +``` + +## configure + +`configure {...}` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call atm.link.0 configure "{'link_type':'eoa','vpi':8,'vci':35,'encapsulation':'llc',\ + 'qos_class':'ubr','peak_cell_rate':10240,'max_burst_size':8124,'sustainable_cell_rate':9600}" +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "atm.link.0", "configure", "{'link_type':'eoa','vpi':8,'vci':35,'encapsulation':'llc'}"] +} +``` + +### Input + +- Type: `object` +- Parameter: `link_type` +- Value: ATM link type with one of values "eoa", "ipoa", "pppoa" and "cip" +- Parameer:`vpi` +- Value: unsigned int as virtual path index +- Parameer:`vci` +- Value: unsigned int as virtual circuit index +- Parameer:`encapsulation` +- Value: ATM link encapsulation with one of values "llc" and "vcmux" +- Parameer:`qos_class` +- Value: ATM QoS class with one of values "ubr", "cbr", "gfr", "vbr_nrt", "vbr_rt", "ubr_plus" and "abr" +- Parameer:`peak_cell_rate` +- Value: unsigned integer +- Parameer:`max_burst_size` +- Value: unsigned integer +- Parameer:`sustainable_cell_rate` +- Value: unsigned integer + +### Output + +None + diff --git a/docs/api/dsl.line.md b/docs/api/dsl.line.md index a1904115a120c48633b5b154b25694612f4a4512..8620141a3eb5d20e9bafe79881645efe49a927cd 100644 --- a/docs/api/dsl.line.md +++ b/docs/api/dsl.line.md @@ -5,6 +5,7 @@ | [status](#status) | | [stats](#stats) | | [stats_interval](#stats_interval) | +| [configure](#configure) | ## status @@ -247,3 +248,50 @@ ubus call dsl.line.0 stats "{ 'interval': 'total'}" "severely_errored_secs": 0 } ``` + +## configure + +`configure {...}` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call dsl.line.0 configure "{'xtse':'01,02,ab,cd,41,52,f8,6e',\ + 'vdsl2_profiles':'8a,8b,8c,8d,17a,30a,35b',\ + 'fast_profiles':'106a,212a','data_gathering':true,'limit_mask':255,'us0_mask':511}" +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "dsl.line.0", "configure", "{'xtse':'01,02,ab,cd,41,52,f8,6e','vdsl2_profiles':'8a,8b,8c,8d,17a,30a,35b'}"] +} +``` + +### Input + +- Type: `object` +- Parameter: `xtse` +- Value: 8 octects which include all modes supported by the DSL line +- Parameer:`vdsl2_profiles` +- Value: Sub/full set of "8a,8b,8c,8d,17a,30a,35b" of VDSL2 profiles +- Parameer:`fast_profiles` +- Value: Sub/full set of "106a,212a" of FAST profiles +- Parameer:`data_gathering` +- Value: true or false to enale/disable data gathering +- Parameer:`limit_mask` +- Value: unsigned integer as limit mask +- Parameer:`us0_mask` +- Value: unsigned integer as us0 mask + + +### Output + +None + diff --git a/docs/api/fast.line.md b/docs/api/fast.line.md new file mode 100644 index 0000000000000000000000000000000000000000..9a90ad9444b2ab67c0f40e1bbee350ec7aded48e --- /dev/null +++ b/docs/api/fast.line.md @@ -0,0 +1,264 @@ +# fast.line.<number> + +| List of Methods | +| --- | +| [status](#status) | +| [stats](#stats) | +| [stats_interval](#stats_interval) | + +## status + +`status` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call fast.line.0 status +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "fast.line.0", "status"] +} +``` + +### Input + +None + +### Output + +- type: `object` +- Example as below +```json +{ + "status": "up", + "upstream": true, + "firmware_version": "A2pvfbH045k.d28a", + "link_status": "up", + "current_profile": "106a", + "power_management_state": "l0", + "max_bit_rate": { + "us": 201000, + "ds": 402000 + }, + "allowed_profiles": [ + "106a", + "212a" + ], + "success_failure_cause": 0, + "upbokler": 180, + "last_transmitted_signal": { + "us": 100, + "ds": 200 + }, + "upbokle": 160, + "line_number": 1, + "noise_margin": { + "us": 146, + "ds": 177 + }, + "attenuation": { + "us": 0, + "ds": 48 + }, + "power": { + "us": 123, + "ds": 106 + }, + "snrm_rmc": { + "us": 12, + "ds": 14 + }, + "bits_rmc_ps": [ + 1, + 3, + 5, + 7 + ], + "fext_to_cancel_enable": { + "us": true, + "ds": true + }, + "etr": { + "us": 250000, + "ds": 350000 + }, + "att_etr": { + "us": 225000, + "ds": 325000 + }, + "min_eftr": { + "us": 200000, + "ds": 300000 + } +} +``` + +## stats + +`stats` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call fast.line.0 stats +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "fast.line.0", "stats"] +} +``` + +### Input + +None + +### Output + +- type: `object` +- Example as below +```json +{ + "total_start": 397, + "showtime_start": 349, + "last_showtime_start": 349, + "current_day_start": 397, + "quarter_hour_start": 397, + "total": { + "errored_secs": 20, + "severely_errored_secs": 5, + "loss": 1, + "lors": 4294967295, + "uas": 1, + "rtx_uc": 4294967295, + "rtx_tx": 0, + "success_bsw": 1024, + "success_sra": 2048, + "success_fra": 1024, + "success_rpa": 2048, + "success_tiga": 1024 + }, + "showtime": { + "errored_secs": 20, + "severely_errored_secs": 5, + "loss": 1, + "lors": 4294967295, + "uas": 1, + "rtx_uc": 4294967295, + "rtx_tx": 0, + "success_bsw": 1024, + "success_sra": 2048, + "success_fra": 1024, + "success_rpa": 2048, + "success_tiga": 1024 + }, + "lastshowtime": { + "errored_secs": 20, + "severely_errored_secs": 5, + "loss": 1, + "lors": 4294967295, + "uas": 1, + "rtx_uc": 4294967295, + "rtx_tx": 0, + "success_bsw": 1024, + "success_sra": 2048, + "success_fra": 1024, + "success_rpa": 2048, + "success_tiga": 1024 + }, + "currentday": { + "errored_secs": 20, + "severely_errored_secs": 5, + "loss": 1, + "lors": 4294967295, + "uas": 1, + "rtx_uc": 4294967295, + "rtx_tx": 0, + "success_bsw": 1024, + "success_sra": 2048, + "success_fra": 1024, + "success_rpa": 2048, + "success_tiga": 1024 + }, + "quarterhour": { + "errored_secs": 20, + "severely_errored_secs": 5, + "loss": 1, + "lors": 4294967295, + "uas": 1, + "rtx_uc": 4294967295, + "rtx_tx": 0, + "success_bsw": 1024, + "success_sra": 2048, + "success_fra": 1024, + "success_rpa": 2048, + "success_tiga": 1024 + } +} +``` + +## stats_interval + +`stats <interval>` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call fast.line.0 stats "{ 'interval': 'total'}" +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "fast.line.0", "stats", "{ 'interval': 'total'}"] +} +``` + +### Input + +- Type: `object` +- Parameter: `interval` +- Value: `total`, `showtime`, `lastshowtime`, `currentday`, or `quarterhour` + +### Output + +- type: `object` +- Example as below +```json +{ + "errored_secs": 20, + "severely_errored_secs": 5, + "loss": 1, + "lors": 4294967295, + "uas": 1, + "rtx_uc": 4294967295, + "rtx_tx": 0, + "success_bsw": 1024, + "success_sra": 2048, + "success_fra": 1024, + "success_rpa": 2048, + "success_tiga": 1024 +} +``` diff --git a/docs/api/ptm.link.md b/docs/api/ptm.link.md new file mode 100644 index 0000000000000000000000000000000000000000..5e8ecbff8937f58da8070fb223039e829a9b21c5 --- /dev/null +++ b/docs/api/ptm.link.md @@ -0,0 +1,43 @@ +# ptm.link.<number> + +| List of Methods | +| --- | +| [status](#status) | + +## status + +`status` + +Type: `Method` + +### Ubus CLI Example + +```bash +ubus call ptm.link.0 status +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "ptm.link.0", "status"] +} +``` + +### Input + +None + +### Output + +- type: `object` +- Example as below +```json +{ + "status": "up", + "mac_addr": "00:11:22:33:44:55" +} +``` diff --git a/docs/testspec.md b/docs/testspec.md index b937640bcf52c5bc5ee64f048120e332ff671f9a..68844b8bf04881c92fae87f84c46bdd623a1d523 100644 --- a/docs/testspec.md +++ b/docs/testspec.md @@ -29,6 +29,7 @@ using JSON-C library APIs. | 1 | status | No argument | [1](./api/dsl.line.md#status) | | 2 | stats | No argument | [2](./api/dsl.line.md#stats) | | 3 | stats | Interval | [3](./api/dsl.line.md#stats_interval) | +| 9 | configure | DSL_config | [9](./api/dsl.line.md#configure) | #### dsl.channel.<number> @@ -45,6 +46,28 @@ using JSON-C library APIs. | 7 | status | No argument | [7](./api/dsl.md#status) | | 8 | stats | No argument | [8](./api/dsl.md#stats) | +#### fast.line.<number> + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 10 | status | No argument | [10](./api/fast.line.md#status) | +| 11 | stats | No argument | [11](./api/fast.line.md#stats) | +| 12 | stats | Interval | [12](./api/fast.line.md#stats_interval) | + +#### atm.link.<number> + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 13 | status | No argument | [13](./api/atm.link.md#status) | +| 14 | stats | No argument | [14](./api/atm.link.md#stats) | +| 15 | configure | ATM_config | [15](./api/atm.link.md#configure) | + +#### ptm.link.<number> + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 16 | status | No argument | [16](./api/ptm.link.md#status) | + ### Unit Tests The *dslmngr* unit tests are written in CMocka, invoking the UBUS callbacks directly from the source code, which is compiled @@ -53,16 +76,20 @@ into a shared library. This means mocking the arguments of a CLI or libubus invo The output of the UBUS callbacks are retrieved by manipulation of the function ubus_send_reply(). Then the output is analyzed and verified by each test case. -| Execution ID | Method | Test Case Name | Function ID Coverage | +| Execution ID | Method | Test Case Name | Function ID Coverage | | :--- | :--- | :--- | :--- | -| 1 | line_status | test_api_dsl_line_status | [1](./api/dsl.line.md#status) | -| 2 | line_stats | test_api_dsl_line_stats | [2](./api/dsl.line.md#stats) | +| 1 | line_status | test_api_dsl_line_status | [1](./api/dsl.line.md#status) | +| 2 | line_stats | test_api_dsl_line_stats | [2](./api/dsl.line.md#stats) | | 3 | line_stats_interval | test_api_dsl_line_stats_interval | [3](./api/dsl.line.md#stats_interval) | | 4 | channel_status | test_api_dsl_channel_status | [4](./api/dsl.channel.md#status) | -| 5 | channel_stats | test_api_dsl_channel_stats | [5](./api/dsl.channel.md#stats) | +| 5 | channel_stats | test_api_dsl_channel_stats | [5](./api/dsl.channel.md#stats) | | 6 | channel_stats_interval | test_api_dsl_channel_stats_interval | [6](./api/dsl.channel.md#stats_interval) | | 7 | dsl_status | test_api_dsl_status | [7](./api/dsl.md#status) | | 8 | dsl_stats | test_api_dsl_stats | [8](./api/dsl.md#stats) | +| 9 | dsl_configure | test_api_dsl_configure | [9](./api/dsl.line.md#configure) | +| 10 | dsl_configure_fail | test_api_dsl_configure_fail | [9](./api/dsl.line.md#configure) | +| 11 | atm_configure | test_api_atm_configure | [15](./api/atm.link.md#configure) | +| 12 | atm_configure_fail | test_api_atm_configure_fai | [15](./api/atm.link.md#configure) | #### test_api_dsl_line_status @@ -191,3 +218,72 @@ Test the *dslmngr* UBUS API callback `dsl_stats_all()`, providing the method [ds Parameters' values included in the returned JSON object of the output shall be equal to those returned by the corresponding stub API in *libdsl* building for TEST platform. + +#### dsl_configure + +##### Description + +Test the *dslmngr* UBUS API callback `dsl_line_configure()`, providing the method [dsl configure](./api/dsl.line.md#configure). + +##### Test Steps + +- Prepare valid input parameters +- Call `dsl_line_configure()` +- Analyze and verify the output + +##### Expected Results + +The dumped input parameters by the corresponding libdsl API must be as same as those prepared in th first step. And the +returned value must indicate success. + +#### dsl_configure_fail + +##### Description + +Test the *dslmngr* UBUS API callback `dsl_line_configure()`, providing the method [dsl configure](./api/dsl.line.md#configure). + +##### Test Steps + +- Prepare invalid input parameters +- Call `dsl_line_configure()` +- Analyze and verify the output + +##### Expected Results + +The dumped input parameters by the corresponding libdsl API must be as same as those prepared in th first step. And the +returned value must indicate failure. + +#### atm_configure + +##### Description + +Test the *dslmngr* UBUS API callback `atm_link_configure()`, providing the method [atm configure](./api/atm.link.md#configure). + +##### Test Steps + +- Prepare valid input parameters +- Call `atm_link_configure()` +- Analyze and verify the output + +##### Expected Results + +The dumped input parameters by the corresponding libdsl API must be as same as those prepared in th first step. And the +returned value must indicate success. + +#### atm_configure_fail + +##### Description + +Test the *dslmngr* UBUS API callback `atm_link_configure()`, providing the method [atm configure](./api/atm.link.md#configure). + +##### Test Steps + +- Prepare valid input parameters +- Call `atm_link_configure()` +- Analyze and verify the output + +##### Expected Results + +The dumped input parameters by the corresponding libdsl API must be as same as those prepared in th first step. And the +returned value must indicate failure. + diff --git a/docs/ubus.splash.md b/docs/ubus.splash.md index 98388171ba8a620f027bc970c2c9e2394c4b0f7c..643fdfd3f087c8ed4c8cf6dee5915fe66f362346 100644 --- a/docs/ubus.splash.md +++ b/docs/ubus.splash.md @@ -3,3 +3,6 @@ * [DSL](./api/dsl.md) * [DSL Line](./api/dsl.line.md) * [DSL Channel](./api/dsl.channel.md) +* [FAST Line](./api/fast.line.md) +* [ATM Link](./api/atm.link.md) +* [PTM Link](./api/ptm.link.md) diff --git a/dslmngr.c b/dslmngr.c index c08ed7468b27205c52bff45bddf13ff5a682fe8a..aa42c2c3f3d80fcc7908488f24635d98f96dd733 100644 --- a/dslmngr.c +++ b/dslmngr.c @@ -32,6 +32,7 @@ #include <uci.h> #include "xdsl.h" +#include "xtm.h" #include "dslmngr.h" #define DSL_OBJECT_LINE "line" @@ -42,6 +43,8 @@ struct value2text { char *text; }; +int current_log_level = LOG_WARNING; + enum { DSL_STATS_INTERVAL, __DSL_STATS_MAX, @@ -51,6 +54,25 @@ static const struct blobmsg_policy dsl_stats_policy[__DSL_STATS_MAX] = { [DSL_STATS_INTERVAL] = { .name = "interval", .type = BLOBMSG_TYPE_STRING }, }; +enum { + DSL_CONFIGURE_XTSE, + DSL_CONFIGURE_VDSL2_PROFILES, + DSL_CONFIGURE_FAST_PROFILES, + DSL_CONFIGURE_ENABLE_DATA_GATHERING, + DSL_CONFIGURE_LIMIT_MASK, + DSL_CONFIGURE_US0_MASK, + __DSL_CONFIGURE_MAX +}; + +static const struct blobmsg_policy dsl_configure_policy[] = { + [DSL_CONFIGURE_XTSE] = { .name = "xtse", .type = BLOBMSG_TYPE_STRING }, + [DSL_CONFIGURE_VDSL2_PROFILES] = { .name = "vdsl2_profiles", .type = BLOBMSG_TYPE_STRING }, + [DSL_CONFIGURE_FAST_PROFILES] = { .name = "fast_profiles", .type = BLOBMSG_TYPE_STRING }, + [DSL_CONFIGURE_ENABLE_DATA_GATHERING] = { .name = "data_gathering", .type = BLOBMSG_TYPE_BOOL }, + [DSL_CONFIGURE_LIMIT_MASK] = { .name = "limit_mask", .type = BLOBMSG_TYPE_INT32 }, + [DSL_CONFIGURE_US0_MASK] = { .name = "us0_mask", .type = BLOBMSG_TYPE_INT32 } +}; + static const char *dsl_if_status_str(enum itf_status status) { switch (status) { @@ -203,18 +225,22 @@ static const char *dsl_line_encoding_str(enum dsl_line_encoding encoding) static const char *dsl_profile_str(enum dsl_profile profile) { - switch (profile) { - case VDSL2_8a: return "8a"; - case VDSL2_8b: return "8b"; - case VDSL2_8c: return "8c"; - case VDSL2_8d: return "8d"; - case VDSL2_12a: return "12a"; - case VDSL2_12b: return "12b"; - case VDSL2_17a: return "17a"; - case VDSL2_30a: return "30a"; - case VDSL2_35b: return "35b"; - default: return "unknown"; - } + const char *str = dsl_get_string_value(vdsl2_profiles, profile); + + if (!str) + return "unknown"; + + return str; +}; + +static const char *fast_profile_str(enum fast_profile profile) +{ + const char *str = dsl_get_string_value(fast_profiles, profile); + + if (!str) + return "unknown"; + + return str; }; static const char *dsl_power_state_str(enum dsl_power_state power_state) @@ -656,18 +682,16 @@ __ret: return retval; } -static struct ubus_method dsl_main_methods[] = { +static struct ubus_method dsl_methods[] = { { .name = "status", .handler = dsl_status_all }, { .name = "stats", .handler = dsl_stats_all } }; - -static struct ubus_object_type dsl_main_type = UBUS_OBJECT_TYPE("dsl", dsl_main_methods); - -static struct ubus_object dsl_main_object = { +static struct ubus_object_type dsl_type = UBUS_OBJECT_TYPE("dsl", dsl_methods); +static struct ubus_object dsl_object = { .name = "dsl", - .type = &dsl_main_type, - .methods = dsl_main_methods, - .n_methods = ARRAY_SIZE(dsl_main_methods), + .type = &dsl_type, + .methods = dsl_methods, + .n_methods = ARRAY_SIZE(dsl_methods), }; int dsl_line_status(struct ubus_context *ctx, struct ubus_object *obj, @@ -777,7 +801,8 @@ __ret: static struct ubus_method dsl_line_methods[] = { { .name = "status", .handler = dsl_line_status }, - UBUS_METHOD("stats", dsl_line_stats, dsl_stats_policy ) + UBUS_METHOD("stats", dsl_line_stats, dsl_stats_policy), + UBUS_METHOD("configure", dsl_line_configure, dsl_configure_policy) }; static struct ubus_object_type dsl_line_type = UBUS_OBJECT_TYPE("dsl.line", dsl_line_methods); @@ -894,16 +919,692 @@ static struct ubus_method dsl_channel_methods[] = { static struct ubus_object_type dsl_channel_type = UBUS_OBJECT_TYPE("dsl.channel", dsl_channel_methods); +static void fast_line_status_to_blob(const struct fast_line *line, struct blob_buf *bb) +{ + void *array; + int i, j, count; + unsigned long opt; + char str[64]; + enum itf_status if_status = line->status; + + /* + * Put most important information at the beginning + */ + if (if_status == IF_UP && line->link_status != LINK_UP) { + /* Some inconsistent status might be retrieved from the driver, i.e. interface status is + * up and the link status is not up. In this case, we force reporting the interface's + * status being down */ + if_status = IF_DOWN; + } + blobmsg_add_string(bb, "status", dsl_if_status_str(if_status)); + blobmsg_add_u8(bb, "upstream", line->upstream); + blobmsg_add_string(bb, "firmware_version", line->firmware_version); + blobmsg_add_string(bb, "link_status", dsl_link_status_str(line->link_status)); + blobmsg_add_string(bb, "current_profile", fast_profile_str(line->current_profile)); + blobmsg_add_string(bb, "power_management_state", dsl_power_state_str(line->power_management_state)); + + // max_bit_rate + unsigned long rates[] = { line->max_bit_rate.us, line->max_bit_rate.ds }; + dsl_add_usds_to_blob("max_bit_rate", false, rates, bb); + + // allowed_profiles + array = blobmsg_open_array(bb, "allowed_profiles"); + for (opt = (unsigned long)FAST_106a; opt <= (unsigned long)FAST_212a; opt <<= 1) { + if (line->allowed_profiles & opt) + blobmsg_add_string(bb, "", fast_profile_str(opt)); + } + blobmsg_close_array(bb, array); + + blobmsg_add_u32(bb, "success_failure_cause", line->success_failure_cause); + blobmsg_add_u32(bb, "upbokler", line->upbokler); + + // last_transmitted_signal + long signals[] = { line->last_transmitted_signal.us, line->last_transmitted_signal.ds }; + dsl_add_usds_to_blob("last_transmitted_signal", true, signals, bb); + + + blobmsg_add_u32(bb, "upbokle", line->upbokle); + dsl_add_int_to_blob("line_number", line->line_number, bb); + + // noise_margin + long margins[] = { line->noise_margin.us, line->noise_margin.ds }; + dsl_add_usds_to_blob("noise_margin", true, margins, bb); + + // attenuation + long attenuations[] = { line->attenuation.us, line->attenuation.ds }; + dsl_add_usds_to_blob("attenuation", true, attenuations, bb); + + // power + long powers[] = { line->power.us, line->power.ds }; + dsl_add_usds_to_blob("power", true, powers, bb); + + // snrm_rmc + long rmc[] = { line->snrm_rmc.us, line->snrm_rmc.ds }; + dsl_add_usds_to_blob("snrm_rmc", true, rmc, bb); + + // bits_rmc_ps + dsl_add_sequence_to_blob("bits_rmc_ps", false, line->bits_rmc_ps.count, + (const long *)line->bits_rmc_ps.elements, bb); + + // fext_to_cancel_enable + void *table = blobmsg_open_table(bb, "fext_to_cancel_enable"); + blobmsg_add_u8(bb, "us", line->fext_to_cancel_enable.us); + blobmsg_add_u8(bb, "ds", line->fext_to_cancel_enable.ds); + blobmsg_close_table(bb, table); + + // etr + unsigned long etr[] = { line->etr.us, line->etr.ds }; + dsl_add_usds_to_blob("etr", false, etr, bb); + + // att_etr + unsigned long att_etr[] = { line->att_etr.us, line->att_etr.ds }; + dsl_add_usds_to_blob("att_etr", false, att_etr, bb); + + // min_eftr + unsigned long min_eftr[] = { line->min_eftr.us, line->min_eftr.ds }; + dsl_add_usds_to_blob("min_eftr", false, min_eftr, bb); +} + +int fast_line_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + static struct blob_buf bb; + struct fast_line line; + int retval = UBUS_STATUS_OK; + int num = -1; + + // Initialize the buffer + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + // Get line status + sscanf(obj->name, "fast.line.%d", &num); + if (xdsl_ops.get_fast_line_info == NULL || (*xdsl_ops.get_fast_line_info)(num, &line) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + fast_line_status_to_blob(&line, &bb); + + // Send the reply + ubus_send_reply(ctx, req, bb.head); + +__ret: + blob_buf_free(&bb); + return retval; +} + +static void fast_line_stats_interval_to_blob(const struct fast_line_stats_interval *stats, struct blob_buf *bb) +{ + blobmsg_add_u64(bb, "errored_secs", stats->errored_secs); + blobmsg_add_u64(bb, "severely_errored_secs", stats->severely_errored_secs); + blobmsg_add_u64(bb, "loss", stats->loss); + blobmsg_add_u64(bb, "lors", stats->lors); + blobmsg_add_u64(bb, "uas", stats->uas); + blobmsg_add_u64(bb, "rtx_uc", stats->rtx_uc); + blobmsg_add_u64(bb, "rtx_tx", stats->rtx_tx); + blobmsg_add_u64(bb, "success_bsw", stats->success_bsw); + blobmsg_add_u64(bb, "success_sra", stats->success_sra); + blobmsg_add_u64(bb, "success_fra", stats->success_fra); + blobmsg_add_u64(bb, "success_rpa", stats->success_rpa); + blobmsg_add_u64(bb, "success_tiga", stats->success_tiga); +} + +int fast_line_stats_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + static struct blob_buf bb; + struct blob_attr *tb[__DSL_STATS_MAX]; + enum dsl_stats_type type = DSL_STATS_QUARTERHOUR + 1; + struct fast_line_stats stats; + struct fast_line_stats_interval stats_interval; + int retval = UBUS_STATUS_OK; + int num = -1; + int i, j; + void *table; + + // Parse and validation check the interval type if any + blobmsg_parse(dsl_stats_policy, __DSL_STATS_MAX, tb, blob_data(msg), blob_len(msg)); + if (tb[DSL_STATS_INTERVAL]) { + const char *st = blobmsg_data(tb[DSL_STATS_INTERVAL]); + + for (i = 0; i < ARRAY_SIZE(dsl_stats_types); i++) { + if (strcasecmp(st, dsl_stats_types[i].text) == 0) { + type = dsl_stats_types[i].value; + break; + } + } + + if (i >= ARRAY_SIZE(dsl_stats_types)) { + DSLMNGR_LOG(LOG_ERR, "Wrong argument for interval statistics type\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + } + + // Initialize the buffer + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + // Get line number + sscanf(obj->name, "fast.line.%d", &num); + + // Get line interval statistics + if (type >= DSL_STATS_TOTAL && type <= DSL_STATS_QUARTERHOUR) { + if (xdsl_ops.get_fast_line_stats_interval == NULL || (*xdsl_ops.get_fast_line_stats_interval) + (num, type, &stats_interval) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + fast_line_stats_interval_to_blob(&stats_interval, &bb); + } else { + // Get line statistics + if (xdsl_ops.get_fast_line_stats == NULL || (*xdsl_ops.get_fast_line_stats)(num, &stats) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + dsl_stats_to_blob(&stats, &bb); + + // Get all interval statistics + for (j = 0; j < ARRAY_SIZE(dsl_stats_types); j++) { + table = blobmsg_open_table(&bb, dsl_stats_types[j].text); + + if (xdsl_ops.get_fast_line_stats_interval == NULL || (*xdsl_ops.get_fast_line_stats_interval) + (num, dsl_stats_types[j].value, &stats_interval) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + fast_line_stats_interval_to_blob(&stats_interval, &bb); + + blobmsg_close_table(&bb, table); + } + } + + // Send the reply + ubus_send_reply(ctx, req, bb.head); + +__ret: + blob_buf_free(&bb); + return retval; +} + +static struct ubus_method fast_line_methods[] = { + { .name = "status", .handler = fast_line_status }, + UBUS_METHOD("stats", fast_line_stats_handler, dsl_stats_policy ) +}; + +static struct ubus_object_type fast_line_type = UBUS_OBJECT_TYPE("fast.line", fast_line_methods); + +static const char *atm_link_type_str(enum atm_link_type type) +{ + const char *str = dsl_get_string_value(atm_link_types, type); + + if (!str) + return "unknown"; + + return str; +} + +static const char *atm_encap_str(enum atm_encapsulation encap) +{ + const char *str = dsl_get_string_value(atm_encapsulations, encap); + + if (!str) + return "unknown"; + + return str; +} + +static const char *atm_aal_str(enum atm_aal aal) +{ + switch (aal) { + case ATM_AAL1: return "aal1"; + case ATM_AAL2: return "aal2"; + case ATM_AAL3: return "aal3"; + case ATM_AAL4: return "aal4"; + case ATM_AAL5: return "aal5"; + default: return "unknown"; + } +} + +static const char *atm_qos_class_str(enum atm_qos_class class) +{ + const char *str = dsl_get_string_value(atm_qos_classes, class); + + if (!str) + return "unknown"; + + return str; +} + +static void atm_add_dest_addr_to_blob(const struct atm_dest_addr *dest_addr, struct blob_buf *bb) +{ + void *table = blobmsg_open_table(bb, "dest_addr"); + blobmsg_add_u32(bb, "vpi", dest_addr->vpi); + blobmsg_add_u32(bb, "vci", dest_addr->vci); + blobmsg_close_table(bb, table); +} + +static void atm_link_status_to_blob(const struct atm_link *link, const struct atm_link_qos *qos, struct blob_buf *bb) +{ + void *array, *table; + int i; + + blobmsg_add_string(bb, "status", dsl_if_status_str(link->status)); + blobmsg_add_string(bb, "link_type", atm_link_type_str(link->link_type)); + blobmsg_add_u8(bb, "auto_config", link->auto_config); + atm_add_dest_addr_to_blob(&link->dest_addr, bb); + blobmsg_add_string(bb, "encapsulation", atm_encap_str(link->encapsulation)); + blobmsg_add_u8(bb, "fcs_preserved", link->fcs_preserved); + + array = blobmsg_open_array(bb, "vc_search_list"); + for (i = 0; i < link->vc_list_count; i++) { + atm_add_dest_addr_to_blob(&link->vc_search_list[i], bb); + } + blobmsg_close_array(bb, array); + + blobmsg_add_string(bb, "aal", atm_aal_str(link->aal)); + + table = blobmsg_open_table(bb, "qos"); + blobmsg_add_string(bb, "qos_class", atm_qos_class_str(qos->qos_class)); + blobmsg_add_u32(bb, "peak_cell_rate", qos->peak_cell_rate); + blobmsg_add_u32(bb, "max_burst_size", qos->max_burst_size); + blobmsg_add_u32(bb, "sustainable_cell_rate", qos->sustainable_cell_rate); + blobmsg_close_table(bb, table); +} + +int atm_link_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + static struct blob_buf bb; + struct atm_link link; + struct atm_link_qos qos; + int retval = UBUS_STATUS_OK; + int num = -1; + + // Initialize the buffer + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + // Get line status + sscanf(obj->name, "atm.link.%d", &num); + if (atm_funcs.get_link_info == NULL || (*atm_funcs.get_link_info)(num, &link, &qos) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + atm_link_status_to_blob(&link, &qos, &bb); + + // Send the reply + ubus_send_reply(ctx, req, bb.head); + +__ret: + blob_buf_free(&bb); + return retval; +} + +static void atm_link_stats_to_blob(const struct atm_link_stats *stats, struct blob_buf *bb) +{ + blobmsg_add_u64(bb, "transmitted_blocks", stats->transmitted_blocks); + blobmsg_add_u64(bb, "received_blocks", stats->received_blocks); + blobmsg_add_u64(bb, "crc_errors", stats->crc_errors); +} + +int atm_link_stats_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + static struct blob_buf bb; + struct atm_link_stats stats; + int retval = UBUS_STATUS_OK; + int num = -1; + + // Initialize the buffer + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + // Get line status + sscanf(obj->name, "atm.link.%d", &num); + if (atm_funcs.get_link_stats == NULL || (*atm_funcs.get_link_stats)(num, &stats) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + atm_link_stats_to_blob(&stats, &bb); + + // Send the reply + ubus_send_reply(ctx, req, bb.head); + + +__ret: + blob_buf_free(&bb); + return retval; +} + +enum { + ATM_CONFIGURE_LINK_TYPE, + ATM_CONFIGURE_VPI, + ATM_CONFIGURE_VCI, + ATM_CONFIGURE_ENCAPSULATION, + ATM_CONFIGURE_QOS_CLASS, + ATM_CONFIGURE_PEAK_CELL_RATE, + ATM_CONFIGURE_MAX_BURST_SIZE, + ATM_CONFIGURE_SUSTAINABLE_CELL_RATE, + __ATM_CONFIGURE_MAX +}; + +static const struct blobmsg_policy atm_configure_policy[] = { + [ATM_CONFIGURE_LINK_TYPE] = { .name = "link_type", .type = BLOBMSG_TYPE_STRING }, + [ATM_CONFIGURE_VPI] = { .name = "vpi", .type = BLOBMSG_TYPE_INT32 }, + [ATM_CONFIGURE_VCI] = { .name = "vci", .type = BLOBMSG_TYPE_INT32 }, + [ATM_CONFIGURE_ENCAPSULATION] = { .name = "encapsulation", .type = BLOBMSG_TYPE_STRING }, + [ATM_CONFIGURE_QOS_CLASS] = { .name = "qos_class", .type = BLOBMSG_TYPE_STRING }, + [ATM_CONFIGURE_PEAK_CELL_RATE] = { .name = "peak_cell_rate", .type = BLOBMSG_TYPE_INT32 }, + [ATM_CONFIGURE_MAX_BURST_SIZE] = { .name = "max_burst_size", .type = BLOBMSG_TYPE_INT32 }, + [ATM_CONFIGURE_SUSTAINABLE_CELL_RATE] = { .name = "sustainable_cell_rate", .type = BLOBMSG_TYPE_INT32 } +}; + +/** + * Handler of UBUS call "atm.link.x configure" + * + * Calling example + * + * ubus call atm.link.0 configure "{'link_type':'eoa','vpi':8,'vci':35,'encapsulation':'llc',\ + 'qos_class':'ubr','peak_cell_rate':10240,'max_burst_size':8124,'sustainable_cell_rate':9600}" + * + */ +int atm_link_configure(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct blob_attr *tb[__ATM_CONFIGURE_MAX]; + struct atm_link link; + struct atm_link_qos qos; + int link_num = -1; + + memset(&link, 0, sizeof(link)); + memset(&qos, 0, sizeof(qos)); + + // Parse and validation check the input parameters + if (blobmsg_parse(atm_configure_policy, __ATM_CONFIGURE_MAX, tb, blob_data(msg), blob_len(msg)) != 0) + return UBUS_STATUS_INVALID_ARGUMENT; + + // link_type + if (tb[ATM_CONFIGURE_LINK_TYPE]) { + const char *type_str = blobmsg_data(tb[ATM_CONFIGURE_LINK_TYPE]); + int type_enum = dsl_get_enum_value(atm_link_types, type_str); + + if (type_enum == -1) { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for link_type. It should be like \"eoa\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + link.link_type = type_enum; + + DSLMNGR_LOG(LOG_DEBUG, "link.link_type = %d(%s)\n", link.link_type, type_str); + } + + // vpi & vci + if (tb[ATM_CONFIGURE_VPI] && tb[ATM_CONFIGURE_VCI]) { + link.dest_addr.vpi = blobmsg_get_u32(tb[ATM_CONFIGURE_VPI]); + link.dest_addr.vci = blobmsg_get_u32(tb[ATM_CONFIGURE_VCI]); + + DSLMNGR_LOG(LOG_DEBUG, "link.dest_addr = { %d, %d }\n", link.dest_addr.vpi, link.dest_addr.vci); + } + + // encapsulation + if (tb[ATM_CONFIGURE_ENCAPSULATION]) { + const char *encap_str = blobmsg_data(tb[ATM_CONFIGURE_ENCAPSULATION]); + int encap_enum = dsl_get_enum_value(atm_encapsulations, encap_str); + + if (encap_enum == -1) { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for encapsulation. It should be like \"llc\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + link.encapsulation = encap_enum; + + DSLMNGR_LOG(LOG_DEBUG, "link.encapsulation = %d(%s)\n", link.encapsulation, encap_str); + } + + // qos_class + if (tb[ATM_CONFIGURE_QOS_CLASS]) { + const char *class_str = blobmsg_data(tb[ATM_CONFIGURE_QOS_CLASS]); + int class_enum = dsl_get_enum_value(atm_qos_classes, class_str); + + if (class_enum == -1) { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for qos_class. It should be like \"ubr\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + qos.qos_class = class_enum; + + DSLMNGR_LOG(LOG_DEBUG, "qos.qos_class = %d(%s)\n", qos.qos_class, class_str); + } + + // peak_cell_rate + if (tb[ATM_CONFIGURE_PEAK_CELL_RATE]) { + qos.peak_cell_rate = blobmsg_get_u32(tb[ATM_CONFIGURE_PEAK_CELL_RATE]); + + DSLMNGR_LOG(LOG_DEBUG, "qos.peak_cell_rate = %u\n", qos.peak_cell_rate); + } + + // max_burst_size + if (tb[ATM_CONFIGURE_MAX_BURST_SIZE]) { + qos.max_burst_size = blobmsg_get_u32(tb[ATM_CONFIGURE_MAX_BURST_SIZE]); + + DSLMNGR_LOG(LOG_DEBUG, "qos.max_burst_size = %u\n", qos.max_burst_size); + } + + // sustainable_cell_rate + if (tb[ATM_CONFIGURE_SUSTAINABLE_CELL_RATE]) { + qos.sustainable_cell_rate = blobmsg_get_u32(tb[ATM_CONFIGURE_SUSTAINABLE_CELL_RATE]); + + DSLMNGR_LOG(LOG_DEBUG, "qos.sustainable_cell_rate = %u\n", qos.sustainable_cell_rate); + } + + // Get link number and call libdsl API + sscanf(obj->name, "atm.link.%d", &link_num); + if (atm_funcs.configure(link_num, &link, &qos) != 0) { + DSLMNGR_LOG(LOG_ERR, "ATM link %d confuration failed\n", link_num); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + return 0; +} + +static struct ubus_method atm_link_methods[] = { + { .name = "status", .handler = atm_link_status }, + { .name = "stats", .handler = atm_link_stats_handler }, + UBUS_METHOD("configure", atm_link_configure, atm_configure_policy) +}; + +static struct ubus_object_type atm_link_type = UBUS_OBJECT_TYPE("atm.link", atm_link_methods); + +static void ptm_link_status_to_blob(const struct ptm_link *link, struct blob_buf *bb) +{ + char mac[18]; + + blobmsg_add_string(bb, "status", dsl_if_status_str(link->status)); + snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x", + link->mac_addr[0], link->mac_addr[1], link->mac_addr[2], + link->mac_addr[3], link->mac_addr[4], link->mac_addr[5]); + blobmsg_add_string(bb, "mac_addr", mac); +} + +int ptm_link_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + static struct blob_buf bb; + struct ptm_link link; + int retval = UBUS_STATUS_OK; + int num = -1; + + // Initialize the buffer + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + // Get line status + sscanf(obj->name, "ptm.link.%d", &num); + if (ptm_funcs.get_link_info == NULL || (*ptm_funcs.get_link_info)(num, &link) != 0) { + retval = UBUS_STATUS_UNKNOWN_ERROR; + goto __ret; + } + ptm_link_status_to_blob(&link, &bb); + + // Send the reply + ubus_send_reply(ctx, req, bb.head); + +__ret: + blob_buf_free(&bb); + return retval; +} + +static struct ubus_method ptm_link_methods[] = { + { .name = "status", .handler = ptm_link_status } +}; + +static struct ubus_object_type ptm_link_type = UBUS_OBJECT_TYPE("ptm.link", ptm_link_methods); + +/** + * Handler of UBUS call "dsl.line.x configure" + * + * Calling example + * + * ubus call dsl.line.0 configure "{'xtse':'01,02,ab,cd,41,52,f8,6e',\ + 'vdsl2_profiles':'8a,8b,8c,8d,17a,30a,35b',\ + 'fast_profiles':'106a,212a','data_gathering':true,'limit_mask':255,'us0_mask':511}" + * + */ +int dsl_line_configure(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct blob_attr *tb[__DSL_CONFIGURE_MAX]; + struct dsl_config_params cfg_params; + int line_num = -1, i; + + if (!xdsl_ops.configure) { + DSLMNGR_LOG(LOG_ERR, "This function is not supported on the current platform yet\n"); + return UBUS_STATUS_NOT_SUPPORTED; + } + + memset(&cfg_params, 0, sizeof(cfg_params)); + + // Parse and validation check the input parameters + if (blobmsg_parse(dsl_configure_policy, __DSL_CONFIGURE_MAX, tb, blob_data(msg), blob_len(msg)) != 0) + return UBUS_STATUS_INVALID_ARGUMENT; + + // XTSE + if (tb[DSL_CONFIGURE_XTSE]) { + const char *xtse_str = blobmsg_data(tb[DSL_CONFIGURE_XTSE]); + + if (!xtse_str || !*xtse_str || + sscanf(xtse_str, "%02hhx,%02hhx,%02hhx,%02hhx,%02hhx,%02hhx,%02hhx,%02hhx", + &cfg_params.xtse[0],&cfg_params.xtse[1],&cfg_params.xtse[2],&cfg_params.xtse[3], + &cfg_params.xtse[4],&cfg_params.xtse[5],&cfg_params.xtse[6],&cfg_params.xtse[7]) != 8) { + DSLMNGR_LOG(LOG_ERR, "Wrong argument for xtse. It should be like \"01,02,ab,cd,41,52,f8,6e\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + DSLMNGR_LOG(LOG_DEBUG, "cfg_params.xtse = {%02hhx,%02hhx,%02hhx,%02hhx,%02hhx,%02hhx,%02hhx,%02hhx}\n", + cfg_params.xtse[0],cfg_params.xtse[1],cfg_params.xtse[2],cfg_params.xtse[3], + cfg_params.xtse[4],cfg_params.xtse[5],cfg_params.xtse[6],cfg_params.xtse[7]); + } + + // VDSL2 profiles + if (tb[DSL_CONFIGURE_VDSL2_PROFILES]) { + const char *profiles_str = blobmsg_data(tb[DSL_CONFIGURE_VDSL2_PROFILES]); + char *dup, *token, *saveptr; + + if (!profiles_str || !*profiles_str) { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for vdsl2_profiles. It should be like \"8a,8b,8c,8d,17a,30a,35b\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + dup = alloca(strlen(profiles_str) + 1); + strcpy(dup, profiles_str); + for (token = strtok_r(dup, ",", &saveptr); token != NULL; token = strtok_r(NULL, ",", &saveptr)) { + int profile = dsl_get_enum_value(vdsl2_profiles, token); + if (profile != -1) + cfg_params.vdsl2_profiles |= profile; + else { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for vdsl2_profiles. It should be like \"8a,8b,8c,8d,17a,30a,35b\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + } + + DSLMNGR_LOG(LOG_DEBUG, "cfg_params.vdsl2_profiles = 0x%lx(%s)\n", cfg_params.vdsl2_profiles, profiles_str); + } + + // FAST profiles + if (tb[DSL_CONFIGURE_FAST_PROFILES]) { + const char *profiles_str = blobmsg_data(tb[DSL_CONFIGURE_FAST_PROFILES]); + char *dup, *token, *saveptr; + + if (!profiles_str || !*profiles_str) { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for fast_profiles. It should be like \"106a,212a\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + dup = alloca(strlen(profiles_str) + 1); + strcpy(dup, profiles_str); + for (token = strtok_r(dup, ",", &saveptr); token != NULL; token = strtok_r(NULL, ",", &saveptr)) { + int profile = dsl_get_enum_value(fast_profiles, token); + if (profile != -1) + cfg_params.fast_profiles |= profile; + else { + DSLMNGR_LOG(LOG_ERR, + "Wrong argument for fast_profiles. It should be like \"106a,212a\"\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + } + + DSLMNGR_LOG(LOG_DEBUG, "cfg_params.fast_profiles = 0x%lx(%s)\n", cfg_params.fast_profiles, profiles_str); + } + + // enable_data_gathering + if (tb[DSL_CONFIGURE_ENABLE_DATA_GATHERING]) { + uint8_t enabled = blobmsg_get_u8(tb[DSL_CONFIGURE_ENABLE_DATA_GATHERING]); + + cfg_params.enable_data_gathering = !!enabled; + + DSLMNGR_LOG(LOG_DEBUG, "cfg_params.enable_data_gathering = %d\n", cfg_params.enable_data_gathering); + } + + // limit_mask + if (tb[DSL_CONFIGURE_LIMIT_MASK]) { + cfg_params.limit_mask = blobmsg_get_u32(tb[DSL_CONFIGURE_LIMIT_MASK]); + + DSLMNGR_LOG(LOG_DEBUG, "cfg_params.limit_mask = 0x%x\n", cfg_params.limit_mask); + } + + // limit_mask + if (tb[DSL_CONFIGURE_US0_MASK]) { + cfg_params.us0_mask = blobmsg_get_u32(tb[DSL_CONFIGURE_US0_MASK]); + + DSLMNGR_LOG(LOG_DEBUG, "cfg_params.us0_mask = 0x%x\n", cfg_params.us0_mask); + } + + // Get line number + sscanf(obj->name, "dsl.line.%d", &line_num); + if (xdsl_ops.configure(line_num, &cfg_params) != 0) { + DSLMNGR_LOG(LOG_ERR, "DSL line %d confuration failed\n", line_num); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + return 0; +} + int dsl_add_ubus_objects(struct ubus_context *ctx) { struct ubus_object *line_objects = NULL; struct ubus_object *channel_objects = NULL; + struct ubus_object *fast_objects = NULL; + struct ubus_object *atm_objects = NULL; + struct ubus_object *ptm_objects = NULL; int ret, max_line, max_channel, i; - ret = ubus_add_object(ctx, &dsl_main_object); + // Add objects dsl + ret = ubus_add_object(ctx, &dsl_object); if (ret) { DSLMNGR_LOG(LOG_ERR, "Failed to add UBUS object '%s', %s\n", - dsl_main_object.name, ubus_strerror(ret)); + dsl_object.name, ubus_strerror(ret)); return -1; } @@ -963,6 +1664,94 @@ int dsl_add_ubus_objects(struct ubus_context *ctx) } } + // Add objects fast.line.x if supported + if (xdsl_ops.get_fast_line_info && xdsl_ops.get_fast_line_stats && + xdsl_ops.get_fast_line_stats_interval) { + fast_objects = calloc(max_line, sizeof(struct ubus_object)); + if (!fast_objects) { + DSLMNGR_LOG(LOG_ERR, "Out of memory\n"); + return -1; + } + for (i = 0; i < max_line; i++) { + char *obj_name; + + if (asprintf(&obj_name, "fast.line.%d", i) <= 0) { + DSLMNGR_LOG(LOG_ERR, "Out of memory\n"); + return -1; + } + + fast_objects[i].name = obj_name; + fast_objects[i].type = &fast_line_type; + fast_objects[i].methods = fast_line_methods; + fast_objects[i].n_methods = ARRAY_SIZE(fast_line_methods); + + ret = ubus_add_object(ctx, &fast_objects[i]); + if (ret) { + DSLMNGR_LOG(LOG_ERR, "Failed to add UBUS object '%s', %s\n", + obj_name, ubus_strerror(ret)); + return -1; + } + } + } + + // Add objects atm.link.x if supported + if (atm_funcs.get_link_info && atm_funcs.get_link_stats && atm_funcs.configure) { + atm_objects = calloc(max_line, sizeof(struct ubus_object)); + if (!atm_objects) { + DSLMNGR_LOG(LOG_ERR, "Out of memory\n"); + return -1; + } + for (i = 0; i < max_line; i++) { + char *obj_name; + + if (asprintf(&obj_name, "atm.link.%d", i) <= 0) { + DSLMNGR_LOG(LOG_ERR, "Out of memory\n"); + return -1; + } + + atm_objects[i].name = obj_name; + atm_objects[i].type = &atm_link_type; + atm_objects[i].methods = atm_link_methods; + atm_objects[i].n_methods = ARRAY_SIZE(atm_link_methods); + + ret = ubus_add_object(ctx, &atm_objects[i]); + if (ret) { + DSLMNGR_LOG(LOG_ERR, "Failed to add UBUS object '%s', %s\n", + obj_name, ubus_strerror(ret)); + return -1; + } + } + } + + // Add objects ptm.link.x if supported + if (ptm_funcs.get_link_info) { + ptm_objects = calloc(max_line, sizeof(struct ubus_object)); + if (!ptm_objects) { + DSLMNGR_LOG(LOG_ERR, "Out of memory\n"); + return -1; + } + for (i = 0; i < max_line; i++) { + char *obj_name; + + if (asprintf(&obj_name, "ptm.link.%d", i) <= 0) { + DSLMNGR_LOG(LOG_ERR, "Out of memory\n"); + return -1; + } + + ptm_objects[i].name = obj_name; + ptm_objects[i].type = &ptm_link_type; + ptm_objects[i].methods = ptm_link_methods; + ptm_objects[i].n_methods = ARRAY_SIZE(ptm_link_methods); + + ret = ubus_add_object(ctx, &ptm_objects[i]); + if (ret) { + DSLMNGR_LOG(LOG_ERR, "Failed to add UBUS object '%s', %s\n", + obj_name, ubus_strerror(ret)); + return -1; + } + } + } + // Returns on success return 0; @@ -971,5 +1760,12 @@ __error_ret: free(line_objects); if (channel_objects) free(channel_objects); + if (fast_objects) + free(fast_objects); + if (atm_objects) + free(atm_objects); + if (ptm_objects) + free(ptm_objects); + return -1; } diff --git a/dslmngr.h b/dslmngr.h index 56a113676ef68f86955995118f16965405c402c8..358c4870915772e337405c4c189af4a0480be0a5 100644 --- a/dslmngr.h +++ b/dslmngr.h @@ -31,7 +31,12 @@ extern "C" { #include <syslog.h> #include <libubus.h> -#define DSLMNGR_LOG(log_level, format...) fprintf(stderr, ##format) +extern int current_log_level; + +#define DSLMNGR_LOG(log_level, format...) do { \ + if (log_level <= current_log_level) \ + fprintf(stderr, ##format); \ + } while(0) #define CHECK_POINT() printf("Check point at %s@%s:%d\n", __func__, __FILE__, __LINE__) @@ -50,6 +55,22 @@ int dsl_channel_stats(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int dsl_stats_all(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); +int fast_line_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); +int fast_line_stats_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); + +int atm_link_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); +int atm_link_stats_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); +int ptm_link_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); + +int dsl_line_configure(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); +int atm_link_configure(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg); #ifdef __cplusplus } diff --git a/schemas/ubus/atm.link_stats.json b/schemas/ubus/atm.link_stats.json new file mode 100644 index 0000000000000000000000000000000000000000..3fd822fa7badb60562b8b21606f8b079632b812b --- /dev/null +++ b/schemas/ubus/atm.link_stats.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/atm.link_stats.json", + "title": "JSON Schema for the output of the UBUS call: atm.link.x stats", + + "definitions": { + "stats_counter": { + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + + "atm_link_stats": { + "$id": "#atm_link_stats", + "type": "object", + + "properties" : { + "transmitted_blocks": { "$ref": "#/definitions/stats_counter" }, + "received_blocks": { "$ref": "#/definitions/stats_counter" }, + "crc_errors": { "$ref": "#/definitions/stats_counter" } + }, + + "required": [ + "transmitted_blocks", + "received_blocks", + "crc_errors" + ] + } + }, + + "$ref": "#atm_link_stats" +} diff --git a/schemas/ubus/atm.link_status.json b/schemas/ubus/atm.link_status.json new file mode 100644 index 0000000000000000000000000000000000000000..e71322fa767aecf8826109aede49ca9ec43be15a --- /dev/null +++ b/schemas/ubus/atm.link_status.json @@ -0,0 +1,82 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/atm.link_status.json", + "title": "JSON Schema for the output of the UBUS call: atm.link.x status", + + "definitions": { + + "if_status": { + "type": "string", + "enum": [ "up", "down", "dormant", "not_present", "lower_layer_down", "error", "unknown" ] + }, + + "atm_link_type": { + "type": "string", + "enum": [ "unconfigured", "eoa", "ipoa", "pppoa", "cip", "unknown" ] + }, + + "destination": { + "type": "object", + "properties": { + "vpi": { "type": "integer" }, + "vci": { "type": "integer" } + }, + "required": [ "vpi", "vci" ] + }, + + "atm_link_status": { + "$id": "#atm_link_status", + "type": "object", + + "properties" : { + + "status": { "$ref": "#/definitions/if_status" }, + "link_type": { "$ref": "#/definitions/atm_link_type" }, + "auto_config": {"type": "boolean" }, + "dest_addr": { "$ref": "#/definitions/destination" }, + "encapsulation": { + "type": "string", + "enum": [ "llc", "vcmux" ] + }, + "fcs_preserved": { "type": "boolean" }, + "vc_search_list": { + "type": "array", + "minItems": 0, + "Items": { "$ref": "#/definitions/destination" } + }, + "aal": { + "type": "string", + "enum": [ "aal1", "aal2", "aal3", "aal4", "aal5" ] + }, + + "qos": { + "type": "object", + "properties": { + "qos_class": { + "type": "string", + "enum": [ "ubr", "cbr", "gfr", "vbr_nrt", "vbr_rt", "ubr_plus", "abr" ] + }, + "peak_cell_rate": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + "max_burst_size": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + "sustainable_cell_rate": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" } + }, + "required": [ "qos_class", "peak_cell_rate", "max_burst_size", "sustainable_cell_rate" ] + } + }, + + "required": [ + "status", + "link_type", + "auto_config", + "dest_addr", + "encapsulation", + "fcs_preserved", + "vc_search_list", + "aal", + "qos" + ] + } + }, + + "$ref": "#atm_link_status" +} diff --git a/schemas/ubus/fast.line_stats.json b/schemas/ubus/fast.line_stats.json new file mode 100644 index 0000000000000000000000000000000000000000..62a351713448b186d9ea1e557758809a2f57abc0 --- /dev/null +++ b/schemas/ubus/fast.line_stats.json @@ -0,0 +1,82 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/fast.line_stats.json", + "title": "JSON Schema for the output of the UBUS call: fast.line.x stats", + + "definitions": { + "stats_counter": { + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + + "line_stats_interval" : { + "$id": "#line_stats_interval", + "type": "object", + + "properties": { + "errored_secs": { "$ref": "#/definitions/stats_counter" }, + "severely_errored_secs": { "$ref": "#/definitions/stats_counter" }, + "loss": { "$ref": "#/definitions/stats_counter" }, + "lors": { "$ref": "#/definitions/stats_counter" }, + "uas": { "$ref": "#/definitions/stats_counter" }, + "rtx_uc": { "$ref": "#/definitions/stats_counter" }, + "rtx_tx": { "$ref": "#/definitions/stats_counter" }, + "success_bsw": { "$ref": "#/definitions/stats_counter" }, + "success_sra": { "$ref": "#/definitions/stats_counter" }, + "success_fra": { "$ref": "#/definitions/stats_counter" }, + "success_rpa": { "$ref": "#/definitions/stats_counter" }, + "success_tiga": { "$ref": "#/definitions/stats_counter" } + }, + + "required": [ + "errored_secs", + "severely_errored_secs", + "loss", + "lors", + "uas", + "rtx_uc", + "rtx_tx", + "success_bsw", + "success_sra", + "success_fra", + "success_rpa", + "success_tiga" + ] + }, + + "line_stats": { + "$id": "#line_stats", + "type": "object", + + "properties" : { + "total_start": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + "showtime_start": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + "last_showtime_start": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + "current_day_start": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + "quarter_hour_start": { "$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger" }, + + "total": { "$ref": "#line_stats_interval" }, + "showtime": { "$ref": "#line_stats_interval" }, + "lastshowtime": { "$ref": "#line_stats_interval" }, + "currentday": { "$ref": "#line_stats_interval" }, + "quarterhour": { "$ref": "#line_stats_interval" } + }, + + "required": [ + "total_start", + "showtime_start", + "last_showtime_start", + "current_day_start", + "quarter_hour_start", + "total", + "showtime", + "lastshowtime", + "currentday", + "quarterhour" + ] + } + }, + + "$ref": "#line_stats" +} diff --git a/schemas/ubus/fast.line_stats_interval.json b/schemas/ubus/fast.line_stats_interval.json new file mode 100644 index 0000000000000000000000000000000000000000..77ff0bb959b11e06b89cc3599da49b690e8ce04f --- /dev/null +++ b/schemas/ubus/fast.line_stats_interval.json @@ -0,0 +1,50 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/fast.line_stats_interval.json", + "title": "JSON Schema for the output of the UBUS call: fast.line.x stats <interval>", + + "definitions": { + "stats_counter": { + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + + "line_stats_interval" : { + "$id": "#line_stats_interval", + "type": "object", + + "properties": { + "errored_secs": { "$ref": "#/definitions/stats_counter" }, + "severely_errored_secs": { "$ref": "#/definitions/stats_counter" }, + "loss": { "$ref": "#/definitions/stats_counter" }, + "lors": { "$ref": "#/definitions/stats_counter" }, + "uas": { "$ref": "#/definitions/stats_counter" }, + "rtx_uc": { "$ref": "#/definitions/stats_counter" }, + "rtx_tx": { "$ref": "#/definitions/stats_counter" }, + "success_bsw": { "$ref": "#/definitions/stats_counter" }, + "success_sra": { "$ref": "#/definitions/stats_counter" }, + "success_fra": { "$ref": "#/definitions/stats_counter" }, + "success_rpa": { "$ref": "#/definitions/stats_counter" }, + "success_tiga": { "$ref": "#/definitions/stats_counter" } + }, + + "required": [ + "errored_secs", + "severely_errored_secs", + "loss", + "lors", + "uas", + "rtx_uc", + "rtx_tx", + "success_bsw", + "success_sra", + "success_fra", + "success_rpa", + "success_tiga" + ] + } + }, + + "$ref": "#line_stats_interval" +} diff --git a/schemas/ubus/fast.line_status.json b/schemas/ubus/fast.line_status.json new file mode 100644 index 0000000000000000000000000000000000000000..498ac009a466cf41412e4136c74c686f8a567c0e --- /dev/null +++ b/schemas/ubus/fast.line_status.json @@ -0,0 +1,122 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/fast.line_status.json", + "title": "JSON Schema for the output of the UBUS call: fast.line.x status", + + "definitions": { + + "if_status": { + "type": "string", + "enum": [ "up", "down", "dormant", "not_present", "lower_layer_down", "error", "unknown" ] + }, + + "link_status": { + "type": "string", + "enum": [ "up", "initializing", "establishing", "no_signal", "disabled", "error", "unknown" ] + }, + + "fast_profile": { + "type": "string", + "enum": [ "106a", "212a", "unknown" ] + }, + + "power_mgmt_state": { + "type": "string", + "enum": [ "l0", "l2_1", "l2_2", "l3", "unknown" ] + }, + + "integer_array": { + "type": "array", + "items": { "type": "integer" }, + "minItems": 0 + }, + + "bidirectional_integers": { + "type": "object", + "properties": { + "us": { "type": "integer" }, + "ds": { "type": "integer" } + }, + "required": [ "us", "ds" ] + }, + + "bidirectional_bools": { + "type": "object", + "properties": { + "us": { "type": "boolean" }, + "ds": { "type": "boolean" } + }, + "required": [ "us", "ds" ] + }, + + "line_status": { + "$id": "#line_status", + "type": "object", + + "properties" : { + + "status": { "$ref": "#/definitions/if_status" }, + "upstream": { "type": "boolean" }, + "firmware_version": {"type": "string" }, + "link_status": { "$ref": "#/definitions/link_status" }, + "current_profile": { "$ref": "#/definitions/fast_profile" }, + "power_management_state": { "$ref": "#/definitions/power_mgmt_state" }, + "max_bit_rate": { "$ref": "#/definitions/bidirectional_integers" }, + + "allowed_profiles": { + "type": "array", + "items": { "$ref": "#/definitions/fast_profile" }, + "minItems": 0 + }, + + "success_failure_cause": { "type": "integer" }, + "upbokler": { "type": "integer" }, + "last_transmitted_signal": { "$ref": "#/definitions/bidirectional_integers" }, + "upbokle": { "type": "integer" }, + "line_number": { "type": "integer" }, + + + "noise_margin": { "$ref": "#/definitions/bidirectional_integers" }, + "last_state_transmitted": { "$ref": "#/definitions/bidirectional_integers" }, + "attenuation": { "type": "integer" }, + "trellis": { "$ref": "#/definitions/bidirectional_integers" }, + "power": { "$ref": "#/definitions/bidirectional_integers" }, + + "snrm_rmc": { "$ref": "#/definitions/bidirectional_integers" }, + "bits_rmc_ps": { "$ref": "#/definitions/integer_array" }, + "attenuation": { "$ref": "#/definitions/bidirectional_integers" }, + "fext_to_cancel_enable": { "$ref": "#/definitions/bidirectional_bools" }, + "etr": { "$ref": "#/definitions/bidirectional_integers" }, + "att_etr": { "$ref": "#/definitions/bidirectional_integers" }, + "min_eftr": { "$ref": "#/definitions/bidirectional_integers" } + }, + + "required": [ + "status", + "upstream", + "firmware_version", + "link_status", + "current_profile", + "power_management_state", + "max_bit_rate", + "allowed_profiles", + "success_failure_cause", + "upbokler", + "last_transmitted_signal", + "upbokle", + "line_number", + "noise_margin", + "attenuation", + "power", + "snrm_rmc", + "bits_rmc_ps", + "fext_to_cancel_enable", + "etr", + "att_etr", + "min_eftr" + ] + } + }, + + "$ref": "#line_status" +} diff --git a/schemas/ubus/ptm.link_status.json b/schemas/ubus/ptm.link_status.json new file mode 100644 index 0000000000000000000000000000000000000000..9e7474b1b7f2c45343b0ddd8fcb79c7f69366282 --- /dev/null +++ b/schemas/ubus/ptm.link_status.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/ptm.link_status.json", + "title": "JSON Schema for the output of the UBUS call: ptm.link.x status", + + "definitions": { + + "if_status": { + "type": "string", + "enum": [ "up", "down", "dormant", "not_present", "lower_layer_down", "error", "unknown" ] + }, + + "mac_address": { + "type": "string", + "pattern": "[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}", + "minLength": 17, + "maxLength": 17 + }, + + "ptm_link_status": { + "$id": "#ptm_link_status", + "type": "object", + + "properties" : { + "status": { "$ref": "#/definitions/if_status" }, + "mac_addr": { "$ref": "#/definitions/mac_address" } + }, + + "required": [ + "status", + "mac_addr" + ] + } + }, + + "$ref": "#ptm_link_status" +} diff --git a/test/api/json/atm.link.validation.json b/test/api/json/atm.link.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..519ea6823296132ea58544214dd8e16112904eff --- /dev/null +++ b/test/api/json/atm.link.validation.json @@ -0,0 +1,30 @@ +{ + "object": "atm.link.0", + + "methods": [ + { + "method": "status", + "rc": 0 + }, + + { + "method": "stats", + "rc": 0 + }, + + { + "method": "configure", + "args": { + "link_type": "eoa", + "vpi": 8, + "vci": 35, + "encapsulation": "llc", + "qos_class": "ubr" + }, + "rc": 0 + } + ] +} + +ubus call atm.link.0 configure "{'link_type':'eoa','vpi':8,'vci':35,'encapsulation':'llc',\ + 'qos_class':'ubr','peak_cell_rate':10240,'max_burst_size':8124,'sustainable_cell_rate':9600}" diff --git a/test/api/json/dsl.line.validation.json b/test/api/json/dsl.line.validation.json index f7358f457dacb4d462156c7cbe6c42c5940dad72..b420b8804b45c4368feb9f74472458547873ba5b 100644 --- a/test/api/json/dsl.line.validation.json +++ b/test/api/json/dsl.line.validation.json @@ -51,5 +51,18 @@ }, "rc": 0 }, + + { + "method": "configure", + "args": { + "xtse": "01,02,ab,cd,41,52,f8,6e", + "vdsl2_profiles": "8a,8b,8c,8d,17a,30a,35b", + "fast_profiles": "106a,212a", + "data_gathering": true, + "limit_mask": 7, + "us0_mask": 3 + }, + "rc": 0 + } ] } diff --git a/test/api/json/fast.line.validation.json b/test/api/json/fast.line.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..df93e2879280466555956ed1c8a5cdb6893d63dc --- /dev/null +++ b/test/api/json/fast.line.validation.json @@ -0,0 +1,55 @@ +{ + "object": "fast.line.0", + + "methods": [ + { + "method": "status", + "rc": 0 + }, + + { + "method": "stats", + "rc": 0 + }, + + { + "method": "stats", + "args": { + "interval": "total" + }, + "rc": 0 + }, + + { + "method": "stats", + "args": { + "interval": "showtime" + }, + "rc": 0 + }, + + { + "method": "stats", + "args": { + "interval": "lastshowtime" + }, + "rc": 0 + }, + + { + "method": "stats", + "args": { + "interval": "currentday" + }, + "rc": 0 + }, + + { + "method": "stats", + "args": { + "interval": "quarterhour" + }, + "rc": 0 + } + ] +} diff --git a/test/api/json/ptm.link.validation.json b/test/api/json/ptm.link.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..e5e973ee811d5543db23887e4f3ac50d5e793998 --- /dev/null +++ b/test/api/json/ptm.link.validation.json @@ -0,0 +1,10 @@ +{ + "object": "ptm.link.0", + + "methods": [ + { + "method": "status", + "rc": 0 + } + ] +} diff --git a/test/cmocka/unit_test_dslmngr.c b/test/cmocka/unit_test_dslmngr.c index 465a80afffa58112187a87c94ca3f7b05a576c29..4099e4ce0b8b061ebcdc40e52e09b1a2d99c9ce5 100644 --- a/test/cmocka/unit_test_dslmngr.c +++ b/test/cmocka/unit_test_dslmngr.c @@ -19,9 +19,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> #include <stdarg.h> #include <stddef.h> #include <setjmp.h> +#include <errno.h> #include <cmocka.h> #include <libubus.h> @@ -36,11 +42,14 @@ #include "dslmngr.h" #include "utils.h" +#define LIBDSL_LOG_INPUT_PARAMS "/tmp/libdsl-input-params.log" + struct test_ctx { struct blob_buf bb; struct ubus_object dsl; struct ubus_object dsl_line; struct ubus_object dsl_channel; + struct ubus_object atm_link; }; /* Overload ubus_send_reply to prevent segment fault*/ @@ -66,6 +75,9 @@ static int setup(void **state) blob_buf_init(&ctx->bb, 0); + // Delete the log file for libdsl input parameters dump + unlink(LIBDSL_LOG_INPUT_PARAMS); + return 0; } @@ -89,6 +101,7 @@ static int group_setup(void **state) ctx->dsl.name = "dsl"; ctx->dsl_line.name = "dsl.line.0"; ctx->dsl_channel.name = "dsl.channel.0"; + ctx->atm_link.name = "atm.link.0"; memset(&ctx->bb, 0, sizeof(struct blob_buf)); *state = ctx; @@ -223,6 +236,210 @@ static void test_api_dsl_stats(void **state) validate_dsl_stats(json_output); } +static struct json_object *get_json_obj_from_log() +{ + int fd = -1; + char *str = NULL; + + // Put the output of ubus call into a string + fd = open(LIBDSL_LOG_INPUT_PARAMS, O_RDONLY); + assert_return_code(fd, errno); + + struct stat st; + int rc = fstat(fd, &st); + assert_true(rc == 0 && st.st_size > 0); + + str = calloc(1, (size_t)st.st_size + 1); + assert_non_null(str); + + ssize_t read_len = read(fd, str, (size_t)st.st_size); + assert_int_equal((int)read_len, (int)st.st_size); + + // Parse the string to a json_object + char *start = strchr(str, '{'); + assert_non_null(start); + //puts(start); + struct json_object *obj = json_tokener_parse(start); + + if (fd >= 0) + close(fd); + if (str) + free(str); + + return obj; +} + +static void test_api_dsl_configure(void **state) +{ + const char *xtse_val = "01,02,ab,cd,41,52,f8,6e"; + const char *vdsl2_profiles_val = "8a,8b,8c,8d,17a,30a,35b"; + const char *fast_profiles_val = "106a,212a"; + const bool data_gathering_val = true; + const unsigned int limit_mask_val = 7; + const unsigned int us0_mask_val = 3; + + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->dsl_line; + + // Prepare the input parameters + blobmsg_add_string(bb, "xtse", xtse_val); + blobmsg_add_string(bb, "vdsl2_profiles", vdsl2_profiles_val); + blobmsg_add_string(bb, "fast_profiles", fast_profiles_val); + blobmsg_add_u8(bb, "data_gathering", data_gathering_val); + blobmsg_add_u32(bb, "limit_mask", limit_mask_val); + blobmsg_add_u32(bb, "us0_mask", us0_mask_val); + + // Call the function to be tested + int res = dsl_line_configure(NULL, obj, NULL, NULL, bb->head); + assert_true(res == UBUS_STATUS_OK); + + // Check the results + struct json_object *jobj = get_json_obj_from_log(); + assert_non_null(jobj); + + struct json_object *tmp = json_object_get_by_string(jobj, "xtse"); + assert_string_equal(json_object_get_string(tmp), xtse_val); + + tmp = json_object_get_by_string(jobj, "vdsl2_profiles"); + assert_string_equal(json_object_get_string(tmp), vdsl2_profiles_val); + + tmp = json_object_get_by_string(jobj, "fast_profiles"); + assert_string_equal(json_object_get_string(tmp), fast_profiles_val); + + tmp = json_object_get_by_string(jobj, "limit_mask"); + assert_int_equal(json_object_get_int(tmp), limit_mask_val); + + tmp = json_object_get_by_string(jobj, "us0_mask"); + assert_int_equal(json_object_get_int(tmp), us0_mask_val); + + // Free the memory + json_object_put(jobj); +} + +static void test_api_dsl_configure_fail(void **state) +{ + const char *xtse_val = "00,00,00,00,00,00,00,00"; // invalid + const char *vdsl2_profiles_val = "30a,35b"; + const char *fast_profiles_val = "106a"; + + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->dsl_line; + + // Prepare the input parameters + blobmsg_add_string(bb, "xtse", xtse_val); + blobmsg_add_string(bb, "vdsl2_profiles", vdsl2_profiles_val); + blobmsg_add_string(bb, "fast_profiles", fast_profiles_val); + + // Call the function to be tested + int res = dsl_line_configure(NULL, obj, NULL, NULL, bb->head); + assert_true(res != UBUS_STATUS_OK); + + // Check the results + struct json_object *jobj = get_json_obj_from_log(); + assert_non_null(jobj); + + struct json_object *tmp = json_object_get_by_string(jobj, "xtse"); + assert_string_equal(json_object_get_string(tmp), xtse_val); + + tmp = json_object_get_by_string(jobj, "vdsl2_profiles"); + assert_string_equal(json_object_get_string(tmp), vdsl2_profiles_val); + + tmp = json_object_get_by_string(jobj, "fast_profiles"); + assert_string_equal(json_object_get_string(tmp), fast_profiles_val); + + // Free the memory + json_object_put(jobj); +} + +static void test_api_atm_configure(void **state) +{ + const char *link_type_val = "eoa"; + const unsigned int vpi_val = 8; // invalid + const unsigned int vci_val = 35; + const char *qos_class_val = "ubr"; + const unsigned int max_burst_size_val = 8124; + + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->atm_link; + + // Prepare the input parameters + blobmsg_add_string(bb, "link_type", link_type_val); + blobmsg_add_u32(bb, "vpi", vpi_val); + blobmsg_add_u32(bb, "vci", vci_val); + blobmsg_add_string(bb, "qos_class", qos_class_val); + blobmsg_add_u32(bb, "max_burst_size", max_burst_size_val); + + // Call the function to be tested + int res = atm_link_configure(NULL, obj, NULL, NULL, bb->head); + assert_true(res == UBUS_STATUS_OK); + + // Check the results + struct json_object *jobj = get_json_obj_from_log(); + assert_non_null(jobj); + + struct json_object *tmp = json_object_get_by_string(jobj, "link_type"); + assert_string_equal(json_object_get_string(tmp), link_type_val); + + tmp = json_object_get_by_string(jobj, "vpi"); + assert_int_equal(json_object_get_int(tmp), vpi_val); + + tmp = json_object_get_by_string(jobj, "vci"); + assert_int_equal(json_object_get_int(tmp), vci_val); + + tmp = json_object_get_by_string(jobj, "qos_class"); + assert_string_equal(json_object_get_string(tmp), qos_class_val); + + tmp = json_object_get_by_string(jobj, "max_burst_size"); + assert_int_equal(json_object_get_int(tmp), max_burst_size_val); + + // Free the memory + json_object_put(jobj); +} + +static void test_api_atm_configure_fail(void **state) +{ + const char *link_type_val = "eoa"; + const unsigned int vpi_val = 0; // invalid + const unsigned int vci_val = 35; + const char *qos_class_val = "ubr"; + + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->atm_link; + + // Prepare the input parameters + blobmsg_add_string(bb, "link_type", link_type_val); + blobmsg_add_u32(bb, "vpi", vpi_val); + blobmsg_add_u32(bb, "vci", vci_val); + blobmsg_add_string(bb, "qos_class", qos_class_val); + + // Call the function to be tested + int res = atm_link_configure(NULL, obj, NULL, NULL, bb->head); + assert_true(res != UBUS_STATUS_OK); + + // Check the results + struct json_object *jobj = get_json_obj_from_log(); + assert_non_null(jobj); + + struct json_object *tmp = json_object_get_by_string(jobj, "link_type"); + assert_string_equal(json_object_get_string(tmp), link_type_val); + + tmp = json_object_get_by_string(jobj, "vpi"); + assert_int_equal(json_object_get_int(tmp), vpi_val); + + tmp = json_object_get_by_string(jobj, "vci"); + assert_int_equal(json_object_get_int(tmp), vci_val); + + tmp = json_object_get_by_string(jobj, "qos_class"); + assert_string_equal(json_object_get_string(tmp), qos_class_val); + + // Free the memory + json_object_put(jobj); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -233,7 +450,11 @@ int main(void) cmocka_unit_test_setup_teardown(test_api_dsl_line_stats_interval, setup, teardown), cmocka_unit_test_setup_teardown(test_api_dsl_channel_stats, setup, teardown), cmocka_unit_test_setup_teardown(test_api_dsl_channel_stats_interval, setup, teardown), - cmocka_unit_test_setup_teardown(test_api_dsl_stats, setup, teardown) + cmocka_unit_test_setup_teardown(test_api_dsl_stats, setup, teardown), + cmocka_unit_test_setup_teardown(test_api_dsl_configure, setup, teardown), + cmocka_unit_test_setup_teardown(test_api_dsl_configure_fail, setup, teardown), + cmocka_unit_test_setup_teardown(test_api_atm_configure, setup, teardown), + cmocka_unit_test_setup_teardown(test_api_atm_configure_fail, setup, teardown) }; return cmocka_run_group_tests(tests, group_setup, group_teardown);