[dpdk-dev] [PATCH 01/24] net/i40e: store ethertype filter

Beilei Xing beilei.xing at intel.com
Fri Dec 2 12:53:22 CET 2016


Add support of storing ethertype filter in SW.

Signed-off-by: Beilei Xing <beilei.xing at intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 160 ++++++++++++++++++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |  25 +++++++
 2 files changed, 184 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..30822a0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -51,6 +51,7 @@
 #include <rte_dev.h>
 #include <rte_eth_ctrl.h>
 #include <rte_tailq.h>
+#include <rte_hash_crc.h>
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -461,6 +462,17 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 
 static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 
+static int i40e_ethertype_filter_convert(
+	const struct rte_eth_ethertype_filter *input,
+	struct i40e_ethertype_filter *filter);
+static struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_info *ethertype_info,
+			const struct i40e_ethertype_filter_input *input);
+static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+				   struct i40e_ethertype_filter *filter);
+static int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+					struct i40e_ethertype_filter *filter);
+
 static const struct rte_pci_id pci_id_i40e_map[] = {
 	{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
 	{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -937,9 +949,18 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	int ret;
 	uint32_t len;
 	uint8_t aq_fail = 0;
+	struct i40e_ethertype_info *ethertype_info = &pf->ethertype;
 
 	PMD_INIT_FUNC_TRACE();
 
+	char ethertype_hash_name[RTE_HASH_NAMESIZE];
+	struct rte_hash_parameters ethertype_hash_params = {
+		.name = ethertype_hash_name,
+		.entries = I40E_MAX_ETHERTYPE_FILTER_NUM,
+		.key_len = sizeof(struct i40e_ethertype_filter_input),
+		.hash_func = rte_hash_crc,
+	};
+
 	dev->dev_ops = &i40e_eth_dev_ops;
 	dev->rx_pkt_burst = i40e_recv_pkts;
 	dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1179,8 +1200,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		pf->flags &= ~I40E_FLAG_DCB;
 	}
 
+	/* Initialize ethertype filter rule list and hash */
+	TAILQ_INIT(&ethertype_info->ethertype_list);
+	snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE,
+		 "ethertype_%s", dev->data->name);
+	ethertype_info->hash_table = rte_hash_create(&ethertype_hash_params);
+	if (!ethertype_info->hash_table) {
+		PMD_INIT_LOG(ERR, "Failed to create ethertype hash table!");
+		ret = -EINVAL;
+		goto err_ethertype_hash_table_create;
+	}
+	ethertype_info->hash_map = rte_zmalloc("i40e_ethertype_hash_map",
+				       sizeof(struct i40e_ethertype_filter *) *
+				       I40E_MAX_ETHERTYPE_FILTER_NUM,
+				       0);
+	if (!ethertype_info->hash_map) {
+		PMD_INIT_LOG(ERR,
+		     "Failed to allocate memory for ethertype hash map!");
+		ret = -ENOMEM;
+		goto err_ethertype_hash_map_alloc;
+	}
+
 	return 0;
 
+err_ethertype_hash_map_alloc:
+	rte_hash_free(ethertype_info->hash_table);
+err_ethertype_hash_table_create:
+	rte_free(dev->data->mac_addrs);
 err_mac_alloc:
 	i40e_vsi_release(pf->main_vsi);
 err_setup_pf_switch:
@@ -1203,23 +1249,40 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 static int
 eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 {
+	struct i40e_pf *pf;
 	struct rte_pci_device *pci_dev;
 	struct i40e_hw *hw;
 	struct i40e_filter_control_settings settings;
+	struct i40e_ethertype_filter *p_ethertype;
 	int ret;
 	uint8_t aq_fail = 0;
+	struct i40e_ethertype_info *ethertype_info;
 
 	PMD_INIT_FUNC_TRACE();
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	pci_dev = dev->pci_dev;
+	ethertype_info = &pf->ethertype;
 
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
+	/* Remove all ethertype director rules and hash */
+	if (ethertype_info->hash_map)
+		rte_free(ethertype_info->hash_map);
+	if (ethertype_info->hash_table)
+		rte_hash_free(ethertype_info->hash_table);
+
+	while ((p_ethertype = TAILQ_FIRST(&ethertype_info->ethertype_list))) {
+		TAILQ_REMOVE(&ethertype_info->ethertype_list,
+			     p_ethertype, rules);
+		rte_free(p_ethertype);
+	}
+
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
@@ -7986,6 +8049,74 @@ i40e_hash_filter_ctrl(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+i40e_ethertype_filter_convert(const struct rte_eth_ethertype_filter *input,
+			      struct i40e_ethertype_filter *filter)
+{
+	rte_memcpy(&filter->input.mac_addr, &input->mac_addr, ETHER_ADDR_LEN);
+	filter->input.ether_type = input->ether_type;
+	filter->flags = input->flags;
+	filter->queue = input->queue;
+
+	return 0;
+}
+
+static struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_info *ethertype_info,
+				const struct i40e_ethertype_filter_input *input)
+{
+	int ret = 0;
+
+	ret = rte_hash_lookup(ethertype_info->hash_table, (const void *)input);
+	if (ret < 0)
+		return NULL;
+
+	return ethertype_info->hash_map[ret];
+}
+
+static int
+i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+				struct i40e_ethertype_filter *filter)
+{
+	struct i40e_ethertype_info *ethertype_info = &pf->ethertype;
+	int ret = 0;
+
+	ret = rte_hash_add_key(ethertype_info->hash_table,
+			       &filter->input);
+	if (ret < 0)
+		PMD_DRV_LOG(ERR,
+			    "Failed to insert ethertype filter"
+			    " to hash table %d!",
+			    ret);
+	ethertype_info->hash_map[ret] = filter;
+
+	TAILQ_INSERT_TAIL(&ethertype_info->ethertype_list, filter, rules);
+
+	return 0;
+}
+
+static int
+i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+			     struct i40e_ethertype_filter *filter)
+{
+	struct i40e_ethertype_info *ethertype_info = &pf->ethertype;
+	int ret = 0;
+
+	ret = rte_hash_del_key(ethertype_info->hash_table,
+			       &filter->input);
+	if (ret < 0)
+		PMD_DRV_LOG(ERR,
+			    "Failed to delete ethertype filter"
+			    " to hash table %d!",
+			    ret);
+	ethertype_info->hash_map[ret] = NULL;
+
+	TAILQ_REMOVE(&ethertype_info->ethertype_list, filter, rules);
+	rte_free(filter);
+
+	return 0;
+}
+
 /*
  * Configure ethertype filter, which can director packet by filtering
  * with mac address and ether_type or only ether_type
@@ -7996,6 +8127,8 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
 			bool add)
 {
 	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct i40e_ethertype_info *ethertype_info = &pf->ethertype;
+	struct i40e_ethertype_filter *ethertype_filter, *node;
 	struct i40e_control_filter_stats stats;
 	uint16_t flags = 0;
 	int ret;
@@ -8014,6 +8147,22 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
 		PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is"
 			" not supported.");
 
+	/* Check if there is the filter in SW list */
+	ethertype_filter = rte_zmalloc("ethertype_filter",
+				       sizeof(*ethertype_filter), 0);
+	i40e_ethertype_filter_convert(filter, ethertype_filter);
+	node = i40e_sw_ethertype_filter_lookup(ethertype_info,
+					       &ethertype_filter->input);
+	if (add && node) {
+		PMD_DRV_LOG(ERR, "Conflict with existing ethertype rules!");
+		rte_free(ethertype_filter);
+		return -EINVAL;
+	} else if (!add && !node) {
+		PMD_DRV_LOG(ERR, "There's no corresponding ethertype filter!");
+		rte_free(ethertype_filter);
+		return -EINVAL;
+	}
+
 	if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
 		flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
 	if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
