From: Yahui Cao Date: Fri, 18 Oct 2019 11:16:00 +0000 (+0800) Subject: net/ice: reject duplicated flow for flow director X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=1a2fc1799f09212e79652b347529cd8d95e99523;p=dpdk.git net/ice: reject duplicated flow for flow director Enable duplication lookup for existing flow director rule entry. Signed-off-by: Yahui Cao Acked-by: Qi Zhang Reviewed-by: Xiaolong Ye --- diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile index f7e1852885..884fc4075c 100644 --- a/drivers/net/ice/Makefile +++ b/drivers/net/ice/Makefile @@ -13,7 +13,7 @@ CFLAGS += $(WERROR_FLAGS) CFLAGS += -DALLOW_EXPERIMENTAL_API LDLIBS += -lrte_eal -lrte_mbuf -lrte_ethdev -lrte_kvargs -LDLIBS += -lrte_bus_pci -lrte_mempool +LDLIBS += -lrte_bus_pci -lrte_mempool -lrte_hash EXPORT_MAP := rte_pmd_ice_version.map diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h index 5129b3b67f..ab8b452e4a 100644 --- a/drivers/net/ice/ice_ethdev.h +++ b/drivers/net/ice/ice_ethdev.h @@ -256,6 +256,20 @@ struct ice_fdir_filter_conf { uint64_t input_set; }; +#define ICE_MAX_FDIR_FILTER_NUM (1024 * 16) + +struct ice_fdir_fltr_pattern { + enum ice_fltr_ptype flow_type; + + union { + struct ice_fdir_v4 v4; + struct ice_fdir_v6 v6; + } ip, mask; + + struct ice_fdir_extra ext_data; + struct ice_fdir_extra ext_mask; +}; + #define ICE_FDIR_COUNTER_DEFAULT_POOL_SIZE 1 #define ICE_FDIR_COUNTER_MAX_POOL_SIZE 32 #define ICE_FDIR_COUNTERS_PER_BLOCK 256 @@ -301,6 +315,9 @@ struct ice_fdir_info { uint64_t dma_addr; /* physic address of packet memory*/ struct ice_fdir_filter_conf conf; + struct ice_fdir_filter_conf **hash_map; + struct rte_hash *hash_table; + struct ice_fdir_counter_pool_container counter; }; diff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir_filter.c index b327ead805..1b6101ec6b 100644 --- a/drivers/net/ice/ice_fdir_filter.c +++ b/drivers/net/ice/ice_fdir_filter.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include "base/ice_fdir.h" #include "base/ice_flow.h" #include "base/ice_type.h" @@ -272,6 +274,60 @@ ice_fdir_counter_free(__rte_unused struct ice_pf *pf, } } +static int +ice_fdir_init_filter_list(struct ice_pf *pf) +{ + struct rte_eth_dev *dev = pf->adapter->eth_dev; + struct ice_fdir_info *fdir_info = &pf->fdir; + char fdir_hash_name[RTE_HASH_NAMESIZE]; + int ret; + + struct rte_hash_parameters fdir_hash_params = { + .name = fdir_hash_name, + .entries = ICE_MAX_FDIR_FILTER_NUM, + .key_len = sizeof(struct ice_fdir_fltr_pattern), + .hash_func = rte_hash_crc, + .hash_func_init_val = 0, + .socket_id = rte_socket_id(), + }; + + /* Initialize hash */ + snprintf(fdir_hash_name, RTE_HASH_NAMESIZE, + "fdir_%s", dev->device->name); + fdir_info->hash_table = rte_hash_create(&fdir_hash_params); + if (!fdir_info->hash_table) { + PMD_INIT_LOG(ERR, "Failed to create fdir hash table!"); + return -EINVAL; + } + fdir_info->hash_map = rte_zmalloc("ice_fdir_hash_map", + sizeof(*fdir_info->hash_map) * + ICE_MAX_FDIR_FILTER_NUM, + 0); + if (!fdir_info->hash_map) { + PMD_INIT_LOG(ERR, + "Failed to allocate memory for fdir hash map!"); + ret = -ENOMEM; + goto err_fdir_hash_map_alloc; + } + return 0; + +err_fdir_hash_map_alloc: + rte_hash_free(fdir_info->hash_table); + + return ret; +} + +static void +ice_fdir_release_filter_list(struct ice_pf *pf) +{ + struct ice_fdir_info *fdir_info = &pf->fdir; + + if (fdir_info->hash_map) + rte_free(fdir_info->hash_map); + if (fdir_info->hash_table) + rte_hash_free(fdir_info->hash_table); +} + /* * ice_fdir_setup - reserve and initialize the Flow Director resources * @pf: board private structure @@ -309,6 +365,12 @@ ice_fdir_setup(struct ice_pf *pf) } pf->fdir.fdir_vsi = vsi; + err = ice_fdir_init_filter_list(pf); + if (err) { + PMD_DRV_LOG(ERR, "Failed to init FDIR filter list."); + return -EINVAL; + } + err = ice_fdir_counter_init(pf); if (err) { PMD_DRV_LOG(ERR, "Failed to init FDIR counter."); @@ -470,6 +532,8 @@ ice_fdir_teardown(struct ice_pf *pf) if (err) PMD_DRV_LOG(ERR, "Failed to release FDIR counter resource."); + ice_fdir_release_filter_list(pf); + ice_tx_queue_release(pf->fdir.txq); pf->fdir.txq = NULL; ice_rx_queue_release(pf->fdir.rxq); @@ -752,6 +816,74 @@ ice_fdir_add_del_filter(struct ice_pf *pf, return ice_fdir_programming(pf, &desc); } +static void +ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key, + struct ice_fdir_filter_conf *filter) +{ + struct ice_fdir_fltr *input = &filter->input; + memset(key, 0, sizeof(*key)); + + key->flow_type = input->flow_type; + rte_memcpy(&key->ip, &input->ip, sizeof(key->ip)); + rte_memcpy(&key->mask, &input->mask, sizeof(key->mask)); + rte_memcpy(&key->ext_data, &input->ext_data, sizeof(key->ext_data)); + rte_memcpy(&key->ext_mask, &input->ext_mask, sizeof(key->ext_mask)); +} + +/* Check if there exists the flow director filter */ +static struct ice_fdir_filter_conf * +ice_fdir_entry_lookup(struct ice_fdir_info *fdir_info, + const struct ice_fdir_fltr_pattern *key) +{ + int ret; + + ret = rte_hash_lookup(fdir_info->hash_table, key); + if (ret < 0) + return NULL; + + return fdir_info->hash_map[ret]; +} + +/* Add a flow director entry into the SW list */ +static int +ice_fdir_entry_insert(struct ice_pf *pf, + struct ice_fdir_filter_conf *entry, + struct ice_fdir_fltr_pattern *key) +{ + struct ice_fdir_info *fdir_info = &pf->fdir; + int ret; + + ret = rte_hash_add_key(fdir_info->hash_table, key); + if (ret < 0) { + PMD_DRV_LOG(ERR, + "Failed to insert fdir entry to hash table %d!", + ret); + return ret; + } + fdir_info->hash_map[ret] = entry; + + return 0; +} + +/* Delete a flow director entry from the SW list */ +static int +ice_fdir_entry_del(struct ice_pf *pf, struct ice_fdir_fltr_pattern *key) +{ + struct ice_fdir_info *fdir_info = &pf->fdir; + int ret; + + ret = rte_hash_del_key(fdir_info->hash_table, key); + if (ret < 0) { + PMD_DRV_LOG(ERR, + "Failed to delete fdir filter to hash table %d!", + ret); + return ret; + } + fdir_info->hash_map[ret] = NULL; + + return 0; +} + static int ice_fdir_create_filter(struct ice_adapter *ad, struct rte_flow *flow, @@ -760,11 +892,22 @@ ice_fdir_create_filter(struct ice_adapter *ad, { struct ice_pf *pf = &ad->pf; struct ice_fdir_filter_conf *filter = meta; - struct ice_fdir_filter_conf *rule; + struct ice_fdir_info *fdir_info = &pf->fdir; + struct ice_fdir_filter_conf *entry, *node; + struct ice_fdir_fltr_pattern key; int ret; - rule = rte_zmalloc("fdir_entry", sizeof(*rule), 0); - if (!rule) { + ice_fdir_extract_fltr_key(&key, filter); + node = ice_fdir_entry_lookup(fdir_info, &key); + if (node) { + rte_flow_error_set(error, EEXIST, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "Rule already exists!"); + return -rte_errno; + } + + entry = rte_zmalloc("fdir_entry", sizeof(*entry), 0); + if (!entry) { rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Failed to allocate memory"); @@ -804,9 +947,18 @@ ice_fdir_create_filter(struct ice_adapter *ad, goto free_counter; } - rte_memcpy(rule, filter, sizeof(*rule)); - flow->rule = rule; + rte_memcpy(entry, filter, sizeof(*entry)); + ret = ice_fdir_entry_insert(pf, entry, &key); + if (ret) { + rte_flow_error_set(error, -ret, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "Insert entry to table failed."); + goto free_entry; + } + + flow->rule = entry; ice_fdir_cnt_update(pf, filter->input.flow_type, false, true); + return 0; free_counter: @@ -816,7 +968,7 @@ free_counter: } free_entry: - rte_free(rule); + rte_free(entry); return -rte_errno; } @@ -826,7 +978,9 @@ ice_fdir_destroy_filter(struct ice_adapter *ad, struct rte_flow_error *error) { struct ice_pf *pf = &ad->pf; - struct ice_fdir_filter_conf *filter; + struct ice_fdir_info *fdir_info = &pf->fdir; + struct ice_fdir_filter_conf *filter, *entry; + struct ice_fdir_fltr_pattern key; int ret; filter = (struct ice_fdir_filter_conf *)flow->rule; @@ -836,6 +990,15 @@ ice_fdir_destroy_filter(struct ice_adapter *ad, filter->counter = NULL; } + ice_fdir_extract_fltr_key(&key, filter); + entry = ice_fdir_entry_lookup(fdir_info, &key); + if (!entry) { + rte_flow_error_set(error, ENOENT, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "Can't find entry."); + return -rte_errno; + } + ret = ice_fdir_add_del_filter(pf, filter, false); if (ret) { rte_flow_error_set(error, -ret, @@ -844,6 +1007,14 @@ ice_fdir_destroy_filter(struct ice_adapter *ad, return -rte_errno; } + ret = ice_fdir_entry_del(pf, &key); + if (ret) { + rte_flow_error_set(error, -ret, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "Remove entry from table failed."); + return -rte_errno; + } + ice_fdir_cnt_update(pf, filter->input.flow_type, false, false); flow->rule = NULL;