diff --git a/Makefile b/Makefile
index 8d4da630d5a9471c617e6ae67d6ae6e77a39902c..0e994ea96dacce08136737ef69c1e24576ab55d6 100644
--- a/Makefile
+++ b/Makefile
@@ -24,12 +24,12 @@ objs_lib += econet/econet.o econet/ecnt_prvt.o
 LIBS += -lapi_lib_switchmgr
 endif
 
-ifeq ($(PLATFORM),IPQ95XX)
-objs_lib += ipq95xx/ipq95xx.o
+ifeq ($(PLATFORM),LINUX)
+objs_lib += linux/common/common_eth.o linux/linux/linux_eth.o
 endif
 
-ifeq ($(PLATFORM),LINUX)
-objs_lib += linux/linux_eth.o
+ifeq ($(PLATFORM),MEDIATEK)
+objs_lib += linux/common/common_eth.o linux/mtk/mtk_eth.o
 endif
 
 all: libethernet.so
diff --git a/ethernet.c b/ethernet.c
index fb73ec3260042bfc26e0ea8a4f0e43fdb4b972a1..8c81568fd9ab3fd778f4f205f125e2d21a93cb69 100644
--- a/ethernet.c
+++ b/ethernet.c
@@ -47,8 +47,8 @@ extern const struct eth_ops test_eth_ops;
 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_MEDIATEK)
+extern const struct eth_ops mtk_eth_ops;
 #elif defined(IOPSYS_LINUX)
 extern const struct eth_ops linux_eth_ops;
 #else
