diff --git a/drivers/net/rnp/base/rnp_api.c b/drivers/net/rnp/base/rnp_api.c
index 550da6217d..cf74769fb6 100644
--- a/drivers/net/rnp/base/rnp_api.c
+++ b/drivers/net/rnp/base/rnp_api.c
@@ -21,3 +21,51 @@ rnp_reset_hw(struct rte_eth_dev *dev, struct rnp_hw *hw)
 		return ops->reset_hw(hw);
 	return -EOPNOTSUPP;
 }
+
+int
+rnp_get_mac_addr(struct rte_eth_dev *dev, uint8_t *macaddr)
+{
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+	const struct rnp_mac_api *ops = RNP_DEV_TO_MAC_OPS(dev);
+
+	if (!macaddr)
+		return -EINVAL;
+	if (ops->get_mac_addr)
+		return ops->get_mac_addr(port, port->attr.nr_lane, macaddr);
+	return -EOPNOTSUPP;
+}
+
+int
+rnp_set_default_mac(struct rte_eth_dev *dev, uint8_t *mac_addr)
+{
+	const struct rnp_mac_api *ops = RNP_DEV_TO_MAC_OPS(dev);
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+
+	if (ops->set_default_mac)
+		return ops->set_default_mac(port, mac_addr);
+	return -EOPNOTSUPP;
+}
+
+int
+rnp_set_rafb(struct rte_eth_dev *dev, uint8_t *addr,
+	     uint8_t vm_pool, uint8_t index)
+{
+	const struct rnp_mac_api *ops = RNP_DEV_TO_MAC_OPS(dev);
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+
+	if (ops->set_rafb)
+		return ops->set_rafb(port, addr, vm_pool, index);
+	return -EOPNOTSUPP;
+}
+
+int
+rnp_clear_rafb(struct rte_eth_dev *dev,
+	       uint8_t vm_pool, uint8_t index)
+{
+	const struct rnp_mac_api *ops = RNP_DEV_TO_MAC_OPS(dev);
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+
+	if (ops->clear_rafb)
+		return ops->clear_rafb(port, vm_pool, index);
+	return -EOPNOTSUPP;
+}
diff --git a/drivers/net/rnp/base/rnp_api.h b/drivers/net/rnp/base/rnp_api.h
index df574dab77..b998b11237 100644
--- a/drivers/net/rnp/base/rnp_api.h
+++ b/drivers/net/rnp/base/rnp_api.h
@@ -4,4 +4,14 @@ int
 rnp_init_hw(struct rte_eth_dev *dev);
 int
 rnp_reset_hw(struct rte_eth_dev *dev, struct rnp_hw *hw);
+int
+rnp_get_mac_addr(struct rte_eth_dev *dev, uint8_t *macaddr);
+int
+rnp_set_default_mac(struct rte_eth_dev *dev, uint8_t *mac_addr);
+int
+rnp_set_rafb(struct rte_eth_dev *dev, uint8_t *addr,
+		uint8_t vm_pool, uint8_t index);
+int
+rnp_clear_rafb(struct rte_eth_dev *dev,
+		uint8_t vm_pool, uint8_t index);
 #endif /* __RNP_API_H__ */
diff --git a/drivers/net/rnp/base/rnp_hw.h b/drivers/net/rnp/base/rnp_hw.h
index 57b7dc75a0..395b9d5c71 100644
--- a/drivers/net/rnp/base/rnp_hw.h
+++ b/drivers/net/rnp/base/rnp_hw.h
@@ -44,6 +44,10 @@ static inline void rnp_wr_reg(volatile void *reg, int val)
 	rnp_rd_reg((uint8_t *)((_hw)->comm_reg_base) + (_off))
 #define rnp_top_wr(_hw, _off, _val)	\
 	rnp_wr_reg((uint8_t *)((_hw)->comm_reg_base) + (_off), (_val))
