diff --git a/libethernet/Makefile b/libethernet/Makefile
index 545074d39e0a3e6c7b9d60bd9a8d83f7c730bb02..8bc1818f170d5a7709c173704380faa294af95bb 100644
--- a/libethernet/Makefile
+++ b/libethernet/Makefile
@@ -12,20 +12,27 @@ objs_lib = ethernet.o
 
 ifeq ($(PLATFORM),BROADCOM)
 objs_lib += bcm/bcm.o
-else ifeq ($(PLATFORM),MEDIATEK)
-objs_lib += ethsw.o
-XXFLAGS += -Wl,-whole-archive -lsw -Wl,-no-whole-archive
-else ifeq ($(PLATFORM),ECONET)
+endif
+
+ifeq ($(PLATFORM),TEST)
+CFLAGS += -DIOPSYS_TEST -I/usr/include/libnl3
+LIBETH_CFLAGS += $(DIAG_CFLAGS) -Werror
+objs_lib += test_stub/stub.o
+endif
+
+ifeq ($(PLATFORM),ECONET)
 CFLAGS += -Itest_stub
 LIBETH_CFLAGS += $(DIAG_CFLAGS) -Werror
 objs_lib += econet/econet.o econet/ecnt_prvt.o
 LIBS += -lapi_lib_switchmgr
-else ifeq ($(PLATFORM),IPQ95XX)
+endif
+
+ifeq ($(PLATFORM),IPQ95XX)
 objs_lib += ipq95xx/ipq95xx.o
-else ifeq ($(PLATFORM),TEST)
-CFLAGS += -DIOPSYS_TEST -I/usr/include/libnl3
-LIBETH_CFLAGS += $(DIAG_CFLAGS) -Werror
-objs_lib += test_stub/stub.o
+endif
+
+ifeq ($(PLATFORM),LINUX)
+objs_lib += linux/linux_eth.o
 endif
 
 all: libethernet.so
@@ -38,5 +45,4 @@ libethernet.so: $(objs_lib)
 		-shared -o $@ $^ $(XXFLAGS) $(LIBS)
 
 clean:
-	rm -f bcm/*.o
 	rm -f *.o *.so
diff --git a/libethernet/ethernet.c b/libethernet/ethernet.c
index 8a0b199b3eeee1493a6f53c5e721ddd10e711e58..67aeeb7d5315618598cbfeb87af51af32ff22946 100644
--- a/libethernet/ethernet.c
+++ b/libethernet/ethernet.c
@@ -38,20 +38,6 @@
 
 #include "ethernet.h"
 
-#if defined(IOPSYS_BROADCOM)
-extern const struct eth_ops bcm_eth_ops;
-#elif defined(IOPSYS_TEST)
-extern const struct eth_ops test_eth_ops;
-#elif defined(IOPSYS_ECONET)
-extern const struct eth_ops econet_gen_eth_ops;
-extern const struct eth_ops econet_nas_wan_eth_ops;
-extern const struct eth_ops econet_ae_wan_eth_ops;
-#elif defined(IPQ95XX)
-extern const struct eth_ops ipq95xx_eth_ops;
-#else
-extern const struct eth_ops ethsw_ops;
-#endif
-
 const struct eth_ops *eth_ops[] = {
 #if defined(IOPSYS_BROADCOM)
 	&bcm_eth_ops,
@@ -63,6 +49,8 @@ const struct eth_ops *eth_ops[] = {
 	&econet_ae_wan_eth_ops,
 #elif defined(IPQ95XX)
 	&ipq95xx_eth_ops,
+#elif defined(IOPSYS_LINUX)
+        &linux_eth_ops,
 #else
 	&ethsw_ops,   /* FIXME */
 #endif