@@ -64,8 +64,8 @@ const struct eth_ops *eth_ops[] = {
 	&econet_gen_eth_ops,
 	&econet_nas_wan_eth_ops,
 	&econet_ae_wan_eth_ops,
-#elif defined(IPQ95XX)
-	&ipq95xx_eth_ops,
+#elif defined(IOPSYS_MEDIATEK)
+	&mtk_eth_ops
 #elif defined(IOPSYS_LINUX)
         &linux_eth_ops,
 #else
diff --git a/ipq95xx/ipq95xx.c b/ipq95xx/ipq95xx.c
deleted file mode 100644
index a6b6c1c69cb699d38cef769bc24a5c7bc81552b9..0000000000000000000000000000000000000000
--- a/ipq95xx/ipq95xx.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * ipq95xx.c
- */
-
-#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/mii.h>
-#include <linux/ethtool.h>
-#include <linux/sockios.h>
-#include <easy/easy.h>
-
-#include "../ethernet.h"
-
-#include "ipq95xx.h"
-
-int ipq95xx_eth_set_link_settings(const char *ifname, struct eth_link link)
-{
-	struct {
-		struct ethtool_link_settings req;
-		__u32 link_mode_data[3 * 32 * 127];
-	} ecmd;
-
-	memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
-
-	if (ipq95xx_eth_get_link_settings(ifname, &link))
-		return -1;
-
-	ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
-
-	ecmd.req.port = link.portid;
-	ecmd.req.speed = link.speed;
-	ecmd.req.autoneg = (link.autoneg == 0 ? false : true);
-	ecmd.req.duplex = (link.fullduplex == 1 ? false : true);
-
-	if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
-		return -1;
-	return 0;
-}
-
-int ipq95xx_eth_get_link_settings(const char *ifname, struct eth_link *link)
-{
-	struct {
-		struct ethtool_link_settings req;
-		__u32 link_mode_data[3 * 32 * 127];
-	} ecmd;
-
-	memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
-
-	ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
-
-	if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
-		return -1;
-
-	if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
-		return -1;
-
-	ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
-
-	if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
-		return -1;
-
-	if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
-		return -1;
-
-	link->portid = ecmd.req.port;
-	link->speed = ecmd.req.speed;
-	link->autoneg = ecmd.req.autoneg == 0 ? false : true;
-	link->fullduplex = ecmd.req.duplex == 1 ? false : true;
-
-	return 0;
-}
-
-int ipq95xx_eth_poweron_phy(const char *ifname, struct eth_phy p)
-{
-	libethernet_err("%s(): TODO\n", __func__);
-	return 0;
-}
-
-int ipq95xx_eth_poweroff_phy(const char *ifname, struct eth_phy p)
-{
-	libethernet_err("%s(): TODO\n", __func__);
-	return 0;
-}
-
-int ipq95xx_eth_reset_phy(const char *ifname, int phy_id)
-{
-	return eth_mii_reset_phy(ifname, phy_id);
-}
-
-int ipq95xx_eth_get_stats(const char *ifname, struct eth_stats *s)
-{
-	struct if_stats ifstats;
-
-	memset(&ifstats, 0, sizeof(struct if_stats));
-
-	if (if_getstats(ifname, &ifstats) < 0)
-		return -1;
-
-	s->rx_packets = ifstats.rx_packets;
-	s->tx_packets = ifstats.tx_packets;
-	s->rx_bytes = ifstats.rx_bytes;
-	s->tx_bytes = ifstats.tx_bytes;
-	s->rx_errors = ifstats.rx_errors;
-	s->tx_errors = ifstats.tx_errors;
-	s->rx_discard_packets = ifstats.rx_dropped;
-	s->tx_discard_packets = ifstats.tx_dropped;
-
-	return 0;
-}
-
-int ipq95xx_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
-{
-	libethernet_err("%s(): TODO\n", __func__);
-        return 0;
-}
-
-const struct eth_ops ipq95xx_eth_ops = {
-        .ifname = "eth",
-        .set_link_settings = ipq95xx_eth_set_link_settings,
-        .get_link_settings = ipq95xx_eth_get_link_settings,
-        .get_stats = ipq95xx_eth_get_stats,
-        .get_rmon_stats = ipq95xx_eth_get_rmon_stats,
-        .poweron_phy = ipq95xx_eth_poweron_phy,
-        .poweroff_phy = ipq95xx_eth_poweroff_phy,
-        .reset_phy = ipq95xx_eth_reset_phy,
-};
diff --git a/ipq95xx/ipq95xx.h b/ipq95xx/ipq95xx.h
deleted file mode 100644
index 6017ae2e22c8d4825f458f9fcf3ed3662781b59b..0000000000000000000000000000000000000000
--- a/ipq95xx/ipq95xx.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef IPQ95XX
-#define IPQ95XX
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int ipq95xx_eth_set_link_settings(const char *ifname, struct eth_link link);
-int ipq95xx_eth_get_link_settings(const char *ifname, struct eth_link *link);
-int ipq95xx_eth_poweron_phy(const char *ifname, struct eth_phy p);
-int ipq95xx_eth_poweroff_phy(const char *ifname, struct eth_phy p);
-int ipq95xx_eth_reset_phy(const char *ifname, int phy_id);
-int ipq95xx_eth_get_stats(const char *ifname, struct eth_stats *s);
-int ipq95xx_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* IPQ95XX */
diff --git a/linux/common/common_eth.c b/linux/common/common_eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..3b1c12a02e233215807e97d193da5f0279d4cebf
--- /dev/null
+++ b/linux/common/common_eth.c
@@ -0,0 +1,62 @@
+/*
+ * common_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 <linux/sockios.h>
+#include <easy/easy.h>
+#include <easy/if_utils.h>
+#include "ethernet.h"
+#include "../linux/linux_eth.h"
+#include "../mtk/mtk_eth.h"
+
+#if defined(IOPSYS_MEDIATEK)
+const struct eth_ops mtk_eth_ops = {
+        .ifname = "lan",
+        .get_stats = mtk_eth_get_stats,
+        .get_rmon_stats = mtk_eth_get_rmon_stats,
+#elif defined(IOPSYS_LINUX)
+const struct eth_ops linux_eth_ops = {
+        .ifname = "eth",
+        .set_link_settings = linux_eth_set_link_settings,
+        .get_link_settings = linux_eth_get_link_settings,
+        .poweron_phy = linux_eth_poweron_phy,
+        .poweroff_phy = linux_eth_poweroff_phy,
+        .reset_phy = linux_eth_reset_phy,
+        .get_stats = linux_eth_get_stats,
+        .get_rmon_stats = linux_eth_get_rmon_stats,
+#endif
+};
diff --git a/linux/linux/linux_eth.c b/linux/linux/linux_eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..e03b7762083cc9a7d6774af004f478c5609b1157
--- /dev/null
+++ b/linux/linux/linux_eth.c
@@ -0,0 +1,348 @@
+/*
+ * linux_eth.c
+ */
+
+#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/mii.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <easy/easy.h>
+#include "ethernet.h"
+#include "linux_eth.h"
+
+typedef enum {
+    iow_rx_byte = 0,
+    iow_rx_packets,
+    iow_rx_dropped,
+    iow_rx_fraglist_packets,
+    iow_rx_nr_frag_packets,
+    iow_rx_nr_frag_headroom_err,
+    iow_tx_byte,
+    iow_tx_packets,
+    iow_tx_dropped,
+    iow_tx_nr_frag_packets,
+    iow_tx_fraglist_packets,
+    iow_tx_fraglist_nr_frags_packets,
+    iow_tx_tso_packets,
+    iow_tx_tso_drop_packets,
+    iow_rx_frame,
+    iow_rx_bytes,
+    iow_rx_bytes_g,
+    iow_rx_broadcast,
+    iow_rx_multicast,
+    iow_rx_crc_err,
+    iow_rx_runt_err,
+    iow_rx_jabber_err,
+    iow_rx_undersize,
+    iow_rx_oversize,
+    iow_rx_pkt64,
+    iow_rx_pkt65to127,
+    iow_rx_pkt128to255,
+    iow_rx_pkt256to511,
+    iow_rx_pkt512to1023,
+    iow_rx_pkt1024tomax,
+    iow_rx_unicast,
+    iow_rx_len_err,
+    iow_rx_outofrange_err_ctr,
+    iow_rx_pause,
+    iow_rx_fifo_overflow,
+    iow_rx_vlan,
+    iow_rx_wdog,
+    iow_rx_lpi_usec_ctr,
+    iow_rx_lpi_tran_ctr,
+    iow_rx_drop_frame_ctr,
+    iow_rx_drop_byte_ctr,
+    iow_tx_bytes,
+    iow_tx_frame,
+    iow_tx_broadcast,
+    iow_tx_broadcast_gb,
+    iow_tx_multicast,
+    iow_tx_multicast_gb,
+    iow_tx_pkt64,
+    iow_tx_pkt65to127,
+    iow_tx_pkt128to255,
+    iow_tx_pkt256to511,
+    iow_tx_pkt512to1023,
+    iow_tx_pkt1024tomax,
+    iow_tx_unicast,
+    iow_tx_underflow_err,
+    iow_tx_bytes_g,
+    iow_tx_frame_g,
+    iow_tx_pause,
+    iow_tx_vlan,
+    iow_tx_lpi_usec_ctr,
+    iow_tx_lpi_tran_ctr,
+    iow_STAT_END,
+} g_linux_indx;
+
+static struct ethtool_stats *g_linux_stats = NULL;
+static struct eth_stats g_linux_ifstats;
+
+int linux_eth_get_link_settings(const char*, struct eth_link*);
+
+int linux_eth_set_link_settings(const char *ifname, struct eth_link link)
+{
+    struct {
+	struct ethtool_link_settings req;
+	__u32 link_mode_data[3 * 32 * 127];
+    } ecmd;
+
+    memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
+
+    if (linux_eth_get_link_settings(ifname, &link))
+	return -1;
+
+    ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
+
+    ecmd.req.port = link.portid;
+    ecmd.req.speed = link.speed;
+    ecmd.req.autoneg = (link.autoneg == 0 ? false : true);
+    ecmd.req.duplex = (link.fullduplex == 1 ? false : true);
+
+    if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
+	return -1;
+    return 0;
+}
+
+int linux_eth_get_link_settings(const char *ifname, struct eth_link *link)
+{
+    struct {
+	struct ethtool_link_settings req;
+	__u32 link_mode_data[3 * 32 * 127];
+    } ecmd;
+
+    memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
+
+    ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
+
+    if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
+	return -1;
+
+    if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
+	return -1;
+
+    ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
+
+    if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
+	return -1;
+
+    if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
+	return -1;
+
+    link->portid = ecmd.req.port;
+    link->speed = ecmd.req.speed;
+    link->autoneg = ecmd.req.autoneg == 0 ? false : true;
+    link->fullduplex = ecmd.req.duplex == 1 ? false : true;
+
+    return 0;
+}
+
+int linux_eth_poweron_phy(const char *ifname, struct eth_phy p)
+{
+    libethernet_err("%s(): TODO\n", __func__);
+    return 0;
+}
+
+int linux_eth_poweroff_phy(const char *ifname, struct eth_phy p)
+{
+    libethernet_err("%s(): TODO\n", __func__);
+    return 0;
+}
+
+int linux_eth_reset_phy(const char *ifname, int phy_id)
+{
+    return eth_mii_reset_phy(ifname, phy_id);
+}
+
+static int linux_get_ifstats(const char *ifname, struct eth_stats *s)
+{
+    struct if_stats easy_ifstat;
+
+    if (!s)
+        return -1;
+
+    memset(&easy_ifstat, 0, sizeof(struct if_stats));
+    if (if_getstats(ifname, &easy_ifstat) < 0) {
+        return -1;
+    }
+
+    s->tx_bytes = easy_ifstat.tx_bytes;
+    s->tx_packets = easy_ifstat.tx_packets;
+    s->tx_errors = easy_ifstat.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 = easy_ifstat.rx_bytes;
+    s->rx_packets = 0;
+    s->rx_errors = easy_ifstat.rx_errors;
+    s->rx_ucast_packets = 0;
+    s->rx_mcast_packets = 0;
+    s->rx_bcast_packets = 0;
+    s->rx_discard_packets = 0;
+    s->rx_unknown_packets = 0;
+
+    return 0;
+}
+ 
+static int linux_get_ethtool_stats(const char *ifname)
+{
+    int fd; 
+    size_t n_stats;
+    size_t stats_size;
+    int status;
+
+    fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0); 
+    if (fd < 0) {
+        syslog(LOG_ERR, "%s(%d): Failed"
+                " to open control socket.\n", __FUNCTION__, __LINE__);
+        return -1;
+    }
+
+    struct ethtool_drvinfo drvinfo = {.cmd = ETHTOOL_GDRVINFO};
+
+    struct ifreq req = {.ifr_data = (void *)&drvinfo};
+
+    strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
+
+    status = ioctl(fd, SIOCETHTOOL, &req);
+
+    if (status < 0) {
+        close(fd);
+        syslog(LOG_ERR, "%s(%d): Failed to get"
+                "driver information from %s:", __FUNCTION__, __LINE__, ifname);
+        return -1; 
+    }
+
+    n_stats = (size_t)drvinfo.n_stats;
+    if (n_stats < 1) {
+        close(fd);
+        syslog(LOG_ERR, "%s(%d): No stats"
+                " available for %s", __FUNCTION__, __LINE__, ifname);
+        return -1;
+    }
+    stats_size = sizeof(struct ethtool_stats) + (n_stats * sizeof(uint64_t));
+
+    g_linux_stats = malloc(stats_size);
+    if (!g_linux_stats) {
+        close(fd);
+        syslog(LOG_ERR, "%s(%d): malloc failed.", 
+                __FUNCTION__, __LINE__);
+        return -1;
+    }
+
+    g_linux_stats->cmd = ETHTOOL_GSTATS;
+    g_linux_stats->n_stats = n_stats;
+    req.ifr_data = (void *)g_linux_stats;
+
+    status = ioctl(fd, SIOCETHTOOL, &req);
+    if (status < 0) {
+        close(fd);
+        if (g_linux_stats)
+	    free(g_linux_stats);
+        syslog(LOG_ERR, "%s(%d): Reading statistics"
+                " from %s failed:", __FUNCTION__, __LINE__, ifname);
+        return -1;
+    }
+
+    close(fd);
+    return 0;
+}
+
+int linux_get_if_stats(const char *ifname)
+{
+    memset(&g_linux_ifstats, 0, sizeof(struct eth_stats));
+
+    syslog(LOG_INFO, "%s(%d): ifname is %s", __FUNCTION__, __LINE__, ifname);
+
+    if (linux_get_ifstats(ifname, &g_linux_ifstats) < 0)
+        return -1;
+    if (linux_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 (linux_get_if_stats(ifname) < 0)
+        return -1;
+
+    s->tx_bytes = g_linux_ifstats.tx_bytes;
+    s->tx_packets = g_linux_ifstats.tx_packets;
+    s->tx_errors = g_linux_ifstats.tx_errors;
+    s->tx_ucast_packets = (uint64_t)g_linux_stats->data[iow_tx_unicast];
+    s->tx_mcast_packets = (uint64_t)g_linux_stats->data[iow_tx_multicast];
+    s->tx_bcast_packets = (uint64_t)g_linux_stats->data[iow_tx_broadcast];
+    s->tx_discard_packets = (uint64_t)g_linux_stats->data[iow_tx_dropped];
+    s->rx_bytes = g_linux_ifstats.rx_bytes;
+    s->rx_packets = (uint64_t)g_linux_stats->data[iow_rx_packets];
+    s->rx_errors = g_linux_ifstats.rx_errors;
+    s->rx_ucast_packets = (uint64_t)g_linux_stats->data[iow_rx_unicast];
+    s->rx_mcast_packets = (uint64_t)g_linux_stats->data[iow_rx_multicast];
+    s->rx_bcast_packets = (uint64_t)g_linux_stats->data[iow_rx_broadcast];
+    s->rx_discard_packets = (uint64_t)g_linux_stats->data[iow_rx_dropped];
+/*FIXME: Doesn't exist a way to get the counter rx_unknown_packets.*/
+    s->rx_unknown_packets = 0;
+
+    free(g_linux_stats);
+
+    return 0;
+}
+
+int linux_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
+{
+    int ret = 0;
+
+    if (linux_get_if_stats(ifname) < 0)
+        ret = -1;
+
+    rmon->tx.packets = (uint64_t)g_linux_stats->data[iow_tx_packets];
+    rmon->tx.bytes = (uint64_t)g_linux_stats->data[iow_tx_bytes];
+    rmon->tx.crc_err_packets = 0;
+/* 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 = (uint64_t)g_linux_stats->data[iow_tx_pkt64];
+    rmon->tx.packets_65to127bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt65to127];
+    rmon->tx.packets_128to255bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt128to255];
+    rmon->tx.packets_256to511bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt256to511];
+    rmon->tx.packets_512to1023bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt512to1023];
+    rmon->tx.packets_1024to1518bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt1024tomax];
+
+    rmon->rx.bytes = (uint64_t)g_linux_stats->data[iow_rx_byte];
+    rmon->rx.packets = (uint64_t)g_linux_stats->data[iow_rx_packets];
+    rmon->rx.bcast_packets = (uint64_t)g_linux_stats->data[iow_rx_broadcast];
+    rmon->rx.mcast_packets = (uint64_t)g_linux_stats->data[iow_rx_multicast];
+    rmon->rx.crc_err_packets = (uint64_t)g_linux_stats->data[iow_rx_crc_err];
+    rmon->rx.under_sz_packets = (uint64_t)g_linux_stats->data[iow_rx_undersize];
+    rmon->rx.over_sz_packets = (uint64_t)g_linux_stats->data[iow_rx_oversize];
+    rmon->rx.packets_64bytes = (uint64_t)g_linux_stats->data[iow_rx_pkt64];
+    rmon->rx.packets_65to127bytes = (uint64_t)g_linux_stats->data[iow_rx_pkt65to127];
+
+    free(g_linux_stats);
+
+    return ret;
+}
diff --git a/linux/linux/linux_eth.h b/linux/linux/linux_eth.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9aee2528deee2b2ad11ee09c4c6df99d97e7bdf
--- /dev/null
+++ b/linux/linux/linux_eth.h
@@ -0,0 +1,20 @@
+#ifndef LINUX_ETH_H
+#define LINUX_ETH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int linux_eth_set_link_settings(const char *ifname, struct eth_link link);
+int linux_eth_get_link_settings(const char *ifname, struct eth_link *link);
+int linux_eth_poweron_phy(const char *ifname, struct eth_phy p);
+int linux_eth_poweroff_phy(const char *ifname, struct eth_phy p);
+int linux_eth_reset_phy(const char *ifname, int phy_id);
+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_ETH_H */
diff --git a/linux/linux_eth.c b/linux/linux_eth.c
deleted file mode 100644
index 6ea972d57ceac4bba67ce150b7da020c9899e5ff..0000000000000000000000000000000000000000
--- a/linux/linux_eth.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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 <linux/sockios.h>
-#include <easy/easy.h>
-#include <easy/if_utils.h>
-
-#include "../ethernet.h"
-
-#include "linux_eth.h"
-
-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;
-
-struct ethnic_stats {
-    uint32_t   cmd;
-    uint32_t   n_stats;
-    uint64_t   data[STATS_END];
-} stat;
-
-static struct eth_stats ifstats;
-
-static int get_ifstats(const char *ifname, struct eth_stats *s)
-{
-    struct if_stats easy_ifstat;
-
-    if (!s)
-        return -1;
-
-    memset(&easy_ifstat, 0, sizeof(struct if_stats));
-    if (if_getstats(ifname, &easy_ifstat) < 0) {
-	return -1;
-    }
-
-    s->tx_bytes = easy_ifstat.tx_bytes;
-    s->tx_packets = easy_ifstat.tx_packets;
-    s->tx_errors = easy_ifstat.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 = easy_ifstat.rx_bytes;
-    s->rx_packets = 0;
-    s->rx_errors = easy_ifstat.rx_errors;
-    s->rx_ucast_packets = 0;
-    s->rx_mcast_packets = 0;
-    s->rx_bcast_packets = 0;
-    s->rx_discard_packets = 0;
-    s->rx_unknown_packets = 0;
-
-    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 = stat.data[TxMulticast];
-    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/linux/linux_eth.h b/linux/linux_eth.h
deleted file mode 100644
index 68befa703799c8fb3c136bcabc94a9b781559431..0000000000000000000000000000000000000000
--- a/linux/linux_eth.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef LINUX_ETH_H
-#define LINUX_ETH_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-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_ETH_H */
diff --git a/linux/mtk/mtk_eth.c b/linux/mtk/mtk_eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f32fad6b7ab3ccc41baec9ba9bbad6a16aeeb2b
--- /dev/null
+++ b/linux/mtk/mtk_eth.c
@@ -0,0 +1,233 @@
+/*
+ * mtk_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 <linux/sockios.h>
+#include <easy/easy.h>
+#include <easy/if_utils.h>
+#include "ethernet.h"
+#include "mtk_eth.h"
+
+typedef enum {
+    iow_tx_packets = 0,
+    iow_tx_bytes,
+    iow_rx_packets,
+    iow_rx_bytes,
+    iow_TxDrop,
+    iow_TxCrcErr,
+    iow_TxUnicast,
+    iow_TxMulticast,
+    iow_TxBroadcast,
+    iow_TxCollision,
+    iow_TxSingleCollision,
+    iow_TxMultipleCollision,
+    iow_TxDeferred,
+    iow_TxLateCollision,
+    iow_TxExcessiveCollistion,
+    iow_TxPause,
+    iow_TxPktSz64,
+    iow_TxPktSz65To127,
+    iow_TxPktSz128To255,
+    iow_TxPktSz256To511,
+    iow_TxPktSz512To1023,
+    iow_Tx1024ToMax,
+    iow_TxBytes,
+    iow_RxDrop,
+    iow_RxFiltering,
+    iow_RxUnicast,
+    iow_RxMulticast,
+    iow_RxBroadcast,
+    iow_RxAlignErr,
+    iow_RxCrcErr,
+    iow_RxUnderSizeErr,
+    iow_RxFragErr,
+    iow_RxOverSzErr,
+    iow_RxJabberErr,
+    iow_RxPause,
+    iow_RxPktSz64,
+    iow_RxPktSz65To127,
+    iow_RxPktSz128To255,
+    iow_RxPktSz256To511,
+    iow_RxPktSz512To1023,
+    iow_RxPktSz1024ToMax,
+    iow_RxBytes,
+    iow_RxCtrlDrop,
+    iow_RxIngressDrop,
+    iow_RxArlDrop,
+    iow_STATS_END,
+} g_indx;
+
+struct mtk_ethnic_stats {
+    uint32_t   cmd;
+    uint32_t   n_stats;
+    uint64_t   data[iow_STATS_END];
+} g_mtk_stat;
+
+static struct eth_stats g_mtk_ifstats;
+
+static int mtk_get_ifstats(const char *ifname, struct eth_stats *s)
+{
+
+    struct if_stats easy_ifstat;
+
+    if (!s)
+        return -1;
+
+    memset(&easy_ifstat, 0, sizeof(struct if_stats));
+    if (if_getstats(ifname, &easy_ifstat) < 0) {
+	return -1;
+    }
+
+    s->tx_bytes = easy_ifstat.tx_bytes;
+    s->tx_packets = easy_ifstat.tx_packets;
+    s->tx_errors = easy_ifstat.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 = easy_ifstat.rx_bytes;
+    s->rx_packets = 0;
+    s->rx_errors = easy_ifstat.rx_errors;
+    s->rx_ucast_packets = 0;
+    s->rx_mcast_packets = 0;
+    s->rx_bcast_packets = 0;
+    s->rx_discard_packets = 0;
+    s->rx_unknown_packets = 0;
+
+    return 0;
+}
+
+
+int mtk_get_ethtool_stats(const char *ifname)
+{
+    int ret = 0;
+
+    g_mtk_stat.cmd = ETHTOOL_GSTATS;
+    if (0 != eth_ioctl(ifname, SIOCETHTOOL, &g_mtk_stat, sizeof(struct mtk_ethnic_stats)))
+        ret = -1;
+
+    if (ret)
+	syslog(LOG_ERR, "%s(%d) nic_stats collection failed.", __FUNCTION__, __LINE__);
+
+    return ret;
+}
+
+
+int mtk_get_if_stats(const char *ifname)
+{
+
+    memset(&g_mtk_ifstats, 0, sizeof(struct eth_stats));
+    memset(&g_mtk_stat, 0, sizeof(struct mtk_ethnic_stats));
+
+    syslog(LOG_INFO, "%s(%d): ifname is %s", __FUNCTION__, __LINE__, ifname);
+
+    if (mtk_get_ifstats(ifname, &g_mtk_ifstats) < 0)
+        return -1;
+    if (mtk_get_ethtool_stats(ifname) < 0)
+	return -1;
+
+    return 0;
+}
+
+int mtk_eth_get_stats(const char *ifname, struct eth_stats *s)
+{
+    if (!s)
+	return -1;
+    if (mtk_get_if_stats(ifname) < 0)
+	return -1;
+
+    s->tx_bytes = g_mtk_ifstats.tx_bytes;
+    s->tx_packets = g_mtk_ifstats.tx_packets;
+    s->tx_errors = g_mtk_ifstats.tx_errors;
+    s->tx_ucast_packets = g_mtk_stat.data[iow_TxUnicast];
+    s->tx_mcast_packets = g_mtk_stat.data[iow_TxMulticast];
+    s->tx_bcast_packets = g_mtk_stat.data[iow_TxBroadcast];
+    s->tx_discard_packets = g_mtk_stat.data[iow_TxDrop];
+    s->rx_bytes = g_mtk_ifstats.rx_bytes;
+    s->rx_packets = g_mtk_stat.data[iow_rx_packets];
+    s->rx_errors = g_mtk_ifstats.rx_errors;
+    s->rx_ucast_packets = g_mtk_stat.data[iow_RxUnicast];
+    s->rx_mcast_packets = g_mtk_stat.data[iow_RxMulticast];
+    s->rx_bcast_packets = g_mtk_stat.data[iow_RxBroadcast];
+    s->rx_discard_packets = g_mtk_stat.data[iow_RxDrop];
+/*FIXME: Doesn't exist a way to get the counter rx_unknown_packets.*/
+    s->rx_unknown_packets = 0;
+
+    return 0;
+}
+
+int mtk_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
+{
+    int ret = 0;
+
+    if (mtk_get_if_stats(ifname) < 0)
+	ret = -1;
+
+    rmon->tx.packets = g_mtk_stat.data[iow_tx_packets];
+    rmon->tx.bytes = g_mtk_stat.data[iow_tx_bytes];
+    rmon->tx.crc_err_packets = g_mtk_stat.data[iow_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 = g_mtk_stat.data[iow_TxPktSz64];
+    rmon->tx.packets_65to127bytes = g_mtk_stat.data[iow_TxPktSz65To127];
+    rmon->tx.packets_128to255bytes = g_mtk_stat.data[iow_TxPktSz128To255];
+    rmon->tx.packets_256to511bytes = g_mtk_stat.data[iow_TxPktSz256To511];
+    rmon->tx.packets_512to1023bytes = g_mtk_stat.data[iow_TxPktSz512To1023];
+    rmon->tx.packets_1024to1518bytes = g_mtk_stat.data[iow_Tx1024ToMax];
+
+    rmon->rx.bytes = g_mtk_stat.data[iow_RxBytes];
+    rmon->rx.packets = g_mtk_stat.data[iow_rx_packets];
+    rmon->rx.bcast_packets = g_mtk_stat.data[iow_RxBroadcast];
+    rmon->rx.mcast_packets = g_mtk_stat.data[iow_RxMulticast];
+    rmon->rx.crc_err_packets = g_mtk_stat.data[iow_RxCrcErr];
+    rmon->rx.under_sz_packets = g_mtk_stat.data[iow_RxUnderSizeErr];
+    rmon->rx.over_sz_packets = g_mtk_stat.data[iow_RxOverSzErr];
+    rmon->rx.packets_64bytes = g_mtk_stat.data[iow_RxPktSz64];
+    rmon->rx.packets_65to127bytes = g_mtk_stat.data[iow_RxPktSz65To127];
+    rmon->rx.packets_128to255bytes = g_mtk_stat.data[iow_RxPktSz128To255];
+    rmon->rx.packets_256to511bytes = g_mtk_stat.data[iow_RxPktSz256To511];
+    rmon->rx.packets_512to1023bytes = g_mtk_stat.data[iow_RxPktSz512To1023];
+    rmon->rx.packets_1024to1518bytes = g_mtk_stat.data[iow_RxPktSz1024ToMax];
+
+    return ret;
+}
diff --git a/linux/mtk/mtk_eth.h b/linux/mtk/mtk_eth.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e5df783df8549e651e064620186d8456ad6809f
--- /dev/null
+++ b/linux/mtk/mtk_eth.h
@@ -0,0 +1,15 @@
+#ifndef MTK_ETH_H
+#define MTK_ETH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mtk_eth_get_stats(const char *ifname, struct eth_stats *s);
+int mtk_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* MTK_ETH_H */