+#define RNP_MACADDR_UPDATE_LO(hw, hw_idx, val) \
+	rnp_eth_wr(hw, RNP_RAL_BASE_ADDR(hw_idx), val)
+#define RNP_MACADDR_UPDATE_HI(hw, hw_idx, val) \
+	rnp_eth_wr(hw, RNP_RAH_BASE_ADDR(hw_idx), val)
 struct rnp_hw;
 /* Mbx Operate info */
 enum MBX_ID {
@@ -112,9 +116,23 @@ struct rnp_mbx_info {
 	rte_atomic16_t state;
 } __rte_cache_aligned;
 
+struct rnp_eth_port;
 struct rnp_mac_api {
 	int32_t (*init_hw)(struct rnp_hw *hw);
 	int32_t (*reset_hw)(struct rnp_hw *hw);
+	/* MAC Address */
+	int32_t (*get_mac_addr)(struct rnp_eth_port *port,
+				uint8_t lane,
+				uint8_t *macaddr);
+	int32_t (*set_default_mac)(struct rnp_eth_port *port, uint8_t *mac);
+	/* Receive Address Filter Table */
+	int32_t (*set_rafb)(struct rnp_eth_port *port,
+			    uint8_t *mac,
+			    uint8_t vm_pool,
+			    uint8_t index);
+	int32_t (*clear_rafb)(struct rnp_eth_port *port,
+			    uint8_t vm_pool,
+			    uint8_t index);
 };
 
 struct rnp_mac_info {
diff --git a/drivers/net/rnp/meson.build b/drivers/net/rnp/meson.build
index c52566c357..7d63460c45 100644
--- a/drivers/net/rnp/meson.build
+++ b/drivers/net/rnp/meson.build
@@ -11,6 +11,7 @@ sources = files(
 		'rnp_ethdev.c',
 		'rnp_mbx.c',
 		'rnp_mbx_fw.c',
+		'rnp_rxtx.c',
 		'base/rnp_api.c',
 )
 
diff --git a/drivers/net/rnp/rnp.h b/drivers/net/rnp/rnp.h
index f6c9231eb1..6f216cc5ca 100644
--- a/drivers/net/rnp/rnp.h
+++ b/drivers/net/rnp/rnp.h
@@ -9,14 +9,90 @@
 
 #define PCI_VENDOR_ID_MUCSE	(0x8848)
 #define RNP_DEV_ID_N10G		(0x1000)
+#define RNP_DEV_ID_N400L_X4	(0x1021)
 #define RNP_MAX_PORT_OF_PF	(4)
 #define RNP_CFG_BAR		(4)
 #define RNP_PF_INFO_BAR		(0)
 
+/* Peer Port Own Independent Resource */
+#define RNP_PORT_MAX_MACADDR         (32)
+#define RNP_PORT_MAX_UC_MAC_SIZE     (256)
+#define RNP_PORT_MAX_VLAN_HASH       (12)
+#define RNP_PORT_MAX_UC_HASH_TB      (8)
+
+/* Hardware Resource info */
+#define RNP_MAX_RX_QUEUE_NUM         (128)
+#define RNP_MAX_TX_QUEUE_NUM         (128)
+#define RNP_N400_MAX_RX_QUEUE_NUM    (8)
+#define RNP_N400_MAX_TX_QUEUE_NUM    (8)
+#define RNP_MAX_HASH_KEY_SIZE        (10)
+#define RNP_MAX_MAC_ADDRS            (128)
+#define RNP_MAX_SUPPORT_VF_NUM       (64)
+#define RNP_MAX_VFTA_SIZE            (128)
+#define RNP_MAX_TC_SUPPORT           (4)
+
+#define RNP_MAX_UC_MAC_SIZE          (4096) /* Max Num of Unicast MAC addr */
+#define RNP_MAX_UC_HASH_TB           (128)
+#define RNP_MAX_MC_MAC_SIZE          (4096) /* Max Num of Multicast MAC addr */
+#define RNP_MAC_MC_HASH_TB           (128)
+#define RNP_MAX_VLAN_HASH_TB_SIZE    (4096)
+
+#define RNP_MAX_UC_HASH_TABLE        (128)
+#define RNP_MAC_MC_HASH_TABLE        (128)
+#define RNP_UTA_BIT_SHIFT            (5)
+
 enum rnp_resource_share_m {
 	RNP_SHARE_CORPORATE = 0,
 	RNP_SHARE_INDEPEND,
 };
+
+/* media type */
+enum rnp_media_type {
+	RNP_MEDIA_TYPE_UNKNOWN,
+	RNP_MEDIA_TYPE_FIBER,
+	RNP_MEDIA_TYPE_COPPER,
+	RNP_MEDIA_TYPE_BACKPLANE,
+	RNP_MEDIA_TYPE_NONE,
+};
+
+struct rnp_phy_meta {
+	uint16_t phy_type;
+	uint32_t speed_cap;
+	uint32_t supported_link;
+	uint16_t link_duplex;
+	uint16_t link_autoneg;
+	uint8_t media_type;
+	bool is_sgmii;
+	bool is_backplane;
+	bool fec;
+	uint32_t phy_identifier;
+};
+
+struct rnp_port_attr {
+	uint16_t max_mac_addrs;   /* Max Support Mac Address */
+	uint16_t uc_hash_tb_size; /* Unicast Hash Table Size */
+	uint16_t max_uc_mac_hash; /* Max Num of hash MAC addr for UC */
+	uint16_t mc_hash_tb_size; /* Multicast Hash Table Size */
+	uint16_t max_mc_mac_hash; /* Max Num Of Hash Mac addr For MC */
+	uint16_t max_vlan_hash;   /* Max Num Of Hash For Vlan ID*/
+	uint32_t hash_table_shift;
+	uint16_t rte_pid;         /* Dpdk Manage Port Sequence Id */
+	uint8_t max_rx_queues;    /* Belong To This Port Rxq Resource */
+	uint8_t max_tx_queues;    /* Belong To This Port Rxq Resource */
+	uint8_t queue_ring_base;
+	uint8_t port_offset;      /* Use For Redir Table Dma Ring Offset Of Port */
+	union {
+		uint8_t nr_lane; /* phy lane of This PF:0~3 */
+		uint8_t nr_port; /* phy lane of This PF:0~3 */
+	};
+	struct rnp_phy_meta phy_meta;
+	bool link_ready;
+	bool pre_link;
+	uint32_t speed;
+	uint16_t max_rx_pktlen;   /* Current Port Max Support Packet Len */
+	uint16_t max_mtu;
+};
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -29,8 +105,16 @@ enum rnp_work_mode {
 
 struct rnp_eth_port {
 	struct rnp_eth_adapter *adapt;
+	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
 	struct rnp_hw *hw;
 	struct rte_eth_dev *eth_dev;
+	struct rnp_port_attr attr;
+	/* Recvice Mac Address Record Table */
+	uint8_t mac_use_tb[RNP_MAX_MAC_ADDRS];
+	uint8_t use_num_mac;
+	bool port_stopped;
+	bool port_closed;
+	enum rnp_resource_share_m s_mode; /* Independent Port Resource */
 } __rte_cache_aligned;
 
 struct rnp_share_ops {
@@ -61,6 +145,10 @@ struct rnp_eth_adapter {
 	(&((struct rnp_eth_adapter *)(RNP_DEV_TO_PORT((eth_dev))->adapt))->hw)
 #define RNP_HW_TO_ADAPTER(hw) \
 	((struct rnp_eth_adapter *)((hw)->back))
+#define RNP_PORT_TO_HW(port) \
+	(&(((struct rnp_eth_adapter *)(port)->adapt)->hw))
+#define RNP_PORT_TO_ADAPTER(port) \
+	((struct rnp_eth_adapter *)((port)->adapt))
 #define RNP_DEV_PP_PRIV_TO_MBX_OPS(dev) \
 	(((struct rnp_share_ops *)(dev)->process_private)->mbx_api)
 #define RNP_DEV_TO_MBX_OPS(dev)	RNP_DEV_PP_PRIV_TO_MBX_OPS(dev)
diff --git a/drivers/net/rnp/rnp_ethdev.c b/drivers/net/rnp/rnp_ethdev.c
index 13d03a23c5..ad99f99d4a 100644
--- a/drivers/net/rnp/rnp_ethdev.c
+++ b/drivers/net/rnp/rnp_ethdev.c
@@ -11,6 +11,7 @@
 #include "rnp_api.h"
 #include "rnp_mbx.h"
 #include "rnp_mbx_fw.h"
+#include "rnp_rxtx.h"
 #include "rnp_logs.h"
 
 static int
@@ -40,6 +41,62 @@ static int rnp_dev_close(struct rte_eth_dev *dev)
 static const struct eth_dev_ops rnp_eth_dev_ops = {
 };
 
+static void
+rnp_setup_port_attr(struct rnp_eth_port *port,
+		    struct rte_eth_dev *dev,
+		    uint8_t num_ports,
+		    uint8_t p_id)
+{
+	struct rnp_port_attr *attr = &port->attr;
+	struct rnp_hw *hw = RNP_DEV_TO_HW(dev);
+	uint32_t lane_bit;
+
+	if (port->s_mode == RNP_SHARE_INDEPEND) {
+		attr->max_mac_addrs = RNP_PORT_MAX_MACADDR;
+		attr->max_uc_mac_hash = RNP_PORT_MAX_UC_MAC_SIZE;
+		attr->uc_hash_tb_size = RNP_PORT_MAX_UC_HASH_TB;
+		attr->max_mc_mac_hash = RNP_PORT_MAX_MACADDR;
+		attr->max_vlan_hash = RNP_PORT_MAX_VLAN_HASH;
+		attr->hash_table_shift = 26 - (attr->max_uc_mac_hash >> 7);
+	} else {
+		attr->max_mac_addrs = RNP_MAX_MAC_ADDRS / num_ports;
+		attr->max_uc_mac_hash = RNP_MAX_UC_MAC_SIZE / num_ports;
+		attr->uc_hash_tb_size = RNP_MAX_UC_HASH_TB;
+		attr->max_mc_mac_hash = RNP_MAX_MC_MAC_SIZE / num_ports;
+		attr->mc_hash_tb_size = RNP_MAC_MC_HASH_TB;
+		attr->max_vlan_hash = RNP_MAX_VLAN_HASH_TB_SIZE / num_ports;
+		attr->hash_table_shift = RNP_UTA_BIT_SHIFT;
+	}
+	if (hw->ncsi_en)
+		attr->uc_hash_tb_size -= hw->ncsi_rar_entries;
+	if (hw->device_id == RNP_DEV_ID_N400L_X4) {
+		attr->max_rx_queues = RNP_N400_MAX_RX_QUEUE_NUM;
+		attr->max_tx_queues = RNP_N400_MAX_TX_QUEUE_NUM;
+	} else {
+		attr->max_rx_queues = RNP_MAX_RX_QUEUE_NUM / num_ports;
+		attr->max_tx_queues = RNP_MAX_TX_QUEUE_NUM / num_ports;
+	}
+
+	attr->rte_pid = dev->data->port_id;
+	lane_bit = hw->phy_port_ids[p_id] & (hw->max_port_num - 1);
+
+	attr->nr_port = lane_bit;
+	attr->port_offset = rnp_eth_rd(hw, RNP_TC_PORT_MAP_TB(attr->nr_port));
+
+	rnp_mbx_get_lane_stat(dev);
+
+	PMD_DRV_LOG(INFO, "PF[%d] SW-ETH-PORT[%d]<->PHY_LANE[%d]\n",
+			hw->function, p_id, lane_bit);
+}
+
+static void
+rnp_init_filter_setup(struct rnp_eth_port *port,
+		      uint8_t num_ports)
+{
+	RTE_SET_USED(port);
+	RTE_SET_USED(num_ports);
+}
+
 static int
 rnp_init_port_resource(struct rnp_eth_adapter *adapter,
 		       struct rte_eth_dev *dev,
@@ -47,11 +104,53 @@ rnp_init_port_resource(struct rnp_eth_adapter *adapter,
 		       uint8_t p_id)
 {
 	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+	struct rte_pci_device *pci_dev = adapter->pdev;
+	struct rnp_hw *hw = &adapter->hw;
 
+	port->adapt = adapter;
+	port->s_mode = adapter->s_mode;
+	port->port_stopped = 1;
+	port->hw = hw;
 	port->eth_dev = dev;
-	adapter->ports[p_id] = port;
+
+	dev->device = &pci_dev->device;
+	rte_eth_copy_pci_info(dev, pci_dev);
 	dev->dev_ops = &rnp_eth_dev_ops;
-	RTE_SET_USED(name);
+	dev->rx_queue_count       = rnp_dev_rx_queue_count;
+	dev->rx_descriptor_status = rnp_dev_rx_descriptor_status;
+	dev->tx_descriptor_status = rnp_dev_tx_descriptor_status;
+	dev->rx_pkt_burst = rnp_recv_pkts;
+	dev->tx_pkt_burst = rnp_xmit_pkts;
+	dev->tx_pkt_prepare = rnp_prep_pkts;
+
+	rnp_setup_port_attr(port, dev, adapter->num_ports, p_id);
+	rnp_init_filter_setup(port, adapter->num_ports);
+	rnp_get_mac_addr(dev, port->mac_addr);
+	dev->data->mac_addrs = rte_zmalloc(name, sizeof(struct rte_ether_addr) *
+			port->attr.max_mac_addrs, 0);
+	if (!dev->data->mac_addrs) {
+		RNP_PMD_DRV_LOG(ERR, "Memory allocation "
+				"for MAC failed! Exiting.\n");
+		return -ENOMEM;
+	}
+	/* Allocate memory for storing hash filter MAC addresses */
+	dev->data->hash_mac_addrs = rte_zmalloc(name,
+			RTE_ETHER_ADDR_LEN * port->attr.max_uc_mac_hash, 0);
+	if (dev->data->hash_mac_addrs == NULL) {
+		RNP_PMD_INIT_LOG(ERR, "Failed to allocate %d bytes "
+				"needed to store MAC addresses",
+				RTE_ETHER_ADDR_LEN * port->attr.max_uc_mac_hash);
+		return -ENOMEM;
+	}
+
+	rnp_set_default_mac(dev, port->mac_addr);
+	rte_ether_addr_copy((const struct rte_ether_addr *)port->mac_addr,
+			dev->data->mac_addrs);
+	/* MTU */
+	dev->data->mtu = RTE_ETHER_MAX_LEN -
+		RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN;
+	adapter->ports[p_id] = port;
+	rte_eth_dev_probing_finish(dev);
 
 	return 0;
 }
@@ -211,9 +310,116 @@ static int32_t rnp_reset_hw_pf(struct rnp_hw *hw)
 	return 0;
 }
 
+static void
+rnp_mac_res_take_in(struct rnp_eth_port *port,
+		    uint8_t index)
+{
+	if (!port->mac_use_tb[index]) {
+		port->mac_use_tb[index] = true;
+		port->use_num_mac++;
+	}
+}
+
+static void
+rnp_mac_res_remove(struct rnp_eth_port *port,
+		   uint8_t index)
+{
+	if (port->mac_use_tb[index]) {
+		port->mac_use_tb[index] = false;
+		port->use_num_mac--;
+	}
+}
+
+static int32_t rnp_set_mac_addr_pf(struct rnp_eth_port *port,
+				   uint8_t *mac, uint8_t vm_pool,
+				   uint8_t index)
+{
+	struct rnp_hw *hw = RNP_PORT_TO_HW(port);
+	struct rnp_port_attr *attr = &port->attr;
+	uint8_t hw_idx;
+	uint32_t value;
+
+	if (port->use_num_mac > port->attr.max_mac_addrs ||
+			index > port->attr.max_mac_addrs)
+		return -ENOMEM;
+
+	if (vm_pool != UINT8_MAX)
+		hw_idx = (attr->nr_port * attr->max_mac_addrs) + vm_pool + index;
+	else
+		hw_idx = (attr->nr_port * attr->max_mac_addrs) + index;
+
+	rnp_mac_res_take_in(port, hw_idx);
+
+	value = (mac[0] << 8) | mac[1];
+	value |= RNP_MAC_FILTER_EN;
+	RNP_MACADDR_UPDATE_HI(hw, hw_idx, value);
+
+	value = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
+	RNP_MACADDR_UPDATE_LO(hw, hw_idx, value);
+
+	return 0;
+}
+
+static void
+rnp_remove_mac_from_hw(struct rnp_eth_port *port,
+		       uint8_t vm_pool, uint8_t index)
+{
+	struct rnp_hw *hw = RNP_PORT_TO_HW(port);
+	struct rnp_port_attr *attr = &port->attr;
+	uint16_t hw_idx;
+
+	if (vm_pool != UINT8_MAX)
+		hw_idx = (attr->nr_port * attr->max_mac_addrs) + vm_pool + index;
+	else
+		hw_idx = (attr->nr_port * attr->max_mac_addrs) + index;
+
+	rnp_mac_res_remove(port, hw_idx);
+
+	rnp_eth_wr(hw, RNP_RAL_BASE_ADDR(hw_idx), 0);
+	rnp_eth_wr(hw, RNP_RAH_BASE_ADDR(hw_idx), 0);
+}
+
+static int32_t
+rnp_clear_mac_addr_pf(struct rnp_eth_port *port,
+		      uint8_t vm_pool, uint8_t index)
+{
+	rnp_remove_mac_from_hw(port, vm_pool, index);
+
+	return 0;
+}
+
+static int32_t rnp_get_mac_addr_pf(struct rnp_eth_port *port,
+				   uint8_t lane,
+				   uint8_t *macaddr)
+{
+	struct rnp_hw *hw = RNP_DEV_TO_HW(port->eth_dev);
+
+	return rnp_fw_get_macaddr(port->eth_dev, hw->pf_vf_num, macaddr, lane);
+}
+
+static int32_t
+rnp_set_default_mac_pf(struct rnp_eth_port *port,
+		       uint8_t *mac)
+{
+	struct rnp_eth_adapter *adap = RNP_PORT_TO_ADAPTER(port);
+	uint16_t max_vfs;
+
+	if (port->s_mode == RNP_SHARE_INDEPEND)
+		return rnp_set_rafb(port->eth_dev, (uint8_t *)mac,
+				UINT8_MAX, 0);
+
+	max_vfs = adap->max_vfs;
+
+	return rnp_set_rafb(port->eth_dev, mac, max_vfs, 0);
+}
+
 const struct rnp_mac_api rnp_mac_ops = {
 	.reset_hw	= rnp_reset_hw_pf,
-	.init_hw	= rnp_init_hw_pf
+	.init_hw	= rnp_init_hw_pf,
+	.get_mac_addr	= rnp_get_mac_addr_pf,
+	.set_default_mac = rnp_set_default_mac_pf,
+	.set_rafb	= rnp_set_mac_addr_pf,
+	.clear_rafb	= rnp_clear_mac_addr_pf
 };
 
 static void
@@ -228,7 +434,11 @@ rnp_common_ops_init(struct rnp_eth_adapter *adapter)
 static int
 rnp_special_ops_init(struct rte_eth_dev *eth_dev)
 {
-	RTE_SET_USED(eth_dev);
+	struct rnp_eth_adapter *adapter = RNP_DEV_TO_ADAPTER(eth_dev);
+	struct rnp_share_ops *share_priv;
+
+	share_priv = adapter->share_priv;
+	share_priv->mac_api = &rnp_mac_ops;
 
 	return 0;
 }
@@ -237,9 +447,9 @@ static int
 rnp_eth_dev_init(struct rte_eth_dev *dev)
 {
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
 	struct rnp_eth_adapter *adapter = NULL;
 	char name[RTE_ETH_NAME_MAX_LEN] = " ";
-	struct rnp_eth_port *port = NULL;
 	struct rte_eth_dev *eth_dev;
 	struct rnp_hw *hw = NULL;
 	int32_t p_id;
@@ -275,13 +485,13 @@ rnp_eth_dev_init(struct rte_eth_dev *dev)
 		return ret;
 	}
 	adapter->share_priv = dev->process_private;
+	port->adapt = adapter;
 	rnp_common_ops_init(adapter);
+	rnp_init_mbx_ops_pf(hw);
 	rnp_get_nic_attr(adapter);
 	/* We need Use Device Id To Change The Resource Mode */
 	rnp_special_ops_init(dev);
-	port->adapt = adapter;
 	port->hw = hw;
-	rnp_init_mbx_ops_pf(hw);
 	for (p_id = 0; p_id < adapter->num_ports; p_id++) {
 		/* port 0 resource has been alloced When Probe */
 		if (!p_id) {
diff --git a/drivers/net/rnp/rnp_mbx_fw.c b/drivers/net/rnp/rnp_mbx_fw.c
index b7c986db12..aea4f1d619 100644
--- a/drivers/net/rnp/rnp_mbx_fw.c
+++ b/drivers/net/rnp/rnp_mbx_fw.c
@@ -270,3 +270,115 @@ int rnp_mbx_fw_reset_phy(struct rte_eth_dev *dev)
 
 	return rnp_fw_send_cmd_wait(dev, &req, &reply);
 }
+
+int
+rnp_fw_get_macaddr(struct rte_eth_dev *dev,
+		   int pfvfnum,
+		   u8 *mac_addr,
+		   int nr_lane)
+{
+	struct rnp_hw *hw = RNP_DEV_TO_HW(dev);
+	struct mbx_req_cookie *cookie;
+	struct mbx_fw_cmd_reply reply;
+	struct mbx_fw_cmd_req req;
+	struct mac_addr *mac;
+	int err;
+
+	memset(&req, 0, sizeof(req));
+	memset(&reply, 0, sizeof(reply));
+
+	if (!mac_addr)
+		return -EINVAL;
+
+	if (hw->mbx.irq_enabled) {
+		cookie = rnp_memzone_reserve(hw->cookie_p_name, 0);
+		if (!cookie)
+			return -ENOMEM;
+		memset(cookie->priv, 0, cookie->priv_len);
+		mac = (struct mac_addr *)cookie->priv;
+		build_get_macaddress_req(&req, 1 << nr_lane, pfvfnum, cookie);
+		err = rnp_mbx_fw_post_req(dev, &req, cookie);
+		if (err)
+			goto quit;
+
+		if ((1 << nr_lane) & mac->lanes) {
+			memcpy(mac_addr, mac->addrs[nr_lane].mac, 6);
+			err = 0;
+		} else {
+			err = -ENODATA;
+		}
+quit:
+		return err;
+	}
+	build_get_macaddress_req(&req, 1 << nr_lane, pfvfnum, &req);
+	err = rnp_fw_send_cmd_wait(dev, &req, &reply);
+	if (err) {
+		RNP_PMD_LOG(ERR, "%s: failed. err:%d\n", __func__, err);
+		return err;
+	}
+
+	if ((1 << nr_lane) & reply.mac_addr.lanes) {
+		memcpy(mac_addr, reply.mac_addr.addrs[nr_lane].mac, 6);
+		return 0;
+	}
+
+	return -ENODATA;
+}
+
+int rnp_mbx_get_lane_stat(struct rte_eth_dev *dev)
+{
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+	struct rnp_phy_meta *phy_meta = &port->attr.phy_meta;
+	struct rnp_hw *hw = RNP_DEV_TO_HW(dev);
+	struct lane_stat_data *lane_stat;
+	int nr_lane = port->attr.nr_lane;
+	struct mbx_req_cookie *cookie;
+	struct mbx_fw_cmd_reply reply;
+	struct mbx_fw_cmd_req req;
+	int err = 0;
+
+	memset(&req, 0, sizeof(req));
+
+	if (hw->mbx.irq_enabled) {
+		cookie = rnp_memzone_reserve(hw->cookie_p_name, 0);
+
+		if (!cookie)
+			return -ENOMEM;
+		memset(cookie->priv, 0, cookie->priv_len);
+		lane_stat = (struct lane_stat_data *)cookie->priv;
+		build_get_lane_status_req(&req, nr_lane, cookie);
+		err = rnp_mbx_fw_post_req(dev, &req, cookie);
+		if (err)
+			goto quit;
+	} else {
+		memset(&reply, 0, sizeof(reply));
+		build_get_lane_status_req(&req, nr_lane, &req);
+		err = rnp_fw_send_cmd_wait(dev, &req, &reply);
+		if (err)
+			goto quit;
+		lane_stat = (struct lane_stat_data *)reply.data;
+	}
+
+	phy_meta->supported_link = lane_stat->supported_link;
+	phy_meta->is_backplane = lane_stat->is_backplane;
+	phy_meta->phy_identifier = lane_stat->phy_addr;
+	phy_meta->link_autoneg = lane_stat->autoneg;
+	phy_meta->link_duplex = lane_stat->duplex;
+	phy_meta->phy_type = lane_stat->phy_type;
+	phy_meta->is_sgmii = lane_stat->is_sgmii;
+	phy_meta->fec = lane_stat->fec;
+
+	if (phy_meta->is_sgmii) {
+		phy_meta->media_type = RNP_MEDIA_TYPE_COPPER;
+		phy_meta->supported_link |=
+			RNP_SPEED_CAP_100M_HALF | RNP_SPEED_CAP_10M_HALF;
+	} else if (phy_meta->is_backplane) {
+		phy_meta->media_type = RNP_MEDIA_TYPE_BACKPLANE;
+	} else {
+		phy_meta->media_type = RNP_MEDIA_TYPE_FIBER;
+	}
+
+	return 0;
+quit:
+	return err;
+}
diff --git a/drivers/net/rnp/rnp_mbx_fw.h b/drivers/net/rnp/rnp_mbx_fw.h
index 44ffe56908..7bf5c2a865 100644
--- a/drivers/net/rnp/rnp_mbx_fw.h
+++ b/drivers/net/rnp/rnp_mbx_fw.h
@@ -19,7 +19,9 @@ struct mbx_req_cookie {
 enum GENERIC_CMD {
 	/* link configuration admin commands */
 	GET_PHY_ABALITY = 0x0601,
+	GET_MAC_ADDRES = 0x0602,
 	RESET_PHY = 0x0603,
+	GET_LANE_STATUS = 0x0610,
 	SET_EVENT_MASK = 0x0613,
 };
 
@@ -82,6 +84,61 @@ struct phy_abilities {
 	};
 } __rte_packed __rte_aligned(4);
 
+#define RNP_SPEED_CAP_UNKNOWN    (0)
+#define RNP_SPEED_CAP_10M_FULL   BIT(2)
+#define RNP_SPEED_CAP_100M_FULL  BIT(3)
+#define RNP_SPEED_CAP_1GB_FULL   BIT(4)
+#define RNP_SPEED_CAP_10GB_FULL  BIT(5)
+#define RNP_SPEED_CAP_40GB_FULL  BIT(6)
+#define RNP_SPEED_CAP_25GB_FULL  BIT(7)
+#define RNP_SPEED_CAP_50GB_FULL  BIT(8)
+#define RNP_SPEED_CAP_100GB_FULL BIT(9)
+#define RNP_SPEED_CAP_10M_HALF   BIT(10)
+#define RNP_SPEED_CAP_100M_HALF  BIT(11)
+#define RNP_SPEED_CAP_1GB_HALF   BIT(12)
+
+struct lane_stat_data {
+	u8 nr_lane;	     /* 0-3 cur port correspond with hw lane */
+	u8 pci_gen	: 4; /* nic cur pci speed genX: 1,2,3 */
+	u8 pci_lanes	: 4; /* nic cur pci x1 x2 x4 x8 x16 */
+	u8 pma_type;
+	u8 phy_type;         /* interface media type */
+
+	u16 linkup	: 1; /* cur port link state */
+	u16 duplex	: 1; /* duplex state only RJ45 valid */
+	u16 autoneg	: 1; /* autoneg state */
+	u16 fec		: 1; /* fec state */
+	u16 rev_an	: 1;
+	u16 link_traing    : 1; /* link-traing state */
+	u16 media_availble : 1;
+	u16 is_sgmii       : 1; /* 1: Twisted Pair 0: FIBRE */
+	u16 link_fault     : 4;
+#define LINK_LINK_FAULT   BIT(0)
+#define LINK_TX_FAULT     BIT(1)
+#define LINK_RX_FAULT     BIT(2)
+#define LINK_REMOTE_FAULT BIT(3)
+	u16 is_backplane : 1; /* 1: Backplane Mode */
+	union {
+		u8 phy_addr; /* Phy MDIO address */
+		struct {
+			u8 mod_abs : 1;
+			u8 fault   : 1;
+			u8 tx_dis  : 1;
+			u8 los     : 1;
+		} sfp;
+	};
+	u8 sfp_connector;
+	u32 speed; /* Current Speed Value */
+
+	u32 si_main;
+	u32 si_pre;
+	u32 si_post;
+	u32 si_tx_boost;
+	u32 supported_link; /* Cur nic Support Link cap */
+	u32 phy_id;
+	u32 advertised_link; /* autoneg mode advertised cap */
+} __rte_packed __rte_aligned(4);
+
 /* firmware -> driver */
 struct mbx_fw_cmd_reply {
 	/* fw must set: DD, CMP, Error(if error), copy value */
@@ -99,6 +156,19 @@ struct mbx_fw_cmd_reply {
 	};
 	/* ===== data ==== [16-64] */
 	union {
+		char data[0];
+
+		struct mac_addr {
+			int lanes;
+			struct _addr {
+				/* for macaddr:01:02:03:04:05:06
+				 *  mac-hi=0x01020304 mac-lo=0x05060000
+				 */
+				unsigned char mac[8];
+			} addrs[4];
+		} mac_addr;
+
+		struct lane_stat_data lanestat;
 		struct phy_abilities phy_abilities;
 	};
 } __rte_packed __rte_aligned(4);
@@ -128,10 +198,19 @@ struct mbx_fw_cmd_req {
 #define REQUEST_BY_PXE  0xa3
 		} get_phy_ablity;
 
+		struct {
+			int lane_mask;
+			int pfvf_num;
+		} get_mac_addr;
+
 		struct {
 			unsigned short enable_stat;
 			unsigned short event_mask; /* enum link_event_mask */
 		} stat_event_mask;
+
+		struct {
+			int nr_lane;
+		} get_lane_st;
 	};
 } __rte_packed __rte_aligned(4);
 
@@ -146,6 +225,23 @@ build_phy_abalities_req(struct mbx_fw_cmd_req *req, void *cookie)
 	req->cookie = cookie;
 }
 
+static inline void
+build_get_macaddress_req(struct mbx_fw_cmd_req *req,
+			 int lane_mask,
+			 int pfvfnum,
+			 void *cookie)
+{
+	req->flags = 0;
+	req->opcode = GET_MAC_ADDRES;
+	req->datalen = sizeof(req->get_mac_addr);
+	req->cookie = cookie;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+
+	req->get_mac_addr.lane_mask = lane_mask;
+	req->get_mac_addr.pfvf_num = pfvfnum;
+}
+
 /* enum link_event_mask or */
 static inline void
 build_link_set_event_mask(struct mbx_fw_cmd_req *req,
@@ -175,9 +271,28 @@ build_reset_phy_req(struct mbx_fw_cmd_req *req,
 	req->cookie = cookie;
 }
 
+static inline void
+build_get_lane_status_req(struct mbx_fw_cmd_req *req,
+			  int nr_lane, void *cookie)
+{
+	req->flags = 0;
+	req->opcode = GET_LANE_STATUS;
+	req->datalen = sizeof(req->get_lane_st);
+	req->cookie = cookie;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->get_lane_st.nr_lane = nr_lane;
+}
+
 int rnp_mbx_get_capability(struct rte_eth_dev *dev,
 			   int *lane_mask,
 			   int *nic_mode);
 int rnp_mbx_link_event_enable(struct rte_eth_dev *dev, int enable);
 int rnp_mbx_fw_reset_phy(struct rte_eth_dev *dev);
+int
+rnp_fw_get_macaddr(struct rte_eth_dev *dev,
+		   int pfvfnum,
+		   u8 *mac_addr,
+		   int nr_lane);
+int rnp_mbx_get_lane_stat(struct rte_eth_dev *dev);
 #endif /* __RNP_MBX_FW_H__*/
diff --git a/drivers/net/rnp/rnp_rxtx.c b/drivers/net/rnp/rnp_rxtx.c
new file mode 100644
index 0000000000..679c0649a7
--- /dev/null
+++ b/drivers/net/rnp/rnp_rxtx.c
@@ -0,0 +1,83 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <rte_version.h>
+#include <rte_ether.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memzone.h>
+#include <rte_vxlan.h>
+#include <rte_gre.h>
+#ifdef RTE_ARCH_ARM64
+#include <rte_cpuflags_64.h>
+#elif defined(RTE_ARCH_ARM)
+#include <rte_cpuflags_32.h>
+#endif
+
+#include "base/rnp_hw.h"
+#include "rnp.h"
+#include "rnp_rxtx.h"
+#include "rnp_logs.h"
+
+int
+rnp_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+	RTE_SET_USED(rx_queue);
+	RTE_SET_USED(offset);
+
+	return 0;
+}
+
+int
+rnp_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+	RTE_SET_USED(tx_queue);
+	RTE_SET_USED(offset);
+
+	return 0;
+}
+
+uint32_t
+rnp_dev_rx_queue_count(void *rx_queue)
+{
+	RTE_SET_USED(rx_queue);
+
+	return 0;
+}
+
+__rte_always_inline uint16_t
+rnp_recv_pkts(void *_rxq,
+	      struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	RTE_SET_USED(_rxq);
+	RTE_SET_USED(rx_pkts);
+	RTE_SET_USED(nb_pkts);
+
+	return 0;
+}
+
+__rte_always_inline uint16_t
+rnp_xmit_pkts(void *_txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	RTE_SET_USED(_txq);
+	RTE_SET_USED(tx_pkts);
+	RTE_SET_USED(nb_pkts);
+
+	return 0;
+}
+
+uint16_t rnp_prep_pkts(void *tx_queue,
+		       struct rte_mbuf **tx_pkts,
+		       uint16_t nb_pkts)
+{
+	RTE_SET_USED(tx_queue);
+	RTE_SET_USED(tx_pkts);
+	RTE_SET_USED(nb_pkts);
+
+	return 0;
+}
diff --git a/drivers/net/rnp/rnp_rxtx.h b/drivers/net/rnp/rnp_rxtx.h
new file mode 100644
index 0000000000..0352971fcb
--- /dev/null
+++ b/drivers/net/rnp/rnp_rxtx.h
@@ -0,0 +1,14 @@
+#ifndef __RNP_RXTX_H__
+#define __RNP_RXTX_H__
+
+uint32_t rnp_dev_rx_queue_count(void *rx_queue);
+int rnp_dev_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int rnp_dev_tx_descriptor_status(void *tx_queue, uint16_t offset);
+uint16_t
+rnp_recv_pkts(void *_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+uint16_t
+rnp_xmit_pkts(void *_txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t rnp_prep_pkts(void *tx_queue,
+		struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts);
+#endif /* __RNP_RXTX_H__ */
