provided mac set/add/remove ops.

Signed-off-by: Junlong Wang <wang.junlong1@zte.com.cn>
---
 doc/guides/nics/features/zxdh.ini  |   2 +
 doc/guides/nics/zxdh.rst           |   2 +
 drivers/net/zxdh/zxdh_common.c     |  24 +++
 drivers/net/zxdh/zxdh_common.h     |   1 +
 drivers/net/zxdh/zxdh_ethdev.c     |  32 +++-
 drivers/net/zxdh/zxdh_ethdev.h     |   3 +
 drivers/net/zxdh/zxdh_ethdev_ops.c | 233 +++++++++++++++++++++++++++++
 drivers/net/zxdh/zxdh_ethdev_ops.h |   4 +
 drivers/net/zxdh/zxdh_msg.h        |  12 ++
 drivers/net/zxdh/zxdh_np.h         |   5 +
 drivers/net/zxdh/zxdh_tables.c     | 197 ++++++++++++++++++++++++
 drivers/net/zxdh/zxdh_tables.h     |  36 +++++
 12 files changed, 549 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/zxdh.ini b/doc/guides/nics/features/zxdh.ini
index 7da3aaced1..dc09fe3453 100644
--- a/doc/guides/nics/features/zxdh.ini
+++ b/doc/guides/nics/features/zxdh.ini
@@ -12,3 +12,5 @@ Multiprocess aware   = Y
 Scattered Rx         = Y
 Link status          = Y
 Link status event    = Y
+Unicast MAC filter   = Y
+Multicast MAC filter = Y
diff --git a/doc/guides/nics/zxdh.rst b/doc/guides/nics/zxdh.rst
index fdbc3b3923..e0b0776aca 100644
--- a/doc/guides/nics/zxdh.rst
+++ b/doc/guides/nics/zxdh.rst
@@ -24,6 +24,8 @@ Features of the ZXDH PMD are:
 - Link Auto-negotiation
 - Link state information
 - Set Link down or up
+- Unicast MAC filter
+- Multicast MAC filter
 
 
 Driver compilation and testing
diff --git a/drivers/net/zxdh/zxdh_common.c b/drivers/net/zxdh/zxdh_common.c
index 4f18c97ed7..75883a8897 100644
--- a/drivers/net/zxdh/zxdh_common.c
+++ b/drivers/net/zxdh/zxdh_common.c
@@ -256,6 +256,30 @@ zxdh_panelid_get(struct rte_eth_dev *dev, uint8_t *panelid)
     return ret;
 }
 
+static int
+zxdh_get_res_hash_id(struct zxdh_res_para *in, uint8_t *hash_id)
+{
+    uint8_t reps = 0;
+    uint16_t reps_len = 0;
+
+    if (zxdh_get_res_info(in, ZXDH_TBL_FIELD_HASHID, &reps, &reps_len) != ZXDH_BAR_MSG_OK)
+        return -1;
+
+    *hash_id = reps;
+    return ZXDH_BAR_MSG_OK;
+}
+
+int32_t
+zxdh_hashidx_get(struct rte_eth_dev *dev, uint8_t *hash_idx)
+{
+    struct zxdh_res_para param;
+
+    zxdh_fill_res_para(dev, &param);
+    int32_t ret = zxdh_get_res_hash_id(&param, hash_idx);
+
+    return ret;
+}
+
 uint32_t
 zxdh_read_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg)
 {
diff --git a/drivers/net/zxdh/zxdh_common.h b/drivers/net/zxdh/zxdh_common.h
index 72c29e1522..826f1fb95d 100644
--- a/drivers/net/zxdh/zxdh_common.h
+++ b/drivers/net/zxdh/zxdh_common.h
@@ -22,6 +22,7 @@ struct zxdh_res_para {
 
 int32_t zxdh_phyport_get(struct rte_eth_dev *dev, uint8_t *phyport);
 int32_t zxdh_panelid_get(struct rte_eth_dev *dev, uint8_t *pannelid);
+int32_t zxdh_hashidx_get(struct rte_eth_dev *dev, uint8_t *hash_idx);
 uint32_t zxdh_read_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg);
 void zxdh_write_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg, uint32_t val);
 void zxdh_release_lock(struct zxdh_hw *hw);
diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c
index d3876ec9b3..85ada87cdc 100644
--- a/drivers/net/zxdh/zxdh_ethdev.c
+++ b/drivers/net/zxdh/zxdh_ethdev.c
@@ -979,6 +979,23 @@ zxdh_set_rxtx_funcs(struct rte_eth_dev *eth_dev)
     return 0;
 }
 
+static int
+zxdh_mac_config(struct rte_eth_dev *eth_dev)
+{
+    struct zxdh_hw *hw = eth_dev->data->dev_private;
+    int ret = 0;
+
+    if (hw->is_pf) {
+        ret = zxdh_set_mac_table(hw->vport.vport,
+                &eth_dev->data->mac_addrs[0], hw->hash_search_index);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "Failed to add mac: port 0x%x", hw->vport.vport);
+            return ret;
+        }
+    }
+    return ret;
+}
+
 static int
 zxdh_dev_start(struct rte_eth_dev *dev)
 {
@@ -1014,6 +1031,9 @@ zxdh_dev_start(struct rte_eth_dev *dev)
         zxdh_queue_notify(vq);
     }
     zxdh_dev_set_link_up(dev);
+    ret = zxdh_mac_config(hw->eth_dev);
+    if (ret)
+        PMD_DRV_LOG(ERR, " mac config failed");
 
     return 0;
 }
@@ -1032,6 +1052,9 @@ static const struct eth_dev_ops zxdh_eth_dev_ops = {
     .link_update             = zxdh_dev_link_update,
     .dev_set_link_up         = zxdh_dev_set_link_up,
     .dev_set_link_down         = zxdh_dev_set_link_down,
+    .mac_addr_add             = zxdh_dev_mac_addr_add,
+    .mac_addr_remove         = zxdh_dev_mac_addr_remove,
+    .mac_addr_set             = zxdh_dev_mac_addr_set,
 };
 
 static int32_t
@@ -1073,15 +1096,20 @@ zxdh_agent_comm(struct rte_eth_dev *eth_dev, struct zxdh_hw *hw)
         PMD_DRV_LOG(ERR, "Failed to get phyport");
         return -1;
     }
-    PMD_DRV_LOG(INFO, "Get phyport success: 0x%x", hw->phyport);
+    PMD_DRV_LOG(DEBUG, "Get phyport success: 0x%x", hw->phyport);
 
     hw->vfid = zxdh_vport_to_vfid(hw->vport);
 
+    if (zxdh_hashidx_get(eth_dev, &hw->hash_search_index) != 0) {
+        PMD_DRV_LOG(ERR, "Failed to get hash idx");
+        return -1;
+    }
+
     if (zxdh_panelid_get(eth_dev, &hw->panel_id) != 0) {
         PMD_DRV_LOG(ERR, "Failed to get panel_id");
         return -1;
     }
-    PMD_DRV_LOG(INFO, "Get panel id success: 0x%x", hw->panel_id);
+    PMD_DRV_LOG(DEBUG, "Get panel id success: 0x%x", hw->panel_id);
 
     return 0;
 }
diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h
index c0b719062c..5b95cb1c2a 100644
--- a/drivers/net/zxdh/zxdh_ethdev.h
+++ b/drivers/net/zxdh/zxdh_ethdev.h
@@ -80,6 +80,8 @@ struct zxdh_hw {
     uint16_t port_id;
     uint16_t vfid;
     uint16_t queue_num;
+    uint16_t mc_num;
+    uint16_t uc_num;
 
     uint8_t *isr;
     uint8_t weak_barriers;
@@ -92,6 +94,7 @@ struct zxdh_hw {
     uint8_t msg_chan_init;
     uint8_t phyport;
     uint8_t panel_id;
+    uint8_t hash_search_index;
     uint8_t has_tx_offload;
     uint8_t has_rx_offload;
     uint8_t admin_status;
diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.c b/drivers/net/zxdh/zxdh_ethdev_ops.c
index 5a0af98cc0..751f80e9b4 100644
--- a/drivers/net/zxdh/zxdh_ethdev_ops.c
+++ b/drivers/net/zxdh/zxdh_ethdev_ops.c
@@ -164,3 +164,236 @@ int zxdh_dev_set_link_down(struct rte_eth_dev *dev)
         PMD_DRV_LOG(ERR, "Set link down failed");
     return ret;
 }
+
+int zxdh_dev_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
+{
+    struct zxdh_hw *hw = (struct zxdh_hw *)dev->data->dev_private;
+    struct rte_ether_addr *old_addr = &dev->data->mac_addrs[0];
+    struct zxdh_msg_info msg_info = {0};
+    uint16_t ret = 0;
+
+    if (!rte_is_valid_assigned_ether_addr(addr)) {
+        PMD_DRV_LOG(ERR, "mac address is invalid!");
+        return -EINVAL;
+    }
+
+    if (hw->is_pf) {
+        ret = zxdh_del_mac_table(hw->vport.vport, old_addr, hw->hash_search_index);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "mac_addr_add failed, code:%d", ret);
+            return ret;
+        }
+        hw->uc_num--;
+
+        ret = zxdh_set_mac_table(hw->vport.vport, addr, hw->hash_search_index);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "mac_addr_add failed, code:%d", ret);
+            return ret;
+        }
+        hw->uc_num++;
+    } else {
+        struct zxdh_mac_filter *mac_filter = &msg_info.data.mac_filter_msg;
+
+        mac_filter->filter_flag = ZXDH_MAC_UNFILTER;
+        mac_filter->mac_flag = true;
+        rte_memcpy(&mac_filter->mac, old_addr, sizeof(struct rte_ether_addr));
+        zxdh_msg_head_build(hw, ZXDH_MAC_DEL, &msg_info);
+        ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(msg_info), NULL, 0);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d ",
+                hw->vport.vport, ZXDH_MAC_DEL);
+            return ret;
+        }
+        hw->uc_num--;
+        PMD_DRV_LOG(INFO, "Success to send msg: port 0x%x msg type %d",
+            hw->vport.vport, ZXDH_MAC_DEL);
+
+        mac_filter->filter_flag = ZXDH_MAC_UNFILTER;
+        rte_memcpy(&mac_filter->mac, addr, sizeof(struct rte_ether_addr));
+        zxdh_msg_head_build(hw, ZXDH_MAC_ADD, &msg_info);
+        ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(msg_info), NULL, 0);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d ",
+                hw->vport.vport, ZXDH_MAC_ADD);
+            return ret;
+        }
+        hw->uc_num++;
+    }
+    rte_ether_addr_copy(addr, (struct rte_ether_addr *)hw->mac_addr);
+    return ret;
+}
+
+int zxdh_dev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+    uint32_t index, uint32_t vmdq __rte_unused)
+{
+    struct zxdh_hw *hw = dev->data->dev_private;
+    struct zxdh_msg_info msg_info = {0};
+    uint16_t i, ret;
+
+    if (index >= ZXDH_MAX_MAC_ADDRS) {
+        PMD_DRV_LOG(ERR, "Add mac index (%u) is out of range", index);
+        return -EINVAL;
+    }
+
+    for (i = 0; (i != ZXDH_MAX_MAC_ADDRS); ++i) {
+        if (memcmp(&dev->data->mac_addrs[i], mac_addr, sizeof(*mac_addr)))
+            continue;
+
+        PMD_DRV_LOG(INFO, "MAC address already configured");
+        return -EADDRINUSE;
+    }
+
+    if (hw->is_pf) {
+        if (rte_is_unicast_ether_addr(mac_addr)) {
+            if (hw->uc_num < ZXDH_MAX_UC_MAC_ADDRS) {
+                ret = zxdh_set_mac_table(hw->vport.vport,
+                            mac_addr, hw->hash_search_index);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "mac_addr_add failed, code:%d", ret);
+                    return ret;
+                }
+                hw->uc_num++;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return -EINVAL;
+            }
+        } else {
+            if (hw->mc_num < ZXDH_MAX_MC_MAC_ADDRS) {
+                ret = zxdh_set_mac_table(hw->vport.vport,
+                            mac_addr, hw->hash_search_index);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "mac_addr_add  failed, code:%d", ret);
+                    return ret;
+                }
+                hw->mc_num++;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return -EINVAL;
+            }
+        }
+    } else {
+        struct zxdh_mac_filter *mac_filter = &msg_info.data.mac_filter_msg;
+
+        mac_filter->filter_flag = ZXDH_MAC_FILTER;
+        rte_memcpy(&mac_filter->mac, mac_addr, sizeof(struct rte_ether_addr));
+        zxdh_msg_head_build(hw, ZXDH_MAC_ADD, &msg_info);
+        if (rte_is_unicast_ether_addr(mac_addr)) {
+            if (hw->uc_num < ZXDH_MAX_UC_MAC_ADDRS) {
+                ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
+                            sizeof(msg_info), NULL, 0);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
+                            hw->vport.vport, ZXDH_MAC_ADD);
+                    return ret;
+                }
+                hw->uc_num++;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return -EINVAL;
+            }
+        } else {
+            if (hw->mc_num < ZXDH_MAX_MC_MAC_ADDRS) {
+                ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
+                            sizeof(msg_info), NULL, 0);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
+                            hw->vport.vport, ZXDH_MAC_ADD);
+                    return ret;
+                }
+                hw->mc_num++;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return -EINVAL;
+            }
+        }
+    }
+    dev->data->mac_addrs[index] = *mac_addr;
+    return 0;
+}
+/**
+ * Fun:
+ */
+void zxdh_dev_mac_addr_remove(struct rte_eth_dev *dev __rte_unused, uint32_t index __rte_unused)
+{
+    struct zxdh_hw *hw    = dev->data->dev_private;
+    struct zxdh_msg_info msg_info = {0};
+    struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[index];
+    uint16_t ret = 0;
+
+    if (index >= ZXDH_MAX_MAC_ADDRS)
+        return;
+
+    if (hw->is_pf) {
+        if (rte_is_unicast_ether_addr(mac_addr)) {
+            if (hw->uc_num <= ZXDH_MAX_UC_MAC_ADDRS) {
+                ret = zxdh_del_mac_table(hw->vport.vport,
+                        mac_addr, hw->hash_search_index);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "mac_addr_del  failed, code:%d", ret);
+                    return;
+                }
+                hw->uc_num--;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return;
+            }
+        } else {
+            if (hw->mc_num <= ZXDH_MAX_MC_MAC_ADDRS) {
+                ret = zxdh_del_mac_table(hw->vport.vport,
+                            mac_addr, hw->hash_search_index);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "mac_addr_del  failed, code:%d", ret);
+                    return;
+                }
+                hw->mc_num--;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return;
+            }
+        }
+    } else {
+        struct zxdh_mac_filter *mac_filter = &msg_info.data.mac_filter_msg;
+
+        mac_filter->filter_flag = ZXDH_MAC_FILTER;
+        rte_memcpy(&mac_filter->mac, mac_addr, sizeof(struct rte_ether_addr));
+        zxdh_msg_head_build(hw, ZXDH_MAC_DEL, &msg_info);
+        if (rte_is_unicast_ether_addr(mac_addr)) {
+            if (hw->uc_num <= ZXDH_MAX_UC_MAC_ADDRS) {
+                ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
+                            sizeof(msg_info), NULL, 0);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
+                            hw->vport.vport, ZXDH_MAC_DEL);
+                    return;
+                }
+                hw->uc_num--;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return;
+            }
+        } else {
+            if (hw->mc_num <= ZXDH_MAX_MC_MAC_ADDRS) {
+                ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
+                            sizeof(msg_info), NULL, 0);
+                if (ret) {
+                    PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
+                            hw->vport.vport, ZXDH_MAC_DEL);
+                    return;
+                }
+                hw->mc_num--;
+            } else {
+                PMD_DRV_LOG(ERR, "MC_MAC is out of range, MAX_MC_MAC:%d",
+                        ZXDH_MAX_MC_MAC_ADDRS);
+                return;
+            }
+        }
+    }
+    memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr));
+}
diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.h b/drivers/net/zxdh/zxdh_ethdev_ops.h
index c6d6ca56fd..4630bb70db 100644
--- a/drivers/net/zxdh/zxdh_ethdev_ops.h
+++ b/drivers/net/zxdh/zxdh_ethdev_ops.h
@@ -10,5 +10,9 @@
 int zxdh_dev_set_link_up(struct rte_eth_dev *dev);
 int zxdh_dev_set_link_down(struct rte_eth_dev *dev);
 int32_t zxdh_dev_link_update(struct rte_eth_dev *dev, int32_t wait_to_complete __rte_unused);
