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;