diff --git a/libethernet/ethernet.h b/libethernet/ethernet.h
index 540aa0a734f44aa248e10c8deab70aa130eff5e7..96303a5055486151c38aec6877ed126425cf4c37 100644
--- a/libethernet/ethernet.h
+++ b/libethernet/ethernet.h
@@ -35,6 +35,23 @@ extern "C" {
 #define libethernet_info(...)	pr_info("libethernet: " __VA_ARGS__)
 #define libethernet_dbg(...)	pr_debug("libethernet: " __VA_ARGS__)
 
+#if defined(IOPSYS_BROADCOM)
+extern const struct eth_ops bcm_eth_ops;
+#elif defined(IOPSYS_TEST)
+extern const struct eth_ops test_eth_ops;
+#elif defined(IOPSYS_ECONET)
+extern const struct eth_ops econet_gen_eth_ops;
+extern const struct eth_ops econet_nas_wan_eth_ops;
+extern const struct eth_ops econet_ae_wan_eth_ops;
+#elif defined(IPQ95XX)
+extern const struct eth_ops ipq95xx_eth_ops;
+#elif defined(IOPSYS_LINUX)
+extern const struct eth_ops linux_eth_ops;
+#else
+extern const struct eth_ops ethsw_ops;
+#endif
+
+
 /* enum eth_duplex - duplex modes */
 enum eth_duplex {
 	AUTO_DUPLEX,
diff --git a/libethernet/linux/linux_eth.c b/libethernet/linux/linux_eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..918765d1bad94ad45a711de4325eff0fd8c1e1c3
--- /dev/null
+++ b/libethernet/linux/linux_eth.c
@@ -0,0 +1,248 @@
+/*
+ * linux_eth.c - Linux based statistics collection ubus methods.
+ *
+ * Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: padmalochan.mohapatra@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 <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <time.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <linux/ethtool.h>
+#include <netlink/genl/genl.h>
+#include <netlink/cache.h>
+#include <netlink/utils.h>
+#include <netlink/object.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/netlink.h>
+#include <netlink/route/rtnl.h>
+#include <netlink/route/link.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/netlink.h>
+#include <netlink/route/rtnl.h>
+#include <netlink/route/link.h>
+#include <linux/sockios.h>
+#include "easy.h"
+#include "if_utils.h"
+#include "../ethernet.h"
+
+#include "linux_eth.h"
+
+/************************************************************
+ * Open a netlink socket connectivity with NETLINK_ROUTE
+ * to read the stats using designated API.
+ ************************************************************
+ */
+static int if_openlnk(const char *ifname, struct nl_sock **s,
+                struct rtnl_link **l)
+{
+    struct rtnl_link *link;
+    struct nl_sock *sk;
+    int ret = 0;
+
+    sk = nl_socket_alloc();
+    if (sk == NULL) {
+        ret = -errno;
+        return ret;
+    }
+
+    if (nl_connect(sk, NETLINK_ROUTE) < 0) {
+	syslog(LOG_ERR, "%s(%d) nl socket connection failed.",
+			__FUNCTION__, __LINE__);
+	ret = -1;
+	goto out;
+    }
+
+    if (rtnl_link_get_kernel(sk, 0, ifname, &link) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    *l = link;
+    *s = sk;
+    return 0;
+
+out:
+    nl_socket_free(sk);
+    return ret;
+}
+
+/************************************************************
+ * Close the socket and free the allocated nl objects.
+ ************************************************************
+ */
+
+static int if_closelnk(struct nl_sock *s, struct rtnl_link *l)
+{
+    rtnl_link_put(l);
+    nl_socket_free(s);
+
+    return 0;
+}
+
+static int get_ifstats(const char *ifname, struct eth_stats *s)
+{
+    struct rtnl_link *link;
+    struct nl_sock *sk;
+    int ret = 0;
+
+    if (!s)
+        return -1;
+
+    ret = if_openlnk(ifname, &sk, &link);
+    if (ret)
+        return -1;
+
+    s->tx_bytes = rtnl_link_get_stat(link, RTNL_LINK_TX_BYTES);
+    s->tx_packets = rtnl_link_get_stat(link, RTNL_LINK_TX_PACKETS);
+    s->tx_errors = rtnl_link_get_stat(link, RTNL_LINK_TX_ERRORS);
+/* Some counters set to zero, and will be populated cross referring
+ * the rmon stats structure.
+ */
+    s->tx_ucast_packets = 0;
+    s->tx_mcast_packets = 0;
+    s->tx_bcast_packets = 0;
+    s->tx_discard_packets = 0;
+    s->rx_bytes = rtnl_link_get_stat(link, RTNL_LINK_RX_BYTES);
+    s->rx_packets = 0;
+    s->rx_errors = rtnl_link_get_stat(link, RTNL_LINK_RX_ERRORS);
+    s->rx_ucast_packets = 0;
+    s->rx_mcast_packets = rtnl_link_get_stat(link, RTNL_LINK_MULTICAST);
+    s->rx_bcast_packets = 0;
+    s->rx_discard_packets = 0;
+    s->rx_unknown_packets = 0;
+
+    if_closelnk(sk, link);
+
+    return 0;
+}
+
+int get_ethtool_stats(const char *ifname)
+{
+    int ret = 0;
+
+    stat.cmd = ETHTOOL_GSTATS;
+    if (0 != eth_ioctl(ifname, SIOCETHTOOL, &stat, sizeof(struct ethnic_stats)))
+        ret = -1;
+
+    if (ret)
+	syslog(LOG_ERR, "%s(%d) nic_stats collection failed.", __FUNCTION__, __LINE__);
+
+    return ret;
+}
+
+int get_stats(const char *ifname)
+{
+    memset(&ifstats, 0, sizeof(struct eth_stats));
+    memset(&stat, 0, sizeof(struct ethnic_stats));
+
+    syslog(LOG_INFO, "%s(%d): ifname is %s", __FUNCTION__, __LINE__, ifname);
+
+    if (get_ifstats(ifname, &ifstats) < 0)
+        return -1;
+    if (get_ethtool_stats(ifname) < 0)
+	return -1;
+
+    return 0;
+}
+
+
+int linux_eth_get_stats(const char *ifname, struct eth_stats *s)
+{
+    if (!s)
+	return -1;
+
+    if (get_stats(ifname) < 0)
+	return -1;
+
+    s->tx_bytes = ifstats.tx_bytes;
+    s->tx_packets = ifstats.tx_packets;
+    s->tx_errors = ifstats.tx_errors;
+    s->tx_ucast_packets = stat.data[TxUnicast];
+    s->tx_mcast_packets = ifstats.tx_mcast_packets;
+    s->tx_bcast_packets = stat.data[TxBroadcast];
+    s->tx_discard_packets = stat.data[TxDrop];
+    s->rx_bytes = ifstats.rx_bytes;
+    s->rx_packets = stat.data[rx_packets];
+    s->rx_errors = ifstats.rx_errors;
+    s->rx_ucast_packets = stat.data[RxUnicast];
+    s->rx_mcast_packets = stat.data[RxMulticast];
+    s->rx_bcast_packets = stat.data[RxBroadcast];
+    s->rx_discard_packets = stat.data[RxDrop];
+/*FIXME: Doesn't exist a way to get the counter rx_unknown_packets.*/
+    s->rx_unknown_packets = 0;
+
+    return 0;
+}
+
+int linux_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
+{
+    int ret = 0;
+
+    if (get_stats(ifname) < 0)
+	ret = -1;
+    rmon->tx.packets = stat.data[tx_packets];
+    rmon->tx.bytes = stat.data[tx_bytes];
+    rmon->tx.crc_err_packets = stat.data[TxCrcErr];
+/* These two counters are marked zero because they dont 
+ * hold much relevancy to Customer 
+ */
+    rmon->tx.under_sz_packets = 0;
+    rmon->tx.over_sz_packets = 0;
+    rmon->tx.packets_64bytes = stat.data[TxPktSz64];
+    rmon->tx.packets_65to127bytes = stat.data[TxPktSz65To127];
+    rmon->tx.packets_128to255bytes = stat.data[TxPktSz128To255];
+    rmon->tx.packets_256to511bytes = stat.data[TxPktSz256To511];
+    rmon->tx.packets_512to1023bytes = stat.data[TxPktSz512To1023];
+    rmon->tx.packets_1024to1518bytes = stat.data[Tx1024ToMax];
+
+    rmon->rx.bytes = stat.data[RxBytes];
+    rmon->rx.packets = stat.data[rx_packets];
+    rmon->rx.bcast_packets = stat.data[RxBroadcast];
+    rmon->rx.mcast_packets = stat.data[RxMulticast];
+    rmon->rx.crc_err_packets = stat.data[RxCrcErr];
+    rmon->rx.under_sz_packets = stat.data[RxUnderSizeErr];
+    rmon->rx.over_sz_packets = stat.data[RxOverSzErr];
+    rmon->rx.packets_64bytes = stat.data[RxPktSz64];
+    rmon->rx.packets_65to127bytes = stat.data[RxPktSz65To127];
+    rmon->rx.packets_128to255bytes = stat.data[RxPktSz128To255];
+    rmon->rx.packets_256to511bytes = stat.data[RxPktSz256To511];
+    rmon->rx.packets_512to1023bytes = stat.data[RxPktSz512To1023];
+    rmon->rx.packets_1024to1518bytes = stat.data[RxPktSz1024ToMax];
+
+    return ret;
+}
+
+const struct eth_ops linux_eth_ops = {
+        .ifname = "lan",
+        .get_stats = linux_eth_get_stats,
+        .get_rmon_stats = linux_eth_get_rmon_stats,
+};
diff --git a/libethernet/linux/linux_eth.h b/libethernet/linux/linux_eth.h
new file mode 100644
index 0000000000000000000000000000000000000000..e625e3d193f439e31f0a7544963b1a38fd86f9e6
--- /dev/null
+++ b/libethernet/linux/linux_eth.h
@@ -0,0 +1,72 @@
+#ifndef LINUX
+#define LINUX
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    tx_packets = 0,
+    tx_bytes,
+    rx_packets,
+    rx_bytes,
+    TxDrop,
+    TxCrcErr,
+    TxUnicast,
+    TxMulticast,
+    TxBroadcast,
+    TxCollision,
+    TxSingleCollision,
+    TxMultipleCollision,
+    TxDeferred,
+    TxLateCollision,
+    TxExcessiveCollistion,
+    TxPause,
+    TxPktSz64,
+    TxPktSz65To127,
+    TxPktSz128To255,
+    TxPktSz256To511,
+    TxPktSz512To1023,
+    Tx1024ToMax,
+    TxBytes,
+    RxDrop,
+    RxFiltering,
+    RxUnicast,
+    RxMulticast,
+    RxBroadcast,
+    RxAlignErr,
+    RxCrcErr,
+    RxUnderSizeErr,
+    RxFragErr,
+    RxOverSzErr,
+    RxJabberErr,
+    RxPause,
+    RxPktSz64,
+    RxPktSz65To127,
+    RxPktSz128To255,
+    RxPktSz256To511,
+    RxPktSz512To1023,
+    RxPktSz1024ToMax,
+    RxBytes,
+    RxCtrlDrop,
+    RxIngressDrop,
+    RxArlDrop,
+    STATS_END,
+} idx;
+
+static struct ethnic_stats {
+    __u32   cmd;
+    __u32   n_stats;
+    __u64   data[STATS_END];
+} stat;
+
+static struct eth_stats ifstats;
+
+int linux_eth_get_stats(const char *ifname, struct eth_stats *s);
+int linux_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LINUX */