+int zxdh_dev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+        uint32_t index, uint32_t vmdq);
+int zxdh_dev_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr);
+void zxdh_dev_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index);
 
 #endif /* ZXDH_ETHDEV_OPS_H */
diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h
index a78075c914..44ce5d1b7f 100644
--- a/drivers/net/zxdh/zxdh_msg.h
+++ b/drivers/net/zxdh/zxdh_msg.h
@@ -46,6 +46,9 @@
 #define ZXDH_MSG_REQ_BODY_MAX_LEN  \
         (ZXDH_MSG_PAYLOAD_MAX_LEN - ZXDH_MSG_HEAD_LEN)
 
+#define ZXDH_MAC_FILTER            0xaa
+#define ZXDH_MAC_UNFILTER          0xff
+
 enum ZXDH_DRIVER_TYPE {
     ZXDH_MSG_CHAN_END_MPF = 0,
     ZXDH_MSG_CHAN_END_PF,
@@ -173,6 +176,8 @@ enum zxdh_msg_type {
     ZXDH_NULL = 0,
     ZXDH_VF_PORT_INIT = 1,
     ZXDH_VF_PORT_UNINIT = 2,
+    ZXDH_MAC_ADD = 3,
+    ZXDH_MAC_DEL = 4,
 
     ZXDH_PORT_ATTRS_SET = 25,
 
@@ -314,6 +319,12 @@ struct zxdh_port_attr_set_msg {
     uint8_t allmulti_follow;
 } __rte_packed;
 
+struct zxdh_mac_filter {
+    uint8_t mac_flag;
+    uint8_t filter_flag;
+    struct rte_ether_addr mac;
+} __rte_packed;
+
 struct zxdh_msg_head {
     enum zxdh_msg_type msg_type;
     uint16_t  vport;
@@ -341,6 +352,7 @@ struct zxdh_msg_info {
         struct zxdh_vf_init_msg vf_init_msg;
         struct zxdh_port_attr_set_msg port_attr_msg;
         struct zxdh_link_info_msg link_msg;
+        struct zxdh_mac_filter mac_filter_msg;
     } __rte_packed data;
 } __rte_packed;
 
diff --git a/drivers/net/zxdh/zxdh_np.h b/drivers/net/zxdh/zxdh_np.h
index ac3931ba65..19d1f03f59 100644
--- a/drivers/net/zxdh/zxdh_np.h
+++ b/drivers/net/zxdh/zxdh_np.h
@@ -532,6 +532,11 @@ typedef struct zxdh_sdt_tbl_porttbl_t {
     uint32_t porttbl_clutch_en;
 } ZXDH_SDTTBL_PORTTBL_T;
 
+typedef struct zxdh_dtb_hash_entry_info_t {
+    uint8_t *p_actu_key;
+    uint8_t *p_rst;
+} ZXDH_DTB_HASH_ENTRY_INFO_T;
+
 int zxdh_np_host_init(uint32_t dev_id, ZXDH_DEV_INIT_CTRL_T *p_dev_init_ctrl);
 int zxdh_np_online_uninit(uint32_t dev_id, char *port_name, uint32_t queue_id);
 int zxdh_np_dtb_table_entry_write(uint32_t dev_id, uint32_t queue_id,
diff --git a/drivers/net/zxdh/zxdh_tables.c b/drivers/net/zxdh/zxdh_tables.c
index db0132ce3f..f5b607584d 100644
--- a/drivers/net/zxdh/zxdh_tables.c
+++ b/drivers/net/zxdh/zxdh_tables.c
@@ -11,6 +11,10 @@
 #define ZXDH_SDT_VPORT_ATT_TABLE          1
 #define ZXDH_SDT_PANEL_ATT_TABLE          2
 
+#define ZXDH_MAC_HASH_INDEX_BASE          64
+#define ZXDH_MAC_HASH_INDEX(index)        (ZXDH_MAC_HASH_INDEX_BASE + (index))
+#define ZXDH_MC_GROUP_NUM                 4
+
 int
 zxdh_set_port_attr(uint16_t vfid, struct zxdh_port_attr_table *port_attr)
 {
@@ -149,3 +153,196 @@ zxdh_get_port_attr(uint16_t vfid, struct zxdh_port_attr_table *port_attr)
 
     return ret;
 }
+
+int
+zxdh_set_mac_table(uint16_t vport, struct rte_ether_addr *addr,  uint8_t hash_search_idx)
+{
+    struct zxdh_mac_unicast_table unicast_table = {0};
+    struct zxdh_mac_multicast_table multicast_table = {0};
+    union zxdh_virport_num vport_num = (union zxdh_virport_num)vport;
+    uint32_t ret;
+    uint16_t group_id = 0;
+
+    if (rte_is_unicast_ether_addr(addr)) {
+        rte_memcpy(unicast_table.key.dmac_addr, addr, sizeof(struct rte_ether_addr));
+        unicast_table.entry.hit_flag = 0;
+        unicast_table.entry.vfid = vport_num.vfid;
+
+        ZXDH_DTB_HASH_ENTRY_INFO_T dtb_hash_entry = {
+            .p_actu_key = (uint8_t *)&unicast_table.key,
+            .p_rst = (uint8_t *)&unicast_table.entry
+        };
+        ZXDH_DTB_USER_ENTRY_T entry_get = {
+            .sdt_no = ZXDH_MAC_HASH_INDEX(hash_search_idx),
+            .p_entry_data = (void *)&dtb_hash_entry
+        };
+
+        ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO,
+                    g_dtb_data.queueid, 1, &entry_get);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "Insert mac_table failed");
+            return -ret;
+        }
+    } else {
+        for (group_id = 0; group_id < 4; group_id++) {
+            multicast_table.key.vf_group_id = group_id;
+            rte_memcpy(multicast_table.key.mac_addr,
+                    addr, sizeof(struct rte_ether_addr));
+            ZXDH_DTB_HASH_ENTRY_INFO_T dtb_hash_entry = {
+                .p_actu_key = (uint8_t *)&multicast_table.key,
+                .p_rst = (uint8_t *)&multicast_table.entry
+            };
+
+            ZXDH_DTB_USER_ENTRY_T entry_get = {
+                .sdt_no = ZXDH_MAC_HASH_INDEX(hash_search_idx),
+                .p_entry_data = (void *)&dtb_hash_entry
+            };
+
+            ret = zxdh_np_dtb_table_entry_get(ZXDH_DEVICE_NO, g_dtb_data.queueid,
+                    &entry_get, 1);
+            uint8_t index = (vport_num.vfid % 64) / 32;
+            if (ret == 0) {
+                if (vport_num.vf_flag) {
+                    if (group_id == vport_num.vfid / 64)
+                        multicast_table.entry.mc_bitmap[index] |=
+                            rte_cpu_to_be_32(UINT32_C(1) <<
+                            (31 - index));
+                } else {
+                    if (group_id == vport_num.vfid / 64)
+                        multicast_table.entry.mc_pf_enable =
+                            rte_cpu_to_be_32((1 << 30));
+                }
+            } else {
+                if (vport_num.vf_flag) {
+                    if (group_id == vport_num.vfid / 64)
+                        multicast_table.entry.mc_bitmap[index] |=
+                            rte_cpu_to_be_32(UINT32_C(1) <<
+                            (31 - index));
+                    else
+                        multicast_table.entry.mc_bitmap[index] =
+                            false;
+                } else {
+                    if (group_id == vport_num.vfid / 64)
+                        multicast_table.entry.mc_pf_enable =
+                            rte_cpu_to_be_32((1 << 30));
+                    else
+                        multicast_table.entry.mc_pf_enable = false;
+                }
+            }
+
+            ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO, g_dtb_data.queueid,
+                        1, &entry_get);
+            if (ret) {
+                PMD_DRV_LOG(ERR, "add mac_table failed, code:%d", ret);
+                return -ret;
+            }
+        }
+    }
+    return 0;
+}
+
+int
+zxdh_del_mac_table(uint16_t vport, struct rte_ether_addr *addr,  uint8_t hash_search_idx)
+{
+    struct zxdh_mac_unicast_table unicast_table = {0};
+    struct zxdh_mac_multicast_table multicast_table = {0};
+    union zxdh_virport_num vport_num = (union zxdh_virport_num)vport;
+    uint32_t ret, del_flag = 0;
+    uint16_t group_id = 0;
+
+    if (rte_is_unicast_ether_addr(addr)) {
+        rte_memcpy(unicast_table.key.dmac_addr, addr, sizeof(struct rte_ether_addr));
+        unicast_table.entry.hit_flag = 0;
+        unicast_table.entry.vfid = vport_num.vfid;
+
+        ZXDH_DTB_HASH_ENTRY_INFO_T dtb_hash_entry = {
+            .p_actu_key = (uint8_t *)&unicast_table.key,
+            .p_rst = (uint8_t *)&unicast_table.entry
+        };
+
+        ZXDH_DTB_USER_ENTRY_T entry_get = {
+            .sdt_no = ZXDH_MAC_HASH_INDEX(hash_search_idx),
+            .p_entry_data = (void *)&dtb_hash_entry
+        };
+
+        ret = zxdh_np_dtb_table_entry_delete(ZXDH_DEVICE_NO,
+                    g_dtb_data.queueid, 1, &entry_get);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "delete l2_fwd_hash_table failed, code:%d", ret);
+            return -ret;
+        }
+    } else {
+        multicast_table.key.vf_group_id = vport_num.vfid / 64;
+        rte_memcpy(multicast_table.key.mac_addr, addr, sizeof(struct rte_ether_addr));
+
+        ZXDH_DTB_HASH_ENTRY_INFO_T dtb_hash_entry = {
+            .p_actu_key = (uint8_t *)&multicast_table.key,
+            .p_rst = (uint8_t *)&multicast_table.entry
+        };
+
+        ZXDH_DTB_USER_ENTRY_T entry_get = {
+            .sdt_no = ZXDH_MAC_HASH_INDEX(hash_search_idx),
+            .p_entry_data = (void *)&dtb_hash_entry
+        };
+
+        ret = zxdh_np_dtb_table_entry_get(ZXDH_DEVICE_NO,
+                    g_dtb_data.queueid, &entry_get, 1);
+        uint8_t index = (vport_num.vfid % 64) / 32;
+        if (vport_num.vf_flag)
+            multicast_table.entry.mc_bitmap[index] &=
+                ~(rte_cpu_to_be_32(UINT32_C(1) << (31 - index)));
+        else
+            multicast_table.entry.mc_pf_enable = 0;
+
+        ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO,
+                    g_dtb_data.queueid, 1, &entry_get);
+        if (ret) {
+            PMD_DRV_LOG(ERR, "mac_addr_add mc_table failed, code:%d", ret);
+            return -ret;
+        }
+
+        for (group_id = 0; group_id < ZXDH_MC_GROUP_NUM; group_id++) {
+            multicast_table.key.vf_group_id = group_id;
+            rte_memcpy(multicast_table.key.mac_addr, addr,
+                sizeof(struct rte_ether_addr));
+            ZXDH_DTB_HASH_ENTRY_INFO_T dtb_hash_entry = {
+                .p_actu_key = (uint8_t *)&multicast_table.key,
+                .p_rst = (uint8_t *)&multicast_table.entry
+            };
+            ZXDH_DTB_USER_ENTRY_T entry_get = {
+                .sdt_no = ZXDH_MAC_HASH_INDEX(hash_search_idx),
+                .p_entry_data = (void *)&dtb_hash_entry
+            };
+
+            ret = zxdh_np_dtb_table_entry_get(ZXDH_DEVICE_NO, g_dtb_data.queueid,
+                        &entry_get, 1);
+            if (multicast_table.entry.mc_bitmap[0] == 0 &&
+                multicast_table.entry.mc_bitmap[1] == 0 &&
+                multicast_table.entry.mc_pf_enable == 0) {
+                if (group_id == (ZXDH_MC_GROUP_NUM - 1))
+                    del_flag = 1;
+            } else {
+                break;
+            }
+        }
+        if (del_flag) {
+            for (group_id = 0; group_id < ZXDH_MC_GROUP_NUM; group_id++) {
+                multicast_table.key.vf_group_id = group_id;
+                rte_memcpy(multicast_table.key.mac_addr, addr,
+                    sizeof(struct rte_ether_addr));
+                ZXDH_DTB_HASH_ENTRY_INFO_T dtb_hash_entry = {
+                    .p_actu_key  = (uint8_t *)&multicast_table.key,
+                    .p_rst = (uint8_t *)&multicast_table.entry
+                };
+                ZXDH_DTB_USER_ENTRY_T entry_get = {
+                    .sdt_no  = ZXDH_MAC_HASH_INDEX(hash_search_idx),
+                    .p_entry_data = (void *)&dtb_hash_entry
+                };
+
+                ret = zxdh_np_dtb_table_entry_delete(ZXDH_DEVICE_NO,
+                            g_dtb_data.queueid, 1, &entry_get);
+            }
+        }
+    }
+    return 0;
+}
diff --git a/drivers/net/zxdh/zxdh_tables.h b/drivers/net/zxdh/zxdh_tables.h
index 8676a8b375..f16c4923ef 100644
--- a/drivers/net/zxdh/zxdh_tables.h
+++ b/drivers/net/zxdh/zxdh_tables.h
@@ -142,10 +142,46 @@ struct zxdh_panel_table {
     uint32_t rsv_2;
 }; /* 16B */
 
