From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 615D65598 for ; Fri, 2 Dec 2016 05:12:58 +0100 (CET) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga103.fm.intel.com with ESMTP; 01 Dec 2016 20:12:57 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,284,1477983600"; d="scan'208";a="907853426" Received: from dpdk9.sh.intel.com ([10.239.129.141]) by orsmga003.jf.intel.com with ESMTP; 01 Dec 2016 20:12:56 -0800 From: Beilei Xing To: jingjing.wu@intel.com, helin.zhang@intel.com Cc: dev@dpdk.org, wenzhuo.lu@intel.com Date: Fri, 2 Dec 2016 06:53:22 -0500 Message-Id: <1480679625-4157-2-git-send-email-beilei.xing@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1480679625-4157-1-git-send-email-beilei.xing@intel.com> References: <1480679625-4157-1-git-send-email-beilei.xing@intel.com> Subject: [dpdk-dev] [PATCH 01/24] net/i40e: store ethertype filter X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Dec 2016 04:12:59 -0000 Add support of storing ethertype filter in SW. Signed-off-by: Beilei Xing --- 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 #include #include +#include #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(ðertype_info->ethertype_list); + snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE, + "ethertype_%s", dev->data->name); + ethertype_info->hash_table = rte_hash_create(ðertype_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(ðertype_info->ethertype_list))) { + TAILQ_REMOVE(ðertype_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(ðertype_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(ðertype_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, + ðertype_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 #include #include +#include #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