[v1,12/12] net/enetc: Add MAC and VLAN filter support

Message ID 20241018072644.2379012-13-vanshika.shukla@nxp.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series ENETC4 PMD support |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/github-robot: build success github build: passed
ci/intel-Functional success Functional PASS
ci/iol-unit-amd64-testing fail Testing issues
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-unit-arm64-testing fail Testing issues
ci/iol-sample-apps-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS

Commit Message

Vanshika Shukla Oct. 18, 2024, 7:26 a.m. UTC
From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces support for:

- Up to 4 MAC addresses filtering
- Up to 4 VLAN filters

Enhances packet filtering capabilities for ENETC4 PMD.

Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   2 +
 drivers/net/enetc/base/enetc4_hw.h  |   3 +
 drivers/net/enetc/enetc.h           |  11 ++
 drivers/net/enetc/enetc4_vf.c       | 229 +++++++++++++++++++++++++++-
 4 files changed, 244 insertions(+), 1 deletion(-)
  

Patch

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 31a1955215..87425f45c9 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -9,6 +9,8 @@  Speed capabilities   = Y
 Link status          = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
+Unicast MAC filter   = Y
+VLAN filter          = Y
 RSS hash             = Y
 Packet type parsing  = Y
 Basic stats          = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 2da779e351..e3eef6fe19 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -71,6 +71,9 @@  struct enetc_msg_swbd {
  */
 #define ENETC4_MAC_MAXFRM_SIZE  2000
 
+/* Number of MAC Address Filter table entries */
+#define ENETC4_MAC_ENTRIES      4
+
 /* Port MAC 0/1 Maximum Frame Length Register */
 #define ENETC4_PM_MAXFRM(mac)		(0x5014 + (mac) * 0x400)
 
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 6b37cd95dd..e79a0bf0a9 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -158,7 +158,10 @@  enum enetc_msg_cmd_class_id {
 /* Enum for command IDs */
 enum enetc_msg_cmd_id {
 	ENETC_CMD_ID_SET_PRIMARY_MAC = 0,
+	ENETC_MSG_ADD_EXACT_MAC_ENTRIES = 1,
 	ENETC_CMD_ID_SET_MAC_PROMISCUOUS = 5,
+	ENETC_MSG_ADD_EXACT_VLAN_ENTRIES = 0,
+	ENETC_MSG_REMOVE_EXACT_VLAN_ENTRIES = 1,
 	ENETC_CMD_ID_SET_VLAN_PROMISCUOUS = 4,
 	ENETC_CMD_ID_GET_LINK_STATUS = 0,
 	ENETC_CMD_ID_REGISTER_LINK_NOTIF = 1,
@@ -170,6 +173,14 @@  enum mac_addr_status {
 	ENETC_INVALID_MAC_ADDR = 0x0,
 	ENETC_DUPLICATE_MAC_ADDR = 0X1,
 	ENETC_MAC_ADDR_NOT_FOUND = 0X2,
+	ENETC_MAC_FILTER_NO_RESOURCE = 0x3
+};
+
+enum vlan_status {
+	ENETC_INVALID_VLAN_ENTRY = 0x0,
+	ENETC_DUPLICATE_VLAN_ENTRY = 0X1,
+	ENETC_VLAN_ENTRY_NOT_FOUND = 0x2,
+	ENETC_VLAN_NO_RESOURCE = 0x3
 };
 
 enum link_status {
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 22266188ee..fb27557378 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -17,6 +17,10 @@ 
 uint16_t enetc_crc_table[ENETC_CRC_TABLE_SIZE];
 bool enetc_crc_gen;
 
+/* Supported Rx offloads */
+static uint64_t dev_vf_rx_offloads_sup =
+	RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
+
 static void
 enetc_gen_crc_table(void)
 {
@@ -53,6 +57,25 @@  enetc_crc_calc(uint16_t crc, const uint8_t *buffer, size_t len)
 	return crc;
 }
 
+static int
+enetc4_vf_dev_infos_get(struct rte_eth_dev *dev,
+			struct rte_eth_dev_info *dev_info)
+{
+	int ret = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ret = enetc4_dev_infos_get(dev, dev_info);
+	if (ret)
+		return ret;
+
+	dev_info->max_mtu = dev_info->max_rx_pktlen - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN);
+	dev_info->max_mac_addrs = ENETC4_MAC_ENTRIES;
+	dev_info->rx_offload_capa |= dev_vf_rx_offloads_sup;
+
+	return 0;
+}
+
 int
 enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
 {
@@ -810,6 +833,201 @@  enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
 	return err;
 }
 
+static int
+enetc4_vf_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *addr,
+			uint32_t index __rte_unused, uint32_t pool __rte_unused)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_cmd_set_primary_mac *cmd;
+	struct enetc_msg_swbd *msg;
+	struct enetc_psi_reply_msg *reply_msg;
+	int msg_size;
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	if (!rte_is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
+	if (!reply_msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
+		return -ENOMEM;
+	}
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		rte_free(reply_msg);
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
+			ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		rte_free(reply_msg);
+		return -ENOMEM;
+	}
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+	cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
+	memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
+	cmd->count = 1;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
+			ENETC_MSG_ADD_EXACT_MAC_ENTRIES, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
+		switch (reply_msg->status) {
+		case ENETC_INVALID_MAC_ADDR:
+			ENETC_PMD_ERR("Invalid MAC address");
+			err = -EINVAL;
+			break;
+		case ENETC_DUPLICATE_MAC_ADDR:
+			ENETC_PMD_ERR("Duplicate MAC address");
+			err = -EINVAL;
+			break;
+		case ENETC_MAC_FILTER_NO_RESOURCE:
+			ENETC_PMD_ERR("Not enough exact-match entries available");
+			err = -EINVAL;
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		}
+	}
+
+	if (err) {
+		ENETC_PMD_ERR("VSI command execute error!");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(reply_msg);
+	rte_free(msg);
+	return err;
+}
+
+static int enetc4_vf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_vlan_exact_filter *cmd;
+	struct enetc_msg_swbd *msg;
+	struct enetc_psi_reply_msg *reply_msg;
+	int msg_size;
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
+	if (!reply_msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
+		return -ENOMEM;
+	}
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		rte_free(reply_msg);
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_vlan_exact_filter),
+			ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		rte_free(reply_msg);
+		return -ENOMEM;
+	}
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+	cmd = (struct enetc_msg_vlan_exact_filter *)msg->vaddr;
+	cmd->vlan_count = 1;
+	cmd->vlan_id = vlan_id;
+
+	/* TPID 2-bit encoding value is taken from the H/W block guide:
+	 *	00b Standard C-VLAN 0x8100
+	 *	01b Standard S-VLAN 0x88A8
+	 *	10b Custom VLAN as defined by CVLANR1[ETYPE]
+	 *	11b Custom VLAN as defined by CVLANR2[ETYPE]
+	 * Currently Standard C-VLAN is supported. To support others in future.
+	 */
+	cmd->tpid = 0;
+
+	if (on) {
+		enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
+				ENETC_MSG_ADD_EXACT_VLAN_ENTRIES, 0, 0, 0);
+	} else {
+		enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
+				ENETC_MSG_REMOVE_EXACT_VLAN_ENTRIES, 0, 0, 0);
+	}
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_VLAN_FILTER) {
+		switch (reply_msg->status) {
+		case ENETC_INVALID_VLAN_ENTRY:
+			ENETC_PMD_ERR("VLAN entry not valid");
+			err = -EINVAL;
+			break;
+		case ENETC_DUPLICATE_VLAN_ENTRY:
+			ENETC_PMD_ERR("Duplicated VLAN entry");
+			err = -EINVAL;
+			break;
+		case ENETC_VLAN_ENTRY_NOT_FOUND:
+			ENETC_PMD_ERR("VLAN entry not found");
+			err = -EINVAL;
+			break;
+		case ENETC_VLAN_NO_RESOURCE:
+			ENETC_PMD_ERR("Not enough exact-match entries available");
+			err = -EINVAL;
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		}
+	}
+
+	if (err) {
+		ENETC_PMD_ERR("VSI command execute error!");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(reply_msg);
+	rte_free(msg);
+	return err;
+}
+
 static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_unused)
 {
 	int err = 0;
@@ -838,6 +1056,12 @@  static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_un
 	return 0;
 }
 