@@ -8034,7 +8183,16 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
 			 stats.mac_etype_free, stats.etype_free);
 	if (ret < 0)
 		return -ENOSYS;
-	return 0;
+
+	/* Add or delete a filter in SW list */
+	if (add)
+		ret = i40e_sw_ethertype_filter_insert(pf, ethertype_filter);
+	else {
+		ret = i40e_sw_ethertype_filter_del(pf, node);
+		rte_free(ethertype_filter);
+	}
+
+	return ret;
 }
 
 /*
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 298cef4..8604198 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -37,6 +37,7 @@
 #include <rte_eth_ctrl.h>
 #include <rte_time.h>
 #include <rte_kvargs.h>
+#include <rte_hash.h>
 
 #define I40E_VLAN_TAG_SIZE        4
 
@@ -396,6 +397,29 @@ struct i40e_fdir_info {
 	struct i40e_fdir_flex_mask flex_mask[I40E_FILTER_PCTYPE_MAX];
 };
 
+#define I40E_MAX_ETHERTYPE_FILTER_NUM 768
+
+/* Ethertype filter struct */
+struct i40e_ethertype_filter_input {
+	struct ether_addr mac_addr;   /**< Mac address to match. */
+	uint16_t ether_type;          /**< Ether type to match */
+};
+
+struct i40e_ethertype_filter {
+	TAILQ_ENTRY(i40e_ethertype_filter) rules;
+	struct i40e_ethertype_filter_input input;
+	uint16_t flags;
+	uint16_t queue;
+};
+
+TAILQ_HEAD(i40e_ethertype_filter_list, i40e_ethertype_filter);
+
+struct i40e_ethertype_info {
+	struct i40e_ethertype_filter_list ethertype_list;
+	struct i40e_ethertype_filter  **hash_map;
+	struct rte_hash *hash_table;
+};
+
 #define I40E_MIRROR_MAX_ENTRIES_PER_RULE   64
 #define I40E_MAX_MIRROR_RULES           64
 /*
@@ -466,6 +490,7 @@ struct i40e_pf {
 	struct i40e_vmdq_info *vmdq;
 
 	struct i40e_fdir_info fdir; /* flow director info */
+	struct i40e_ethertype_info ethertype; /* Ethertype filter info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
-- 
2.5.5



More information about the dev mailing list