+struct zxdh_mac_unicast_key {
+    uint16_t rsv;
+    uint8_t  dmac_addr[6];
+};
+
+struct zxdh_mac_unicast_entry {
+    uint8_t rsv1     : 7,
+            hit_flag : 1;
+    uint8_t rsv;
+    uint16_t vfid;
+};
+
+struct zxdh_mac_unicast_table {
+    struct zxdh_mac_unicast_key key;
+    struct zxdh_mac_unicast_entry entry;
+};
+
+struct zxdh_mac_multicast_key {
+    uint8_t rsv;
+    uint8_t vf_group_id;
+    uint8_t mac_addr[6];
+};
+
+struct zxdh_mac_multicast_entry {
+    uint32_t mc_pf_enable;
+    uint32_t rsv1;
+    uint32_t mc_bitmap[2];
+};
+
+struct zxdh_mac_multicast_table {
+    struct zxdh_mac_multicast_key key;
+    struct zxdh_mac_multicast_entry entry;
+};
+
 int zxdh_port_attr_init(struct rte_eth_dev *dev);
 int zxdh_panel_table_init(struct rte_eth_dev *dev);
 int zxdh_set_port_attr(uint16_t vfid, struct zxdh_port_attr_table *port_attr);
 int zxdh_port_attr_uninit(struct rte_eth_dev *dev);
 int zxdh_get_port_attr(uint16_t vfid, struct zxdh_port_attr_table *port_attr);
+int zxdh_set_mac_table(uint16_t vport, struct rte_ether_addr *addr,  uint8_t hash_search_idx);
+int zxdh_del_mac_table(uint16_t vport, struct rte_ether_addr *addr,  uint8_t hash_search_idx);
 
 #endif /* ZXDH_TABLES_H */
-- 
2.27.0