provided promiscuous/allmulticast ops. Signed-off-by: Junlong Wang --- doc/guides/nics/features/zxdh.ini | 2 + doc/guides/nics/zxdh.rst | 2 + drivers/net/zxdh/zxdh_ethdev.c | 21 ++- drivers/net/zxdh/zxdh_ethdev.h | 2 + drivers/net/zxdh/zxdh_ethdev_ops.c | 132 +++++++++++++++++ drivers/net/zxdh/zxdh_ethdev_ops.h | 4 + drivers/net/zxdh/zxdh_msg.h | 10 ++ drivers/net/zxdh/zxdh_tables.c | 223 +++++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_tables.h | 22 +++ 9 files changed, 417 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/features/zxdh.ini b/doc/guides/nics/features/zxdh.ini index dc09fe3453..e9b237e102 100644 --- a/doc/guides/nics/features/zxdh.ini +++ b/doc/guides/nics/features/zxdh.ini @@ -14,3 +14,5 @@ Link status = Y Link status event = Y Unicast MAC filter = Y Multicast MAC filter = Y +Promiscuous mode = Y +Allmulticast mode = Y diff --git a/doc/guides/nics/zxdh.rst b/doc/guides/nics/zxdh.rst index e0b0776aca..0399df1302 100644 --- a/doc/guides/nics/zxdh.rst +++ b/doc/guides/nics/zxdh.rst @@ -26,6 +26,8 @@ Features of the ZXDH PMD are: - Set Link down or up - Unicast MAC filter - Multicast MAC filter +- Promiscuous mode +- Multicast mode Driver compilation and testing diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 85ada87cdc..1d64b877c1 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -901,8 +901,16 @@ zxdh_tables_uninit(struct rte_eth_dev *dev) int ret; ret = zxdh_port_attr_uninit(dev); - if (ret) + if (ret) { PMD_DRV_LOG(ERR, "zxdh_port_attr_uninit failed"); + return ret; + } + + ret = zxdh_promisc_table_uninit(dev); + if (ret) { + PMD_DRV_LOG(ERR, "uninit promisc_table failed"); + return ret; + } return ret; } @@ -1055,6 +1063,10 @@ static const struct eth_dev_ops zxdh_eth_dev_ops = { .mac_addr_add = zxdh_dev_mac_addr_add, .mac_addr_remove = zxdh_dev_mac_addr_remove, .mac_addr_set = zxdh_dev_mac_addr_set, + .promiscuous_enable = zxdh_dev_promiscuous_enable, + .promiscuous_disable = zxdh_dev_promiscuous_disable, + .allmulticast_enable = zxdh_dev_allmulticast_enable, + .allmulticast_disable = zxdh_dev_allmulticast_disable, }; static int32_t @@ -1306,6 +1318,13 @@ zxdh_tables_init(struct rte_eth_dev *dev) PMD_DRV_LOG(ERR, " panel table init failed"); return ret; } + + ret = zxdh_promisc_table_init(dev); + if (ret) { + PMD_DRV_LOG(ERR, "promisc_table_init failed"); + return ret; + } + return ret; } diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 5b95cb1c2a..3cdac5de73 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -98,6 +98,8 @@ struct zxdh_hw { uint8_t has_tx_offload; uint8_t has_rx_offload; uint8_t admin_status; + uint8_t promisc_status; + uint8_t allmulti_status; }; struct zxdh_dtb_shared_data { diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.c b/drivers/net/zxdh/zxdh_ethdev_ops.c index 751f80e9b4..aed4e6410c 100644 --- a/drivers/net/zxdh/zxdh_ethdev_ops.c +++ b/drivers/net/zxdh/zxdh_ethdev_ops.c @@ -397,3 +397,135 @@ void zxdh_dev_mac_addr_remove(struct rte_eth_dev *dev __rte_unused, uint32_t ind } memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); } + +int zxdh_dev_promiscuous_enable(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + struct zxdh_msg_info msg_info = {0}; + int16_t ret = 0; + + if (hw->promisc_status == 0) { + if (hw->is_pf) { + ret = zxdh_dev_unicast_table_set(hw, hw->vport.vport, true); + if (hw->allmulti_status == 0) + ret = zxdh_dev_multicast_table_set(hw, hw->vport.vport, true); + + } else { + struct zxdh_port_promisc_msg *promisc_msg = &msg_info.data.port_promisc_msg; + + zxdh_msg_head_build(hw, ZXDH_PORT_PROMISC_SET, &msg_info); + promisc_msg->mode = ZXDH_PROMISC_MODE; + promisc_msg->value = true; + if (hw->allmulti_status == 0) + promisc_msg->mc_follow = true; + + 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_PROMISC_MODE); + return ret; + } + } + hw->promisc_status = 1; + } + return ret; +} +/** + * Fun: + */ +int zxdh_dev_promiscuous_disable(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + int16_t ret = 0; + struct zxdh_msg_info msg_info = {0}; + + if (hw->promisc_status == 1) { + if (hw->is_pf) { + ret = zxdh_dev_unicast_table_set(hw, hw->vport.vport, false); + if (hw->allmulti_status == 0) + ret = zxdh_dev_multicast_table_set(hw, hw->vport.vport, false); + + } else { + struct zxdh_port_promisc_msg *promisc_msg = &msg_info.data.port_promisc_msg; + + zxdh_msg_head_build(hw, ZXDH_PORT_PROMISC_SET, &msg_info); + promisc_msg->mode = ZXDH_PROMISC_MODE; + promisc_msg->value = false; + if (hw->allmulti_status == 0) + promisc_msg->mc_follow = true; + + 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_PROMISC_MODE); + return ret; + } + } + hw->promisc_status = 0; + } + return ret; +} +/** + * Fun: + */ +int zxdh_dev_allmulticast_enable(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + int16_t ret = 0; + struct zxdh_msg_info msg_info = {0}; + + if (hw->allmulti_status == 0) { + if (hw->is_pf) { + ret = zxdh_dev_multicast_table_set(hw, hw->vport.vport, true); + } else { + struct zxdh_port_promisc_msg *promisc_msg = &msg_info.data.port_promisc_msg; + + zxdh_msg_head_build(hw, ZXDH_PORT_PROMISC_SET, &msg_info); + + promisc_msg->mode = ZXDH_ALLMULTI_MODE; + promisc_msg->value = true; + 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_ALLMULTI_MODE); + return ret; + } + } + hw->allmulti_status = 1; + } + return ret; +} + +int zxdh_dev_allmulticast_disable(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + int16_t ret = 0; + struct zxdh_msg_info msg_info = {0}; + + if (hw->allmulti_status == 1) { + if (hw->is_pf) { + if (hw->promisc_status == 1) + goto end; + ret = zxdh_dev_multicast_table_set(hw, hw->vport.vport, false); + } else { + struct zxdh_port_promisc_msg *promisc_msg = &msg_info.data.port_promisc_msg; + + zxdh_msg_head_build(hw, ZXDH_PORT_PROMISC_SET, &msg_info); + if (hw->promisc_status == 1) + goto end; + promisc_msg->mode = ZXDH_ALLMULTI_MODE; + promisc_msg->value = false; + 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_ALLMULTI_MODE); + return ret; + } + } + hw->allmulti_status = 0; + } + return ret; +end: + hw->allmulti_status = 0; + return ret; +} diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.h b/drivers/net/zxdh/zxdh_ethdev_ops.h index 4630bb70db..394ddedc0e 100644 --- a/drivers/net/zxdh/zxdh_ethdev_ops.h +++ b/drivers/net/zxdh/zxdh_ethdev_ops.h @@ -14,5 +14,9 @@ int zxdh_dev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_ad 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); +int zxdh_dev_promiscuous_enable(struct rte_eth_dev *dev); +int zxdh_dev_promiscuous_disable(struct rte_eth_dev *dev); +int zxdh_dev_allmulticast_enable(struct rte_eth_dev *dev); +int zxdh_dev_allmulticast_disable(struct rte_eth_dev *dev); #endif /* ZXDH_ETHDEV_OPS_H */ diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h index 44ce5d1b7f..2abf579a80 100644 --- a/drivers/net/zxdh/zxdh_msg.h +++ b/drivers/net/zxdh/zxdh_msg.h @@ -48,6 +48,8 @@ #define ZXDH_MAC_FILTER 0xaa #define ZXDH_MAC_UNFILTER 0xff +#define ZXDH_PROMISC_MODE 1 +#define ZXDH_ALLMULTI_MODE 2 enum ZXDH_DRIVER_TYPE { ZXDH_MSG_CHAN_END_MPF = 0, @@ -180,6 +182,7 @@ enum zxdh_msg_type { ZXDH_MAC_DEL = 4, ZXDH_PORT_ATTRS_SET = 25, + ZXDH_PORT_PROMISC_SET = 26, ZXDH_MSG_TYPE_END, }; @@ -325,6 +328,12 @@ struct zxdh_mac_filter { struct rte_ether_addr mac; } __rte_packed; +struct zxdh_port_promisc_msg { + uint8_t mode; + uint8_t value; + uint8_t mc_follow; +} __rte_packed; + struct zxdh_msg_head { enum zxdh_msg_type msg_type; uint16_t vport; @@ -353,6 +362,7 @@ struct zxdh_msg_info { struct zxdh_port_attr_set_msg port_attr_msg; struct zxdh_link_info_msg link_msg; struct zxdh_mac_filter mac_filter_msg; + struct zxdh_port_promisc_msg port_promisc_msg; } __rte_packed data; } __rte_packed; diff --git a/drivers/net/zxdh/zxdh_tables.c b/drivers/net/zxdh/zxdh_tables.c index f5b607584d..45aeb3e3e4 100644 --- a/drivers/net/zxdh/zxdh_tables.c +++ b/drivers/net/zxdh/zxdh_tables.c @@ -10,10 +10,15 @@ #define ZXDH_SDT_VPORT_ATT_TABLE 1 #define ZXDH_SDT_PANEL_ATT_TABLE 2 +#define ZXDH_SDT_BROCAST_ATT_TABLE 6 +#define ZXDH_SDT_UNICAST_ATT_TABLE 10 +#define ZXDH_SDT_MULTICAST_ATT_TABLE 11 #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 +#define ZXDH_BASE_VFID 1152 +#define ZXDH_TABLE_HIT_FLAG 128 int zxdh_set_port_attr(uint16_t vfid, struct zxdh_port_attr_table *port_attr) @@ -346,3 +351,221 @@ zxdh_del_mac_table(uint16_t vport, struct rte_ether_addr *addr, uint8_t hash_se } return 0; } + +int +zxdh_promisc_table_init(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint32_t ret, vf_group_id = 0; + struct zxdh_brocast_table brocast_table = {0}; + struct zxdh_unitcast_table uc_table = {0}; + struct zxdh_multicast_table mc_table = {0}; + + if (!hw->is_pf) + return 0; + + for (; vf_group_id < 4; vf_group_id++) { + brocast_table.flag = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG); + ZXDH_DTB_ERAM_ENTRY_INFO_T eram_brocast_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vf_group_id, + .p_data = (uint32_t *)&brocast_table + }; + ZXDH_DTB_USER_ENTRY_T entry_brocast = { + .sdt_no = ZXDH_SDT_BROCAST_ATT_TABLE, + .p_entry_data = (void *)&eram_brocast_entry + }; + + ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO, + g_dtb_data.queueid, 1, &entry_brocast); + if (ret) { + PMD_DRV_LOG(ERR, "write brocast table failed"); + return ret; + } + + uc_table.uc_flood_pf_enable = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG); + ZXDH_DTB_ERAM_ENTRY_INFO_T eram_uc_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vf_group_id, + .p_data = (uint32_t *)&uc_table + }; + ZXDH_DTB_USER_ENTRY_T entry_unicast = { + .sdt_no = ZXDH_SDT_UNICAST_ATT_TABLE, + .p_entry_data = (void *)&eram_uc_entry + }; + + ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO, + g_dtb_data.queueid, 1, &entry_unicast); + if (ret) { + PMD_DRV_LOG(ERR, "write unicast table failed"); + return ret; + } + + mc_table.mc_flood_pf_enable = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG); + ZXDH_DTB_ERAM_ENTRY_INFO_T eram_mc_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vf_group_id, + .p_data = (uint32_t *)&mc_table + }; + ZXDH_DTB_USER_ENTRY_T entry_multicast = { + .sdt_no = ZXDH_SDT_MULTICAST_ATT_TABLE, + .p_entry_data = (void *)&eram_mc_entry + }; + + ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO, g_dtb_data.queueid, + 1, &entry_multicast); + if (ret) { + PMD_DRV_LOG(ERR, "write multicast table failed"); + return ret; + } + } + + return ret; +} + +int +zxdh_promisc_table_uninit(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint32_t ret, vf_group_id = 0; + struct zxdh_brocast_table brocast_table = {0}; + struct zxdh_unitcast_table uc_table = {0}; + struct zxdh_multicast_table mc_table = {0}; + + if (!hw->is_pf) + return 0; + + for (; vf_group_id < 4; vf_group_id++) { + brocast_table.flag = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG); + ZXDH_DTB_ERAM_ENTRY_INFO_T eram_brocast_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vf_group_id, + .p_data = (uint32_t *)&brocast_table + }; + ZXDH_DTB_USER_ENTRY_T entry_brocast = { + .sdt_no = ZXDH_SDT_BROCAST_ATT_TABLE, + .p_entry_data = (void *)&eram_brocast_entry + }; + + ret = zxdh_np_dtb_table_entry_delete(ZXDH_DEVICE_NO, + g_dtb_data.queueid, 1, &entry_brocast); + if (ret) { + PMD_DRV_LOG(ERR, "write brocast table failed"); + return ret; + } + + uc_table.uc_flood_pf_enable = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG); + ZXDH_DTB_ERAM_ENTRY_INFO_T eram_uc_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vf_group_id, + .p_data = (uint32_t *)&uc_table + }; + ZXDH_DTB_USER_ENTRY_T entry_unicast = { + .sdt_no = ZXDH_SDT_UNICAST_ATT_TABLE, + .p_entry_data = (void *)&eram_uc_entry + }; + + ret = zxdh_np_dtb_table_entry_delete(ZXDH_DEVICE_NO, + g_dtb_data.queueid, 1, &entry_unicast); + if (ret) { + PMD_DRV_LOG(ERR, "write unicast table failed"); + return ret; + } + + mc_table.mc_flood_pf_enable = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG); + ZXDH_DTB_ERAM_ENTRY_INFO_T eram_mc_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vf_group_id, + .p_data = (uint32_t *)&mc_table + }; + ZXDH_DTB_USER_ENTRY_T entry_multicast = { + .sdt_no = ZXDH_SDT_MULTICAST_ATT_TABLE, + .p_entry_data = (void *)&eram_mc_entry + }; + + ret = zxdh_np_dtb_table_entry_delete(ZXDH_DEVICE_NO, g_dtb_data.queueid, + 1, &entry_multicast); + if (ret) { + PMD_DRV_LOG(ERR, "write multicast table failed"); + return ret; + } + } + + return ret; +} + +int +zxdh_dev_unicast_table_set(struct zxdh_hw *hw, uint16_t vport, bool enable) +{ + int16_t ret = 0; + struct zxdh_unitcast_table uc_table = {0}; + union zxdh_virport_num vport_num = (union zxdh_virport_num)vport; + + ZXDH_DTB_ERAM_ENTRY_INFO_T uc_table_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vport_num.vfid / 64, + .p_data = (uint32_t *)&uc_table + }; + ZXDH_DTB_USER_ENTRY_T entry = { + .sdt_no = ZXDH_SDT_UNICAST_ATT_TABLE, + .p_entry_data = (void *)&uc_table_entry + }; + + ret = zxdh_np_dtb_table_entry_get(ZXDH_DEVICE_NO, g_dtb_data.queueid, &entry, 1); + if (ret) { + PMD_DRV_LOG(ERR, "unicast_table_get_failed:%d", hw->vfid); + return -ret; + } + + if (vport_num.vf_flag) { + if (enable) + uc_table.bitmap[(vport_num.vfid % 64) / 32] |= + UINT32_C(1) << (31 - (vport_num.vfid % 64) % 32); + else + uc_table.bitmap[(vport_num.vfid % 64) / 32] &= + ~(UINT32_C(1) << (31 - (vport_num.vfid % 64) % 32)); + } else { + uc_table.uc_flood_pf_enable = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG + (enable << 6)); + } + + ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO, g_dtb_data.queueid, 1, &entry); + if (ret) { + PMD_DRV_LOG(ERR, "unicast_table_set_failed:%d", hw->vfid); + return -ret; + } + return 0; +} + +int +zxdh_dev_multicast_table_set(struct zxdh_hw *hw, uint16_t vport, bool enable) +{ + int16_t ret = 0; + struct zxdh_multicast_table mc_table = {0}; + union zxdh_virport_num vport_num = (union zxdh_virport_num)vport; + + ZXDH_DTB_ERAM_ENTRY_INFO_T mc_table_entry = { + .index = ((hw->vfid - ZXDH_BASE_VFID) << 2) + vport_num.vfid / 64, + .p_data = (uint32_t *)&mc_table + }; + ZXDH_DTB_USER_ENTRY_T entry = { + .sdt_no = ZXDH_SDT_MULTICAST_ATT_TABLE, + .p_entry_data = (void *)&mc_table_entry + }; + + ret = zxdh_np_dtb_table_entry_get(ZXDH_DEVICE_NO, g_dtb_data.queueid, &entry, 1); + if (ret) { + PMD_DRV_LOG(ERR, "allmulti_table_get_failed:%d", hw->vfid); + return -ret; + } + + if (vport_num.vf_flag) { + if (enable) + mc_table.bitmap[(vport_num.vfid % 64) / 32] |= + UINT32_C(1) << (31 - (vport_num.vfid % 64) % 32); + else + mc_table.bitmap[(vport_num.vfid % 64) / 32] &= + ~(UINT32_C(1) << (31 - (vport_num.vfid % 64) % 32)); + + } else { + mc_table.mc_flood_pf_enable = rte_be_to_cpu_32(ZXDH_TABLE_HIT_FLAG + (enable << 6)); + } + ret = zxdh_np_dtb_table_entry_write(ZXDH_DEVICE_NO, g_dtb_data.queueid, 1, &entry); + if (ret) { + PMD_DRV_LOG(ERR, "allmulti_table_set_failed:%d", hw->vfid); + return -ret; + } + return 0; +} diff --git a/drivers/net/zxdh/zxdh_tables.h b/drivers/net/zxdh/zxdh_tables.h index f16c4923ef..0a1ddf7d9e 100644 --- a/drivers/net/zxdh/zxdh_tables.h +++ b/drivers/net/zxdh/zxdh_tables.h @@ -176,12 +176,34 @@ struct zxdh_mac_multicast_table { struct zxdh_mac_multicast_entry entry; }; +struct zxdh_brocast_table { + uint32_t flag; + uint32_t rsv; + uint32_t bitmap[2]; +}; + +struct zxdh_unitcast_table { + uint32_t uc_flood_pf_enable; + uint32_t rsv; + uint32_t bitmap[2]; +}; + +struct zxdh_multicast_table { + uint32_t mc_flood_pf_enable; + uint32_t rsv; + uint32_t bitmap[2]; +}; + 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_promisc_table_init(struct rte_eth_dev *dev); +int zxdh_promisc_table_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); +int zxdh_dev_unicast_table_set(struct zxdh_hw *hw, uint16_t vport, bool enable); +int zxdh_dev_multicast_table_set(struct zxdh_hw *hw, uint16_t vport, bool enable); #endif /* ZXDH_TABLES_H */ -- 2.27.0