diff --git a/Makefile b/Makefile index a25ab0d229fa8dadc635839e4a8073cf9c6c223e..76415d730d0aab8aa0698a35a08fd41aa2e951fb 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ OBJS += dslmngr_nl.o CODECOVERAGE_SRC = dslmngr.c PROG_CFLAGS = $(CFLAGS) -fstrict-aliasing -fPIC -PROG_LDFLAGS = $(LDFLAGS) -ldsl +PROG_LDFLAGS = $(LDFLAGS) -ldsl -leasy PROG_LDFLAGS += -pthread -luci -lubus -lubox -lblobmsg_json -lnl-genl-3 -lnl-3 ifeq ($(TARGET_PLATFORM),INTEL) diff --git a/dslmngr.c b/dslmngr.c index 5a30ae154d03f22fd4c23b518c357a1f06fbed46..02e52b3430ae34ed28e0b7d70b780845d080cd4a 100644 --- a/dslmngr.c +++ b/dslmngr.c @@ -30,6 +30,8 @@ #include <libubox/ustream.h> #include <libubox/utils.h> #include <uci.h> +#include <net/if.h> +#include <easy/easy.h> #include "xdsl.h" #include "xtm.h" @@ -569,6 +571,18 @@ static struct value2text dsl_stats_types[] = { { DSL_STATS_QUARTERHOUR, "quarterhour" } }; +static void dsl_if_stats_to_blob(const struct if_stats *stats, struct blob_buf *bb) +{ + blobmsg_add_u64(bb, "bytes_sent", stats->tx_bytes); + blobmsg_add_u64(bb, "bytes_received", stats->rx_bytes); + blobmsg_add_u64(bb, "packets_sent", stats->tx_packets); + blobmsg_add_u64(bb, "packets_received", stats->rx_packets); + blobmsg_add_u64(bb, "errors_sent", stats->tx_errors); + blobmsg_add_u64(bb, "errors_received", stats->rx_errors); + blobmsg_add_u64(bb, "discard_packets_sent", stats->tx_dropped); + blobmsg_add_u64(bb, "discard_packets_received", stats->rx_dropped); +} + static void dsl_stats_to_blob(const struct dsl_line_channel_stats *stats, struct blob_buf *bb) { blobmsg_add_u64(bb, "total_start", stats->total_start); @@ -594,12 +608,16 @@ static void dsl_stats_channel_interval_to_blob(const struct dsl_channel_stats_in blobmsg_add_u64(bb, "xtuc_crc_errors", stats->xtuc_crc_errors); } +static int uci_get_ifname(char *ifname, size_t len, bool is_fast); + 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; + char ifname[IFNAMSIZ]; + struct if_stats if_stats; struct dsl_line_channel_stats stats; struct dsl_line_stats_interval line_stats_interval; struct dsl_channel_stats_interval channel_stats_interval; @@ -622,6 +640,9 @@ int dsl_stats_all(struct ubus_context *ctx, struct ubus_object *obj, // Line statistics blobmsg_add_u32(&bb, "id", (unsigned int)i + 1); + if (uci_get_ifname(ifname, sizeof(ifname), false) == 0 && + if_getstats(ifname, &if_stats) == 0) + dsl_if_stats_to_blob(&if_stats, &bb); dsl_stats_to_blob(&stats, &bb); // Line interval statistics @@ -730,6 +751,8 @@ int dsl_line_stats(struct ubus_context *ctx, struct ubus_object *obj, static struct blob_buf bb; struct blob_attr *tb[__DSL_STATS_MAX]; enum dsl_stats_type type = DSL_STATS_QUARTERHOUR + 1; + char ifname[IFNAMSIZ]; + struct if_stats if_stats; struct dsl_line_channel_stats stats; struct dsl_line_stats_interval line_stats_interval; int retval = UBUS_STATUS_OK; @@ -772,6 +795,10 @@ int dsl_line_stats(struct ubus_context *ctx, struct ubus_object *obj, } dsl_stats_line_interval_to_blob(&line_stats_interval, &bb); } else { + // Get interface counters + if (uci_get_ifname(ifname, sizeof(ifname), false) == 0 && + if_getstats(ifname, &if_stats) == 0) + dsl_if_stats_to_blob(&if_stats, &bb); // Get line statistics if (xdsl_ops.get_line_stats == NULL || (*xdsl_ops.get_line_stats)(num, &stats) != 0) { retval = UBUS_STATUS_UNKNOWN_ERROR; @@ -846,6 +873,8 @@ int dsl_channel_stats(struct ubus_context *ctx, struct ubus_object *obj, static struct blob_buf bb; struct blob_attr *tb[__DSL_STATS_MAX]; enum dsl_stats_type type = DSL_STATS_QUARTERHOUR + 1; + char ifname[IFNAMSIZ]; + struct if_stats if_stats; struct dsl_line_channel_stats stats; struct dsl_channel_stats_interval channel_stats_interval; int retval = UBUS_STATUS_OK; @@ -888,6 +917,10 @@ int dsl_channel_stats(struct ubus_context *ctx, struct ubus_object *obj, } dsl_stats_channel_interval_to_blob(&channel_stats_interval, &bb); } else { + // Get interface counters + if (uci_get_ifname(ifname, sizeof(ifname), false) == 0 && + if_getstats(ifname, &if_stats) == 0) + dsl_if_stats_to_blob(&if_stats, &bb); // Get channel statistics if (xdsl_ops.get_channel_stats == NULL || (*xdsl_ops.get_channel_stats)(num, &stats) != 0) { retval = UBUS_STATUS_UNKNOWN_ERROR; @@ -1078,6 +1111,8 @@ int fast_stats_all(struct ubus_context *ctx, struct ubus_object *obj, struct fast_line_stats_interval line_stats_interval; int i, j, max_line; void *array_line, *table_line, *table_interval; + char ifname[IFNAMSIZ]; + struct if_stats if_stats; // Initialize the buffer memset(&bb, 0, sizeof(bb)); @@ -1095,6 +1130,9 @@ int fast_stats_all(struct ubus_context *ctx, struct ubus_object *obj, // Line statistics blobmsg_add_u32(&bb, "id", (unsigned int)i + 1); + if (uci_get_ifname(ifname, sizeof(ifname), true) == 0 && + if_getstats(ifname, &if_stats) == 0) + dsl_if_stats_to_blob(&if_stats, &bb); dsl_stats_to_blob(&stats, &bb); // Line interval statistics @@ -1179,6 +1217,8 @@ int fast_line_stats_handler(struct ubus_context *ctx, struct ubus_object *obj, int num = -1; int i, j; void *table; + char ifname[IFNAMSIZ]; + struct if_stats if_stats; // Parse and validation check the interval type if any blobmsg_parse(dsl_stats_policy, __DSL_STATS_MAX, tb, blob_data(msg), blob_len(msg)); @@ -1215,6 +1255,10 @@ int fast_line_stats_handler(struct ubus_context *ctx, struct ubus_object *obj, } fast_line_stats_interval_to_blob(&stats_interval, &bb); } else { + // Get interface counters + if (uci_get_ifname(ifname, sizeof(ifname), false) == 0 && + if_getstats(ifname, &if_stats) == 0) + dsl_if_stats_to_blob(&if_stats, &bb); // Get line statistics if (xdsl_ops.get_fast_line_stats == NULL || (*xdsl_ops.get_fast_line_stats)(num, &stats) != 0) { retval = UBUS_STATUS_UNKNOWN_ERROR; @@ -1908,6 +1952,66 @@ __error_ret: return -1; } +static int uci_get_ifname(char *ifname, size_t len, bool is_fast) +{ + struct uci_context *ctx; + struct uci_package *pkg; + struct uci_element *e; + const char *value; + bool use_ptm = is_fast; + int i = 0; // always check line 0 for now + + /* First, we need to check if we are running ADSL or not */ + if (!is_fast) { + struct dsl_line line; + if (xdsl_ops.get_line_info == NULL || (*xdsl_ops.get_line_info)(i, &line) != 0) { + return -1; + } + if (line.standard_used.use_xtse) { + if (XTSE_BIT_GET(line.standard_used.xtse, G_993_2_EUROPE) || + XTSE_BIT_GET(line.standard_used.xtse, G_993_2_JAPAN) || + XTSE_BIT_GET(line.standard_used.xtse, G_993_2_NORTH_AMERICA)) + use_ptm= true; + } else { + if (line.standard_used.mode & + (MOD_G_993_1 | MOD_G_993_1_Annex_A | + MOD_G_993_2_Annex_A | MOD_G_993_2_Annex_B | + MOD_G_993_2_Annex_C)) + use_ptm= true; + } + } + + ctx = uci_alloc_context(); + if (!ctx) + return -1; + + if (uci_load(ctx, "dsl", &pkg)) { + uci_free_context(ctx); + return -1; + } + + uci_foreach_element(&pkg->sections, e) { + struct uci_section *s = uci_to_section(e); + if (!strcmp(s->type, use_ptm ? "ptm-device" : "atm-device")) { + value = uci_lookup_option_string(ctx, s, "device"); + if (value) { + if (snprintf(ifname, len, "%s", value) >= len) { + // truncated + uci_free_context(ctx); + return -2; + } + // success + uci_free_context(ctx); + return 0; + } + } + } + + // not found + uci_free_context(ctx); + return -1; +} + static int uci_get_oem_params(char *vendor_id, char *sw_version, char *serial_nr) { struct uci_context *ctx;