diff --git a/Makefile b/Makefile
index 375683dc4a15999e1383c1a0b623cf144074484c..8172bce395a549b795283dce38511977688fb9fd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,21 @@
PROG = dslmngr
-OBJS = dslmngr.o dslmngr_nl.o main.o
+OBJS = dslmngr.o main.o
-PROG_CFLAGS = $(CFLAGS) -fstrict-aliasing -I./libdsl
-PROG_LDFLAGS = $(LDFLAGS) -L. -L./libdsl -ldsl -pthread
-PROG_LDFLAGS += -luci -lubus -lubox -lblobmsg_json -lnl-genl-3 -lnl-3
+PROG_CFLAGS = $(CFLAGS) -fstrict-aliasing
+PROG_LDFLAGS = $(LDFLAGS) -ldsl
+PROG_LDFLAGS += -pthread -luci -lubus -lubox -lblobmsg_json -lnl-genl-3 -lnl-3
+
+ifeq ($(TARGET_PLATFORM),INTEL)
+PROG_LDFLAGS += -L/opt/intel/usr/lib -ldslfapi -lhelper -lsysfapi
+endif
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
-all: libdsl.so dslmngr
-
dslmngr: $(OBJS)
$(CC) $(PROG_LDFLAGS) -o $@ $^
-libdsl.so:
- $(MAKE) -C libdsl $@
-
clean:
- $(MAKE) -C libdsl clean
rm -f *.o $(PROG)
+
+.PHONY: clean
diff --git a/README b/README
index 0b0923753ff98eed0656fe9813b15439444b707f..d2d0fcc8d26f34c6ec5cb74d8270848ee6570a8c 100644
--- a/README
+++ b/README
@@ -1,12 +1,10 @@
-PrplWrt DSL PoC consists of two parts.
-
libdsl: SoC independent DSL API covering functions to configure DSL and gather stats.
dsmngr: Userspace application to configure DSL from UCI options and provide ubus interface to start/stop DSL and gather stats. dslmngr links with libdsl and utilizes the libdsl functions.
-----------------
- |xdsl object @ubus|
+ |dsl object @ubus|
-----------------
||
-------
@@ -20,3 +18,529 @@ dsmngr: Userspace application to configure DSL from UCI options and provide ubus
----------
|DSL Driver|
----------
+
+ -----------------------------------------------------------------------
+| UBUS Data Model |
+ -----------------------------------------------------------------------
+ubus call dsl status
+{
+ "line": [
+ {
+ "id": 0,
+ "status": "up",
+ "upstream": true,
+ "firmware_version": "8.11.0.15.0.7",
+ "link_status": "up",
+ "xtse_used": [
+ "00",
+ "00",
+ "00",
+ "00",
+ "00",
+ "00",
+ "00",
+ "01"
+ ],
+ "current_profile": "17a",
+ "power_management_state": "l0",
+ "max_bit_rate": {
+ "us": 65067,
+ "ds": 141161
+ },
+ "line_encoding": "dmt",
+ "xtse": [
+ "15",
+ "00",
+ "04",
+ "00",
+ "0c",
+ "05",
+ "05",
+ "07"
+ ],
+ "allowed_profiles": [
+ "8a",
+ "8b",
+ "8c",
+ "8b",
+ "12a",
+ "12b",
+ "17a",
+ "30a",
+ "35b"
+ ],
+ "success_failure_cause": 0,
+ "upbokler_pb": [
+ 2,
+ 15,
+ 12,
+ 2048,
+ 2048
+ ],
+ "rxthrsh_ds": [
+ 18,
+ 18,
+ 2048,
+ 2048,
+ 2048
+ ],
+ "act_ra_mode": {
+ "us": 3,
+ "ds": 3
+ },
+ "snr_mroc_us": 0,
+ "last_state_transmitted": {
+ "us": 0,
+ "ds": 0
+ },
+ "us0_mask": 62451,
+ "trellis": {
+ "us": 1,
+ "ds": 1
+ },
+ "act_snr_mode": {
+ "us": 0,
+ "ds": 0
+ },
+ "line_number": 0,
+ "noise_margin": {
+ "us": 139,
+ "ds": 184
+ },
+ "snr_mpb_us": [
+ 99,
+ 182,
+ 123,
+ -32768,
+ -32768
+ ],
+ "snr_mpb_ds": [
+ 184,
+ 182,
+ 186,
+ -32768,
+ -32768
+ ],
+ "attenuation": {
+ "us": 38,
+ "ds": 35
+ },
+ "power": {
+ "us": 133,
+ "ds": 125
+ },
+ "xtur_vendor": "4946544E",
+ "xtur_country": "B500",
+ "xtur_ansi_std": 0,
+ "xtur_ansi_rev": 0,
+ "xtuc_vendor": "4244434D",
+ "xtuc_country": "B500",
+ "xtuc_ansi_std": 0,
+ "xtuc_ansi_rev": 0,
+ "channel": [
+ {
+ "id": 0,
+ "status": "up",
+ "link_encapsulation_used": "vdsl2_ptm",
+ "curr_rate": {
+ "us": 59998,
+ "ds": 100000
+ },
+ "actndr": {
+ "us": 59998,
+ "ds": 100000
+ },
+ "link_encapsulation_supported": [
+ "adsl2_atm",
+ "vdsl2_ptm"
+ ],
+ "lpath": 0,
+ "intlvdepth": 1,
+ "intlvblock": 255,
+ "actual_interleaving_delay": 0,
+ "actinp": 0,
+ "inpreport": false,
+ "nfec": 255,
+ "rfec": 16,
+ "lsymb": 26823,
+ "actinprein": {
+ "us": 0,
+ "ds": 0
+ }
+ }
+ ]
+ }
+ ]
+}
+ubus call dsl stats
+{
+ "line": [
+ {
+ "id": 0,
+ "total_start": 193,
+ "showtime_start": 86,
+ "last_showtime_start": 0,
+ "current_day_start": 32512,
+ "quarter_hour_start": 112,
+ "total": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "showtime": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "lastshowtime": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "currentday": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "quarterhour": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "channel": [
+ {
+ "id": 0,
+ "total_start": 193,
+ "showtime_start": 86,
+ "last_showtime_start": 0,
+ "current_day_start": 32512,
+ "quarter_hour_start": 112,
+ "total": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "showtime": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "lastshowtime": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "currentday": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "quarterhour": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ }
+ }
+ ]
+ }
+ ]
+}
+ubus call dsl.line.0 status
+{
+ "status": "up",
+ "upstream": true,
+ "firmware_version": "8.11.0.15.0.7",
+ "link_status": "up",
+ "xtse_used": [
+ "00",
+ "00",
+ "00",
+ "00",
+ "00",
+ "00",
+ "00",
+ "01"
+ ],
+ "current_profile": "17a",
+ "power_management_state": "l0",
+ "max_bit_rate": {
+ "us": 65067,
+ "ds": 141209
+ },
+ "line_encoding": "dmt",
+ "xtse": [
+ "15",
+ "00",
+ "04",
+ "00",
+ "0c",
+ "05",
+ "05",
+ "07"
+ ],
+ "allowed_profiles": [
+ "8a",
+ "8b",
+ "8c",
+ "8b",
+ "12a",
+ "12b",
+ "17a",
+ "30a",
+ "35b"
+ ],
+ "success_failure_cause": 0,
+ "upbokler_pb": [
+ 2,
+ 15,
+ 12,
+ 2048,
+ 2048
+ ],
+ "rxthrsh_ds": [
+ 18,
+ 18,
+ 2048,
+ 2048,
+ 2048
+ ],
+ "act_ra_mode": {
+ "us": 3,
+ "ds": 3
+ },
+ "snr_mroc_us": 0,
+ "last_state_transmitted": {
+ "us": 0,
+ "ds": 0
+ },
+ "us0_mask": 62451,
+ "trellis": {
+ "us": 1,
+ "ds": 1
+ },
+ "act_snr_mode": {
+ "us": 0,
+ "ds": 0
+ },
+ "line_number": 0,
+ "noise_margin": {
+ "us": 139,
+ "ds": 184
+ },
+ "snr_mpb_us": [
+ 101,
+ 183,
+ 124,
+ -32768,
+ -32768
+ ],
+ "snr_mpb_ds": [
+ 184,
+ 182,
+ 186,
+ -32768,
+ -32768
+ ],
+ "attenuation": {
+ "us": 38,
+ "ds": 35
+ },
+ "power": {
+ "us": 133,
+ "ds": 125
+ },
+ "xtur_vendor": "4946544E",
+ "xtur_country": "B500",
+ "xtur_ansi_std": 0,
+ "xtur_ansi_rev": 0,
+ "xtuc_vendor": "4244434D",
+ "xtuc_country": "B500",
+ "xtuc_ansi_std": 0,
+ "xtuc_ansi_rev": 0
+}
+ubus call dsl.line.0 stats
+{
+ "total_start": 193,
+ "showtime_start": 86,
+ "last_showtime_start": 0,
+ "current_day_start": 32512,
+ "quarter_hour_start": 112,
+ "total": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "showtime": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "lastshowtime": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "currentday": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ },
+ "quarterhour": {
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+ }
+}
+ubus call dsl.line.0 stats "{'interval':'total'}"
+{
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+}
+ubus call dsl.line.0 stats "{'interval':'showtime'}"
+{
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+}
+ubus call dsl.line.0 stats "{'interval':'lastshowtime'}"
+{
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+}
+ubus call dsl.line.0 stats "{'interval':'currentday'}"
+{
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+}
+ubus call dsl.line.0 stats "{'interval':'quarterhour'}"
+{
+ "errored_secs": 0,
+ "severely_errored_secs": 0
+}
+ubus call dsl.channel.0 status
+{
+ "status": "up",
+ "link_encapsulation_used": "vdsl2_ptm",
+ "curr_rate": {
+ "us": 59998,
+ "ds": 100000
+ },
+ "actndr": {
+ "us": 59998,
+ "ds": 100000
+ },
+ "link_encapsulation_supported": [
+ "adsl2_atm",
+ "vdsl2_ptm"
+ ],
+ "lpath": 0,
+ "intlvdepth": 1,
+ "intlvblock": 255,
+ "actual_interleaving_delay": 0,
+ "actinp": 0,
+ "inpreport": false,
+ "nfec": 255,
+ "rfec": 16,
+ "lsymb": 26823,
+ "actinprein": {
+ "us": 0,
+ "ds": 0
+ }
+}
+ubus call dsl.channel.0 stats
+{
+ "total_start": 193,
+ "showtime_start": 86,
+ "last_showtime_start": 0,
+ "current_day_start": 32512,
+ "quarter_hour_start": 112,
+ "total": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "showtime": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "lastshowtime": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "currentday": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ },
+ "quarterhour": {
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+ }
+}
+ubus call dsl.channel.0 stats "{'interval':'total'}"
+{
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+}
+ubus call dsl.channel.0 stats "{'interval':'showtime'}"
+{
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+}
+ubus call dsl.channel.0 stats "{'interval':'lastshowtime'}"
+{
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+}
+ubus call dsl.channel.0 stats "{'interval':'currentday'}"
+{
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+}
+ubus call dsl.channel.0 stats "{'interval':'quarterhour'}"
+{
+ "xtur_fec_errors": 0,
+ "xtuc_fec_errors": 0,
+ "xtur_hec_errors": 0,
+ "xtuc_hec_errors": 0,
+ "xtur_crc_errors": 0,
+ "xtuc_crc_errors": 0
+}
diff --git a/dslmngr.c b/dslmngr.c
index 5c9a9837abf5940098750598f1af8c2667b1ccb1..52a0c5677e69d8f4f3ccc3fba4e2063c4c9508d5 100644
--- a/dslmngr.c
+++ b/dslmngr.c
@@ -1,9 +1,10 @@
/*
- * dslmngr.c - provides "xdsl" UBUS object
+ * dslmngr.c - provides "dsl" UBUS object
*
- * Copyright (C) 2018 Inteno Broadband Technology AB. All rights reserved.
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
- * Author: anjan.chanda@inteno.se
+ * Author: anjan.chanda@iopsys.eu
+ * yalu.zhang@iopsys.eu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,471 +26,834 @@
#include <libubox/uloop.h>
#include <libubox/ustream.h>
#include <libubox/utils.h>
-#include <libubus.h>
#include <uci.h>
-#include <xdsl.h>
-
+#include "xdsl.h"
#include "dslmngr.h"
-enum {
- DSL_STATS_TYPE,
- __DSL_STATS_MAX,
-};
+#define DSL_OBJECT_LINE "line"
+#define DSL_OBJECT_CHANNEL "channel"
-static const struct blobmsg_policy dsl_stats_policy[__DSL_STATS_MAX] = {
- [DSL_STATS_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
+struct value2text {
+ int value;
+ char *text;
};
enum {
- DSL_STATUS_LINE_ID,
- __DSL_STATUS_MAX,
+ DSL_STATS_INTERVAL,
+ __DSL_STATS_MAX,
};
-static const struct blobmsg_policy dsl_status_policy[__DSL_STATUS_MAX] = {
- [DSL_STATUS_LINE_ID] = { .name = "line", .type = BLOBMSG_TYPE_INT32 },
+static const struct blobmsg_policy dsl_stats_policy[__DSL_STATS_MAX] = {
+ [DSL_STATS_INTERVAL] = { .name = "interval", .type = BLOBMSG_TYPE_STRING },
};
+static const char *dsl_if_status_str(enum dsl_if_status status)
+{
+ switch (status) {
+ case IF_UP: return "up";
+ case IF_DOWN: return "down";
+ case IF_DORMANT: return "dormant";
+ case IF_NOTPRESENT: return "not_present";
+ case IF_LLDOWN: return "lower_layer_down";
+ case IF_ERROR: return "error";
+ case IF_UNKNOWN:
+ default: return "unknown";
+ }
+}
+
+static const char *dsl_link_status_str(enum dsl_link_status status)
+{
+ switch (status) {
+ case LINK_UP: return "up";
+ case LINK_INITIALIZING: return "initializing";
+ case LINK_ESTABLISHING: return "establishing";
+ case LINK_NOSIGNAL: return "no_signal";
+ case LINK_DISABLED: return "disabled";
+ case LINK_ERROR: return "error";
+ default: return "unknown";
+ }
+}
+static const char *dsl_mod_str(enum dsl_modtype mod)
+{
+ switch (mod) {
+ case MOD_G_922_1_ANNEX_A: return "gdmt_annexa";
+ case MOD_G_922_1_ANNEX_B: return "gdmt_annexb";
+ case MOD_G_922_1_ANNEX_C: return "gdmt_annexc";
+ case MOD_T1_413: return "t1413";
+ case MOD_T1_413i2: return "t1413_i2";
+ case MOD_ETSI_101_388: return "etsi_101_388";
+ case MOD_G_992_2: return "glite";
+ case MOD_G_992_3_Annex_A: return "adsl2_annexa";
+ case MOD_G_992_3_Annex_B: return "adsl2_annexb";
+ case MOD_G_992_3_Annex_C: return "adsl2_annexc";
+ case MOD_G_992_3_Annex_I: return "adsl2_annexi";
+ case MOD_G_992_3_Annex_J: return "adsl2_annexj";
+ case MOD_G_992_3_Annex_L: return "adsl2_annexl";
+ case MOD_G_992_3_Annex_M: return "adsl2_annexm";
+ case MOD_G_992_4: return "splitterless_adsl2";
+ case MOD_G_992_5_Annex_A: return "adsl2p_annexa";
+ case MOD_G_992_5_Annex_B: return "adsl2p_annexb";
+ case MOD_G_992_5_Annex_C: return "adsl2p_annexc";
+ case MOD_G_992_5_Annex_I: return "adsl2p_annexi";
+ case MOD_G_992_5_Annex_J: return "adsl2p_annexj";
+ case MOD_G_992_5_Annex_M: return "adsl2p_annexm";
+ case MOD_G_993_1: return "vdsl";
+ case MOD_G_993_1_Annex_A: return "vdsl_annexa";
+ case MOD_G_993_2_Annex_A: return "vdsl2_annexa";
+ case MOD_G_993_2_Annex_B: return "vdsl2_annexb";
+ case MOD_G_993_2_Annex_C: return "vdsl2_annexc";
+ default: return "unknown";
+ }
+}
-const char *dsl_mode_str(enum dsl_modtype v)
+static const char *dsl_line_encoding_str(enum dsl_line_encoding encoding)
{
-#define E2S(v) case v: return #v
- switch(v) {
- E2S(MOD_GDMT);
- E2S(MOD_T1413);
- E2S(MOD_GLITE);
- E2S(MOD_ADSL2);
- E2S(MOD_ADSL2P);
- E2S(MOD_READSL2);
- E2S(MOD_VDSL);
- E2S(MOD_VDSL2);
- E2S(MOD_VDSL2P);
- E2S(MOD_GFAST);
- E2S(MOD_UNDEFINED);
- default:
- return "MOD_Undefined";
+ switch (encoding) {
+ case LE_DMT: return "dmt";
+ case LE_CAP: return "cap";
+ case LE_2B1Q: return "2b1q";
+ case LE_43BT: return "43bt";
+ case LE_PAM: return "pam";
+ case LE_QAM: return "qam";
+ default: return "unknown";
}
-};
+}
-const char *dsl_tc_str(enum dsl_traffictype v)
+static const char *dsl_profile_str(enum dsl_profile profile)
{
-#define E2S(v) case v: return #v
- switch(v) {
- E2S(TC_PTM);
- E2S(TC_ATM);
- E2S(TC_RAW);
- E2S(TC_NOT_CONNECTED);
- default:
- return "TC_Undefined";
+ switch (profile) {
+ case VDSL2_8a: return "8a";
+ case VDSL2_8b: return "8b";
+ case VDSL2_8c: return "8c";
+ case VDSL2_8d: return "8b";
+ 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 *dsl_pwr_state_str(enum dsl_powerstate v)
+static const char *dsl_power_state_str(enum dsl_power_state power_state)
{
-#define E2S(v) case v: return #v
- switch(v) {
- E2S(L0);
- E2S(L1);
- E2S(L2);
- E2S(L3);
- default:
- return "Unknown";
+ switch (power_state) {
+ case DSL_L0: return "l0";
+ case DSL_L1: return "l1";
+ case DSL_L2: return "l2";
+ case DSL_L3: return "l3";
+ case DSL_L4: return "l4";
+ default: return "unknown";
}
};
-const char *dsl_line_status_str(enum dsl_linestate v)
+static void dsl_add_sequence_to_blob(const char *name, bool is_signed, size_t count,
+ const long *head, struct blob_buf *bb)
{
-#define E2S(v) case v: return #v
- switch(v) {
- E2S(LINE_DOWN);
- E2S(LINE_HANDSHAKING);
- E2S(LINE_TRAINING);
- E2S(LINE_SHOWTIME);
- default:
- return "LINE_Unknown";
+ void *array;
+ size_t i;
+
+ array = blobmsg_open_array(bb, name);
+ for (i = 0; i < count; i++) {
+ if (is_signed)
+ blobmsg_add_u32(bb, "", (uint32_t)head[i]);
+ else
+ blobmsg_add_u64(bb, "", (uint64_t)head[i]);
}
-};
+ blobmsg_close_array(bb, array);
+}
-const char *dsl_stattype_str(enum dsl_stattype t)
+static void dsl_add_usds_to_blob(const char *name, bool is_signed, const long *head, struct blob_buf *bb)
{
- switch (t) {
- case STAT_CURR_LINK:
- return "since linkup";
- case STAT_CURR_15MINS:
- return "current 15 mins";
- case STAT_PREV_15MINS:
- return "previous 15 mins";
- case STAT_CURR_24HRS:
- return "current day";
- case STAT_PREV_24HRS:
- return "previous day";
- case STAT_TOTAL:
- return "total";
- default:
- return "";
+ void *table;
+ int i;
+
+ table = blobmsg_open_table(bb, name);
+ for (i = 0; i < 2; i++) {
+ if (is_signed)
+ blobmsg_add_u32(bb, i == 0 ? "us" : "ds", (uint32_t)head[i]);
+ else
+ blobmsg_add_u64(bb, i == 0 ? "us" : "ds", (uint64_t)head[i]);
}
+ blobmsg_close_table(bb, table);
}
-void dslstats_to_blob_buffer(struct dsl_perfcounters *perf, struct blob_buf *b)
+static void dsl_add_int_to_blob(const char *name, long int value, struct blob_buf *bb)
{
- //blobmsg_add_string(b, "type", dsl_stattype_str(perf->type));
- blobmsg_add_u64(b, "es_down", perf->es.ds);
- blobmsg_add_u64(b, "es_up", perf->es.us);
- blobmsg_add_u64(b, "ses_down", perf->ses.ds);
- blobmsg_add_u64(b, "ses_up", perf->ses.us);
- blobmsg_add_u64(b, "uas_down", perf->uas.ds);
- blobmsg_add_u64(b, "uas_up", perf->uas.us);
+ blobmsg_add_u32(bb, name, (uint32_t)value);
}
-void dslinfo_to_blob_buffer(struct dsl_info *info, int lineid, struct blob_buf *b)
+static void dsl_status_line_to_blob(const struct dsl_line *line, struct blob_buf *bb)
{
- void *array, *obj;
- struct dsl_link *link = &info->link;
+ void *array;
int i;
+ unsigned long opt;
+ char str[64];
+
+ /*
+ * Put most important information at the beginning
+ */
+ blobmsg_add_string(bb, "status", dsl_if_status_str(line->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));
+ // standard_used
+ if (line->standard_used.use_xtse) {
+ array = blobmsg_open_array(bb, "xtse_used");
+ for (i = 0; i < ARRAY_SIZE(line->standard_used.xtse); i++) {
+ snprintf(str, sizeof(str), "%02x", line->standard_used.xtse[i]);
+ blobmsg_add_string(bb, "", str);
+ }
+ blobmsg_close_array(bb, array);
+ } else {
+ for (opt = (unsigned long)MOD_G_922_1_ANNEX_A;
+ opt <= (unsigned long)MOD_G_993_2_Annex_C;
+ opt <<= 1) {
+ if (line->standard_used.mode & opt) {
+ blobmsg_add_string(bb, "standard_used", dsl_mod_str(opt));
+ break;
+ }
+ }
+ }
+ // current_profile
+ blobmsg_add_string(bb, "current_profile", dsl_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);
+
+ blobmsg_add_string(bb, "line_encoding", dsl_line_encoding_str(line->line_encoding));
+
+ // standards_supported
+ if (line->standard_supported.use_xtse) {
+ array = blobmsg_open_array(bb, "xtse");
+ for (i = 0; i < ARRAY_SIZE(line->standard_supported.xtse); i++) {
+ snprintf(str, sizeof(str), "%02x", line->standard_supported.xtse[i]);
+ blobmsg_add_string(bb, "", str);
+ }
+ blobmsg_close_array(bb, array);
+ } else {
+ array = blobmsg_open_array(bb, "standards_supported");
+ for (opt = (unsigned long)MOD_G_922_1_ANNEX_A;
+ opt <= (unsigned long)MOD_G_993_2_Annex_C;
+ opt <<= 1) {
+ if (line->standard_supported.mode & opt)
+ blobmsg_add_string(bb, "", dsl_mod_str(opt));
+ }
+ blobmsg_close_array(bb, array);
+ }
+
+ // allowed_profiles
+ array = blobmsg_open_array(bb, "allowed_profiles");
+ for (opt = (unsigned long)VDSL2_8a; opt <= (unsigned long)VDSL2_35b; opt <<= 1) {
+ if (line->allowed_profiles & opt)
+ blobmsg_add_string(bb, "", dsl_profile_str(opt));
+ }
+ blobmsg_close_array(bb, array);
+
+ blobmsg_add_u32(bb, "success_failure_cause", line->success_failure_cause);
+
+ // upbokler_pb
+ dsl_add_sequence_to_blob("upbokler_pb", false, line->upbokler_pb.count,
+ (const long *)line->upbokler_pb.array, bb);
+
+ // rxthrsh_ds
+ dsl_add_sequence_to_blob("rxthrsh_ds", false, line->rxthrsh_ds.count,
+ (const long *)line->rxthrsh_ds.array, bb);
+
+ // act_ra_mode
+ unsigned long ra_modes[] = { line->act_ra_mode.us, line->act_ra_mode.ds };
+ dsl_add_usds_to_blob("act_ra_mode", false, ra_modes, bb);
+
+ blobmsg_add_u64(bb, "snr_mroc_us", line->snr_mroc_us);
+
+ // last_state_transmitted
+ unsigned long lst[] = { line->last_state_transmitted.us, line->last_state_transmitted.ds };
+ dsl_add_usds_to_blob("last_state_transmitted", false, lst, bb);
+
+ // us0_mask
+ blobmsg_add_u64(bb, "us0_mask", line->us0_mask);
+
+ // trellis
+ long trellis[] = { line->trellis.us, line->trellis.ds };
+ dsl_add_usds_to_blob("trellis", true, trellis, bb);
+
+ // act_snr_mode
+ unsigned long snr_modes[] = { line->act_snr_mode.us, line->act_snr_mode.ds };
+ dsl_add_usds_to_blob("act_snr_mode", false, snr_modes, bb);
- blobmsg_add_string(b, "mode", dsl_mode_str(link->mode) + 4);
- blobmsg_add_string(b, "traffic", dsl_tc_str(link->tc_type) + 3);
- //blobmsg_add_string(b, "status", link->status);
- blobmsg_add_string(b, "link_power_state",
- dsl_pwr_state_str(link->pwr_state));
- blobmsg_add_string(b, "line_status",
- dsl_line_status_str(link->training_status) + 5);
- blobmsg_add_u8(b, "trellis_up", link->trellis_enabled.us);
- blobmsg_add_u8(b, "trellis_down", link->trellis_enabled.ds);
- blobmsg_add_u32(b, "snr_up_x10", link->snr_margin.us);
- blobmsg_add_u32(b, "snr_down_x10", link->snr_margin.ds);
- blobmsg_add_u32(b, "pwr_up_x10", link->power.us);
- blobmsg_add_u32(b, "pwr_down_x10", link->power.ds);
- blobmsg_add_u32(b, "attn_up_x10", link->attn.us);
- blobmsg_add_u32(b, "attn_down_x10", link->attn.ds);
- blobmsg_add_u32(b, "max_rate_up", link->rate_kbps_max.us);
- blobmsg_add_u32(b, "max_rate_down", link->rate_kbps_max.ds);
-
- if (lineid == -1)
- array = blobmsg_open_array(b, "line");
-
- for (i = 0; i < info->num_lines; i++) {
- struct dsl_line *line = &info->line[i];
- struct dsl_line_params *p = &line->param;
-
- if (lineid != -1 && lineid != i)
- continue;
-
- obj = blobmsg_open_table(b, NULL);
- blobmsg_add_u32(b, "id", i);
- blobmsg_add_u32(b, "rate_up", line->rate_kbps.us);
- blobmsg_add_u32(b, "rate_down", line->rate_kbps.ds);
- blobmsg_add_u32(b, "msgc_up", p->msgc.us);
- blobmsg_add_u32(b, "msgc_down", p->msgc.ds);
- blobmsg_add_u32(b, "b_down", p->b.ds);
- blobmsg_add_u32(b, "b_up", p->b.us);
- blobmsg_add_u32(b, "m_down", p->m.ds);
- blobmsg_add_u32(b, "m_up", p->m.us);
- blobmsg_add_u32(b, "t_down", p->t.ds);
- blobmsg_add_u32(b, "t_up", p->t.us);
- blobmsg_add_u32(b, "r_down", p->r.ds);
- blobmsg_add_u32(b, "r_up", p->r.us);
- blobmsg_add_u32(b, "s_down_x10000", p->s.ds * 10000);
- blobmsg_add_u32(b, "s_up_x10000", p->s.us * 10000);
- blobmsg_add_u32(b, "l_down", p->l.ds);
- blobmsg_add_u32(b, "l_up", p->l.us);
- blobmsg_add_u32(b, "d_down", p->d.ds);
- blobmsg_add_u32(b, "d_up", p->d.us);
- blobmsg_add_u32(b, "delay_down", p->delay.ds);
- blobmsg_add_u32(b, "delay_up", p->delay.us);
- blobmsg_add_u32(b, "inp_down_x100", p->inp.ds * 100);
- blobmsg_add_u32(b, "inp_up_x100", p->inp.us * 100);
- blobmsg_add_u64(b, "sf_down", line->cnts.sf.ds);
- blobmsg_add_u64(b, "sf_up", line->cnts.sf.us);
- blobmsg_add_u64(b, "sf_err_down", line->cnts.sferr.ds);
- blobmsg_add_u64(b, "sf_err_up", line->cnts.sferr.us);
- blobmsg_add_u64(b, "rs_down", line->cnts.rs.ds);
- blobmsg_add_u64(b, "rs_up", line->cnts.rs.us);
- blobmsg_add_u64(b, "rs_corr_down", line->cnts.rscorr.ds);
- blobmsg_add_u64(b, "rs_corr_up", line->cnts.rscorr.us);
- blobmsg_add_u64(b, "rs_uncorr_down", line->cnts.rsuncorr.ds);
- blobmsg_add_u64(b, "rs_uncorr_up", line->cnts.rsuncorr.us);
- blobmsg_add_u64(b, "hec_down", line->err.hec.ds);
- blobmsg_add_u64(b, "hec_up", line->err.hec.us);
- blobmsg_add_u64(b, "ocd_down", line->err.ocd.ds);
- blobmsg_add_u64(b, "ocd_up", line->err.ocd.us);
- blobmsg_add_u64(b, "lcd_down", line->err.lcd.ds);
- blobmsg_add_u64(b, "lcd_up", line->err.lcd.us);
- blobmsg_add_u64(b, "fec_down", line->err.fec.ds);
- blobmsg_add_u64(b, "fec_up", line->err.fec.us);
- blobmsg_add_u64(b, "crc_down", line->err.crc.ds);
- blobmsg_add_u64(b, "crc_up", line->err.crc.us);
- blobmsg_close_table(b, obj);
+ // line_number
+ 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);
+
+ // snr_mpb_us
+ dsl_add_sequence_to_blob("snr_mpb_us", true, line->snr_mpb_us.count,
+ (const long *)line->snr_mpb_us.array, bb);
+
+ // snr_mpb_ds
+ dsl_add_sequence_to_blob("snr_mpb_ds", true, line->snr_mpb_ds.count,
+ (const long *)line->snr_mpb_ds.array, 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);
+
+ blobmsg_add_string(bb, "xtur_vendor", line->xtur_vendor);
+ blobmsg_add_string(bb, "xtur_country", line->xtur_country);
+ blobmsg_add_u64(bb, "xtur_ansi_std", line->xtur_ansi_std);
+ blobmsg_add_u64(bb, "xtur_ansi_rev", line->xtur_ansi_rev);
+
+ blobmsg_add_string(bb, "xtuc_vendor", line->xtuc_vendor);
+ blobmsg_add_string(bb, "xtuc_country", line->xtuc_country);
+ blobmsg_add_u64(bb, "xtuc_ansi_std", line->xtuc_ansi_std);
+ blobmsg_add_u64(bb, "xtuc_ansi_rev", line->xtuc_ansi_rev);
+}
+
+static const char *dsl_link_encap_str(enum dsl_link_encapsulation encap)
+{
+ switch (encap) {
+ case G_992_3_ANNEK_K_ATM: return "adsl2_atm";
+ case G_992_3_ANNEK_K_PTM: return "adsl2_ptm";
+ case G_993_2_ANNEK_K_ATM: return "vdsl2_atm";
+ case G_993_2_ANNEK_K_PTM: return "vdsl2_ptm";
+ case G_994_1_AUTO: return "auto";
+ default: return "unknown";
+ }
+};
+
+static void dsl_status_channel_to_blob(const struct dsl_channel *channel, struct blob_buf *bb)
+{
+ void *array;
+ unsigned long opt;
+
+ blobmsg_add_string(bb, "status", dsl_if_status_str(channel->status));
+ blobmsg_add_string(bb, "link_encapsulation_used", dsl_link_encap_str(channel->link_encapsulation_used));
+
+ // curr_rate
+ unsigned long curr_rates[] = { channel->curr_rate.us, channel->curr_rate.ds };
+ dsl_add_usds_to_blob("curr_rate", false, curr_rates, bb);
+
+ // actndr
+ unsigned long act_rates[] = { channel->actndr.us, channel->actndr.ds };
+ dsl_add_usds_to_blob("actndr", false, act_rates, bb);
+
+ // link_encapsulation_supported
+ array = blobmsg_open_array(bb, "link_encapsulation_supported");
+ for (opt = (unsigned long)G_992_3_ANNEK_K_ATM; opt <= (unsigned long)G_994_1_AUTO; opt <<= 1) {
+ if (channel->link_encapsulation_supported & opt)
+ blobmsg_add_string(bb, "", dsl_link_encap_str(opt));
}
- if (lineid == -1)
- blobmsg_close_array(b, array);
-
- array = blobmsg_open_table(b, "counters");
- obj = blobmsg_open_table(b, "total");
- blobmsg_add_u64(b, "es_down", link->perf_cnts.es.ds);
- blobmsg_add_u64(b, "es_up", link->perf_cnts.es.us);
- blobmsg_add_u64(b, "ses_down", link->perf_cnts.ses.ds);
- blobmsg_add_u64(b, "ses_up", link->perf_cnts.ses.us);
- blobmsg_add_u64(b, "uas_down", link->perf_cnts.uas.ds);
- blobmsg_add_u64(b, "uas_up", link->perf_cnts.uas.us);
- blobmsg_close_table(b, obj);
- blobmsg_close_array(b, array);
+ blobmsg_close_array(bb, array);
+
+ blobmsg_add_u64(bb, "lpath", channel->lpath);
+ blobmsg_add_u64(bb, "intlvdepth", channel->intlvdepth);
+ dsl_add_int_to_blob("intlvblock", channel->intlvblock, bb);
+ blobmsg_add_u64(bb, "actual_interleaving_delay", channel->actual_interleaving_delay);
+ dsl_add_int_to_blob("actinp", channel->actinp, bb);
+ blobmsg_add_u8(bb, "inpreport", channel->inpreport);
+ dsl_add_int_to_blob("nfec", channel->nfec, bb);
+ dsl_add_int_to_blob("rfec", channel->rfec, bb);
+ dsl_add_int_to_blob("lsymb", channel->lsymb, bb);
+
+ // actinprein
+ unsigned long act_inps[] = { channel->actinprein.us, channel->actinprein.ds };
+ dsl_add_usds_to_blob("actinprein", false, act_inps, bb);
}
-static int uci_get_dsl_type(char *type)
+static int dsl_status_all(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
- static struct uci_context *ctx = NULL;
- static struct uci_package *pkg = NULL;
- struct uci_element *e;
- int ret = 0;
+ static struct blob_buf bb;
+ struct dsl_line line;
+ struct dsl_channel channel;
+ int retval = UBUS_STATUS_OK;
+ int i, max_line;
+ void *array_line, *array_chan, *table_line, *table_chan;
+
+ // Initialize the buffer
+ memset(&bb, 0, sizeof(bb));
+ blob_buf_init(&bb, 0);
- ctx = uci_alloc_context();
- if (uci_load(ctx, "dsl", &pkg))
- return -1;
+ array_line = blobmsg_open_array(&bb, DSL_OBJECT_LINE);
+ for (i = 0, max_line = dsl_get_line_number(); i < max_line; i++) {
+ if (xdsl_ops.get_line_info == NULL || (*xdsl_ops.get_line_info)(i, &line) != 0 ||
+ xdsl_ops.get_channel_info == NULL || (*xdsl_ops.get_channel_info)(i, &channel) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
- uci_foreach_element(&pkg->sections, e) {
- struct uci_section *s = uci_to_section(e);
- const char *dsl_type;
+ // Line table
+ table_line = blobmsg_open_table(&bb, "");
- if (strcmp(s->type, "dsl-line"))
- continue;
+ // Line parameters
+ blobmsg_add_u32(&bb, "id", (unsigned int)i);
+ dsl_status_line_to_blob(&line, &bb);
- dsl_type = uci_lookup_option_string(ctx, s, "type");
- if (dsl_type)
- sprintf(type, "%s", dsl_type);
- else
- ret = -1;
+ // Embed channel(s) inside a line in the format channel: [{},{}...]
+ array_chan = blobmsg_open_array(&bb, DSL_OBJECT_CHANNEL);
+ table_chan = blobmsg_open_table(&bb, "");
+ // Channel parameters
+ blobmsg_add_u32(&bb, "id", 0);
+ dsl_status_channel_to_blob(&channel, &bb);
+ blobmsg_close_table(&bb, table_chan);
+ blobmsg_close_array(&bb, array_chan);
+
+ blobmsg_close_table(&bb, table_line);
}
- uci_free_context(ctx);
- return ret;
+ blobmsg_close_array(&bb, array_line);
+
+ // Send the reply
+ ubus_send_reply(ctx, req, bb.head);
+
+__ret:
+ blob_buf_free(&bb);
+ return retval;
}
-static int uci_get_dsl_config(struct dsl_config *cfg)
+static struct value2text dsl_stats_types[] = {
+ { DSL_STATS_TOTAL, "total" },
+ { DSL_STATS_SHOWTIME, "showtime" },
+ { DSL_STATS_LASTSHOWTIME, "lastshowtime" },
+ { DSL_STATS_CURRENTDAY, "currentday" },
+ { DSL_STATS_QUARTERHOUR, "quarterhour" }
+};
+
+static void dsl_stats_to_blob(const struct dsl_line_channel_stats *stats, struct blob_buf *bb)
{
- static struct uci_context *ctx = NULL;
- static struct uci_package *pkg = NULL;
- struct uci_element *e;
+ blobmsg_add_u64(bb, "total_start", stats->total_start);
+ blobmsg_add_u64(bb, "showtime_start", stats->showtime_start);
+ blobmsg_add_u64(bb, "last_showtime_start", stats->last_showtime_start);
+ blobmsg_add_u64(bb, "current_day_start", stats->current_day_start);
+ blobmsg_add_u64(bb, "quarter_hour_start", stats->quarter_hour_start);
+}
- memset(cfg, 0, sizeof(struct dsl_config));
+static void dsl_stats_line_interval_to_blob(const struct dsl_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);
+}
- ctx = uci_alloc_context();
- if (uci_load(ctx, "dsl", &pkg))
- return -1;
+static void dsl_stats_channel_interval_to_blob(const struct dsl_channel_stats_interval *stats, struct blob_buf *bb)
+{
+ blobmsg_add_u64(bb, "xtur_fec_errors", stats->xtur_fec_errors);
+ blobmsg_add_u64(bb, "xtuc_fec_errors", stats->xtuc_fec_errors);
+ blobmsg_add_u64(bb, "xtur_hec_errors", stats->xtur_hec_errors);
+ blobmsg_add_u64(bb, "xtuc_hec_errors", stats->xtuc_hec_errors);
+ blobmsg_add_u64(bb, "xtur_crc_errors", stats->xtur_crc_errors);
+ blobmsg_add_u64(bb, "xtuc_crc_errors", stats->xtuc_crc_errors);
+}
- uci_foreach_element(&pkg->sections, e) {
- struct uci_section *s = uci_to_section(e);
- struct uci_option *o;
- struct uci_ptr ptr;
- char mode_path[64] = {0};
- char profile_path[64] = {0};
- const char *bitswap, *sra, *us0, *trellis;
-
- if (strcmp(s->type, "dsl-line"))
- continue;
-
- sprintf(mode_path, "dsl.%s.mode", s->e.name);
- if (uci_lookup_ptr(ctx, &ptr, mode_path, true) == UCI_OK) {
- struct uci_element *ent;
- o = ptr.o;
- if (o->type == UCI_TYPE_LIST) {
- uci_foreach_element(&o->v.list, ent) {
- if (!strcmp(ent->name, "gdmt"))
- cfg->mode |= (1 << MOD_GDMT);
- if (!strcmp(ent->name, "glite"))
- cfg->mode |= (1 << MOD_GLITE);
- if (!strcmp(ent->name, "t1413"))
- cfg->mode |= (1 << MOD_T1413);
- if (!strcmp(ent->name, "adsl2"))
- cfg->mode |= (1 << MOD_ADSL2);
- if (!strcmp(ent->name, "adsl2p"))
- cfg->mode |= (1 << MOD_ADSL2P);
- if (!strcmp(ent->name, "vdsl2"))
- cfg->mode |= (1 << MOD_VDSL2);
- if (!strcmp(ent->name, "gfast"))
- cfg->mode |= (1 << MOD_GFAST);
- }
- }
+static 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 retval = UBUS_STATUS_OK;
+ static struct blob_buf bb;
+ enum dsl_stats_type type;
+ struct dsl_line_channel_stats stats;
+ struct dsl_line_stats_interval line_stats_interval;
+ struct dsl_channel_stats_interval channel_stats_interval;
+ int i, j, max_line;
+ void *array_line, *array_chan, *table_line, *table_interval, *table_chan;
+
+ // Initialize the buffer
+ memset(&bb, 0, sizeof(bb));
+ blob_buf_init(&bb, 0);
+
+ array_line = blobmsg_open_array(&bb, DSL_OBJECT_LINE);
+ for (i = 0, max_line = dsl_get_line_number(); i < max_line; i++) {
+ if (xdsl_ops.get_line_stats == NULL || (*xdsl_ops.get_line_stats)(i, &stats) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
}
- sprintf(profile_path, "dsl.%s.profile", s->e.name);
- if (uci_lookup_ptr(ctx, &ptr, profile_path, true) == UCI_OK) {
- struct uci_element *ent;
- o = ptr.o;
- if (o->type == UCI_TYPE_LIST) {
- uci_foreach_element(&o->v.list, ent) {
- if (!strcmp(ent->name, "8a"))
- cfg->vdsl2_profile |= VDSL2_8a;
- if (!strcmp(ent->name, "8b"))
- cfg->vdsl2_profile |= VDSL2_8b;
- if (!strcmp(ent->name, "8c"))
- cfg->vdsl2_profile |= VDSL2_8c;
- if (!strcmp(ent->name, "8d"))
- cfg->vdsl2_profile |= VDSL2_8d;
- if (!strcmp(ent->name, "12a"))
- cfg->vdsl2_profile |= VDSL2_12a;
- if (!strcmp(ent->name, "12b"))
- cfg->vdsl2_profile |= VDSL2_12b;
- if (!strcmp(ent->name, "17a"))
- cfg->vdsl2_profile |= VDSL2_17a;
- if (!strcmp(ent->name, "30a"))
- cfg->vdsl2_profile |= VDSL2_30a;
- if (!strcmp(ent->name, "35b"))
- cfg->vdsl2_profile |= VDSL2_35b;
- }
+ // Line table
+ table_line = blobmsg_open_table(&bb, "");
+
+ // Line statistics
+ blobmsg_add_u32(&bb, "id", (unsigned int)i);
+ dsl_stats_to_blob(&stats, &bb);
+
+ // Line interval statistics
+ for (j = 0; j < ARRAY_SIZE(dsl_stats_types); j++) {
+ table_interval = blobmsg_open_table(&bb, dsl_stats_types[j].text);
+
+ if (xdsl_ops.get_line_stats_interval == NULL || (*xdsl_ops.get_line_stats_interval)
+ (i, dsl_stats_types[j].value, &line_stats_interval) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
}
+ dsl_stats_line_interval_to_blob(&line_stats_interval, &bb);
+
+ blobmsg_close_table(&bb, table_interval);
}
- trellis = uci_lookup_option_string(ctx, s, "trellis");
- bitswap = uci_lookup_option_string(ctx, s, "bitswap");
- sra = uci_lookup_option_string(ctx, s, "sra");
- us0 = uci_lookup_option_string(ctx, s, "us0");
+ // Embed channel(s) inside a line in the format channel: [{},{}...]
+ array_chan = blobmsg_open_array(&bb, DSL_OBJECT_CHANNEL);
+ table_chan = blobmsg_open_table(&bb, "");
- if (trellis && atoi(trellis) == 1)
- cfg->trellis = 1;
+ // Channel statistics
+ blobmsg_add_u32(&bb, "id", 0);
+ if (xdsl_ops.get_channel_stats == NULL || (*xdsl_ops.get_channel_stats)(i, &stats) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_stats_to_blob(&stats, &bb);
- if (bitswap && atoi(bitswap) == 1)
- cfg->bitswap = 1;
+ // Line interval statistics
+ for (j = 0; j < ARRAY_SIZE(dsl_stats_types); j++) {
+ table_interval = blobmsg_open_table(&bb, dsl_stats_types[j].text);
- if (sra && atoi(sra) == 1)
- cfg->sra = 1;
+ if (xdsl_ops.get_channel_stats_interval == NULL || (*xdsl_ops.get_channel_stats_interval)
+ (i, dsl_stats_types[j].value, &channel_stats_interval) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_stats_channel_interval_to_blob(&channel_stats_interval, &bb);
- if (us0 && atoi(us0) == 1)
- cfg->us0 = 1;
- }
- uci_free_context(ctx);
- return 0;
-}
+ blobmsg_close_table(&bb, table_interval);
+ }
-int dslmngr_dsl_start(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
-{
- struct dsl_config cfg, *cfgptr = NULL;
- char type[128] = {0};
+ // Close the tables and arrays for the channel
+ blobmsg_close_table(&bb, table_chan);
+ blobmsg_close_array(&bb, array_chan);
- if (uci_get_dsl_type(type) == -1)
- return UBUS_STATUS_UNKNOWN_ERROR;
+ // Close the table for one line
+ blobmsg_close_table(&bb, table_line);
+ }
+ blobmsg_close_array(&bb, array_line);
- if (uci_get_dsl_config(&cfg) == 0)
- cfgptr = &cfg;
+ // Send the reply
+ ubus_send_reply(ctx, req, bb.head);
- if (dsl_start(type, cfgptr) < 0)
- return UBUS_STATUS_UNKNOWN_ERROR;
+__ret:
+ blob_buf_free(&bb);
- return UBUS_STATUS_OK;
+ return retval;
}
-int dslmngr_dsl_stop(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+static struct ubus_method dsl_main_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 = {
+ .name = "dsl",
+ .type = &dsl_main_type,
+ .methods = dsl_main_methods,
+ .n_methods = ARRAY_SIZE(dsl_main_methods),
+};
+
+static int dsl_line_status(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
- char type[128] = {0};
+ static struct blob_buf bb;
+ struct dsl_line line;
+ int retval = UBUS_STATUS_OK;
+ int num = -1;
- if (uci_get_dsl_type(type) == -1)
- return UBUS_STATUS_UNKNOWN_ERROR;
+ // Initialize the buffer
+ memset(&bb, 0, sizeof(bb));
+ blob_buf_init(&bb, 0);
- if (dsl_stop(type) < 0)
- return UBUS_STATUS_UNKNOWN_ERROR;
+ // Get line status
+ sscanf(obj->name, "dsl.line.%d", &num);
+ if (xdsl_ops.get_line_info == NULL || (*xdsl_ops.get_line_info)(num, &line) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_status_line_to_blob(&line, &bb);
- return UBUS_STATUS_OK;
+ // Send the reply
+ ubus_send_reply(ctx, req, bb.head);
+
+__ret:
+ blob_buf_free(&bb);
+ return retval;
}
-int dslmngr_dump_dslstats(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+static int dsl_line_stats(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];
- struct dsl_perfcounters stats;
- enum dsl_stattype type = STAT_CURR_LINK;
- char dsltype[128] = {0};
-
- blobmsg_parse(dsl_stats_policy, __DSL_STATS_MAX, tb,
- blob_data(msg), blob_len(msg));
-
- memset(&stats, 0, sizeof(struct dsl_perfcounters));
- if ((tb[DSL_STATS_TYPE])) {
- char st[64] = {0};
-
- strncpy(st, blobmsg_data(tb[DSL_STATS_TYPE]), sizeof(st)-1);
- if (!strncasecmp(st, "now15", 5))
- type = STAT_CURR_15MINS;
- else if (!strncasecmp(st, "prev15", 6))
- type = STAT_PREV_15MINS;
- else if (!strncasecmp(st, "now24", 6))
- type = STAT_CURR_24HRS;
- else if (!strncasecmp(st, "prev24", 6))
- type = STAT_PREV_24HRS;
- else if (!strncasecmp(st, "total", 6))
- type = STAT_TOTAL;
- else if (!strncasecmp(st, "link", 6))
- type = STAT_CURR_LINK;
- else
+ enum dsl_stats_type type = DSL_STATS_QUARTERHOUR + 1;
+ struct dsl_line_channel_stats stats;
+ struct dsl_line_stats_interval line_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, "dsl.line.%d", &num);
+
+ // Get line interval statistics
+ if (type >= DSL_STATS_TOTAL && type <= DSL_STATS_QUARTERHOUR) {
+ if (xdsl_ops.get_line_stats_interval == NULL || (*xdsl_ops.get_line_stats_interval)
+ (num, type, &line_stats_interval) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_stats_line_interval_to_blob(&line_stats_interval, &bb);
+ } else {
+ // Get line statistics
+ if (xdsl_ops.get_line_stats == NULL || (*xdsl_ops.get_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_line_stats_interval == NULL || (*xdsl_ops.get_line_stats_interval)
+ (num, dsl_stats_types[j].value, &line_stats_interval) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_stats_line_interval_to_blob(&line_stats_interval, &bb);
+
+ blobmsg_close_table(&bb, table);
+ }
}
- if (uci_get_dsl_type(dsltype) == -1)
- return UBUS_STATUS_UNKNOWN_ERROR;
+ // Send the reply
+ ubus_send_reply(ctx, req, bb.head);
+
+__ret:
+ blob_buf_free(&bb);
+ return retval;
+}
- if (dsl_get_stats(dsltype, type, &stats) < 0)
- return UBUS_STATUS_UNKNOWN_ERROR;
+static struct ubus_method dsl_line_methods[] = {
+ { .name = "status", .handler = dsl_line_status },
+ UBUS_METHOD("stats", dsl_line_stats, dsl_stats_policy )
+};
+
+static struct ubus_object_type dsl_line_type = UBUS_OBJECT_TYPE("dsl.line", dsl_line_methods);
+
+static int dsl_channel_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 dsl_channel channel;
+ int retval = UBUS_STATUS_OK;
+ int num = -1;
+ // Initialize the buffer
+ memset(&bb, 0, sizeof(bb));
blob_buf_init(&bb, 0);
- dslstats_to_blob_buffer(&stats, &bb);
+ // Get channel status
+ sscanf(obj->name, "dsl.channel.%d", &num);
+ if (xdsl_ops.get_channel_info == NULL || (*xdsl_ops.get_channel_info)(num, &channel) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_status_channel_to_blob(&channel, &bb);
+
+ // Send the reply
ubus_send_reply(ctx, req, bb.head);
- return UBUS_STATUS_OK;
+__ret:
+ blob_buf_free(&bb);
+ return retval;
}
-int dslmngr_dump_dslstatus(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+static int dsl_channel_stats(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 dsl_info dslinfo;
- struct blob_attr *tb[__DSL_STATUS_MAX];
- int ret;
- int lineid = -1;
- char type[128] = {0};
-
- blobmsg_parse(dsl_status_policy, __DSL_STATUS_MAX, tb,
- blob_data(msg), blob_len(msg));
-
- if (tb[DSL_STATUS_LINE_ID]) {
- lineid = blobmsg_get_u32(tb[DSL_STATUS_LINE_ID]);
- if (lineid < 0 || lineid > XDSL_MAX_LINES)
+ struct blob_attr *tb[__DSL_STATS_MAX];
+ enum dsl_stats_type type = DSL_STATS_QUARTERHOUR + 1;
+ struct dsl_line_channel_stats stats;
+ struct dsl_channel_stats_interval channel_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;
+ }
}
- if (uci_get_dsl_type(type) == -1)
- return UBUS_STATUS_UNKNOWN_ERROR;
+ // Initialize the buffer
+ memset(&bb, 0, sizeof(bb));
+ blob_buf_init(&bb, 0);
- memset(&dslinfo, 0, sizeof(dslinfo));
- ret = dsl_get_status(type, &dslinfo);
- if (ret != 0)
- return UBUS_STATUS_UNKNOWN_ERROR;
+ // Get channel number
+ sscanf(obj->name, "dsl.channel.%d", &num);
- blob_buf_init(&bb, 0);
- dslinfo_to_blob_buffer(&dslinfo, lineid, &bb);
+ // Get channel interval statistics
+ if (type >= DSL_STATS_TOTAL && type <= DSL_STATS_QUARTERHOUR) {
+ if (xdsl_ops.get_channel_stats_interval == NULL || (*xdsl_ops.get_channel_stats_interval)
+ (num, type, &channel_stats_interval) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_stats_channel_interval_to_blob(&channel_stats_interval, &bb);
+ } else {
+ // Get channel statistics
+ if (xdsl_ops.get_channel_stats == NULL || (*xdsl_ops.get_channel_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_channel_stats_interval == NULL || (*xdsl_ops.get_channel_stats_interval)
+ (num, dsl_stats_types[j].value, &channel_stats_interval) != 0) {
+ retval = UBUS_STATUS_UNKNOWN_ERROR;
+ goto __ret;
+ }
+ dsl_stats_channel_interval_to_blob(&channel_stats_interval, &bb);
+
+ blobmsg_close_table(&bb, table);
+ }
+ }
+
+ // Send the reply
ubus_send_reply(ctx, req, bb.head);
- return UBUS_STATUS_OK;
+
+__ret:
+ blob_buf_free(&bb);
+ return retval;
}
-struct ubus_method dsl_methods[] = {
- UBUS_METHOD("status", dslmngr_dump_dslstatus, dsl_status_policy),
- UBUS_METHOD_NOARG("start", dslmngr_dsl_start),
- UBUS_METHOD_NOARG("stop", dslmngr_dsl_stop),
- UBUS_METHOD("stats", dslmngr_dump_dslstats, dsl_stats_policy),
+static struct ubus_method dsl_channel_methods[] = {
+ { .name = "status", .handler = dsl_channel_status },
+ UBUS_METHOD("stats", dsl_channel_stats, dsl_stats_policy )
};
-struct ubus_object_type dsl_type = UBUS_OBJECT_TYPE("xdsl", dsl_methods);
+static struct ubus_object_type dsl_channel_type = UBUS_OBJECT_TYPE("dsl.channel", dsl_channel_methods);
-struct ubus_object dsl_object = {
- .name = "xdsl",
- .type = &dsl_type,
- .methods = dsl_methods,
- .n_methods = ARRAY_SIZE(dsl_methods),
-};
+int dsl_add_ubus_objects(struct ubus_context *ctx)
+{
+ struct ubus_object *line_objects = NULL;
+ struct ubus_object *channel_objects = NULL;
+ int ret, max_line, max_channel, i;
+
+ ret = ubus_add_object(ctx, &dsl_main_object);
+ if (ret) {
+ DSLMNGR_LOG(LOG_ERR, "Failed to add UBUS object '%s', %s\n",
+ dsl_main_object.name, ubus_strerror(ret));
+ return -1;
+ }
+
+ // Add objects dsl.line.x
+ max_line = dsl_get_line_number();
+ line_objects = calloc(max_line, sizeof(struct ubus_object));
+ if (!line_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, "dsl.line.%d", i) <= 0) {
+ DSLMNGR_LOG(LOG_ERR, "Out of memory\n");
+ return -1;
+ }
+
+ line_objects[i].name = obj_name;
+ line_objects[i].type = &dsl_line_type;
+ line_objects[i].methods = dsl_line_methods;
+ line_objects[i].n_methods = ARRAY_SIZE(dsl_line_methods);
+
+ ret = ubus_add_object(ctx, &line_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 dsl.channel.x
+ max_channel = dsl_get_channel_number();
+ channel_objects = calloc(max_channel, sizeof(struct ubus_object));
+ if (!channel_objects) {
+ DSLMNGR_LOG(LOG_ERR, "Out of memory\n");
+ return -1;
+ }
+ for (i = 0; i < max_channel; i++) {
+ char *obj_name;
+
+ if (asprintf(&obj_name, "dsl.channel.%d", i) <= 0) {
+ DSLMNGR_LOG(LOG_ERR, "Out of memory\n");
+ return -1;
+ }
+
+ channel_objects[i].name = obj_name;
+ channel_objects[i].type = &dsl_channel_type;
+ channel_objects[i].methods = dsl_channel_methods;
+ channel_objects[i].n_methods = ARRAY_SIZE(dsl_channel_methods);
+
+ ret = ubus_add_object(ctx, &channel_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;
+
+__error_ret:
+ if (line_objects)
+ free(line_objects);
+ if (channel_objects)
+ free(channel_objects);
+ return -1;
+}
diff --git a/dslmngr.h b/dslmngr.h
index eb23fd138a1e1a0009ae557fa0fe33578bd164bb..bfd0c41019198446b00f548aca847ec166157333 100644
--- a/dslmngr.h
+++ b/dslmngr.h
@@ -1,10 +1,43 @@
-#ifndef DSLMNGR_H
-#define DSLMNGR_H
+/*
+ * dslmngr header file
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: anjan.chanda@iopsys.eu
+ * yalu.zhang@iopsys.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 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
+ */
+#ifndef _DSLMNGR_H
+#define _DSLMNGR_H
-/* ubus published objects */
-extern struct ubus_object dsl_object;
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdio.h>
+#include <syslog.h>
+#include <libubus.h>
-extern int dslmngr_nl_msgs_handler(struct ubus_context *ctx);
+#define DSLMNGR_LOG(log_level, format...) fprintf(stderr, ##format)
-#endif /* DSLMNGR_H */
+#define CHECK_POINT() printf("Check point at %s@%s:%d\n", __func__, __FILE__, __LINE__)
+
+int dsl_add_ubus_objects(struct ubus_context *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _DSLMNGR_H */
diff --git a/dslmngr_nl.c b/dslmngr_nl.c
index fac3cb173711ad5ab294bd9c3201e7c3e9fcf5f2..3c4607f6809f130f3549e0f18b453b2805334851 100644
--- a/dslmngr_nl.c
+++ b/dslmngr_nl.c
@@ -1,9 +1,10 @@
/*
* dslmngr_nl.c - converts netlink messages to UBUS events
*
- * Copyright (C) 2018 Inteno Broadband Technology AB. All rights reserved.
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
- * Author: anjan.chanda@inteno.se
+ * Author: anjan.chanda@iopsys.eu
+ * yalu.zhang@iopsys.eu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,24 +20,22 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
-
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
-
#include <netlink/attr.h>
-
-#include <libubox/blobmsg_json.h>
+#include "libubox/blobmsg_json.h"
#include "libubus.h"
-#define XDSL_GENL_NAME "xdsl"
-#define XDSL_GENL_GRP "notify"
+#define NETLINK_FAMILY_NAME "easysoc"
+#define NETLINK_GROUP_NAME "notify"
+
+#define MAX_MSG 128
/* nl attributes */
enum {
@@ -44,8 +43,6 @@ enum {
XDSL_NL_MSG,
__XDSL_NL_MAX,
};
-#define XDSL_NL_MAX (__XDSL_NL_MAX - 1)
-#define MAX_MSG 128
static struct nla_policy nl_notify_policy[__XDSL_NL_MAX] = {
[XDSL_NL_MSG] = { .type = NLA_STRING },
@@ -115,12 +112,8 @@ int dslmngr_nl_msgs_handler(struct ubus_context *ctx)
}
if ((grp = genl_ctrl_resolve_grp(sock,
- XDSL_GENL_NAME,
- XDSL_GENL_GRP)) < 0) {
- /* fprintf(stderr, "Error: %s (%s grp %s)\n",
- nl_geterror(grp),
- XDSL_GENL_NAME,
- XDSL_GENL_GRP); */
+ NETLINK_FAMILY_NAME,
+ NETLINK_GROUP_NAME)) < 0) {
return -1;
}
@@ -131,8 +124,8 @@ int dslmngr_nl_msgs_handler(struct ubus_context *ctx)
if (err < 0) {
fprintf(stderr, "Error: %s (%s grp %s)\n",
nl_geterror(err),
- XDSL_GENL_NAME,
- XDSL_GENL_GRP);
+ NETLINK_FAMILY_NAME,
+ NETLINK_GROUP_NAME);
}
}
diff --git a/libdsl/Makefile b/libdsl/Makefile
index 8921e20043c253a1ec8728bd601eb952ff41e57a..96daaea0cb229fe2a43137f72742b3cd68c86ef6 100644
--- a/libdsl/Makefile
+++ b/libdsl/Makefile
@@ -1,10 +1,11 @@
LIBDSL = libdsl.so
-OBJS = dsl.o
-ifneq ($(INTELCPE),)
- OBJS += intel.o
- LIBDSL_CFLAGS += -DINCLUDE_DSL_CPE_API_VRX
+if ($(PLATFORM),INTEL)
+SRCS := $(shell ls intel/*.c)
+else
+$(error Unknown PLATFORM: $(PLATFORM))
endif
+OBJS := $(SRCS:.c=.o)
all: $(LIBDSL)
@@ -16,3 +17,12 @@ libdsl.so: $(OBJS)
clean:
rm -f *.o $(LIBDSL)
+
+export SRCS OBJS CFLAGS LOCAL_CFLAGS
+debug:
+ @echo "PLATFORM = $$PLATFORM"
+ @echo "SRCS = $$SRCS"
+ @echo "OBJS = $$OBJS"
+ @echo "CFLAGS = $$CFLAGS"
+
+.PHONY: all clean debug
diff --git a/libdsl/dsl.c b/libdsl/dsl.c
deleted file mode 100644
index 89c15e180ad31d0dcd90ca6fd62ea75e2033100e..0000000000000000000000000000000000000000
--- a/libdsl/dsl.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * dsl.c - glue file for backend implementations
- *
- * Copyright (C) 2018 Inteno Broadband Technology AB. All rights reserved.
- *
- * Author: anjan.chanda@inteno.se
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 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 <string.h>
-
-#include "xdsl.h"
-
-#ifdef INTELCPE
-extern const struct dsl_ops intel_xdsl_ops;
-#endif
-
-const struct dsl_ops *dsl_backends[] = {
-#ifdef INTELCPE
- &intel_xdsl_ops,
-#endif
-};
-
-const struct dsl_ops *get_dsl_backend(char *name)
-{
- int i;
-
- for (i = 0; i < sizeof(dsl_backends)/sizeof(dsl_backends[0]); i++)
- if (!strncmp(dsl_backends[i]->name, name,
- strlen(dsl_backends[i]->name)))
- return dsl_backends[i];
-
- return NULL;
-}
-
-int dsl_start(char *name, struct dsl_config *cfg)
-{
- const struct dsl_ops *dsl = get_dsl_backend(name);
-
- if (dsl && dsl->start)
- return dsl->start(name, cfg);
-
- return -1;
-}
-
-int dsl_stop(char *name)
-{
- const struct dsl_ops *dsl = get_dsl_backend(name);
-
- if (dsl && dsl->stop)
- return dsl->stop(name);
-
- return -1;
-}
-
-int dsl_get_max_bitrate(char *name, dsl_long_t *max_rate_kbps)
-{
- const struct dsl_ops *dsl = get_dsl_backend(name);
-
- if (dsl && dsl->get_max_bitrate)
- return dsl->get_max_bitrate(name, max_rate_kbps);
-
- return -1;
-}
-
-int dsl_get_bitrate(char *name, dsl_long_t *rate_kbps)
-{
- const struct dsl_ops *dsl = get_dsl_backend(name);
-
- if (dsl && dsl->get_bitrate)
- return dsl->get_bitrate(name, rate_kbps);
-
- return -1;
-}
-
-int dsl_get_status(char *name, struct dsl_info *info)
-{
- const struct dsl_ops *dsl = get_dsl_backend(name);
-
- if (dsl && dsl->get_status)
- return dsl->get_status(name, info);
-
- return -1;
-}
-
-int dsl_get_stats(char *name, enum dsl_stattype type,
- struct dsl_perfcounters *c)
-{
- const struct dsl_ops *dsl = get_dsl_backend(name);
-
- if (dsl && dsl->get_stats)
- return dsl->get_stats(name, type, c);
-
- return -1;
-}
diff --git a/libdsl/intel/intel_dsl_api.c b/libdsl/intel/intel_dsl_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..85cedff44c6ce020ece72e787a1fc0b8a2d45011
--- /dev/null
+++ b/libdsl/intel/intel_dsl_api.c
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: anjan.chanda@iopsys.eu
+ * yalu.zhang@iopsys.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 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 <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <stdbool.h>
+#include <syslog.h>
+
+#define INCLUDE_DSL_CPE_API_VRX // This is needed by drv_dsl_cpe_api.h
+#include "drv_dsl_cpe_api/drv_dsl_cpe_api_ioctl.h"
+#include "drv_dsl_cpe_api/drv_dsl_cpe_api.h"
+#include "dsl-fapi/dsl_fapi.h"
+
+#include "xdsl.h"
+#include "utils.h"
+
+/**
+ * Mappings among string values and enum ones
+ */
+struct str_enum_map {
+ char *val_str;
+ int val_enum;
+};
+
+const struct dsl_ops xdsl_ops = {
+ .get_line_info = dsl_get_line_info,
+ .get_line_stats = dsl_get_line_stats,
+ .get_line_stats_interval = dsl_get_line_stats_interval,
+ .get_channel_info = dsl_get_channel_info,
+ .get_channel_stats = dsl_get_channel_stats,
+ .get_channel_stats_interval = dsl_get_channel_stats_interval
+};
+
+// TODO: this needs to be updated when supporting DSL bonding
+static int max_line_num = 1;
+static int max_chan_num = 1;
+
+int dsl_get_line_number(void)
+{
+ return max_line_num;
+}
+
+int dsl_get_channel_number(void)
+{
+ return max_chan_num;
+}
+
+/**
+ This function converts a string value to the corresponding enum value.
+
+ \param mappings
+ The mapping arrays whose element contains a string value and an enum one.
+ This parameter must end with { NULL, -1 }.
+
+ \param str_value
+ The string value to be searched.
+
+ \return
+ Returns 0 on success. Otherwise a negative value is returned.
+*/
+static int dsl_get_enum_value(const struct str_enum_map *mappings, const char *str_value)
+{
+ const struct str_enum_map *element;
+
+ for (element = mappings; element->val_str != NULL; element++) {
+ if (strcasecmp(element->val_str, str_value) == 0)
+ return element->val_enum;
+ }
+
+ return -1;
+}
+
+#define OPEN_DSL_FAPI_CTX(dev_num) do { \
+ if (dev_num < 0 || dev_num >= max_line_num) \
+ return -1; \
+ fapi_ctx = fapi_dsl_open(0); \
+ if (!fapi_ctx) { \
+ LIBDSL_LOG(LOG_ERR, "fapi_dsl_open() failed\n"); \
+ return -1; \
+ } \
+ } while (0)
+
+static const struct str_enum_map if_status[] = {
+ { "Up", IF_UP },
+ { "Down", IF_DOWN },
+ { "Unknown", IF_UNKNOWN },
+ { "Dormant", IF_DORMANT },
+ { "NotPresent", IF_NOTPRESENT },
+ { "LowerLayerDown", IF_LLDOWN },
+ { "Error", IF_ERROR },
+ { NULL, -1 }
+};
+
+static enum dsl_if_status ifstatus_str2enum(const char *status_str)
+{
+ int status = dsl_get_enum_value(if_status, status_str);
+
+ if (status >= 0)
+ return (enum dsl_if_status)status;
+
+ return IF_ERROR;
+}
+
+static const struct str_enum_map link_status[] = {
+ { "Up", LINK_UP },
+ { "Initializing", LINK_INITIALIZING },
+ { "EstablishingLink", LINK_ESTABLISHING },
+ { "NoSignal", LINK_NOSIGNAL },
+ { "Disabled", LINK_DISABLED },
+ { "Error", LINK_ERROR },
+ { NULL, -1 }
+};
+
+static enum dsl_link_status linkstatus_str2enum(const char *status_str)
+{
+ int status = dsl_get_enum_value(link_status, status_str);
+
+ if (status >= 0)
+ return (enum dsl_link_status)status;
+
+ return LINK_ERROR;
+}
+
+static const struct str_enum_map profiles[] = {
+ { "8a", VDSL2_8a },
+ { "8b", VDSL2_8b },
+ { "8c", VDSL2_8c },
+ { "8d", VDSL2_8d },
+ { "12a", VDSL2_12a },
+ { "12b", VDSL2_12b },
+ { "17a", VDSL2_17a },
+ { "30a", VDSL2_30a },
+ { "35b", VDSL2_35b },
+ { NULL, -1 }
+};
+
+static enum dsl_profile profile_str2enum(const char *prof_str)
+{
+ int profile = dsl_get_enum_value(profiles, prof_str);
+
+ if (profile >= 0)
+ return (enum dsl_profile)profile;
+
+ return (enum dsl_profile)0;
+}
+
+static const struct str_enum_map power_states[] = {
+ { "L0", DSL_L0},
+ { "L1", DSL_L1},
+ { "L2", DSL_L2},
+ { "L3", DSL_L3},
+ { "L4", DSL_L4},
+ { NULL, -1 }
+};
+
+static enum dsl_power_state powerstate_str2enum(const char *power_state)
+{
+ int state = dsl_get_enum_value(power_states, power_state);
+
+ if (state >= 0)
+ return (enum dsl_power_state)state;
+
+ return (enum dsl_power_state)0;
+}
+
+int dsl_get_line_info(int line_num, struct dsl_line *line)
+{
+ int retval = 0;
+ struct fapi_dsl_ctx *fapi_ctx;
+ struct dsl_fapi_line_obj obj;
+ char *token, *saveptr;
+ int num, i;
+
+ // Open the DSL FAPI context
+ OPEN_DSL_FAPI_CTX(line_num);
+
+ // Get the data
+ memset(&obj, 0, sizeof(obj));
+ if (fapi_dsl_line_get(fapi_ctx, &obj) != FAPI_DSL_STATUS_SUCCESS) {
+ LIBDSL_LOG(LOG_ERR, "fapi_dsl_line_get() failed\n");
+ retval = -1;
+ goto __ret;
+ }
+
+ // Initialize the output buffer
+ memset(line, 0, sizeof(*line));
+
+ /**
+ * Convert the values
+ */
+ line->status = ifstatus_str2enum(obj.status);
+ line->upstream = obj.upstream;
+ strncpy(line->firmware_version, obj.firmware_version, sizeof(line->firmware_version) - 1);
+ line->link_status = linkstatus_str2enum(obj.link_status);
+
+ // Supported standards and currently used standard
+ line->standard_supported.use_xtse = true;
+ memcpy(line->standard_supported.xtse, obj.xtse, sizeof(line->standard_supported.xtse));
+ line->standard_used.use_xtse = true;
+ memcpy(line->standard_used.xtse, obj.xtse_used, sizeof(line->standard_used.xtse));
+
+ // Line encoding, it is always DMT for Intel
+ line->line_encoding = LE_DMT;
+
+ // Allowed profiles and the currently used profile
+ token = strtok_r(obj.allowed_profiles, ",", &saveptr);
+ while (token != NULL) {
+ line->allowed_profiles |= profile_str2enum(token);
+ // Move to the next token
+ token = strtok_r(NULL, ",", &saveptr);
+ }
+ line->current_profile = profile_str2enum(obj.current_profile);
+
+ line->power_management_state = powerstate_str2enum(obj.power_management_state);
+ line->success_failure_cause = obj.success_failure_cause;
+
+ // upbokler_pb
+ token = strtok_r(obj.upbokler_pb, ",", &saveptr);
+ for (num = sizeof (line->upbokler_pb.array) / sizeof (line->upbokler_pb.array[0]);
+ line->upbokler_pb.count < num && token != NULL;
+ line->upbokler_pb.count++, token = strtok_r(NULL, ",", &saveptr)) {
+ line->upbokler_pb.array[line->upbokler_pb.count] = atoi(token);
+ }
+
+ // rxthrsh_ds
+ token = strtok_r(obj.rxthrsh_ds, ",", &saveptr);
+ for (num = sizeof (line->rxthrsh_ds.array) / sizeof (line->rxthrsh_ds.array[0]);
+ line->rxthrsh_ds.count < num && token != NULL;
+ line->rxthrsh_ds.count++, token = strtok_r(NULL, ",", &saveptr)) {
+ line->rxthrsh_ds.array[line->rxthrsh_ds.count] = atoi(token);
+ }
+
+ line->act_ra_mode.us = obj.act_ra_mode_us;
+ line->act_ra_mode.ds = obj.act_ra_mode_ds;
+
+ line->snr_mroc_us = obj.snr_mroc_us;
+
+ line->last_state_transmitted.us = obj.last_state_transmitted_upstream;
+ line->last_state_transmitted.ds = obj.last_state_transmitted_downstream;
+
+ line->us0_mask = obj.us0_mask;
+
+ line->trellis.us = obj.trellis_us;
+ line->trellis.ds = obj.trellis_ds;
+
+ line->act_snr_mode.us = obj.act_snr_mode_us;
+ line->act_snr_mode.ds = obj.act_snr_mode_ds;
+
+ line->line_number = obj.line_number;
+
+ /* Note that there is a mistake in DSL FAPI which uses bps instead of kbps */
+ line->max_bit_rate.us = obj.upstream_max_bit_rate / 1000;
+ line->max_bit_rate.ds = obj.downstream_max_bit_rate / 1000;
+
+ line->noise_margin.us = obj.upstream_noise_margin;
+ line->noise_margin.ds = obj.downstream_noise_margin;
+
+ // snr_mpb_us
+ token = strtok_r(obj.snr_mpb_us, ",", &saveptr);
+ for (num = sizeof (line->snr_mpb_us.array) / sizeof (line->snr_mpb_us.array[0]);
+ line->snr_mpb_us.count < num && token != NULL;
+ line->snr_mpb_us.count++, token = strtok_r(NULL, ",", &saveptr)) {
+ line->snr_mpb_us.array[line->snr_mpb_us.count] = atoi(token);
+ }
+
+ // snr_mpb_ds
+ token = strtok_r(obj.snr_mpb_ds, ",", &saveptr);
+ for (num = sizeof (line->snr_mpb_ds.array) / sizeof (line->snr_mpb_ds.array[0]);
+ line->snr_mpb_ds.count < num && token != NULL;
+ line->snr_mpb_ds.count++, token = strtok_r(NULL, ",", &saveptr)) {
+ line->snr_mpb_ds.array[line->snr_mpb_ds.count] = atoi(token);
+ }
+
+ line->attenuation.us = obj.upstream_attenuation;
+ line->attenuation.ds = obj.downstream_attenuation;
+
+ line->power.us = obj.upstream_power;
+ line->power.ds = obj.downstream_power;
+
+ // XTU-R vendor ID
+ num = (sizeof(line->xtur_vendor) / 2) < sizeof(obj.xtur_vendor) ?
+ (sizeof(line->xtur_vendor) / 2) : sizeof(obj.xtur_vendor);
+ for (i = 0; i < num; i++)
+ sprintf(line->xtur_vendor + i * 2, "%02X", obj.xtur_vendor[i]);
+
+ // XTU-R country
+ num = (sizeof(line->xtur_country) / 2) < sizeof(obj.xtur_country) ?
+ (sizeof(line->xtur_country) / 2) : sizeof(obj.xtur_country);
+ for (i = 0; i < num; i++)
+ sprintf(line->xtur_country + i * 2, "%02X", obj.xtur_country[i]);
+
+ line->xtur_ansi_std = obj.xtur_ansi_std;
+ line->xtur_ansi_rev = obj.xtur_ansi_rev;
+
+ // XTU-C vendor ID
+ num = (sizeof(line->xtuc_vendor) / 2) < (sizeof(obj.xtuc_vendor) / sizeof(obj.xtuc_vendor[0]))?
+ (sizeof(line->xtuc_vendor) / 2) : (sizeof(obj.xtuc_vendor) / sizeof(obj.xtuc_vendor[0]));
+ for (i = 0; i < num; i++)
+ sprintf(line->xtuc_vendor + i * 2, "%02X", obj.xtuc_vendor[i]);
+
+ // XTU-C country
+ num = (sizeof(line->xtuc_country) / 2) < sizeof(obj.xtuc_country) ?
+ (sizeof(line->xtuc_country) / 2) : (sizeof(obj.xtuc_country) / sizeof(obj.xtuc_country[0]));
+ for (i = 0; i < num; i++)
+ sprintf(line->xtuc_country + i * 2, "%02X", obj.xtuc_country[i]);
+
+ line->xtuc_ansi_std = obj.xtuc_ansi_std;
+ line->xtuc_ansi_rev = obj.xtuc_ansi_rev;
+
+__ret:
+ if (fapi_ctx)
+ fapi_dsl_close(fapi_ctx);
+ return retval;
+}
+
+int dsl_get_line_stats(int line_num, struct dsl_line_channel_stats *stats)
+{
+ int retval = 0;
+ struct fapi_dsl_ctx *fapi_ctx;
+ struct dsl_fapi_line_stats_obj obj;
+
+ // Open the DSL FAPI context
+ OPEN_DSL_FAPI_CTX(line_num);
+
+ // Get the data
+ memset(&obj, 0, sizeof(obj));
+ if (fapi_dsl_line_stats_get(fapi_ctx, &obj) != FAPI_DSL_STATUS_SUCCESS) {
+ LIBDSL_LOG(LOG_ERR, "fapi_dsl_line_stats_get() failed\n");
+ retval = -1;
+ goto __ret;
+ }
+
+ // Initialize the output buffer
+ memset(stats, 0, sizeof(*stats));
+
+ // Fill in the output parameter
+ stats->total_start = obj.total_start;
+ stats->showtime_start = obj.showtime_start;
+ stats->last_showtime_start = obj.last_showtime_start;
+ stats->current_day_start = obj.current_day_start;
+ stats->quarter_hour_start = obj.quarter_hour_start;
+
+__ret:
+ if (fapi_ctx)
+ fapi_dsl_close(fapi_ctx);
+ return retval;
+}
+
+int dsl_get_line_stats_interval(int line_num, enum dsl_stats_type type, struct dsl_line_stats_interval *stats)
+{
+ int retval = 0;
+ struct fapi_dsl_ctx *fapi_ctx;
+ struct dsl_fapi_line_stats_interval_obj obj;
+ enum fapi_dsl_status status;
+
+ // Open the DSL FAPI context
+ OPEN_DSL_FAPI_CTX(line_num);
+
+ // Get the data
+ memset(&obj, 0, sizeof(obj));
+ switch (type) {
+ case DSL_STATS_TOTAL:
+ status = fapi_dsl_line_stats_total_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_SHOWTIME:
+ status = fapi_dsl_line_stats_showtime_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_LASTSHOWTIME:
+ status = fapi_dsl_line_stats_last_showtime_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_CURRENTDAY:
+ status = fapi_dsl_line_stats_current_day_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_QUARTERHOUR:
+ status = fapi_dsl_line_stats_quarter_hour_get(fapi_ctx, &obj);
+ break;
+ default:
+ LIBDSL_LOG(LOG_ERR, "Unknown interval type for DSL line statistics, %d\n", type);
+ retval = -1;
+ goto __ret;
+ }
+
+ if (status != FAPI_DSL_STATUS_SUCCESS) {
+ LIBDSL_LOG(LOG_ERR,
+ "Failed to call DSL FAPI to retrieve the DSL line statistics interval %d\n", type);
+ retval = -1;
+ goto __ret;
+ }
+
+ // Initialize the output buffer
+ memset(stats, 0, sizeof(*stats));
+
+ // Fill in the output parameter
+ stats->errored_secs = obj.errored_secs;
+ stats->severely_errored_secs = obj.severely_errored_secs;
+
+__ret:
+ if (fapi_ctx)
+ fapi_dsl_close(fapi_ctx);
+ return retval;
+}
+
+static const struct str_enum_map link_encaps[] = {
+ { "G.992.3_Annex_K_ATM", G_992_3_ANNEK_K_ATM },
+ { "G.992.3_Annex_K_PTM", G_992_3_ANNEK_K_PTM },
+ { "G.993.2_Annex_K_ATM", G_993_2_ANNEK_K_ATM },
+ { "G.993.2_Annex_K_PTM", G_993_2_ANNEK_K_PTM},
+ { "G.994.1 (Auto)", G_994_1_AUTO },
+ { NULL, -1 }
+};
+
+static enum dsl_link_encapsulation linkencap_str2enum(const char *link_encap)
+{
+ int encap = dsl_get_enum_value(link_encaps, link_encap);
+
+ if (encap >= 0)
+ return (enum dsl_link_encapsulation)encap;
+
+ return (enum dsl_link_encapsulation)0;
+}
+
+int dsl_get_channel_info(int chan_num, struct dsl_channel *channel)
+{
+ int retval = 0;
+ struct fapi_dsl_ctx *fapi_ctx;
+ struct dsl_fapi_channel_obj obj;
+ char *token, *saveptr;
+
+ // Open the DSL FAPI context
+ OPEN_DSL_FAPI_CTX(chan_num);
+
+ // Get the data
+ memset(&obj, 0, sizeof(obj));
+ if (fapi_dsl_channel_get(fapi_ctx, &obj) != FAPI_DSL_STATUS_SUCCESS) {
+ LIBDSL_LOG(LOG_ERR, "fapi_dsl_channel_get() failed\n");
+ retval = -1;
+ goto __ret;
+ }
+
+ // Initialize the output buffer
+ memset(channel, 0, sizeof(*channel));
+
+ /**
+ * Fill in the output parameter
+ */
+ channel->status = ifstatus_str2enum(obj.status);
+
+ // link_encapsulation_supported and link_encapsulation_used
+ token = strtok_r(obj.link_encapsulation_supported, ",", &saveptr);
+ while (token != NULL) {
+ channel->link_encapsulation_supported |= linkencap_str2enum(token);;
+ // Move to the next token
+ token = strtok_r(NULL, ",", &saveptr);
+ }
+ channel->link_encapsulation_used = linkencap_str2enum(obj.link_encapsulation_used);
+
+ channel->lpath = obj.lpath;
+ channel->intlvdepth = obj.intlvdepth;
+ channel->intlvblock = obj.intlvblock;
+ channel->actual_interleaving_delay = obj.actual_interleaving_delay;
+ channel->actinp = obj.actinp;
+ channel->inpreport = obj.inpreport;
+ channel->nfec = obj.nfec;
+ channel->rfec = obj.rfec;
+ channel->lsymb = obj.lsymb;
+
+ /* Note that there is a mistake in DSL FAPI which uses bps instead of kbps */
+ channel->curr_rate.us = obj.upstream_curr_rate / 1000;
+ channel->curr_rate.ds = obj.downstream_curr_rate / 1000;
+ channel->actndr.us = obj.actndr_us / 1000;
+ channel->actndr.ds = obj.actndr_ds / 1000;
+
+ channel->actinprein.us = obj.actinprein_us;
+ channel->actinprein.ds = obj.actinprein_ds;
+
+__ret:
+ if (fapi_ctx)
+ fapi_dsl_close(fapi_ctx);
+ return retval;
+}
+
+int dsl_get_channel_stats(int chan_num, struct dsl_line_channel_stats *stats)
+{
+ int retval = 0;
+ struct fapi_dsl_ctx *fapi_ctx;
+ struct dsl_fapi_channel_stats_obj obj;
+
+ // Open the DSL FAPI context
+ OPEN_DSL_FAPI_CTX(chan_num);
+
+ // Get the data
+ memset(&obj, 0, sizeof(obj));
+ if (fapi_dsl_channel_stats_get(fapi_ctx, &obj) != FAPI_DSL_STATUS_SUCCESS) {
+ LIBDSL_LOG(LOG_ERR, "fapi_dsl_channel_stats_get() failed\n");
+ retval = -1;
+ goto __ret;
+ }
+
+ // Initialize the output buffer
+ memset(stats, 0, sizeof(*stats));
+
+ // Fill in the output parameter
+ stats->total_start = obj.total_start;
+ stats->showtime_start = obj.showtime_start;
+ stats->last_showtime_start = obj.last_showtime_start;
+ stats->current_day_start = obj.current_day_start;
+ stats->quarter_hour_start = obj.quarter_hour_start;
+
+__ret:
+ if (fapi_ctx)
+ fapi_dsl_close(fapi_ctx);
+ return retval;
+}
+
+int dsl_get_channel_stats_interval(int chan_num, enum dsl_stats_type type, struct dsl_channel_stats_interval *stats)
+{
+ int retval = 0;
+ struct fapi_dsl_ctx *fapi_ctx;
+ struct dsl_fapi_channel_stats_interval_obj obj;
+ enum fapi_dsl_status status;
+
+ // Open the DSL FAPI context
+ OPEN_DSL_FAPI_CTX(chan_num);
+
+ // Get the data
+ memset(&obj, 0, sizeof(obj));
+ switch (type) {
+ case DSL_STATS_TOTAL:
+ status = fapi_dsl_channel_stats_total_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_SHOWTIME:
+ status = fapi_dsl_channel_stats_showtime_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_LASTSHOWTIME:
+ status = fapi_dsl_channel_stats_last_showtime_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_CURRENTDAY:
+ status = fapi_dsl_channel_stats_current_day_get(fapi_ctx, &obj);
+ break;
+ case DSL_STATS_QUARTERHOUR:
+ status = fapi_dsl_channel_stats_quarter_hour_get(fapi_ctx, &obj);
+ break;
+ default:
+ LIBDSL_LOG(LOG_ERR, "Unknown interval type for DSL channel statistics, %d\n", type);
+ retval = -1;
+ goto __ret;
+ }
+
+ if (status != FAPI_DSL_STATUS_SUCCESS) {
+ LIBDSL_LOG(LOG_ERR,
+ "Failed to call DSL FAPI to retrieve the channel statistics interval %d\n", type);
+ retval = -1;
+ goto __ret;
+ }
+
+ // Initialize the output buffer
+ memset(stats, 0, sizeof(*stats));
+
+ // Fill in the output parameter
+ stats->xtur_fec_errors = obj.xtu_rfec_errors;
+ stats->xtuc_fec_errors = obj.xtu_cfec_errors;
+
+ stats->xtur_hec_errors = obj.xtu_rhec_errors;
+ stats->xtuc_hec_errors = obj.xtu_chec_errors;
+
+ stats->xtur_crc_errors = obj.xtu_rcrc_errors;
+ stats->xtuc_crc_errors = obj.xtu_ccrc_errors;
+
+__ret:
+ if (fapi_ctx)
+ fapi_dsl_close(fapi_ctx);
+ return retval;
+}
diff --git a/libdsl/utils.h b/libdsl/utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..05b5de460b6be49732b89b93e270687c0824c5a3
--- /dev/null
+++ b/libdsl/utils.h
@@ -0,0 +1,36 @@
+/*
+ * utils.h - private header file
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: yalu.zhang@iopsys.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 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
+ */
+#ifndef _UTILS_H
+#define _UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+#define LIBDSL_LOG(log_level, format...) fprintf(stderr, ##format)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _UTILS_H */
diff --git a/libdsl/xdsl.h b/libdsl/xdsl.h
index 7e6fb8f6d0127ef50c7757f1682d79899f3ce141..8fe02cd1dcc6e47a90a8030b8ad1d231d632a626 100644
--- a/libdsl/xdsl.h
+++ b/libdsl/xdsl.h
@@ -1,9 +1,12 @@
/*
- * xdsl.h - XDSL library header file
+ * xdsl.h - library header file
+ * This file provides definition for the libdsl APIs and related
+ * structures.
*
- * Copyright (C) 2018 Inteno Broadband Technology AB. All rights reserved.
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
- * Author: anjan.chanda@inteno.se
+ * Author: anjan.chanda@iopsys.eu
+ * yalu.zhang@iopsys.eu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,271 +25,469 @@
#ifndef _XDSL_H
#define _XDSL_H
-#include <stdint.h>
-#include <stdbool.h>
-
#ifdef __cplusplus
extern "C" {
#endif
-typedef struct dsl_long_data { long us; long ds; } dsl_long_t;
-typedef struct dsl_bool_data { bool us; bool ds; } dsl_bool_t;
+#include <stdint.h>
+#include <stdbool.h>
-enum {
- trellis_off,
- trellis_on,
-};
+/** Common definitions */
+#define XDSL_MAX_LINES 1
-/** enum dsl_modetype - dsl modes */
-enum dsl_modtype {
- MOD_GDMT, /* G.992.1 */
- MOD_T1413, /* T1.413 */
- MOD_GLITE, /* G.992.2 */
- MOD_ADSL2, /* G.992.3 */
- MOD_ADSL2P, /* G.992.5 */
- MOD_READSL2, /* G.992.3 Annex L */
- MOD_VDSL, /* G.993.1 */
- MOD_VDSL2, /* G.993.2 */
- MOD_VDSL2P, /* G.993.2 Annex Q */
- MOD_GFAST, /* G.9700, G.9701 */
- MOD_UNDEFINED
-};
+typedef struct { long us; long ds; } dsl_long_t;
+typedef struct { unsigned long us; unsigned long ds; } dsl_ulong_t;
+typedef struct { bool us; bool ds; } dsl_bool_t;
+typedef struct { long array[24]; int count; } dsl_long_sequence_t;
+typedef struct { unsigned long array[24]; int count; } dsl_ulong_sequence_t;
-#define is_adsl(m) (m >= MOD_GDMT && m < MOD_ADSL2)
-#define is_adsl2(m) (m >= MOD_ADSL2 && m < MOD_VDSL)
-#define is_vdsl2(m) (m > MOD_VDSL && m <= MOD_VDSL2P)
-#define is_gfast(m) (m == MOD_GFAST)
-
-/** enum dsl_linestatus - line status */
-enum dsl_linestatus {
- LINE_UP,
- LINE_INITING,
- LINE_ESTABLISHING,
- LINE_NOSIGNAL,
- LINE_ERROR,
+/** enum dsl_status - operational status of a line or channel */
+enum dsl_if_status {
+ /* Starts with non-zero in order to distinguish from an uninitialized value which is usually 0 */
+ IF_UP = 1,
+ IF_DOWN,
+ IF_UNKNOWN,
+ IF_DORMANT,
+ IF_NOTPRESENT,
+ IF_LLDOWN,
+ IF_ERROR
};
-/** enum dsl_linestate - physical line state */
-enum dsl_linestate {
- LINE_DOWN, /* no sync */
- LINE_HANDSHAKING, /* hello exchange phase */
- LINE_TRAINING, /* establishing sync */
- LINE_SHOWTIME, /* successfully synced */
- LINE_UNKNOWN, /* unknown state */
+/** enum dsl_link_status - link status */
+enum dsl_link_status {
+ /* Starts with non-zero in order to distinguish from an uninitialized value which is usually 0 */
+ LINK_UP = 1,
+ LINK_INITIALIZING,
+ LINK_ESTABLISHING,
+ LINK_NOSIGNAL,
+ LINK_DISABLED,
+ LINK_ERROR
};
-/** enum dsl_vdsl2_profile - vdsl2 profiles */
-enum dsl_vdsl2_profile {
- VDSL2_8a = 1<<0,
- VDSL2_8b = 1<<1,
- VDSL2_8c = 1<<2,
- VDSL2_8d = 1<<3,
- VDSL2_12a = 1<<4,
- VDSL2_12b = 1<<5,
- VDSL2_17a = 1<<6,
- VDSL2_30a = 1<<7,
- VDSL2_35b = 1<<8,
+/** enum dsl_modtype - DSL modes */
+enum dsl_modtype {
+ MOD_G_922_1_ANNEX_A = 1,
+ MOD_G_922_1_ANNEX_B = 1 << 1,
+ MOD_G_922_1_ANNEX_C = 1 << 2,
+ MOD_T1_413 = 1 << 3,
+ MOD_T1_413i2 = 1 << 4,
+ MOD_ETSI_101_388 = 1 << 5,
+ MOD_G_992_2 = 1 << 6,
+ MOD_G_992_3_Annex_A = 1 << 7,
+ MOD_G_992_3_Annex_B = 1 << 8,
+ MOD_G_992_3_Annex_C = 1 << 9,
+ MOD_G_992_3_Annex_I = 1 << 10,
+ MOD_G_992_3_Annex_J = 1 << 11,
+ MOD_G_992_3_Annex_L = 1 << 12,
+ MOD_G_992_3_Annex_M = 1 << 13,
+ MOD_G_992_4 = 1 << 14,
+ MOD_G_992_5_Annex_A = 1 << 15,
+ MOD_G_992_5_Annex_B = 1 << 16,
+ MOD_G_992_5_Annex_C = 1 << 17,
+ MOD_G_992_5_Annex_I = 1 << 18,
+ MOD_G_992_5_Annex_J = 1 << 19,
+ MOD_G_992_5_Annex_M = 1 << 20,
+ MOD_G_993_1 = 1 << 21,
+ MOD_G_993_1_Annex_A = 1 << 22,
+ MOD_G_993_2_Annex_A = 1 << 23,
+ MOD_G_993_2_Annex_B = 1 << 24,
+ MOD_G_993_2_Annex_C = 1 << 25
};
-/** struct dsl_caps - dsl capabiltities */
-struct dsl_caps {
- uint32_t stds; /** bitmap of STD_* */
- uint32_t modes; /** bitmap of MOD_* */
- uint32_t profiles; /** bitmap of PROFILE_ * */
- dsl_long_t rate_kbps_max; /** max bitrate in Kbps */
-};
+/** enum dsl_xtse_bit - XTSE bit definition. Refer to dsl_line.xtse for details */
+enum dsl_xtse_bit {
+ /* Octet 1 - ADSL, i.e. g.dmt */
+ T1_413 = 1,
+ ETSI_101_388 = 2,
+ G_992_1_POTS_NON_OVERLAPPED = 3, /* Annex A */
+ G_992_1_POTS_OVERLAPPED = 4, /* Annex A */
+ G_992_1_ISDN_NON_OVERLAPPED = 5, /* Annex B */
+ G_992_1_ISDN_OVERLAPPED = 6, /* Annex B */
+ G_992_1_TCM_ISDN_NON_OVERLAPPED = 7, /* Annex C */
+ G_992_1_TCM_ISDN_OVERLAPPED = 8, /* Annex C */
-/** enum dsl_stattype - type of collected statistics */
-enum dsl_stattype {
- STAT_CURR_LINK, /** since latest linkup */
- STAT_CURR_15MINS, /** latest 15 mins stats */
- STAT_PREV_15MINS, /** previous 15 mins stats */
- STAT_CURR_24HRS, /** current day's stats */
- STAT_PREV_24HRS, /** previous day's stats */
- STAT_TOTAL, /** total stats since power up */
-};
+ /* Octet 2 - Splitter-less ADSL, i.e. g.lite */
+ G_992_2_POTS_NON_OVERLAPPED = 9, /* Annex A */
+ G_992_2_POTS_OVERLAPPED = 10, /* Annex B */
+ G_992_2_TCM_ISDN_NON_OVERLAPPED = 11, /* Annex C */
+ G_992_2_TCM_ISDN_OVERLAPPED = 12, /* Annex C */
+ /* Bits 13 - 16 are reserved */
-/** struct dsl_counters - dsl statistics counters */
-struct dsl_counters {
- unsigned long tx_bytes;
- unsigned long rx_bytes;
- unsigned long tx_packets;
- unsigned long rx_packets;
+ /* Octet 3 - ADSL2 */
+ /* Bits 17 - 18 are reserved */
+ G_992_3_POTS_NON_OVERLAPPED = 19, /* Annex A */
+ G_992_3_POTS_OVERLAPPED = 20, /* Annex A */
+ G_992_3_ISDN_NON_OVERLAPPED = 21, /* Annex B */
+ G_992_3_ISDN_OVERLAPPED = 22, /* Annex B */
+ G_992_3_TCM_ISDN_NON_OVERLAPPED = 23, /* Annex C */
+ G_992_3_TCM_ISDN_OVERLAPPED = 24, /* Annex C */
- /** packets dropped due to packets */
- unsigned long tx_error_packets;
- unsigned long rx_error_packets;
+ /* Octet 4 - Splitter-less ADSL2 and ADSL2 */
+ G_992_4_POTS_NON_OVERLAPPED = 25, /* Annex A */
+ G_992_4_POTS_OVERLAPPED = 26, /* Annex A */
+ /* Bits 27 - 28 are reserved */
+ G_992_3_ANNEX_I_NON_OVERLAPPED = 29, /* All digital mode */
+ G_992_3_ANNEX_I_OVERLAPPED = 30, /* All digital mode */
+ G_992_3_ANNEX_J_NON_OVERLAPPED = 31, /* All digital mode */
+ G_992_3_ANNEX_J_OVERLAPPED = 32, /* All digital mode */
- /** no-error packets dropped due to other factors */
- unsigned long tx_dropped_packets;
- unsigned long rx_dropped_pcakets;
-};
-/* Traffic type */
-enum dsl_traffictype {
- TC_PTM,
- TC_ATM,
- TC_RAW,
- TC_NOT_CONNECTED,
+ /* Octet 5 - Splitter-less ADSL2 and ADSL2 */
+ G_992_4_ANNEX_I_NON_OVERLAPPED = 33, /* All digital mode */
+ G_992_4_ANNEX_I_OVERLAPPED = 34, /* All digital mode */
+ G_992_3_POTS_MODE_1 = 35, /* Annex L, non-overlapped, wide upstream */
+ G_992_3_POTS_MODE_2 = 36, /* Annex L, non-overlapped, narrow upstream */
+ G_992_3_POTS_MODE_3 = 37, /* Annex L, overlapped, wide upstream */
+ G_992_3_POTS_MODE_4 = 38, /* Annex L, overlapped, narrow upstream */
+ G_992_3_EXT_POTS_NON_OVERLAPPED = 39, /* Annex M */
+ G_992_3_EXT_POTS_OVERLAPPED = 40, /* Annex M */
+
+ /* Octet 6 - ADSL2+ */
+ G_992_5_POTS_NON_OVERLAPPED = 41, /* Annex A */
+ G_992_5_POTS_OVERLAPPED = 42, /* Annex A */
+ G_992_5_ISDN_NON_OVERLAPPED = 43, /* Annex B */
+ G_992_5_ISDN_OVERLAPPED = 44, /* Annex B */
+ G_992_5_TCM_ISDN_NON_OVERLAPPED = 45, /* Annex C */
+ G_992_5_TCM_ISDN_OVERLAPPED = 46, /* Annex C */
+ G_992_5_ANNEX_I_NON_OVERLAPPED = 47, /* All digital mode */
+ G_992_5_ANNEX_I_OVERLAPPED = 48, /* All digital mode */
+
+ /* Octet 7 - ADSL2+ */
+ G_992_5_ANNEX_J_NON_OVERLAPPED = 49, /* All digital mode */
+ G_992_5_ANNEX_J_OVERLAPPED = 50, /* All digital mode */
+ G_992_5_EXT_POTS_NON_OVERLAPPED = 51, /* Annex M */
+ G_992_5_EXT_POTS_OVERLAPPED = 52, /* Annex M */
+ /* Bits 53 - 56 are reserved */
+
+ /* Octet 8 - VDSL2 */
+ G_993_2_NORTH_AMERICA = 57, /* Annex A */
+ G_993_2_EUROPE = 58, /* Annex B */
+ G_993_2_JAPAN = 59, /* Annex C */
+ /* Bits 60 - 64 are reserved */
};
-/**enum dsl_powerstate - power states */
-enum dsl_powerstate {
- L0,
- L1,
- L2,
- L3,
+/**
+ * This macro determines whether a XTSE bit is set
+ *
+ * @param[in] xtse unsigned char[8] as defined in dsl_line.xtse
+ * @param[in] bit Bit number as defined in G.997.1 clause 7.3.1.1.1 XTU transmission system enabling (XTSE)
+ *
+ * @return A non-zero value is the bit is set. Otherwise 0
+ */
+#define XTSE_BIT_GET(xtse, bit) (xtse[((bit) - 1) / 8] & (1 << (((bit) - 1) % 8)))
+
+/** struct dsl_standard - DSL standards */
+struct dsl_standard {
+ bool use_xtse; /* true if xtse is used. false if mode is used */
+ union {
+ /** Bit maps defined in dsl_modtype */
+ unsigned long mode;
+ /** Transmission system types to be allowed by the xTU on this line instance */
+ unsigned char xtse[8];
+ };
};
-/** struct dsl_line_params - dsl line parameters */
-struct dsl_line_params {
- dsl_long_t msgc; /** # of bytes in OH channel message */
- dsl_long_t k; /** # of bytes in DMT frame */
- dsl_long_t b; /** # of bytes in Mux data frame */
- dsl_long_t t; /** # of Mux data frames in OH subframe */
- dsl_long_t r; /** # of check bytes in FEC data frames (RFEC) */
- dsl_long_t s; /** ratio of FEC over PMD data frame */
- dsl_long_t l; /** # of bits in PMD data frame (LSYMB) */
- dsl_long_t d; /** interleave depth (INTLVDEPTH)*/
- dsl_long_t m; /** # of Mux frames per FEC data frame */
- dsl_long_t i;
- dsl_long_t n; /** length of code word (NFEC) */
- dsl_long_t q; /** # of RS code words per DTU */
- dsl_long_t v; /** # of padding octets per DTU */
- dsl_long_t delay; /** delay in msecs due to interleaving */
- dsl_long_t inp; /** actual Impulse Noise Protection (DMT symbol) */
- dsl_long_t inprein; /** actual INP against REIN noise (ACTINPREIN) */
+/** enum dsl_line_encoding - Line encoding */
+enum dsl_line_encoding {
+ /* Starts with non-zero in order to distinguish from an uninitialized value which is usually 0 */
+ LE_DMT = 1,
+ LE_CAP,
+ LE_2B1Q,
+ LE_43BT,
+ LE_PAM,
+ LE_QAM
};
-/** struct dsl_line_errors - dsl line errors */
-struct dsl_line_errors {
- dsl_long_t sferr;
- dsl_long_t rs_corr;
- dsl_long_t rs_uncorr;
- dsl_long_t hec;
- dsl_long_t ocd;
- dsl_long_t lcd;
- dsl_long_t fec;
- dsl_long_t crc;
- dsl_long_t ohf;
- dsl_long_t lof;
- dsl_long_t lol;
- dsl_long_t lom;
- dsl_long_t los;
- dsl_long_t lop;
+/** enum dsl_profile - DSL profiles */
+enum dsl_profile {
+ VDSL2_8a = 1,
+ VDSL2_8b = 1 << 1,
+ VDSL2_8c = 1 << 2,
+ VDSL2_8d = 1 << 3,
+ VDSL2_12a = 1 << 4,
+ VDSL2_12b = 1 << 5,
+ VDSL2_17a = 1 << 6,
+ VDSL2_30a = 1 << 7,
+ VDSL2_35b = 1 << 8,
};
-/** struct dsl_perfcounters - dsl performance counters */
-struct dsl_perfcounters {
- enum dsl_stattype type; /** stats type */
- unsigned long secs; /** stats collected duration (in seconds) */
- dsl_long_t es; /** errored seconds */
- dsl_long_t ses; /** severly errored seconds */
- dsl_long_t uas; /** unavailable seconds */
- dsl_long_t as; /** available seconds */
+/** enum dsl_power_state - power states */
+enum dsl_power_state {
+ /* Starts with non-zero in order to distinguish from an uninitialized value which is usually 0 */
+ DSL_L0 = 1,
+ DSL_L1,
+ DSL_L2,
+ DSL_L3,
+ DSL_L4
};
-/** struct dsl_line_counters - stats counters */
-struct dsl_line_counters {
- dsl_long_t sf; /** super frames */
- dsl_long_t sferr; /** super frame errors TODO: move */
- dsl_long_t rs; /** total RS codewords tx/rx */
- dsl_long_t rscorr; /** RS correctable errors TODO: move */
- dsl_long_t rsuncorr; /** RS uncorrectable errors TODO: move */
+/** struct dsl_line - DSL line parameters */
+struct dsl_line {
+ /** The current operational state of the DSL line */
+ enum dsl_if_status status;
+ /** Whether the interface points towards the Internet (true) or towards End Devices (false) */
+ bool upstream;
+ /** The version of the modem firmware currently installed for this interface */
+ char firmware_version[64];
+ /** Status of the DSL physical link */
+ enum dsl_link_status link_status;
+ /** The transmission system types or standards supported */
+ struct dsl_standard standard_supported;
+ /** The currently used transmission system type, or the standard on this line instance */
+ struct dsl_standard standard_used;
+ /** The line encoding method used in establishing the Layer 1 DSL connection between the CPE and the DSLAM */
+ enum dsl_line_encoding line_encoding;
+ /** VDSL2 profiles are allowed on the line. The bitmap is defined in enum dsl_profile */
+ unsigned long allowed_profiles;
+ /** VDSL2 profile is currently in use on the line */
+ enum dsl_profile current_profile;
+ /** The power management state of the line */
+ enum dsl_power_state power_management_state;
+ /** The success failure cause of the initialization */
+ unsigned int success_failure_cause;
+ /** VTU-R estimated upstream power back-off electrical length per band */
+ dsl_ulong_sequence_t upbokler_pb;
+ /** Downstream receiver signal level threshold */
+ dsl_ulong_sequence_t rxthrsh_ds;
+ /** The actual active rate adaptation mode in both directions */
+ dsl_ulong_t act_ra_mode;
+ /** The actual signal-to-noise margin of the robust overhead channel (ROC) */
+ unsigned int snr_mroc_us;
+ /** The last successful transmitted initialization state in both directions */
+ dsl_ulong_t last_state_transmitted;
+ /** The allowed VDSL2 US0 PSD masks for Annex A operation */
+ unsigned int us0_mask;
+ /** Whether trellis coding is enabled in the downstream and upstream directions */
+ dsl_long_t trellis;
+ /** Whether the OPTIONAL virtual noise mechanism is in use in both directions */
+ dsl_ulong_t act_snr_mode;
+ /** The line pair that the modem is using to connection */
+ int line_number;
+ /** The current maximum attainable data rate in both directions (expressed in Kbps) */
+ dsl_ulong_t max_bit_rate;
+ /** The current signal-to-noise ratio margin (expressed in 0.1dB) in both directions */
+ dsl_long_t noise_margin;
+ /** The current signal-to-noise ratio margin of each upstream band */
+ dsl_long_sequence_t snr_mpb_us;
+ /** The current signal-to-noise ratio margin of each downstream band */
+ dsl_long_sequence_t snr_mpb_ds;
+ /** The current upstream and downstream signal loss (expressed in 0.1dB). */
+ dsl_long_t attenuation;
+ /** The current output and received power at the CPE's DSL line (expressed in 0.1dBmV) */
+ dsl_long_t power;
+ /** xTU-R vendor identifier as defined in G.994.1 and T1.413 in hex binary format */
+ char xtur_vendor[16 + 1]; // Adding '\0' in the end for convenient manipulation
+ /** T.35 country code of the xTU-R vendor as defined in G.994.1 in hex binary format */
+ char xtur_country[4 + 1]; // Adding '\0' in the end for convenient manipulation
+ /** xTU-R T1.413 Revision Number as defined in T1.413 Issue 2 */
+ unsigned int xtur_ansi_std;
+ /** xTU-R Vendor Revision Number as defined in T1.413 Issue 2 */
+ unsigned int xtur_ansi_rev;
+ /** xTU-C vendor identifier as defined in G.994.1 and T1.413 in hex binary format */
+ char xtuc_vendor[16 + 1]; // Adding '\0' in the end for convenient manipulation
+ /** T.35 country code of the xTU-C vendor as defined in G.994.1 in hex binary format */
+ char xtuc_country[4 + 1]; // Adding '\0' in the end for convenient manipulation
+ /** xTU-C T1.413 Revision Number as defined in T1.413 Issue 2 */
+ unsigned int xtuc_ansi_std;
+ /** xTU-C Vendor Revision Number as defined in T1.413 Issue 2 */
+ unsigned int xtuc_ansi_rev;
};
-/** struct dsl_line_rtxcounters - retransmit counters */
-struct dsl_line_rtxcounters {
- dsl_long_t tx; /** # of retransmitted DTUs */
- dsl_long_t corr; /** # of corrected retransmissions */
- dsl_long_t uncorr; /** # of DTU errors which couldnot be corrected */
+/** struct dsl_line_channel_stats - Statistics counters for DSL line and channel */
+struct dsl_line_channel_stats {
+ /** The number of seconds since the beginning of the period used for collection of Total statistics */
+ unsigned int total_start;
+ /** The number of seconds since the most recent DSL Showtime */
+ unsigned int showtime_start;
+ /** The number of seconds since the second most recent DSL Showtime-the beginning of the period used for
+ * collection of LastShowtime statistics */
+ unsigned int last_showtime_start;
+ /** The number of seconds since the beginning of the period used for collection of CurrentDay statistics */
+ unsigned int current_day_start;
+ /** The number of seconds since the beginning of the period used for collection of QuarterHour statistics */
+ unsigned int quarter_hour_start;
};
-/** struct dsl_link - xdsl link information */
-struct dsl_link {
- char name[64]; /** real name */
- char alias[64]; /** name alias */
- char fw_version[64]; /** firmware version */
- enum dsl_linestate linestate;
- enum dsl_powerstate pwr_state; /** L0..L3 */
- enum dsl_traffictype tc_type; /** Traffic type */
- enum dsl_modtype mode; /** dsl mode adsl, vdsl2, etc. */
- int annex_info; /* TODO: xdsl_mode-> annex_info */
- unsigned int vdsl2_profile; /** 8a,.. 30a, 35b */
- dsl_long_t rate_kbps_max; /** max attainable rate in Kbps */
- dsl_bool_t trellis_enabled; /** whether trellis coding used */
- dsl_long_t snr_margin; /** snr margin in 0.1 dB */
- dsl_long_t attn; /** attenuation in 0.1 dB */
- dsl_long_t power; /** power in 0.1 dBmV */
- long status;
- unsigned int training_status;
- unsigned long uptime; /** seconds since link up */
- struct dsl_perfcounters perf_cnts; /** perforamce stats */
+/** struct dsl_line_stats_interval - This is a common structure for all interval statistics */
+struct dsl_line_stats_interval {
+ /** Number of errored seconds */
+ unsigned int errored_secs;
+ /** Number of severely errored seconds */
+ unsigned int severely_errored_secs;
};
-/** struct dsl_line - dsl line information structure */
-struct dsl_line {
- dsl_long_t rate_kbps; /** rate in Kbps */
- struct dsl_line_counters cnts; /** line stats */
- struct dsl_line_rtxcounters rtx_cnts; /** line retransmit counters */
- struct dsl_line_params param; /** line parameters */
- struct dsl_line_errors err; /** line errors */
+/**
+ * enum dsl_stats_type - Type of DSL interval statistics
+ */
+enum dsl_stats_type {
+ /* Starts with non-zero in order to distinguish from an uninitialized value which is usually 0 */
+ DSL_STATS_TOTAL = 1,
+ DSL_STATS_SHOWTIME,
+ DSL_STATS_LASTSHOWTIME,
+ DSL_STATS_CURRENTDAY,
+ DSL_STATS_QUARTERHOUR
};
-#define XDSL_MAX_LINES 2
+/** enum dsl_link_encapsulation - Type of link encapsulation method defineds as bit maps */
+enum dsl_link_encapsulation {
+ G_992_3_ANNEK_K_ATM = 1,
+ G_992_3_ANNEK_K_PTM = 1 << 1,
+ G_993_2_ANNEK_K_ATM = 1 << 2,
+ G_993_2_ANNEK_K_PTM = 1 << 3,
+ G_994_1_AUTO = 1 << 4
+};
-/** struct dsl_info - dsl information structure */
-struct dsl_info {
- struct dsl_link link; /** dsl link informantion */
- uint32_t num_lines; /** # of phy lines */
- struct dsl_line line[XDSL_MAX_LINES]; /** dsl lines */
+/** struct dsl_channel - DSL channel parameters */
+struct dsl_channel {
+ /** The current operational state of the DSL channel */
+ enum dsl_if_status status;
+ /** Which link encapsulation standards and recommendations are supported by the channel */
+ unsigned long link_encapsulation_supported;
+ /** The link encapsulation standard that the channel instance is using for the connection. */
+ enum dsl_link_encapsulation link_encapsulation_used;
+ /** The index of the latency path supporting the bearer channel */
+ unsigned int lpath;
+ /** The interleaver depth D for the latency path indicated in lpath */
+ unsigned int intlvdepth;
+ /** The interleaver block length in use on the latency path indicated in lpath */
+ int intlvblock;
+ /** The actual delay, in milliseconds, of the latency path due to interleaving */
+ unsigned int actual_interleaving_delay;
+ /** The actual impulse noise protection (INP) provided by the latency path indicated in lpath */
+ int actinp;
+ /** Whether the value reported in actinp was computed assuming the receiver does not use erasure decoding */
+ bool inpreport;
+ /** Reports the size, in octets, of the Reed-Solomon codeword in use on the latency path indicated in lpath */
+ int nfec;
+ /** The number of redundancy bytes per Reed-Solomon codeword on the latency path indicated in lpath */
+ int rfec;
+ /** The number of bits per symbol assigned to the latency path indicated in lpath */
+ int lsymb;
+ /** The current physical layer aggregate data rate (expressed in Kbps) in both directions. */
+ dsl_ulong_t curr_rate;
+ /** Actual net data rate expressed in Kbps in both directions */
+ dsl_ulong_t actndr;
+ /** Actual impulse noise protection in both directions against REIN, expressed in 0.1 DMT symbols */
+ dsl_ulong_t actinprein;
};
-struct dsl_config {
- unsigned int mode; /** bitmap of modes */
- unsigned int vdsl2_profile;
- int us0;
- int trellis;
- int bitswap;
- int sra;
+/** This value shall be used if any of elements defined in "struct dsl_channel_stats_interval" is unavailable */
+#define DSL_INVALID_STATS_COUNTER 4294967295
+/**
+ * struct dsl_channel_stats_interval - This is a common structure for all interval statistics
+ */
+struct dsl_channel_stats_interval {
+ /** Number of FEC errors */
+ unsigned int xtur_fec_errors;
+ /** Number of FEC errors detected by the ATU-C */
+ unsigned int xtuc_fec_errors;
+ /** Number of HEC errors */
+ unsigned int xtur_hec_errors;
+ /** Number of HEC errors detected by the ATU-C */
+ unsigned int xtuc_hec_errors;
+ /** Number of CRC errors */
+ unsigned int xtur_crc_errors;
+ /** Number of CRC errors detected by the ATU-C */
+ unsigned int xtuc_crc_errors;
};
+/**
+ * This function gets the number of DSL lines
+ *
+ * @return the number of DSL lines on success. Otherwise a negative value is returned.
+ *
+ * Note that this API must be implemented on all platforms on which libdsl is enabled.
+ */
+int dsl_get_line_number(void);
+
+/**
+ * This function gets the number of DSL channels
+ *
+ * @return the number of DSL channels on success. Otherwise a negative value is returned.
+ *
+ * Note that this API must be implemented on all platforms on which libdsl is enabled.
+ */
+int dsl_get_channel_number(void);
+
+/**
+ * This function gets the DSL line information
+ *
+ * @param[in] line_num - The line number which starts with 0
+ * @param[out] line - The output parameter to receive the data
+ *
+ * @return 0 on success. Otherwise a negative value is returned
+ */
+int dsl_get_line_info(int line_num, struct dsl_line *line);
+
+/**
+ * This function gets the statistics counters of a DSL line
+ *
+ * @param[in] line_num - The line number which starts with 0
+ * @param[out] stats The output parameter to receive the data
+ *
+ * @return 0 on success. Otherwise a negative value is returned
+ */
+int dsl_get_line_stats(int line_num, struct dsl_line_channel_stats *stats);
+
+/**
+ * This function gets the interval statistics counters of a DSL line
+ *
+ * @param[in] line_num - The line number which starts with 0
+ * @param[in] type The type of interval statistics
+ * @param[out] stats The output parameter to receive the data
+ *
+ * @return 0 on success. Otherwise a negative value is returned
+ */
+int dsl_get_line_stats_interval(int line_num, enum dsl_stats_type type, struct dsl_line_stats_interval *stats);
+
+/**
+ * This function gets the DSL channel information
+ *
+ * @param[in] chan_num - The channel number which starts with 0
+ * @param[out] channel The output parameter to receive the data
+ *
+ * @return 0 on success. Otherwise a negative value is returned
+ */
+int dsl_get_channel_info(int chan_num, struct dsl_channel *channel);
+
+/**
+ * This function gets the statistics counters of a DSL channel
+ *
+ * @param[in] chan_num - The channel number which starts with 0
+ * @param[out] stats The output parameter to receive the data
+ *
+ * @return 0 on success. Otherwise a negative value is returned
+ */
+int dsl_get_channel_stats(int chan_num, struct dsl_line_channel_stats *stats);
+
+/**
+ * This function gets the interval statistics counters of a DSL channel
+ *
+ * @param[in] chan_num - The channel number which starts with 0
+ * @param[in] type The type of interval statistics
+ * @param[out] stats The output parameter to receive the data
+ *
+ * @return 0 on success. Otherwise a negative value is returned
+ */
+int dsl_get_channel_stats_interval(int chan_num, enum dsl_stats_type type, struct dsl_channel_stats_interval *stats);
+
+/**
+ * struct dsl_ops - This structure defines the DSL operations.
+ * A function pointer shall be NULL if the operation
+ */
struct dsl_ops {
- /** name to match dsl backend */
- const char *name;
-
- int (*start)(char *name, struct dsl_config *cfg);
- int (*stop)(char *name);
- int (*set_alias)(char *name, char *alias);
- int (*get_mode)(char *name, enum dsl_modtype *m);
- int (*get_supported_standards)(char *name, uint32_t *std);
- int (*get_active_standards)(char *name, uint32_t *std);
- int (*get_line_status)(char *name, enum dsl_linestatus *s);
- int (*get_supported_profiles)(char *name, uint32_t *p);
- int (*get_active_profiles)(char *name, uint32_t *p);
- int (*get_max_bitrate)(char *name, dsl_long_t *max_rate_kbps);
- int (*get_bitrate)(char *name, dsl_long_t *rate_kbps);
- int (*get_stats)(char *name, enum dsl_stattype type,
- struct dsl_perfcounters *c);
- int (*get_status)(char *name, struct dsl_info *info);
+ int (*get_line_info)(int line_num, struct dsl_line *line);
+ int (*get_line_stats)(int line_num, struct dsl_line_channel_stats *stats);
+ int (*get_line_stats_interval)(int line_num, enum dsl_stats_type type,
+ struct dsl_line_stats_interval *stats);
+ int (*get_channel_info)(int chan_num, struct dsl_channel *channel);
+ int (*get_channel_stats)(int chan_num, struct dsl_line_channel_stats *stats);
+ int (*get_channel_stats_interval)(int chan_num, enum dsl_stats_type type,
+ struct dsl_channel_stats_interval *stats);
};
-
-/* API list */
-int dsl_start(char *name, struct dsl_config *cfg);
-int dsl_stop(char *name);
-int dsl_set_alias(char *name, char *alias);
-int dsl_get_mode(char *name, enum dsl_modtype *m);
-int dsl_get_supported_standards(char *name, uint32_t *std);
-int dsl_get_active_standards(char *name, uint32_t *std);
-int dsl_get_line_status(char *name, enum dsl_linestatus *s);
-int dsl_get_supported_profiles(char *name, uint32_t *p);
-int dsl_get_active_profiles(char *name, uint32_t *p);
-int dsl_get_max_bitrate(char *name, dsl_long_t *max_rate_kbps);
-int dsl_get_bitrate(char *name, dsl_long_t *rate_kbps);
-int dsl_get_stats(char *name, enum dsl_stattype type,
- struct dsl_perfcounters *c);
-int dsl_get_status(char *name, struct dsl_info *info);
+/** This global variable must be defined for each platform specific implementation */
+extern const struct dsl_ops xdsl_ops;
#ifdef __cplusplus
}
diff --git a/main.c b/main.c
index 36570fb3822076091a7ada221987443cc5c09d07..6d515343aec8cbd909fef031ea587755cad3da31 100644
--- a/main.c
+++ b/main.c
@@ -1,9 +1,10 @@
/*
* main.c - dslmngr application
*
- * Copyright (C) 2018 Inteno Broadband Technology AB. All rights reserved.
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
- * Author: anjan.chanda@inteno.se
+ * Author: anjan.chanda@iopsys.eu
+ * yalu.zhang@iopsys.eu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,7 +28,6 @@
#define _GNU_SOURCE
#endif
#include <pthread.h>
-
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <libubox/uloop.h>
@@ -37,39 +37,28 @@
#include "dslmngr.h"
-#define DSLMGR_EVENT_THREAD "dslmngr_eventd"
-
-
-static void dslmngr_cmd_main(struct ubus_context *ctx)
-{
- int ret;
-
- ret = ubus_add_object(ctx, &dsl_object);
- if (ret)
- fprintf(stderr, "Failed to add 'xdsl' object: %s\n",
- ubus_strerror(ret));
-
- uloop_run();
-}
-
+#if 0 // Converting netlink to UBUS is done by inbd for now
void *dslmngr_event_main(void *arg)
{
struct ubus_context *ctx = (struct ubus_context *)arg;
pthread_t me = pthread_self();
- pthread_setname_np(me, DSLMGR_EVENT_THREAD);
+ pthread_setname_np(me, "dslmngr_eventd");
dslmngr_nl_msgs_handler(ctx);
return NULL;
}
+#endif
int main(int argc, char **argv)
{
const char *ubus_socket = NULL;
- int ch;
- pthread_t evtid;
- pthread_attr_t attr, *pattr = NULL;
struct ubus_context *ctx = NULL;
+ int ch, ret;
+#if 0
+ pthread_t evtid;
+ pthread_attr_t attr;
+#endif
while ((ch = getopt(argc, argv, "cs:")) != -1) {
switch (ch) {
@@ -80,19 +69,10 @@ int main(int argc, char **argv)
break;
}
}
-
argc -= optind;
argv += optind;
- uloop_init();
- ctx = ubus_connect(ubus_socket);
- if (!ctx) {
- fprintf(stderr, "Failed to connect to ubus\n");
- return -1;
- }
-
- ubus_add_uloop(ctx);
-
+#if 0 // Converting netlink to UBUS is done by inbd for now
if (pthread_attr_init(&attr) == 0) {
struct sched_param sp;
@@ -100,17 +80,31 @@ int main(int argc, char **argv)
pthread_attr_setschedpolicy(&attr, SCHED_RR);
sp.sched_priority = 99;
pthread_attr_setschedparam(&attr, &sp);
- pattr = &attr;
}
- if (pthread_create(&evtid, pattr, &dslmngr_event_main, ctx) != 0)
+ if (pthread_create(&evtid, &attr, &dslmngr_event_main, ctx) != 0)
fprintf(stderr, "pthread_create error!\n");
dslmngr_cmd_main(ctx);
+#endif
+
+ uloop_init();
+ ctx = ubus_connect(ubus_socket);
+ if (!ctx) {
+ DSLMNGR_LOG(LOG_ERR, "Failed to connect to ubus\n");
+ return -1;
+ }
+
+ ubus_add_uloop(ctx);
+
+ if (dsl_add_ubus_objects(ctx) != 0)
+ goto __ret;
uloop_run();
+
+__ret:
ubus_free(ctx);
uloop_done();
- return 0;
+ return ret;
}