+static int
+enetc4_vf_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
+{
+	return 0;
+}
+
 static int
 enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
 {
@@ -901,14 +1125,17 @@  static const struct eth_dev_ops enetc4_vf_ops = {
 	.dev_start            = enetc4_vf_dev_start,
 	.dev_stop             = enetc4_vf_dev_stop,
 	.dev_close            = enetc4_dev_close,
-	.dev_infos_get        = enetc4_dev_infos_get,
 	.stats_get            = enetc4_vf_stats_get,
+	.dev_infos_get        = enetc4_vf_dev_infos_get,
+	.mtu_set              = enetc4_vf_mtu_set,
 	.mac_addr_set         = enetc4_vf_set_mac_addr,
+	.mac_addr_add	      = enetc4_vf_mac_addr_add,
 	.promiscuous_enable   = enetc4_vf_promisc_enable,
 	.promiscuous_disable  = enetc4_vf_promisc_disable,
 	.allmulticast_enable  = enetc4_vf_multicast_enable,
 	.allmulticast_disable = enetc4_vf_multicast_disable,
 	.link_update	      = enetc4_vf_link_update,
+	.vlan_filter_set      = enetc4_vf_vlan_filter_set,
 	.vlan_offload_set     = enetc4_vf_vlan_offload_set,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,