From: Jie Liu <[email protected]> - Support primary/secondary MAC address setup. - Enable L2 broadcast/multicast filter bits. - Add multicast address update logic.
Signed-off-by: Jie Liu <[email protected]> --- drivers/net/sxe2/meson.build | 1 + drivers/net/sxe2/sxe2_cmd_chnl.c | 198 ++++++++ drivers/net/sxe2/sxe2_cmd_chnl.h | 17 + drivers/net/sxe2/sxe2_drv_cmd.h | 89 +++- drivers/net/sxe2/sxe2_ethdev.c | 70 ++- drivers/net/sxe2/sxe2_ethdev.h | 43 +- drivers/net/sxe2/sxe2_filter.c | 784 ++++++++++++++++++++++++++++++ drivers/net/sxe2/sxe2_filter.h | 98 ++++ drivers/net/sxe2/sxe2_mac.c | 432 ++++++++++++++++ drivers/net/sxe2/sxe2_mac.h | 36 +- drivers/net/sxe2/sxe2_txrx_poll.c | 49 ++ 11 files changed, 1809 insertions(+), 8 deletions(-) create mode 100644 drivers/net/sxe2/sxe2_filter.c create mode 100644 drivers/net/sxe2/sxe2_filter.h diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build index e22204e850..8ff74e5233 100644 --- a/drivers/net/sxe2/meson.build +++ b/drivers/net/sxe2/meson.build @@ -61,6 +61,7 @@ sources += files( 'sxe2_txrx.c', 'sxe2_txrx_vec.c', 'sxe2_mac.c', + 'sxe2_filter.c', ) allow_internal_get_api = true diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c index 07eeb7f38c..1fa9ad718e 100644 --- a/drivers/net/sxe2/sxe2_cmd_chnl.c +++ b/drivers/net/sxe2/sxe2_cmd_chnl.c @@ -343,3 +343,201 @@ int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter) l_end: return ret; } + +int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set) +{ + int32_t ret = 0; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_promisc_filter_cfg_req promisc_filter_cfg_req = {0}; + + promisc_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + promisc_filter_cfg_req.is_add = set; + promisc_filter_cfg_req.type = SXE2_PROMISC_FILTER_TYPE_PROMISC; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_PROMISC_CFG, + &promisc_filter_cfg_req, + sizeof(promisc_filter_cfg_req), + NULL, 0); + + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "promic config failed, ret=%d", ret); + + return ret; +} + +int32_t sxe2_drv_allmulti_config(struct sxe2_adapter *adapter, bool set) +{ + int32_t ret = 0; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_promisc_filter_cfg_req promisc_filter_cfg_req = {0}; + + promisc_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + promisc_filter_cfg_req.is_add = set; + promisc_filter_cfg_req.type = SXE2_PROMISC_FILTER_TYPE_ALLMULTI; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_ALLMULTI_CFG, + &promisc_filter_cfg_req, + sizeof(promisc_filter_cfg_req), + NULL, 0); + + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "allmulti config failed, ret=%d", ret); + + return ret; +} + +int32_t sxe2_drv_uc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add) +{ + int32_t ret = 0; + int32_t i; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_mac_filter_cfg_req mac_filter_cfg_req = {0}; + + mac_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + for (i = 0; i < SXE2_ETH_ALEN; i++) + mac_filter_cfg_req.addr[i] = addr->addr_bytes[i]; + mac_filter_cfg_req.is_add = add; + mac_filter_cfg_req.type = SXE2_MAC_FILTER_TYPE_UC; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_ADDR_UC, + &mac_filter_cfg_req, sizeof(mac_filter_cfg_req), + NULL, 0); + + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "uc config query failed, ret=%d", ret); + + return ret; +} + +int32_t sxe2_drv_mc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add) +{ + int32_t ret = 0; + int32_t i; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_mac_filter_cfg_req mac_filter_cfg_req = {0}; + + mac_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + for (i = 0; i < SXE2_ETH_ALEN; i++) + mac_filter_cfg_req.addr[i] = addr->addr_bytes[i]; + + mac_filter_cfg_req.is_add = add; + mac_filter_cfg_req.type = SXE2_MAC_FILTER_TYPE_MC; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_ADDR_MC, + &mac_filter_cfg_req, sizeof(mac_filter_cfg_req), + NULL, 0); + + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "mac config query failed, ret=%d", ret); + + return ret; +} + +int32_t sxe2_drv_vlan_config_query(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_drv_vlan_cfg_query_resp vlan_cfg_query_resp = {0}; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_CFG_QUERY, + NULL, 0, + &vlan_cfg_query_resp, + sizeof(vlan_cfg_query_resp)); + + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "vlan config query failed, ret=%d", ret); + + adapter->filter_ctxt.vlan_info.port_vlan_exist = vlan_cfg_query_resp.port_vlan_exist; + adapter->filter_ctxt.vlan_info.is_switchdev = vlan_cfg_query_resp.is_switchdev; + + + adapter->filter_ctxt.vlan_info.tpid = vlan_cfg_query_resp.tpid; + adapter->filter_ctxt.vlan_info.vid = vlan_cfg_query_resp.vid; + + adapter->filter_ctxt.vlan_info.outer_insert = vlan_cfg_query_resp.outer_insert; + adapter->filter_ctxt.vlan_info.outer_strip = vlan_cfg_query_resp.outer_strip; + adapter->filter_ctxt.vlan_info.inner_insert = vlan_cfg_query_resp.inner_insert; + adapter->filter_ctxt.vlan_info.inner_strip = vlan_cfg_query_resp.inner_strip; + + return ret; +} + +int32_t sxe2_drv_vlan_filter_id_config(struct sxe2_adapter *adapter, + struct sxe2_vlan *vlan, bool on) +{ + int32_t ret = 0; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_vlan_filter_cfg_req vlan_filter_cfg_req = {0}; + + vlan_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + vlan_filter_cfg_req.tpid_id = vlan->tpid; + vlan_filter_cfg_req.vlan_id = vlan->vid; + vlan_filter_cfg_req.prio = vlan->prio; + vlan_filter_cfg_req.is_add = on; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_FILTER_ADD_DEL, + &vlan_filter_cfg_req, sizeof(vlan_filter_cfg_req), + NULL, 0); + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "vlan config failed, ret=%d", ret); + + return ret; +} + +int32_t sxe2_drv_vlan_insert_strip_cfg(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_drv_vlan_offload_cfg_req vlan_offload_cfg_req = {0}; + + vlan_offload_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + vlan_offload_cfg_req.tpid = adapter->filter_ctxt.vlan_info.tpid; + vlan_offload_cfg_req.outer_insert = adapter->filter_ctxt.vlan_info.outer_insert; + vlan_offload_cfg_req.outer_strip = adapter->filter_ctxt.vlan_info.outer_strip; + vlan_offload_cfg_req.inner_insert = adapter->filter_ctxt.vlan_info.inner_insert; + vlan_offload_cfg_req.inner_strip = adapter->filter_ctxt.vlan_info.inner_strip; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_OFFLOAD_CFG, + &vlan_offload_cfg_req, + sizeof(vlan_offload_cfg_req), + NULL, 0); + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "vlan config query failed, ret=%d", ret); + + return ret; +} + +int32_t sxe2_drv_vlan_filter_switch(struct sxe2_adapter *adapter, bool on) +{ + int32_t ret = 0; + struct sxe2_common_device *cdev = adapter->cdev; + struct sxe2_drv_cmd_params param = {0}; + struct sxe2_vlan_filter_switch_req vlan_filter_switch_req = {0}; + + vlan_filter_switch_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id; + vlan_filter_switch_req.is_oper_enable = on; + + sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_FILTER_SWITCH, + &vlan_filter_switch_req, + sizeof(vlan_filter_switch_req), + NULL, 0); + ret = sxe2_drv_cmd_exec(cdev, ¶m); + if (ret) + PMD_DEV_LOG_WARN(adapter, DRV, "vlan config filter failed, ret=%d", ret); + + return ret; +} diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h index 34004d37e2..fb01c41aad 100644 --- a/drivers/net/sxe2/sxe2_cmd_chnl.h +++ b/drivers/net/sxe2/sxe2_cmd_chnl.h @@ -36,4 +36,21 @@ int32_t sxe2_drv_txq_ctxt_cfg(struct sxe2_adapter *adapter, int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter); +int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set); + +int32_t sxe2_drv_allmulti_config(struct sxe2_adapter *adapter, bool set); + +int32_t sxe2_drv_uc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add); + +int32_t sxe2_drv_mc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add); + +int32_t sxe2_drv_vlan_config_query(struct sxe2_adapter *adapter); + +int32_t sxe2_drv_vlan_filter_id_config(struct sxe2_adapter *adapter, + struct sxe2_vlan *vlan, bool on); + +int32_t sxe2_drv_vlan_insert_strip_cfg(struct sxe2_adapter *adapter); + +int32_t sxe2_drv_vlan_filter_switch(struct sxe2_adapter *adapter, bool on); + #endif /* __SXE2_CMD_CHNL_H__ */ diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h index e0ec70638e..c9d7cc719b 100644 --- a/drivers/net/sxe2/sxe2_drv_cmd.h +++ b/drivers/net/sxe2/sxe2_drv_cmd.h @@ -111,6 +111,17 @@ enum sxe2_phys_port_name_type { SXE2_PHYS_PORT_NAME_TYPE_UNKNOWN, }; +struct sxe2_switchdev_info { + uint8_t is_switchdev; + uint8_t master; + uint8_t representor; + uint8_t port_name_type; + uint32_t ctrl_num; + uint32_t pf_num; + uint32_t vf_num; + uint32_t mpesw_owner; +}; + struct sxe2_switchdev_mode_info { uint8_t pf_id; uint8_t is_switchdev; @@ -228,11 +239,87 @@ struct sxe2_drv_vsi_info_get_resp { }; struct sxe2_drv_link_info_resp { - __le32 speed; + uint32_t speed; uint8_t status; uint8_t rsv[3]; }; +struct sxe2_drv_vlan_cfg_query_resp { + uint16_t vsi_id; + uint8_t port_vlan_exist; + uint8_t is_switchdev; + uint16_t tpid; + uint16_t vid; + uint8_t outer_insert; + uint8_t outer_strip; + uint8_t inner_insert; + uint8_t inner_strip; +}; + +struct sxe2_drv_vlan_offload_cfg_req { + uint16_t vsi_id; + uint16_t tpid; + uint8_t outer_insert; + uint8_t outer_strip; + uint8_t inner_insert; + uint8_t inner_strip; +}; + +struct sxe2_drv_port_vlan_cfg_req { + uint16_t vsi_id; + uint16_t tpid; + uint16_t vid; + uint8_t prio; + uint8_t rsv; +}; + +enum sxe2_mac_filter_type { + SXE2_MAC_FILTER_TYPE_UC = 0, + SXE2_MAC_FILTER_TYPE_MC, + SXE2_MAC_FILTER_TYPE_MAX, +}; + +struct sxe2_mac_filter_cfg_req { + uint16_t vsi_id; + uint8_t addr[SXE2_ETH_ALEN]; + uint8_t type; + uint8_t is_add; + uint8_t rsv[2]; +}; + +enum sxe2_promisc_filter_type { + SXE2_PROMISC_FILTER_TYPE_PROMISC = 0, + SXE2_PROMISC_FILTER_TYPE_ALLMULTI, + SXE2_PROMISC_FILTER_TYPE_MAX, +}; + +struct sxe2_promisc_filter_cfg_req { + uint16_t vsi_id; + uint8_t type; + uint8_t is_add; +}; + +struct sxe2_srcvsi_ext_cfg_req { + uint16_t vsi_id; + uint16_t srcvsi_list[SXE2_SRCVSI_PRUNE_MAX_NUM]; + uint8_t srcvsi_cnt; + uint8_t is_add; +}; + +struct sxe2_vlan_filter_cfg_req { + uint16_t vsi_id; + uint16_t vlan_id; + uint16_t tpid_id; + uint8_t prio; + uint8_t is_add; +}; + +struct sxe2_vlan_filter_switch_req { + uint16_t vsi_id; + uint8_t is_oper_enable; + uint8_t rsv; +}; + enum sxe2_drv_cmd_module { SXE2_DRV_CMD_MODULE_HANDSHAKE = 0, SXE2_DRV_CMD_MODULE_DEV = 1, diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c index 01552a8202..9b117f097e 100644 --- a/drivers/net/sxe2/sxe2_ethdev.c +++ b/drivers/net/sxe2/sxe2_ethdev.c @@ -111,8 +111,20 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = { .tx_burst_mode_get = sxe2_tx_burst_mode_get, .tx_done_cleanup = sxe2_tx_done_cleanup, + .promiscuous_enable = sxe2_promisc_enable, + .promiscuous_disable = sxe2_promisc_disable, + .allmulticast_enable = sxe2_allmulti_enable, + .allmulticast_disable = sxe2_allmulti_disable, + + .mac_addr_add = sxe2_mac_addr_add, + .mac_addr_remove = sxe2_mac_addr_del, + .mac_addr_set = sxe2_mac_addr_set, + .set_mc_addr_list = sxe2_set_mc_addr_list, .mtu_set = sxe2_mtu_set, .buffer_split_supported_hdr_ptypes_get = sxe2_buffer_split_supported_hdr_ptypes_get, + + .vlan_filter_set = sxe2_dev_vlan_filter_set, + .vlan_offload_set = sxe2_dev_vlan_offload_set, }; static int32_t sxe2_dev_configure(struct rte_eth_dev *dev) @@ -123,6 +135,13 @@ static int32_t sxe2_dev_configure(struct rte_eth_dev *dev) if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; + ret = sxe2_vlan_default_cfg(dev); + if (ret) { + PMD_LOG_ERR(INIT, "Failed to init vlan, ret=%d", ret); + goto end; + } + +end: return ret; } @@ -138,6 +157,8 @@ static int32_t sxe2_dev_stop(struct rte_eth_dev *dev) sxe2_txqs_all_stop(dev); sxe2_rxqs_all_stop(dev); + (void)sxe2_filter_rule_stop(dev); + dev->data->dev_started = 0; adapter->started = 0; l_end: @@ -165,16 +186,23 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev) goto l_end; } + ret = sxe2_filter_rule_start(dev); + if (ret) { + PMD_LOG_ERR(INIT, "Failed to add all mc addr to fw."); + goto l_end; + } + ret = sxe2_queues_start(dev); if (ret) { PMD_LOG_ERR(INIT, "enable queues failed"); - goto l_end; + goto l_start_queues_err; } dev->data->dev_started = 1; adapter->started = 1; goto l_end; - +l_start_queues_err: + (void)sxe2_filter_rule_stop(dev); l_end: return ret; } @@ -194,6 +222,7 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, dev_info->min_mtu = RTE_ETHER_MIN_MTU; dev_info->rx_offload_capa = + RTE_ETH_RX_OFFLOAD_VLAN_STRIP | RTE_ETH_RX_OFFLOAD_KEEP_CRC | RTE_ETH_RX_OFFLOAD_SCATTER | RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | @@ -202,9 +231,15 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, RTE_ETH_RX_OFFLOAD_SCTP_CKSUM | RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM | RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT | +#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC + RTE_ETH_RX_OFFLOAD_QINQ_STRIP | +#endif + RTE_ETH_RX_OFFLOAD_VLAN_EXTEND | RTE_ETH_RX_OFFLOAD_TCP_LRO; dev_info->tx_offload_capa = + RTE_ETH_TX_OFFLOAD_VLAN_INSERT | + RTE_ETH_TX_OFFLOAD_QINQ_INSERT | RTE_ETH_TX_OFFLOAD_MULTI_SEGS | RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE | RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | @@ -428,6 +463,12 @@ static int32_t sxe2_eth_init(struct rte_eth_dev *dev) { int32_t ret = 0; + ret = sxe2_filter_init(dev); + if (ret) { + PMD_LOG_ERR(INIT, "Failed to initialize l2 filter, ret:%d", ret); + goto l_end; + } + ret = sxe2_link_update_init(dev); if (ret) { PMD_LOG_ERR(INIT, "Failed to initialize link update, ret:%d", ret); @@ -439,12 +480,37 @@ static int32_t sxe2_eth_init(struct rte_eth_dev *dev) PMD_LOG_ERR(INIT, "Failed to set mtu, ret=%d", ret); goto l_end; } + + ret = sxe2_mac_addr_init(dev); + if (ret != 0) { + PMD_LOG_ERR(INIT, "Failed to initialize mac address, ret:%d", ret); + goto l_end; + } + + ret = sxe2_mac_default_cfg(dev); + if (ret != 0) { + PMD_LOG_ERR(INIT, "Failed to configure default mac address, ret:%d", ret); + goto l_err; + } + + ret = sxe2_vlan_cfg_init(dev); + if (ret) { + PMD_LOG_ERR(INIT, "Failed to initialize vlan config, ret:%d", ret); + goto l_err; + } + goto l_end; + +l_err: + sxe2_mac_addr_uinit(dev); + (void)sxe2_filter_uinit(dev); l_end: return ret; } static void sxe2_eth_uinit(struct rte_eth_dev *dev __rte_unused) { + sxe2_mac_addr_uinit(dev); + (void)sxe2_filter_uinit(dev); } static void sxe2_drv_dev_caps_set(struct sxe2_adapter *adapter, diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h index 66f49ac0cc..cc8a84c0a0 100644 --- a/drivers/net/sxe2/sxe2_ethdev.h +++ b/drivers/net/sxe2/sxe2_ethdev.h @@ -13,9 +13,11 @@ #include "sxe2_common.h" #include "sxe2_vsi.h" -#include "sxe2_queue.h" #include "sxe2_irq.h" +#include "sxe2_queue.h" +#include "sxe2_mac.h" #include "sxe2_osal.h" +#include "sxe2_filter.h" struct sxe2_link_msg { uint32_t speed; @@ -33,7 +35,7 @@ enum sxe2_fnav_tunnel_flag_type { #define SXE2_FRAME_SIZE_MAX 9832 #define SXE2_VLAN_TAG_SIZE 4 #define SXE2_ETH_OVERHEAD \ - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + SXE2_VLAN_TAG_SIZE) + (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + 2 * SXE2_VLAN_TAG_SIZE) #define SXE2_ETH_MAX_LEN (RTE_ETHER_MTU + SXE2_ETH_OVERHEAD) #ifdef SXE2_TEST @@ -265,6 +267,27 @@ struct sxe2_link_context { uint32_t speed; }; +struct sxe2_filter_context { + rte_spinlock_t filter_lock; + struct sxe2_vlan_info vlan_info; + struct sxe2_uc_filter_list_head uc_list; + struct sxe2_mc_filter_list_head mc_list; + struct sxe2_vlan_filter_list_head vlan_list; + uint8_t uc_num; + uint8_t mc_num; + uint8_t vlan_num; + uint8_t rsv; + uint32_t hw_promisc_flags; + uint32_t cur_promisc_flags; + + bool hw_uplink_config; + bool cur_uplink_config; + bool hw_repr_config; + bool cur_repr_config; + bool hw_l2_config; + bool cur_l2_config; +}; + struct sxe2_adapter { struct sxe2_common_device *cdev; struct sxe2_dev_info dev_info; @@ -274,10 +297,14 @@ struct sxe2_adapter { struct sxe2_irq_context irq_ctxt; struct sxe2_queue_context q_ctxt; struct sxe2_vsi_context vsi_ctxt; + struct sxe2_filter_context filter_ctxt; struct sxe2_link_context link_ctxt; struct sxe2_devargs devargs; - uint16_t dev_port_id; - uint64_t cap_flags; + struct sxe2_switchdev_info switchdev_info; + bool rule_started; + bool flow_isolated; + uint16_t dev_port_id; + uint64_t cap_flags; enum sxe2_dev_type dev_type; uint32_t ptype_tbl[SXE2_MAX_PTYPE_NUM]; struct rte_ether_addr mac_addr; @@ -316,4 +343,12 @@ int32_t sxe2_dev_pci_map_init(struct rte_eth_dev *dev); void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev); +static inline bool +sxe2_dev_port_vlan_check(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *ad = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + + return ad->filter_ctxt.vlan_info.port_vlan_exist; +} + #endif /* __SXE2_ETHDEV_H__ */ diff --git a/drivers/net/sxe2/sxe2_filter.c b/drivers/net/sxe2/sxe2_filter.c new file mode 100644 index 0000000000..cfeeb7a6c3 --- /dev/null +++ b/drivers/net/sxe2/sxe2_filter.c @@ -0,0 +1,784 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd. + */ + +#include <rte_os.h> +#include <rte_tailq.h> +#include "sxe2_osal.h" +#include "sxe2_mac.h" +#include "sxe2_common_log.h" +#include "sxe2_ethdev.h" +#include "sxe2_cmd_chnl.h" + +static struct sxe2_mac_filter *sxe2_uc_filter_find(struct sxe2_adapter *adapter, + struct rte_ether_addr *macaddr) +{ + struct sxe2_mac_filter *filter = NULL; + struct sxe2_mac_filter *entry = NULL; + struct sxe2_mac_filter *next_entry = NULL; + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.uc_list, next, next_entry) { + if (rte_is_same_ether_addr(macaddr, &entry->mac_addr)) { + filter = entry; + break; + } + } + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + + return filter; +} + +int32_t sxe2_uc_filter_add(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr, bool default_config) +{ + struct sxe2_mac_filter *filter = NULL; + bool hw_config = false; + int32_t ret = 0; + + filter = sxe2_uc_filter_find(adapter, mac_addr); + if (filter) { + if (default_config && !filter->default_config) + filter->default_config = true; + PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter already exists."); + goto l_end; + } + + if (!adapter->rule_started) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add hw uc addr in port stop status"); + } else if (adapter->flow_isolated) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw uc addr in flow isolation mode"); + } else if (adapter->switchdev_info.is_switchdev) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw uc addr in switchdev mode"); + } else { + ret = sxe2_drv_uc_config(adapter, mac_addr, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add uc rule"); + ret = -EINVAL; + goto l_end; + } + hw_config = true; + } + + filter = rte_zmalloc("sxe2_uc_filter", + sizeof(struct sxe2_mac_filter), 0); + if (!filter) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to allocate memory"); + ret = -ENOMEM; + goto l_end; + } + filter->hw_config = hw_config; + filter->default_config = default_config; + rte_ether_addr_copy(mac_addr, &filter->mac_addr); + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_INSERT_TAIL(&adapter->filter_ctxt.uc_list, filter, next); + adapter->filter_ctxt.uc_num++; + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + + PMD_DEV_LOG_INFO(adapter, DRV, "add mac rule, mac num %u.", adapter->filter_ctxt.uc_num); + ret = 0; + +l_end: + return ret; +} + +int32_t sxe2_uc_filter_del(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr) +{ + struct sxe2_mac_filter *filter = NULL; + int32_t ret = -1; + + filter = sxe2_uc_filter_find(adapter, mac_addr); + if (!filter) { + PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter not exists."); + ret = 0; + goto l_end; + } + if (filter->hw_config) { + ret = sxe2_drv_uc_config(adapter, mac_addr, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mac rule"); + if (ret == -EPERM) + goto l_free; + ret = -EINVAL; + goto l_end; + } + } + PMD_DEV_LOG_INFO(adapter, DRV, "remove mac rule, uc num %u.", adapter->filter_ctxt.uc_num); + ret = 0; + +l_free: + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_REMOVE(&adapter->filter_ctxt.uc_list, filter, next); + adapter->filter_ctxt.uc_num--; + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + rte_free(filter); + filter = NULL; +l_end: + return ret; +} + +void sxe2_uc_filter_clear(struct sxe2_adapter *adapter, bool default_config) +{ + struct sxe2_mac_filter *entry; + struct sxe2_mac_filter *next_entry; + + RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.uc_list, next, next_entry) { + if (entry->default_config && !default_config) + continue; + + if (sxe2_uc_filter_del(adapter, &entry->mac_addr)) + PMD_DEV_LOG_ERR(adapter, DRV, "This MAC filter delete fail."); + } +} + +static struct sxe2_mac_filter *sxe2_mc_filter_find(struct sxe2_adapter *adapter, + struct rte_ether_addr *macaddr) +{ + struct sxe2_mac_filter *filter = NULL; + struct sxe2_mac_filter *entry = NULL; + struct sxe2_mac_filter *next_entry = NULL; + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.mc_list, next, next_entry) { + if (rte_is_same_ether_addr(macaddr, &entry->mac_addr)) { + filter = entry; + break; + } + } + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + + return filter; +} + +int32_t sxe2_mc_filter_add(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr, bool default_config) +{ + struct sxe2_mac_filter *filter = NULL; + bool hw_config = false; + int32_t ret = 0; + + filter = sxe2_mc_filter_find(adapter, mac_addr); + if (filter) { + if (default_config && !filter->default_config) + filter->default_config = true; + PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter already exists."); + goto l_end; + } + + if (!adapter->rule_started) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add hw mc addr in port stop status"); + } else if (adapter->flow_isolated) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw mc addr in flow isolation mode"); + } else if (adapter->switchdev_info.is_switchdev) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw mc addr in switchdev mode"); + } else { + ret = sxe2_drv_mc_config(adapter, mac_addr, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add mac rule"); + ret = -EINVAL; + goto l_end; + } + hw_config = true; + } + + filter = rte_zmalloc("sxe2_mc_filter", + sizeof(struct sxe2_mac_filter), 0); + if (!filter) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to allocate memory"); + ret = -ENOMEM; + goto l_end; + } + filter->hw_config = hw_config; + filter->default_config = default_config; + rte_ether_addr_copy(mac_addr, &filter->mac_addr); + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_INSERT_TAIL(&adapter->filter_ctxt.mc_list, filter, next); + adapter->filter_ctxt.mc_num++; + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + + PMD_DEV_LOG_INFO(adapter, DRV, "add mc rule, mc num %u.", adapter->filter_ctxt.mc_num); + ret = 0; + +l_end: + return ret; +} + +int32_t sxe2_mc_filter_del(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr) +{ + struct sxe2_mac_filter *filter = NULL; + int32_t ret = -1; + + filter = sxe2_mc_filter_find(adapter, mac_addr); + if (!filter) { + PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter not exists."); + ret = 0; + goto l_end; + } + + if (filter->hw_config) { + ret = sxe2_drv_mc_config(adapter, mac_addr, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mc rule"); + if (ret == -EPERM) + goto l_free; + ret = -EINVAL; + goto l_end; + } + } + PMD_DEV_LOG_INFO(adapter, DRV, "remove mc rule, mc num %u.", adapter->filter_ctxt.mc_num); + ret = 0; + +l_free: + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_REMOVE(&adapter->filter_ctxt.mc_list, filter, next); + adapter->filter_ctxt.mc_num--; + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + rte_free(filter); + filter = NULL; +l_end: + return ret; +} + +void sxe2_mc_filter_clear(struct sxe2_adapter *adapter, bool default_config) +{ + struct sxe2_mac_filter *entry; + struct sxe2_mac_filter *next_entry; + + RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.mc_list, next, next_entry) { + if (entry->default_config && !default_config) + continue; + if (sxe2_mc_filter_del(adapter, &entry->mac_addr)) + PMD_DEV_LOG_ERR(adapter, DRV, "This MAC filter delete fail."); + } +} + +static struct sxe2_vlan_filter *sxe2_vlan_filter_find(struct sxe2_adapter *adapter, + struct sxe2_vlan *vlan) +{ + struct sxe2_vlan_filter *f; + struct sxe2_vlan_filter *save_f = NULL; + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_FOREACH(f, &adapter->filter_ctxt.vlan_list, next) + { + if (vlan->tpid == f->vlan_info.tpid && + vlan->vid == f->vlan_info.vid) { + save_f = f; + break; + } + } + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + + return save_f; +} + +int32_t sxe2_vlan_filter_add(struct sxe2_adapter *adapter, + struct sxe2_vlan *vlan, bool default_config) +{ + struct sxe2_vlan_filter *filter = NULL; + bool hw_config = false; + int32_t ret = 0; + + if (!vlan || vlan->vid > RTE_ETHER_MAX_VLAN_ID) { + PMD_DEV_LOG_ERR(adapter, DRV, "This vlan filter is invalid."); + ret = -EINVAL; + goto l_end; + } + + filter = sxe2_vlan_filter_find(adapter, vlan); + if (filter) { + PMD_DEV_LOG_INFO(adapter, DRV, "This vlan filter already exists."); + ret = 0; + goto l_end; + } + if (!adapter->rule_started) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add vlan in port stop status"); + } else if (adapter->flow_isolated) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan in flow isolation mode"); + } else if (adapter->switchdev_info.is_switchdev) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan in switchdev mode"); + } else { + ret = sxe2_drv_vlan_filter_id_config(adapter, vlan, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan rule"); + ret = -EINVAL; + goto l_end; + } + hw_config = true; + } + + filter = rte_zmalloc("sxe2_vlan_filter", sizeof(*filter), 0); + if (!filter) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to allocate memory"); + ret = -ENOMEM; + goto l_end; + } + + filter->hw_config = hw_config; + filter->default_config = default_config; + + filter->vlan_info.tpid = vlan->tpid; + filter->vlan_info.vid = vlan->vid; + filter->vlan_info.prio = vlan->prio; + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_INSERT_TAIL(&adapter->filter_ctxt.vlan_list, filter, next); + adapter->filter_ctxt.vlan_num++; + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + + ret = 0; + +l_end: + return ret; +} + +int32_t sxe2_vlan_filter_del(struct sxe2_adapter *adapter, struct sxe2_vlan *vlan) +{ + struct sxe2_vlan_filter *filter = NULL; + int32_t ret = -1; + + if (!vlan || vlan->vid > RTE_ETHER_MAX_VLAN_ID) { + PMD_DEV_LOG_INFO(adapter, DRV, "This vlan filter is invalid."); + ret = -EINVAL; + goto l_end; + } + + filter = sxe2_vlan_filter_find(adapter, vlan); + if (!filter) { + PMD_DEV_LOG_INFO(adapter, DRV, "This vlan filter not exists."); + ret = 0; + goto l_end; + } + + if (filter->hw_config) { + ret = sxe2_drv_vlan_filter_id_config(adapter, vlan, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete vlan rule"); + if (ret == -EPERM) + goto l_free; + ret = -EINVAL; + goto l_end; + } + } + ret = 0; + +l_free: + + rte_spinlock_lock(&adapter->filter_ctxt.filter_lock); + TAILQ_REMOVE(&adapter->filter_ctxt.vlan_list, filter, next); + adapter->filter_ctxt.vlan_num--; + rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock); + rte_free(filter); + filter = NULL; +l_end: + return ret; +} + +void sxe2_vlan_filters_clear(struct sxe2_adapter *adapter, bool default_config) +{ + int32_t ret = 0; + struct sxe2_vlan_filter *v_f; + void *temp; + + if (adapter->filter_ctxt.vlan_num == 0) + goto l_end; + + RTE_TAILQ_FOREACH_SAFE(v_f, &adapter->filter_ctxt.vlan_list, next, temp) + { + if (v_f->default_config && !default_config) + continue; + ret = sxe2_vlan_filter_del(adapter, &v_f->vlan_info); + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "This vlan filter delete fail."); + } + +l_end: +} + +int32_t sxe2_vlan_filter_ctrl(struct sxe2_adapter *adapter, bool flag) +{ + struct sxe2_vlan_info *vlan_info = &adapter->filter_ctxt.vlan_info; + int32_t ret = 0; + + if (vlan_info->filter_on == flag) + goto l_end; + if (!adapter->rule_started) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add vlan filter ctrl in port stop status"); + } else if (adapter->flow_isolated) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan filter ctrl in flow isolation mode"); + } else if (adapter->switchdev_info.is_switchdev) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan filter ctrl in switchdev mode"); + } else { + ret = sxe2_drv_vlan_filter_switch(adapter, flag); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan filter ctrl"); + goto l_end; + } + vlan_info->hw_filter_on = flag; + } + vlan_info->filter_on = flag; + +l_end: + return ret; +} + +int32_t sxe2_promisc_add(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + + if (!adapter->rule_started) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot enable promiscuous in port stop status"); + } else if (adapter->flow_isolated) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable promiscuous in flow isolation mode"); + } else if (adapter->switchdev_info.is_switchdev) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable promiscuous in switchdev mode"); + } else if (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC)) { + ret = sxe2_drv_promisc_config(adapter, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg promiscuous, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC; + } + adapter->filter_ctxt.cur_promisc_flags |= SXE2_PROMISC; + +l_end: + return ret; +} + +int32_t sxe2_promisc_del(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + + if (!adapter->flow_isolated && + (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC)) { + ret = sxe2_drv_promisc_config(adapter, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg promiscuous, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC; + } + + adapter->filter_ctxt.cur_promisc_flags &= ~SXE2_PROMISC; + +l_end: + return ret; +} + +int32_t sxe2_allmulti_add(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + + if (!adapter->rule_started) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot enable allmulticast in port stop status"); + } else if (adapter->flow_isolated) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable allmulticast in flow isolation mode"); + } else if (adapter->switchdev_info.is_switchdev) { + PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable allmulticast in switchdev mode"); + } else if (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST)) { + ret = sxe2_drv_allmulti_config(adapter, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg allmulticast, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC_MULTICAST; + } + adapter->filter_ctxt.cur_promisc_flags |= SXE2_PROMISC_MULTICAST; + +l_end: + return ret; +} + +int32_t sxe2_allmulti_del(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + + if (!adapter->flow_isolated && + (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST)) { + ret = sxe2_drv_allmulti_config(adapter, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg allmulticast, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC_MULTICAST; + } + + adapter->filter_ctxt.cur_promisc_flags &= ~SXE2_PROMISC_MULTICAST; +l_end: + return ret; +} + +static int32_t sxe2_all_filter_hw_clear(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + struct sxe2_mac_filter *mac_entry; + struct sxe2_mac_filter *next_mac_entry; + struct sxe2_vlan_filter *vlan_entry; + struct sxe2_vlan_filter *next_vlan_entry; + + if (adapter->filter_ctxt.uc_num > 0) { + RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.uc_list, next, + next_mac_entry) { + if (mac_entry->hw_config) { + ret = sxe2_drv_uc_config(adapter, &mac_entry->mac_addr, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mac rule"); + ret = -EINVAL; + goto l_end; + } + mac_entry->hw_config = false; + } + } + } + + if (adapter->filter_ctxt.mc_num > 0) { + RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.mc_list, next, + next_mac_entry) { + if (mac_entry->hw_config) { + ret = sxe2_drv_mc_config(adapter, &mac_entry->mac_addr, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mc rule"); + ret = -EINVAL; + goto l_end; + } + mac_entry->hw_config = false; + } + } + } + + if (adapter->filter_ctxt.vlan_num > 0) { + RTE_TAILQ_FOREACH_SAFE(vlan_entry, &adapter->filter_ctxt.vlan_list, next, + next_vlan_entry) { + if (vlan_entry->hw_config) { + ret = sxe2_drv_vlan_filter_id_config(adapter, + &vlan_entry->vlan_info, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete vlan rule"); + ret = -EINVAL; + goto l_end; + } + vlan_entry->hw_config = false; + } + } + } + + if (adapter->filter_ctxt.vlan_info.hw_filter_on) { + ret = sxe2_drv_vlan_filter_switch(adapter, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete vlan rule"); + ret = -EINVAL; + goto l_end; + } + adapter->filter_ctxt.vlan_info.hw_filter_on = false; + } + + if (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC) { + ret = sxe2_drv_promisc_config(adapter, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg promiscuous, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC; + } + + if (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST) { + ret = sxe2_drv_allmulti_config(adapter, false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg allmulticast, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC_MULTICAST; + } +l_end: + return ret; +} + +static int32_t sxe2_all_filter_hw_set(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + struct sxe2_mac_filter *mac_entry; + struct sxe2_mac_filter *next_mac_entry; + struct sxe2_vlan_filter *vlan_entry; + struct sxe2_vlan_filter *next_vlan_entry; + + if (adapter->filter_ctxt.uc_num > 0) { + RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.uc_list, next, + next_mac_entry) { + if (!mac_entry->hw_config) { + ret = sxe2_drv_uc_config(adapter, &mac_entry->mac_addr, + true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to add uc rule, ret:%d", ret); + ret = -EINVAL; + goto l_end; + } + mac_entry->hw_config = true; + ret = 0; + } + } + } + + if (adapter->filter_ctxt.mc_num > 0) { + RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.mc_list, next, + next_mac_entry) { + if (!mac_entry->hw_config) { + ret = sxe2_drv_mc_config(adapter, &mac_entry->mac_addr, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to add mc rule, ret:%d", ret); + ret = -EINVAL; + goto l_end; + } + mac_entry->hw_config = true; + ret = 0; + } + } + } + + if (adapter->filter_ctxt.vlan_num > 0) { + RTE_TAILQ_FOREACH_SAFE(vlan_entry, &adapter->filter_ctxt.vlan_list, next, + next_vlan_entry) { + if (!vlan_entry->hw_config) { + ret = sxe2_drv_vlan_filter_id_config(adapter, + &vlan_entry->vlan_info, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to add vlan rule, ret:%d", ret); + ret = -EINVAL; + goto l_end; + } + vlan_entry->hw_config = true; + ret = 0; + } + } + } + + if (adapter->filter_ctxt.vlan_info.filter_on) { + if (!(adapter->filter_ctxt.vlan_info.hw_filter_on)) { + ret = sxe2_drv_vlan_filter_switch(adapter, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to add vlan ctrl, ret:%d", ret); + ret = -EINVAL; + goto l_end; + } + adapter->filter_ctxt.vlan_info.hw_filter_on = true; + ret = 0; + } + } + + if ((adapter->filter_ctxt.cur_promisc_flags & SXE2_PROMISC) && + (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC))) { + ret = sxe2_drv_promisc_config(adapter, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to set promisc, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC; + ret = 0; + } + + if ((adapter->filter_ctxt.cur_promisc_flags & SXE2_PROMISC_MULTICAST) && + (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST))) { + ret = sxe2_drv_allmulti_config(adapter, true); + if (ret && ret != -EEXIST) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to set allmulti, ret:%d", ret); + goto l_end; + } + adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC_MULTICAST; + ret = 0; + } +l_end: + return ret; +} + +int32_t sxe2_l2_rule_update(struct sxe2_adapter *adapter) +{ + int32_t ret = 0; + + if (!adapter->flow_isolated && !adapter->switchdev_info.is_switchdev && + adapter->rule_started) { + adapter->filter_ctxt.cur_l2_config = true; + } else { + adapter->filter_ctxt.cur_l2_config = false; + } + + if (adapter->filter_ctxt.cur_l2_config != + adapter->filter_ctxt.hw_l2_config) { + if (adapter->filter_ctxt.cur_l2_config) { + ret = sxe2_all_filter_hw_set(adapter); + if (!ret) + adapter->filter_ctxt.hw_l2_config = true; + } else { + ret = sxe2_all_filter_hw_clear(adapter); + if (!ret) + adapter->filter_ctxt.hw_l2_config = false; + } + } + return ret; +} + +int32_t sxe2_filter_rule_stop(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + adapter->rule_started = 0; + + ret = sxe2_l2_rule_update(adapter); + if (ret != 0) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to update l2 rule"); + + return ret; +} + +int32_t sxe2_filter_rule_start(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + adapter->rule_started = 1; + + ret = sxe2_l2_rule_update(adapter); + if (ret != 0) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to update l2 rule"); + + return ret; +} + +int32_t sxe2_filter_init(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + + rte_spinlock_init(&adapter->filter_ctxt.filter_lock); + + TAILQ_INIT(&adapter->filter_ctxt.uc_list); + adapter->filter_ctxt.uc_num = 0; + + TAILQ_INIT(&adapter->filter_ctxt.mc_list); + adapter->filter_ctxt.mc_num = 0; + + TAILQ_INIT(&adapter->filter_ctxt.vlan_list); + adapter->filter_ctxt.vlan_num = 0; + return 0; +} + +int32_t sxe2_filter_uinit(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + sxe2_uc_filter_clear(adapter, true); + adapter->filter_ctxt.uc_num = 0; + + sxe2_mc_filter_clear(adapter, true); + adapter->filter_ctxt.mc_num = 0; + + sxe2_vlan_filters_clear(adapter, true); + adapter->filter_ctxt.vlan_num = 0; + return 0; +} diff --git a/drivers/net/sxe2/sxe2_filter.h b/drivers/net/sxe2/sxe2_filter.h new file mode 100644 index 0000000000..6262e8c845 --- /dev/null +++ b/drivers/net/sxe2/sxe2_filter.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd. + */ + +#ifndef __SXE2_FILTER_H__ +#define __SXE2_FILTER_H__ +#include <ethdev_driver.h> + +#define SXE2_PROMISC (1UL << 0UL) +#define SXE2_PROMISC_MULTICAST (1UL << 1UL) + +struct sxe2_vlan_info { + uint8_t port_vlan_exist; + uint8_t is_switchdev; + uint16_t max_cnt; + uint16_t cnt; + + bool filter_on; + bool hw_filter_on; + + uint16_t tpid; + uint16_t vid; + + uint8_t outer_insert; + uint8_t outer_strip; + uint8_t inner_insert; + uint8_t inner_strip; +}; + +struct sxe2_vlan { + uint16_t tpid; + uint16_t vid; + uint8_t prio; +}; + +struct sxe2_vlan_filter { + TAILQ_ENTRY(sxe2_vlan_filter) next; + bool hw_config; + bool default_config; + struct sxe2_vlan vlan_info; +}; + +TAILQ_HEAD(sxe2_vlan_filter_list_head, sxe2_vlan_filter); + +struct sxe2_mac_filter { + TAILQ_ENTRY(sxe2_mac_filter) next; + bool hw_config; + bool default_config; + struct rte_ether_addr mac_addr; +}; + +TAILQ_HEAD(sxe2_uc_filter_list_head, sxe2_mac_filter); +TAILQ_HEAD(sxe2_mc_filter_list_head, sxe2_mac_filter); + +int32_t sxe2_uc_filter_add(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr, bool default_config); + +int32_t sxe2_uc_filter_del(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr); + +void sxe2_uc_filter_clear(struct sxe2_adapter *adapter, bool default_config); + +int32_t sxe2_mc_filter_add(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr, bool default_config); + +int32_t sxe2_mc_filter_del(struct sxe2_adapter *adapter, + struct rte_ether_addr *mac_addr); + +void sxe2_mc_filter_clear(struct sxe2_adapter *adapter, bool default_config); + +int32_t sxe2_vlan_filter_add(struct sxe2_adapter *adapter, + struct sxe2_vlan *vlan, bool default_config); + +int32_t sxe2_vlan_filter_del(struct sxe2_adapter *adapter, struct sxe2_vlan *vlan); + +void sxe2_vlan_filters_clear(struct sxe2_adapter *adapter, bool default_config); + +int32_t sxe2_vlan_filter_ctrl(struct sxe2_adapter *adapter, bool flag); + +int32_t sxe2_promisc_add(struct sxe2_adapter *adapter); + +int32_t sxe2_promisc_del(struct sxe2_adapter *adapter); + +int32_t sxe2_allmulti_add(struct sxe2_adapter *adapter); + +int32_t sxe2_allmulti_del(struct sxe2_adapter *adapter); + +int32_t sxe2_l2_rule_update(struct sxe2_adapter *adapter); + +int32_t sxe2_filter_rule_stop(struct rte_eth_dev *dev); + +int32_t sxe2_filter_rule_start(struct rte_eth_dev *dev); + +int32_t sxe2_filter_init(struct rte_eth_dev *dev); + +int32_t sxe2_filter_uinit(struct rte_eth_dev *dev); + +#endif /* __SXE2_FILTER_H__ */ diff --git a/drivers/net/sxe2/sxe2_mac.c b/drivers/net/sxe2/sxe2_mac.c index 3c2f909002..d94936a742 100644 --- a/drivers/net/sxe2/sxe2_mac.c +++ b/drivers/net/sxe2/sxe2_mac.c @@ -10,6 +10,438 @@ #include "sxe2_cmd_chnl.h" #include "sxe2_host_regs.h" +int32_t sxe2_mac_default_cfg(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret; + struct rte_ether_addr broadcast = { + .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} }; + struct rte_ether_addr mac_addr; + + rte_ether_addr_copy((struct rte_ether_addr *) + adapter->dev_info.mac.perm_addr, &mac_addr); + ret = sxe2_uc_filter_add(adapter, &mac_addr, true); + if (ret != 0) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add default MAC filter"); + goto l_end; + } + + rte_ether_addr_copy(&broadcast, &mac_addr); + ret = sxe2_mc_filter_add(adapter, &mac_addr, true); + if (ret != 0) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add broadcast MAC filter"); + goto l_end; + } + + ret = 0; +l_end: + return ret; +} + +int32_t sxe2_mac_addr_init(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = -1; + PMD_INIT_FUNC_TRACE(); + + if (!rte_is_unicast_ether_addr + ((struct rte_ether_addr *)adapter->dev_info.mac.perm_addr)) { + PMD_DEV_LOG_ERR(adapter, DRV, "Invalid MAC address"); + ret = -EINVAL; + goto l_end; + } + + dev->data->mac_addrs = rte_zmalloc("sxe2_mac_adds", + sizeof(struct rte_ether_addr) * SXE2_NUM_MACADDR_MAX, 0); + if (!dev->data->mac_addrs) { + PMD_LOG_ERR(DRV, "Failed to allocate memory to store mac address"); + ret = -ENOMEM; + goto l_end; + } + + rte_ether_addr_copy((struct rte_ether_addr *)adapter->dev_info.mac.perm_addr, + &dev->data->mac_addrs[0]); + + ret = 0; + +l_end: + return ret; +} + +void sxe2_mac_addr_uinit(struct rte_eth_dev *dev) +{ + PMD_INIT_FUNC_TRACE(); + if (dev != NULL && dev->data->mac_addrs != NULL) { + rte_free(dev->data->mac_addrs); + dev->data->mac_addrs = NULL; + } +} + +int32_t sxe2_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, + __rte_unused uint32_t index, __rte_unused uint32_t pool) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = -1; + + if (rte_is_zero_ether_addr(mac_addr)) { + PMD_DEV_LOG_ERR(adapter, DRV, "Invalid MAC Address"); + ret = -EINVAL; + goto l_end; + } + + if (rte_is_multicast_ether_addr(mac_addr)) + ret = sxe2_mc_filter_add(adapter, mac_addr, true); + else + ret = sxe2_uc_filter_add(adapter, mac_addr, false); + + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add MAC filter"); + +l_end: + return ret; +} + +void sxe2_mac_addr_del(struct rte_eth_dev *dev, uint32_t index) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[index]; + int32_t ret = -1; + + if (rte_is_multicast_ether_addr(mac_addr)) + ret = sxe2_mc_filter_del(adapter, mac_addr); + else + ret = sxe2_uc_filter_del(adapter, mac_addr); + + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to remove MAC filter"); +} + +int32_t sxe2_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + struct rte_ether_addr *old_addr = (struct rte_ether_addr *)&adapter->dev_info.mac.perm_addr; + struct rte_ether_addr temp_addr; + + if (rte_is_same_ether_addr(old_addr, mac_addr)) + goto l_end; + + if (rte_is_multicast_ether_addr(mac_addr)) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set multicast addr"); + ret = -EINVAL; + goto l_end; + } + + ret = sxe2_uc_filter_del(adapter, old_addr); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to remove MAC filter"); + goto l_end; + } + + rte_ether_addr_copy(old_addr, &temp_addr); + + rte_ether_addr_copy(mac_addr, old_addr); + + ret = sxe2_uc_filter_add(adapter, mac_addr, true); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add MAC filter"); + rte_ether_addr_copy(&temp_addr, old_addr); + (void)sxe2_uc_filter_add(adapter, old_addr, true); + goto l_end; + } +l_end: + return ret; +} + +int32_t sxe2_set_mc_addr_list(struct rte_eth_dev *dev, + struct rte_ether_addr *mc_addrs, + uint32_t mc_addrs_num) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + uint32_t i; + const uint8_t *mac; + + if (mc_addrs_num > SXE2_NUM_MACADDR_MAX) { + PMD_DEV_LOG_ERR(adapter, DRV, "Too many multicast MAC addresses, "); + ret = -1; + goto l_end; + } + + sxe2_mc_filter_clear(adapter, false); + + for (i = 0; i < mc_addrs_num; i++) { + if (!rte_is_multicast_ether_addr(&mc_addrs[i])) { + mac = mc_addrs[i].addr_bytes; + PMD_DEV_LOG_ERR(adapter, DRV, + "Invalid mac: %02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], + mac[5]); + ret = -EINVAL; + goto add_err; + } + + ret = sxe2_mc_filter_add(adapter, &mc_addrs[i], false); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Failed to remove old multicast MAC filter list"); + goto add_err; + } + } + goto l_end; +add_err: + sxe2_mc_filter_clear(adapter, false); +l_end: + return ret; +} + +int32_t sxe2_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int32_t on) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + struct sxe2_vlan vlan = { + .tpid = RTE_ETHER_TYPE_VLAN, + .vid = vlan_id, + .prio = 0 + }; + int32_t ret = 0; + + if (sxe2_dev_port_vlan_check(dev)) { + PMD_DEV_LOG_ERR(adapter, DRV, "Filter not supported with Port VLAN"); + ret = -ENOTSUP; + goto l_end; + } + + if (vlan_id == 0) + goto l_end; + + if (on) { + ret = sxe2_vlan_filter_add(adapter, &vlan, false); + if (ret < 0) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan filter"); + goto l_end; + } + } else { + ret = sxe2_vlan_filter_del(adapter, &vlan); + if (ret < 0) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to remove vlan filter"); + goto l_end; + } + } + +l_end: + return ret; +} + +int32_t sxe2_dev_vlan_offload_set(struct rte_eth_dev *dev, int32_t mask) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode; + struct sxe2_vlan_info new_info = adapter->filter_ctxt.vlan_info; + bool port_vlan = new_info.port_vlan_exist; + + uint8_t out_strip_mask = SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021Q | + SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021AD | + SXE2_DPDK_OFFLOAD_OUTER_STRIP_QINQ1; + + if (txmode->offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT) { + if (!(txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)) { + PMD_DEV_LOG_ERR(adapter, DRV, + "VLAN INSERT must be enabled when QinQ INSERT is enabled"); + return -EINVAL; + } + if (port_vlan) { + PMD_DEV_LOG_ERR(adapter, DRV, + "QINQ INSERT not supported with Port VLAN"); + return -EINVAL; + } + } + + if (mask & RTE_ETH_QINQ_STRIP_MASK) { + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) { + if (port_vlan) { + PMD_DEV_LOG_ERR(adapter, DRV, + "QinQ strip not supported with Port VLAN"); + return -EINVAL; + } + new_info.inner_strip = SXE2_VSI_TSR_ID_VLAN; + } else { + new_info.inner_strip = 0; + } + } + + if (mask & RTE_ETH_VLAN_STRIP_MASK) { + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) { + new_info.outer_strip = + port_vlan ? 0 : out_strip_mask; + new_info.inner_strip = + port_vlan ? new_info.inner_strip : new_info.inner_strip; + } else { + if (new_info.inner_strip != 0) { + PMD_DEV_LOG_ERR(adapter, DRV, + "Must disable QinQ strip before disabling VLAN strip"); + return -EINVAL; + } + new_info.outer_strip = 0; + } + } + + if (mask & (RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_QINQ_STRIP_MASK)) { + struct sxe2_vlan_info old_info = adapter->filter_ctxt.vlan_info; + adapter->filter_ctxt.vlan_info = new_info; + + ret = sxe2_drv_vlan_insert_strip_cfg(adapter); + if (ret) { + adapter->filter_ctxt.vlan_info = old_info; + return ret; + } + } + if (mask & RTE_ETH_VLAN_FILTER_MASK) { + if (adapter->filter_ctxt.vlan_info.port_vlan_exist) { + ret = 0; + PMD_DEV_LOG_INFO(adapter, INIT, "vlan filter is not support when port vlan is enabled"); + goto l_end; + } + + ret = sxe2_vlan_filter_ctrl(adapter, + !!(rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER)); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, + "sxe2_drv_vlan_filter_switch failed ret:%d", ret); + goto l_end; + } + } + + PMD_DEV_LOG_DEBUG(adapter, DRV, + "mask:0x%x rx mode offload:0x%" PRIx64 " vlan offload set done", + mask, rxmode->offloads); +l_end: + return ret; +} + +static int32_t sxe2_vlan_filter_zero(struct sxe2_adapter *adapter) +{ + struct sxe2_vlan vlan; + int32_t ret; + uint16_t tpids[] = {RTE_ETHER_TYPE_VLAN, RTE_ETHER_TYPE_QINQ, RTE_ETHER_TYPE_QINQ1}; + uint8_t i; + + vlan = (struct sxe2_vlan){0, 0, 0}; + ret = sxe2_vlan_filter_add(adapter, &vlan, true); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add VLAN ID 0"); + goto l_end; + } + + for (i = 0; i < RTE_DIM(tpids); i++) { + vlan = (struct sxe2_vlan){tpids[i], 0, 0}; + ret = sxe2_vlan_filter_add(adapter, &vlan, true); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add VLAN ID 0 when tpid:0x%x", + tpids[i]); + goto l_end; + } + } + +l_end: + return ret; +} + +int32_t sxe2_vlan_cfg_init(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + + ret = sxe2_drv_vlan_config_query(adapter); + if (ret) { + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to query vlan config, ret=%d", ret); + goto l_end; + } + + if (!sxe2_dev_port_vlan_check(dev)) + adapter->filter_ctxt.vlan_info.outer_insert = + SXE2_DPDK_OFFLOAD_OUTER_INSERT_8021Q | + SXE2_DPDK_OFFLOAD_INSERT_ENABLE; + else + adapter->filter_ctxt.vlan_info.outer_insert = 0; + + adapter->filter_ctxt.vlan_info.inner_insert = + SXE2_DPDK_OFFLOAD_INNER_INSERT_QINQ1 | SXE2_DPDK_OFFLOAD_INSERT_ENABLE; + + if (!sxe2_dev_port_vlan_check(dev)) { + ret = sxe2_vlan_filter_zero(adapter); + if (ret != 0) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan filter switch:0 " + "for port:%d", adapter->port_idx); + } + +l_end: + return ret; +} + +int32_t sxe2_vlan_default_cfg(struct rte_eth_dev *dev) +{ + int32_t ret = 0; + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + + ret = sxe2_dev_vlan_offload_set(dev, RTE_ETH_VLAN_STRIP_MASK | + RTE_ETH_QINQ_STRIP_MASK | + RTE_ETH_VLAN_FILTER_MASK); + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cfg vlan offload, ret:%d", ret); + + return ret; +} + +int32_t sxe2_promisc_enable(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + + ret = sxe2_promisc_add(adapter); + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to enable promisc, ret:%d", ret); + + return ret; +} + +int32_t sxe2_promisc_disable(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + + ret = sxe2_promisc_del(adapter); + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to disable promisc, ret:%d", ret); + + return ret; +} + +int32_t sxe2_allmulti_enable(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + + ret = sxe2_allmulti_add(adapter); + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to enable allmulti, ret:%d", ret); + + return ret; +} + +int32_t sxe2_allmulti_disable(struct rte_eth_dev *dev) +{ + struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); + int32_t ret = 0; + + ret = sxe2_allmulti_del(adapter); + if (ret) + PMD_DEV_LOG_ERR(adapter, DRV, "Failed to disable allmulti, ret:%d", ret); + + return ret; +} + int32_t sxe2_link_update_init(struct rte_eth_dev *dev) { struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); diff --git a/drivers/net/sxe2/sxe2_mac.h b/drivers/net/sxe2/sxe2_mac.h index 28dc05e125..55fd1829a0 100644 --- a/drivers/net/sxe2/sxe2_mac.h +++ b/drivers/net/sxe2/sxe2_mac.h @@ -34,7 +34,7 @@ SXE2_DPDK_OFFLOAD_OUTER_STRIP_QINQ1) #define SXE2_DPDK_OFFLOAD_STRIP_OFFSET SXE2_VSI_TSR_SHOW_TAG_S -#define SXE2_DPDK_OFFLOAD_INSERT_ENABLE (BIT(3)) +#define SXE2_DPDK_OFFLOAD_INSERT_ENABLE (RTE_BIT32(3)) struct sxe2_mac_mc_list { uint32_t count; @@ -43,6 +43,40 @@ struct sxe2_mac_mc_list { int32_t sxe2_link_update_init(struct rte_eth_dev *dev); +int32_t sxe2_mac_default_cfg(struct rte_eth_dev *dev); + +int32_t sxe2_vlan_cfg_init(struct rte_eth_dev *dev); + +int32_t sxe2_mac_addr_init(struct rte_eth_dev *dev); + +void sxe2_mac_addr_uinit(struct rte_eth_dev *dev); + +int32_t sxe2_mac_addr_add(struct rte_eth_dev *dev, + struct rte_ether_addr *mac_addr, + __rte_unused uint32_t index, __rte_unused uint32_t pool); + +void sxe2_mac_addr_del(struct rte_eth_dev *dev, uint32_t index); + +int32_t sxe2_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr); + +int32_t sxe2_set_mc_addr_list(struct rte_eth_dev *dev, + struct rte_ether_addr *mc_addrs, + uint32_t mc_addrs_num); + +int32_t sxe2_promisc_enable(struct rte_eth_dev *dev); + +int32_t sxe2_promisc_disable(struct rte_eth_dev *dev); + +int32_t sxe2_allmulti_enable(struct rte_eth_dev *dev); + +int32_t sxe2_allmulti_disable(struct rte_eth_dev *dev); + +int32_t sxe2_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int32_t on); + +int32_t sxe2_dev_vlan_offload_set(struct rte_eth_dev *dev, int32_t mask); + +int32_t sxe2_vlan_default_cfg(struct rte_eth_dev *dev); + int32_t sxe2_link_update(struct rte_eth_dev *dev, __rte_unused int32_t wait_to_complete); int32_t sxe2_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); diff --git a/drivers/net/sxe2/sxe2_txrx_poll.c b/drivers/net/sxe2/sxe2_txrx_poll.c index b9d34afb31..21d5c38725 100644 --- a/drivers/net/sxe2/sxe2_txrx_poll.c +++ b/drivers/net/sxe2/sxe2_txrx_poll.c @@ -660,6 +660,53 @@ sxe2_rx_desc_error_para(__rte_unused struct sxe2_rx_queue *rxq, return flags; } +static inline void sxe2_rx_desc_vlan_para_fill(struct rte_mbuf *mbuf, + union sxe2_rx_desc *desc) +{ + if (0 == (rte_le_to_cpu_64(desc->wb.status_err_ptype_len) & + SXE2_RX_DESC_STATUS_L2TAG1_P_MASK)) { + mbuf->vlan_tci = 0; + } else { + mbuf->ol_flags |= (RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED); + mbuf->vlan_tci = rte_le_to_cpu_16(desc->wb.l2tag1); + PMD_LOG_DEBUG(RX, "Rx desc mbuf vlan, vlan_tci:%u", + mbuf->vlan_tci); + } +#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC + if (0 == (rte_le_to_cpu_32(desc->wb.status_lrocnt_fdpf_id) & + SXE2_RX_DESC_EXT_STATUS_L2TAG2P_MASK)) { + mbuf->vlan_tci_outer = 0; + } else { + mbuf->ol_flags |= RTE_MBUF_F_RX_QINQ_STRIPPED | RTE_MBUF_F_RX_QINQ | + RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN; + mbuf->vlan_tci_outer = mbuf->vlan_tci; + mbuf->vlan_tci = rte_le_to_cpu_16(desc->wb.l2tag2_2nd); + PMD_LOG_DEBUG(RX, "Rx desc out vlan, l2tag2_1st:%u l2tag2_2nd:%u.", + rte_le_to_cpu_16(desc->wb.l2tag2_1st), + rte_le_to_cpu_16(desc->wb.l2tag2_2nd)); + } +#endif +} + +static inline void +sxe2_rx_desc_filter_para_fill(struct sxe2_rx_queue *rxq __rte_unused, + struct rte_mbuf *mbuf, union sxe2_rx_desc *desc) +{ + if (SXE2_RX_DESC_STATUS_RSS_VLD_MASK & + rte_le_to_cpu_64(desc->wb.status_err_ptype_len)) { + mbuf->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + mbuf->hash.rss = rte_le_to_cpu_32(desc->wb.filter_status); + PMD_LOG_DEBUG(RX, "rss id:%u", mbuf->hash.rss); + } +#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC + if (SXE2_RX_DESC_FD_VLD_MASK & desc->wb.rxdid_src) { + mbuf->ol_flags |= (RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID); + mbuf->hash.fdir.hi = rte_le_to_cpu_32(desc->wb.fd_filter_id); + PMD_LOG_DEBUG(RX, "fdir id:%u", mbuf->hash.fdir.hi); + } +#endif +} + static __rte_always_inline void sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf, union sxe2_rx_desc *rxd) @@ -673,6 +720,8 @@ sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf mbuf->packet_type = ptype_tbl[SXE2_RX_DESC_PTYPE_VAL_GET(qword1)]; pkt_flags = sxe2_rx_desc_error_para(rxq, rxd); + sxe2_rx_desc_vlan_para_fill(mbuf, rxd); + sxe2_rx_desc_filter_para_fill(rxq, mbuf, rxd); mbuf->ol_flags |= pkt_flags; } -- 2.47.3

