Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/74292/?format=api
http://patches.dpdk.org/api/patches/74292/?format=api", "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200717171959.44998-3-chenmin.sun@intel.com/", "project": { "id": 1, "url": "http://patches.dpdk.org/api/projects/1/?format=api", "name": "DPDK", "link_name": "dpdk", "list_id": "dev.dpdk.org", "list_email": "dev@dpdk.org", "web_url": "http://core.dpdk.org", "scm_url": "git://dpdk.org/dpdk", "webscm_url": "http://git.dpdk.org/dpdk", "list_archive_url": "https://inbox.dpdk.org/dev", "list_archive_url_format": "https://inbox.dpdk.org/dev/{}", "commit_url_format": "" }, "msgid": "<20200717171959.44998-3-chenmin.sun@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dev/20200717171959.44998-3-chenmin.sun@intel.com", "date": "2020-07-17T17:19:57", "name": "[v5,2/4] net/i40e: FDIR flow memory management optimization", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "6f1db8110691e65e0ef5b621488b0c189527f0e8", "submitter": { "id": 1212, "url": "http://patches.dpdk.org/api/people/1212/?format=api", "name": "Chenmin Sun", "email": "chenmin.sun@intel.com" }, "delegate": { "id": 1540, "url": "http://patches.dpdk.org/api/users/1540/?format=api", "username": "qzhan15", "first_name": "Qi", "last_name": "Zhang", "email": "qi.z.zhang@intel.com" }, "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200717171959.44998-3-chenmin.sun@intel.com/mbox/", "series": [ { "id": 11120, "url": "http://patches.dpdk.org/api/series/11120/?format=api", "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11120", "date": "2020-07-17T17:19:55", "name": "i40e FDIR update rate optimization", "version": 5, "mbox": "http://patches.dpdk.org/series/11120/mbox/" } ], "comments": "http://patches.dpdk.org/api/patches/74292/comments/", "check": "success", "checks": "http://patches.dpdk.org/api/patches/74292/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-To": "patchwork@inbox.dpdk.org", "Received": [ "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 03BD6A0528;\n\tFri, 17 Jul 2020 10:23:33 +0200 (CEST)", "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 8BE8A1BF7D;\n\tFri, 17 Jul 2020 10:23:18 +0200 (CEST)", "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n by dpdk.org (Postfix) with ESMTP id D3B861BF6F\n for <dev@dpdk.org>; Fri, 17 Jul 2020 10:23:14 +0200 (CEST)", "from orsmga005.jf.intel.com ([10.7.209.41])\n by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 17 Jul 2020 01:23:14 -0700", "from npg-dpdk-vpp-scm-1.sh.intel.com ([10.67.118.226])\n by orsmga005.jf.intel.com with ESMTP; 17 Jul 2020 01:23:12 -0700" ], "IronPort-SDR": [ "\n n5oA61JrYoI7YQjTSlpguCWXJ0LhNJR/4zY6OsxLM9oikxyU+nK3mOt0mgP3DjBCAv4Ok8qPnh\n QDySjTSI/tJg==", "\n Y4fj8gg1TnanLuCMF9GEjqnAsHykoMFtYk/NMknQHf74I3r6BEg6QDyRkddCL/zy72iPnqo5+l\n Kscur0uyN1Yg==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6000,8403,9684\"; a=\"148714435\"", "E=Sophos;i=\"5.75,362,1589266800\"; d=\"scan'208\";a=\"148714435\"", "E=Sophos;i=\"5.75,362,1589266800\"; d=\"scan'208\";a=\"460777153\"" ], "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "From": "chenmin.sun@intel.com", "To": "qi.z.zhang@intel.com, beilei.xing@intel.com, jingjing.wu@intel.com,\n haiyue.wang@intel.com", "Cc": "dev@dpdk.org,\n\tchenmin.sun@intel.com", "Date": "Sat, 18 Jul 2020 01:19:57 +0800", "Message-Id": "<20200717171959.44998-3-chenmin.sun@intel.com>", "X-Mailer": "git-send-email 2.17.1", "In-Reply-To": "<20200717171959.44998-1-chenmin.sun@intel.com>", "References": "<20200715195329.34699-1-chenmin.sun@intel.com>\n <20200717171959.44998-1-chenmin.sun@intel.com>", "Subject": "[dpdk-dev] [PATCH v5 2/4] net/i40e: FDIR flow memory management\n\toptimization", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.15", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://mails.dpdk.org/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org", "Sender": "\"dev\" <dev-bounces@dpdk.org>" }, "content": "From: Chenmin Sun <chenmin.sun@intel.com>\n\nThis patch allocated some memory pool for flow management to avoid\ncalling rte_zmalloc/rte_free every time.\nThis patch also improves the hash table operation. When adding/removing\na flow, the software will directly add/delete it from the hash table.\nIf any error occurs, it then roll back the operation it just done.\n\nSigned-off-by: Chenmin Sun <chenmin.sun@intel.com>\n---\n drivers/net/i40e/i40e_ethdev.c | 94 +++++++++++++++++++++++--\n drivers/net/i40e/i40e_ethdev.h | 43 +++++++++---\n drivers/net/i40e/i40e_fdir.c | 121 ++++++++++++++++++++++++---------\n drivers/net/i40e/i40e_flow.c | 92 ++++++++++++++++++-------\n 4 files changed, 280 insertions(+), 70 deletions(-)", "diff": "diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c\nindex dca84a1f1..690164320 100644\n--- a/drivers/net/i40e/i40e_ethdev.c\n+++ b/drivers/net/i40e/i40e_ethdev.c\n@@ -1051,6 +1051,10 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)\n \tchar fdir_hash_name[RTE_HASH_NAMESIZE];\n \tuint32_t alloc = hw->func_caps.fd_filters_guaranteed;\n \tuint32_t best = hw->func_caps.fd_filters_best_effort;\n+\tstruct rte_bitmap *bmp = NULL;\n+\tuint32_t bmp_size;\n+\tvoid *mem = NULL;\n+\tuint32_t i = 0;\n \tint ret;\n \n \tstruct rte_hash_parameters fdir_hash_params = {\n@@ -1083,6 +1087,18 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)\n \t\tgoto err_fdir_hash_map_alloc;\n \t}\n \n+\tfdir_info->fdir_filter_array = rte_zmalloc(\"fdir_filter\",\n+\t\t\tsizeof(struct i40e_fdir_filter) *\n+\t\t\tI40E_MAX_FDIR_FILTER_NUM,\n+\t\t\t0);\n+\n+\tif (!fdir_info->fdir_filter_array) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"Failed to allocate memory for fdir filter array!\");\n+\t\tret = -ENOMEM;\n+\t\tgoto err_fdir_filter_array_alloc;\n+\t}\n+\n \tfdir_info->fdir_space_size = alloc + best;\n \tfdir_info->fdir_actual_cnt = 0;\n \tfdir_info->fdir_guarantee_total_space = alloc;\n@@ -1091,8 +1107,53 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)\n \n \tPMD_DRV_LOG(INFO, \"FDIR guarantee space: %u, best_effort space %u.\", alloc, best);\n \n+\tfdir_info->fdir_flow_pool.pool =\n+\t\t\trte_zmalloc(\"i40e_fdir_entry\",\n+\t\t\t\tsizeof(struct i40e_fdir_entry) *\n+\t\t\t\tfdir_info->fdir_space_size,\n+\t\t\t\t0);\n+\n+\tif (!fdir_info->fdir_flow_pool.pool) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"Failed to allocate memory for bitmap flow!\");\n+\t\tret = -ENOMEM;\n+\t\tgoto err_fdir_bitmap_flow_alloc;\n+\t}\n+\n+\tfor (i = 0; i < fdir_info->fdir_space_size; i++)\n+\t\tfdir_info->fdir_flow_pool.pool[i].idx = i;\n+\n+\tbmp_size =\n+\t\trte_bitmap_get_memory_footprint(fdir_info->fdir_space_size);\n+\tmem = rte_zmalloc(\"fdir_bmap\", bmp_size, RTE_CACHE_LINE_SIZE);\n+\tif (mem == NULL) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"Failed to allocate memory for fdir bitmap!\");\n+\t\tret = -ENOMEM;\n+\t\tgoto err_fdir_mem_alloc;\n+\t}\n+\tbmp = rte_bitmap_init(fdir_info->fdir_space_size, mem, bmp_size);\n+\tif (bmp == NULL) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"Failed to initialization fdir bitmap!\");\n+\t\tret = -ENOMEM;\n+\t\tgoto err_fdir_bmp_alloc;\n+\t}\n+\tfor (i = 0; i < fdir_info->fdir_space_size; i++)\n+\t\trte_bitmap_set(bmp, i);\n+\n+\tfdir_info->fdir_flow_pool.bitmap = bmp;\n+\n \treturn 0;\n \n+err_fdir_bmp_alloc:\n+\trte_free(mem);\n+err_fdir_mem_alloc:\n+\trte_free(fdir_info->fdir_flow_pool.pool);\n+err_fdir_bitmap_flow_alloc:\n+\trte_free(fdir_info->fdir_filter_array);\n+err_fdir_filter_array_alloc:\n+\trte_free(fdir_info->hash_map);\n err_fdir_hash_map_alloc:\n \trte_hash_free(fdir_info->hash_table);\n \n@@ -1790,16 +1851,30 @@ i40e_rm_fdir_filter_list(struct i40e_pf *pf)\n \tstruct i40e_fdir_info *fdir_info;\n \n \tfdir_info = &pf->fdir;\n-\t/* Remove all flow director rules and hash */\n+\n+\t/* Remove all flow director rules */\n+\twhile ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list)))\n+\t\tTAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);\n+}\n+\n+static void\n+i40e_fdir_memory_cleanup(struct i40e_pf *pf)\n+{\n+\tstruct i40e_fdir_info *fdir_info;\n+\n+\tfdir_info = &pf->fdir;\n+\n+\t/* flow director memory cleanup */\n \tif (fdir_info->hash_map)\n \t\trte_free(fdir_info->hash_map);\n \tif (fdir_info->hash_table)\n \t\trte_hash_free(fdir_info->hash_table);\n-\n-\twhile ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))) {\n-\t\tTAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);\n-\t\trte_free(p_fdir);\n-\t}\n+\tif (fdir_info->fdir_flow_pool.bitmap)\n+\t\trte_bitmap_free(fdir_info->fdir_flow_pool.bitmap);\n+\tif (fdir_info->fdir_flow_pool.pool)\n+\t\trte_free(fdir_info->fdir_flow_pool.pool);\n+\tif (fdir_info->fdir_filter_array)\n+\t\trte_free(fdir_info->fdir_filter_array);\n }\n \n void i40e_flex_payload_reg_set_default(struct i40e_hw *hw)\n@@ -2659,9 +2734,14 @@ i40e_dev_close(struct rte_eth_dev *dev)\n \t/* Remove all flows */\n \twhile ((p_flow = TAILQ_FIRST(&pf->flow_list))) {\n \t\tTAILQ_REMOVE(&pf->flow_list, p_flow, node);\n-\t\trte_free(p_flow);\n+\t\t/* Do not free FDIR flows since they are static allocated */\n+\t\tif (p_flow->filter_type != RTE_ETH_FILTER_FDIR)\n+\t\t\trte_free(p_flow);\n \t}\n \n+\t/* release the fdir static allocated memory */\n+\ti40e_fdir_memory_cleanup(pf);\n+\n \t/* Remove all Traffic Manager configuration */\n \ti40e_tm_conf_uninit(dev);\n \ndiff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h\nindex eb505c799..f4f34dad3 100644\n--- a/drivers/net/i40e/i40e_ethdev.h\n+++ b/drivers/net/i40e/i40e_ethdev.h\n@@ -264,6 +264,15 @@ enum i40e_flxpld_layer_idx {\n #define I40E_DEFAULT_DCB_APP_NUM 1\n #define I40E_DEFAULT_DCB_APP_PRIO 3\n \n+/*\n+ * Struct to store flow created.\n+ */\n+struct rte_flow {\n+\tTAILQ_ENTRY(rte_flow) node;\n+\tenum rte_filter_type filter_type;\n+\tvoid *rule;\n+};\n+\n /**\n * The overhead from MTU to max frame size.\n * Considering QinQ packet, the VLAN tag needs to be counted twice.\n@@ -674,6 +683,23 @@ struct i40e_fdir_filter {\n \tstruct i40e_fdir_filter_conf fdir;\n };\n \n+/* fdir memory pool entry */\n+struct i40e_fdir_entry {\n+\tstruct rte_flow flow;\n+\tuint32_t idx;\n+};\n+\n+/* pre-allocated fdir memory pool */\n+struct i40e_fdir_flow_pool {\n+\t/* a bitmap to manage the fdir pool */\n+\tstruct rte_bitmap *bitmap;\n+\t/* the size the pool is pf->fdir->fdir_space_size */\n+\tstruct i40e_fdir_entry *pool;\n+};\n+\n+#define FLOW_TO_FLOW_BITMAP(f) \\\n+\tcontainer_of((f), struct i40e_fdir_entry, flow)\n+\n TAILQ_HEAD(i40e_fdir_filter_list, i40e_fdir_filter);\n /*\n * A structure used to define fields of a FDIR related info.\n@@ -697,6 +723,8 @@ struct i40e_fdir_info {\n \tstruct i40e_fdir_filter_list fdir_list;\n \tstruct i40e_fdir_filter **hash_map;\n \tstruct rte_hash *hash_table;\n+\t/* An array to store the inserted rules input */\n+\tstruct i40e_fdir_filter *fdir_filter_array;\n \n \t/*\n \t * Priority ordering at filter invalidation(destroying a flow) between\n@@ -721,6 +749,8 @@ struct i40e_fdir_info {\n \tuint32_t fdir_guarantee_free_space;\n \t/* the fdir total guaranteed space */\n \tuint32_t fdir_guarantee_total_space;\n+\t/* the pre-allocated pool of the rte_flow */\n+\tstruct i40e_fdir_flow_pool fdir_flow_pool;\n \n \t/* Mark if flex pit and mask is set */\n \tbool flex_pit_flag[I40E_MAX_FLXPLD_LAYER];\n@@ -918,15 +948,6 @@ struct i40e_mirror_rule {\n \n TAILQ_HEAD(i40e_mirror_rule_list, i40e_mirror_rule);\n \n-/*\n- * Struct to store flow created.\n- */\n-struct rte_flow {\n-\tTAILQ_ENTRY(rte_flow) node;\n-\tenum rte_filter_type filter_type;\n-\tvoid *rule;\n-};\n-\n TAILQ_HEAD(i40e_flow_list, rte_flow);\n \n /* Struct to store Traffic Manager shaper profile. */\n@@ -1358,6 +1379,10 @@ int i40e_ethertype_filter_set(struct i40e_pf *pf,\n int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,\n \t\t\t const struct rte_eth_fdir_filter *filter,\n \t\t\t bool add);\n+struct rte_flow *\n+i40e_fdir_entry_pool_get(struct i40e_fdir_info *fdir_info);\n+void i40e_fdir_entry_pool_put(struct i40e_fdir_info *fdir_info,\n+\t\tstruct rte_flow *flow);\n int i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,\n \t\t\t const struct i40e_fdir_filter_conf *filter,\n \t\t\t bool add);\ndiff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c\nindex c37343f8f..fb778202f 100644\n--- a/drivers/net/i40e/i40e_fdir.c\n+++ b/drivers/net/i40e/i40e_fdir.c\n@@ -180,6 +180,7 @@ i40e_fdir_setup(struct i40e_pf *pf)\n \t\tPMD_DRV_LOG(INFO, \"FDIR initialization has been done.\");\n \t\treturn I40E_SUCCESS;\n \t}\n+\n \t/* make new FDIR VSI */\n \tvsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);\n \tif (!vsi) {\n@@ -1570,6 +1571,7 @@ static int\n i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter)\n {\n \tstruct i40e_fdir_info *fdir_info = &pf->fdir;\n+\tstruct i40e_fdir_filter *hash_filter;\n \tint ret;\n \n \tif (filter->fdir.input.flow_ext.pkt_template)\n@@ -1585,9 +1587,14 @@ i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter)\n \t\t\t ret);\n \t\treturn ret;\n \t}\n-\tfdir_info->hash_map[ret] = filter;\n \n-\tTAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules);\n+\tif (fdir_info->hash_map[ret])\n+\t\treturn -1;\n+\n+\thash_filter = &fdir_info->fdir_filter_array[ret];\n+\trte_memcpy(hash_filter, filter, sizeof(*filter));\n+\tfdir_info->hash_map[ret] = hash_filter;\n+\tTAILQ_INSERT_TAIL(&fdir_info->fdir_list, hash_filter, rules);\n \n \treturn 0;\n }\n@@ -1616,11 +1623,57 @@ i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct i40e_fdir_input *input)\n \tfdir_info->hash_map[ret] = NULL;\n \n \tTAILQ_REMOVE(&fdir_info->fdir_list, filter, rules);\n-\trte_free(filter);\n \n \treturn 0;\n }\n \n+struct rte_flow *\n+i40e_fdir_entry_pool_get(struct i40e_fdir_info *fdir_info)\n+{\n+\tstruct rte_flow *flow = NULL;\n+\tuint64_t slab = 0;\n+\tuint32_t pos = 0;\n+\tuint32_t i = 0;\n+\tint ret;\n+\n+\tif (fdir_info->fdir_actual_cnt >=\n+\t\t\tfdir_info->fdir_space_size) {\n+\t\tPMD_DRV_LOG(ERR, \"Fdir space full\");\n+\t\treturn NULL;\n+\t}\n+\n+\tret = rte_bitmap_scan(fdir_info->fdir_flow_pool.bitmap, &pos,\n+\t\t\t&slab);\n+\n+\t/* normally this won't happen as the fdir_actual_cnt should be\n+\t * same with the number of the set bits in fdir_flow_pool,\n+\t * but anyway handle this error condition here for safe\n+\t */\n+\tif (ret == 0) {\n+\t\tPMD_DRV_LOG(ERR, \"fdir_actual_cnt out of sync\");\n+\t\treturn NULL;\n+\t}\n+\n+\ti = rte_bsf64(slab);\n+\tpos += i;\n+\trte_bitmap_clear(fdir_info->fdir_flow_pool.bitmap, pos);\n+\tflow = &fdir_info->fdir_flow_pool.pool[pos].flow;\n+\n+\tmemset(flow, 0, sizeof(struct rte_flow));\n+\n+\treturn flow;\n+}\n+\n+void\n+i40e_fdir_entry_pool_put(struct i40e_fdir_info *fdir_info,\n+\t\tstruct rte_flow *flow)\n+{\n+\tstruct i40e_fdir_entry *f;\n+\n+\tf = FLOW_TO_FLOW_BITMAP(flow);\n+\trte_bitmap_set(fdir_info->fdir_flow_pool.bitmap, f->idx);\n+}\n+\n /*\n * i40e_add_del_fdir_filter - add or remove a flow director filter.\n * @pf: board private structure\n@@ -1699,7 +1752,7 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,\n \tunsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;\n \tenum i40e_filter_pctype pctype;\n \tstruct i40e_fdir_info *fdir_info = &pf->fdir;\n-\tstruct i40e_fdir_filter *fdir_filter, *node;\n+\tstruct i40e_fdir_filter *node;\n \tstruct i40e_fdir_filter check_filter; /* Check if the filter exists */\n \tint ret = 0;\n \n@@ -1732,25 +1785,36 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,\n \t/* Check if there is the filter in SW list */\n \tmemset(&check_filter, 0, sizeof(check_filter));\n \ti40e_fdir_filter_convert(filter, &check_filter);\n-\tnode = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input);\n-\tif (add && node) {\n-\t\tPMD_DRV_LOG(ERR,\n-\t\t\t \"Conflict with existing flow director rules!\");\n-\t\treturn -EINVAL;\n-\t}\n \n-\tif (!add && !node) {\n-\t\tPMD_DRV_LOG(ERR,\n-\t\t\t \"There's no corresponding flow firector filter!\");\n-\t\treturn -EINVAL;\n+\tif (add) {\n+\t\tret = i40e_sw_fdir_filter_insert(pf, &check_filter);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t \"Conflict with existing flow director rules!\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tnode = i40e_sw_fdir_filter_lookup(fdir_info,\n+\t\t\t\t&check_filter.fdir.input);\n+\t\tif (!node) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t \"There's no corresponding flow firector filter!\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\t\"Error deleting fdir rule from hash table!\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n \t}\n \n \tmemset(pkt, 0, I40E_FDIR_PKT_LEN);\n-\n \tret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt);\n \tif (ret < 0) {\n \t\tPMD_DRV_LOG(ERR, \"construct packet for fdir fails.\");\n-\t\treturn ret;\n+\t\tgoto error_op;\n \t}\n \n \tif (hw->mac.type == I40E_MAC_X722) {\n@@ -1763,7 +1827,7 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,\n \tif (ret < 0) {\n \t\tPMD_DRV_LOG(ERR, \"fdir programming fails for PCTYPE(%u).\",\n \t\t\t pctype);\n-\t\treturn ret;\n+\t\tgoto error_op;\n \t}\n \n \tif (add) {\n@@ -1771,29 +1835,24 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,\n \t\tif (fdir_info->fdir_invalprio == 1 &&\n \t\t\t\tfdir_info->fdir_guarantee_free_space > 0)\n \t\t\tfdir_info->fdir_guarantee_free_space--;\n-\n-\t\tfdir_filter = rte_zmalloc(\"fdir_filter\",\n-\t\t\t\t\t sizeof(*fdir_filter), 0);\n-\t\tif (fdir_filter == NULL) {\n-\t\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n-\t\t\treturn -ENOMEM;\n-\t\t}\n-\n-\t\trte_memcpy(fdir_filter, &check_filter, sizeof(check_filter));\n-\t\tret = i40e_sw_fdir_filter_insert(pf, fdir_filter);\n-\t\tif (ret < 0)\n-\t\t\trte_free(fdir_filter);\n \t} else {\n \t\tfdir_info->fdir_actual_cnt--;\n \t\tif (fdir_info->fdir_invalprio == 1 &&\n \t\t\t\tfdir_info->fdir_guarantee_free_space <\n \t\t\t\tfdir_info->fdir_guarantee_total_space)\n \t\t\tfdir_info->fdir_guarantee_free_space++;\n-\n-\t\tret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);\n \t}\n \n \treturn ret;\n+\n+error_op:\n+\t/* roll back */\n+\tif (add)\n+\t\ti40e_sw_fdir_filter_del(pf, &check_filter.fdir.input);\n+\telse\n+\t\ti40e_sw_fdir_filter_insert(pf, &check_filter);\n+\n+\treturn ret;\n }\n \n /*\ndiff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c\nindex 1f2da7926..8c36f29b9 100644\n--- a/drivers/net/i40e/i40e_flow.c\n+++ b/drivers/net/i40e/i40e_flow.c\n@@ -145,6 +145,8 @@ const struct rte_flow_ops i40e_flow_ops = {\n \n static union i40e_filter_t cons_filter;\n static enum rte_filter_type cons_filter_type = RTE_ETH_FILTER_NONE;\n+/* internal pattern w/o VOID items */\n+struct rte_flow_item g_items[32];\n \n /* Pattern matched ethertype filter */\n static enum rte_flow_item_type pattern_ethertype[] = {\n@@ -5264,7 +5266,6 @@ i40e_flow_validate(struct rte_eth_dev *dev,\n \t\t\t\t NULL, \"NULL attribute.\");\n \t\treturn -rte_errno;\n \t}\n-\n \tmemset(&cons_filter, 0, sizeof(cons_filter));\n \n \t/* Get the non-void item of action */\n@@ -5286,12 +5287,18 @@ i40e_flow_validate(struct rte_eth_dev *dev,\n \t}\n \titem_num++;\n \n-\titems = rte_zmalloc(\"i40e_pattern\",\n-\t\t\t item_num * sizeof(struct rte_flow_item), 0);\n-\tif (!items) {\n-\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,\n-\t\t\t\t NULL, \"No memory for PMD internal items.\");\n-\t\treturn -ENOMEM;\n+\tif (item_num <= ARRAY_SIZE(g_items)) {\n+\t\titems = g_items;\n+\t} else {\n+\t\titems = rte_zmalloc(\"i40e_pattern\",\n+\t\t\t\t item_num * sizeof(struct rte_flow_item), 0);\n+\t\tif (!items) {\n+\t\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM_NUM,\n+\t\t\t\t\tNULL,\n+\t\t\t\t\t\"No memory for PMD internal items.\");\n+\t\t\treturn -ENOMEM;\n+\t\t}\n \t}\n \n \ti40e_pattern_skip_void_item(items, pattern);\n@@ -5303,16 +5310,21 @@ i40e_flow_validate(struct rte_eth_dev *dev,\n \t\t\trte_flow_error_set(error, EINVAL,\n \t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n \t\t\t\t\t pattern, \"Unsupported pattern\");\n-\t\t\trte_free(items);\n+\n+\t\t\tif (items != g_items)\n+\t\t\t\trte_free(items);\n \t\t\treturn -rte_errno;\n \t\t}\n+\n \t\tif (parse_filter)\n \t\t\tret = parse_filter(dev, attr, items, actions,\n \t\t\t\t\t error, &cons_filter);\n+\n \t\tflag = true;\n \t} while ((ret < 0) && (i < RTE_DIM(i40e_supported_patterns)));\n \n-\trte_free(items);\n+\tif (items != g_items)\n+\t\trte_free(items);\n \n \treturn ret;\n }\n@@ -5325,21 +5337,33 @@ i40e_flow_create(struct rte_eth_dev *dev,\n \t\t struct rte_flow_error *error)\n {\n \tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n-\tstruct rte_flow *flow;\n+\tstruct rte_flow *flow = NULL;\n+\tstruct i40e_fdir_info *fdir_info = &pf->fdir;\n \tint ret;\n \n-\tflow = rte_zmalloc(\"i40e_flow\", sizeof(struct rte_flow), 0);\n-\tif (!flow) {\n-\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n-\t\t\t\t \"Failed to allocate memory\");\n-\t\treturn flow;\n-\t}\n-\n \tret = i40e_flow_validate(dev, attr, pattern, actions, error);\n \tif (ret < 0)\n \t\treturn NULL;\n \n+\tif (cons_filter_type == RTE_ETH_FILTER_FDIR) {\n+\t\tflow = i40e_fdir_entry_pool_get(fdir_info);\n+\t\tif (flow == NULL) {\n+\t\t\trte_flow_error_set(error, ENOBUFS,\n+\t\t\t RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t \"Fdir space full\");\n+\n+\t\t\treturn flow;\n+\t\t}\n+\t} else {\n+\t\tflow = rte_zmalloc(\"i40e_flow\", sizeof(struct rte_flow), 0);\n+\t\tif (!flow) {\n+\t\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\t\t \"Failed to allocate memory\");\n+\t\t\treturn flow;\n+\t\t}\n+\t}\n+\n \tswitch (cons_filter_type) {\n \tcase RTE_ETH_FILTER_ETHERTYPE:\n \t\tret = i40e_ethertype_filter_set(pf,\n@@ -5351,7 +5375,7 @@ i40e_flow_create(struct rte_eth_dev *dev,\n \t\tbreak;\n \tcase RTE_ETH_FILTER_FDIR:\n \t\tret = i40e_flow_add_del_fdir_filter(dev,\n-\t\t\t\t &cons_filter.fdir_filter, 1);\n+\t\t\t &cons_filter.fdir_filter, 1);\n \t\tif (ret)\n \t\t\tgoto free_flow;\n \t\tflow->rule = TAILQ_LAST(&pf->fdir.fdir_list,\n@@ -5385,7 +5409,12 @@ i40e_flow_create(struct rte_eth_dev *dev,\n \trte_flow_error_set(error, -ret,\n \t\t\t RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n \t\t\t \"Failed to create flow.\");\n-\trte_free(flow);\n+\n+\tif (cons_filter_type != RTE_ETH_FILTER_FDIR)\n+\t\trte_free(flow);\n+\telse\n+\t\ti40e_fdir_entry_pool_put(fdir_info, flow);\n+\n \treturn NULL;\n }\n \n@@ -5396,6 +5425,7 @@ i40e_flow_destroy(struct rte_eth_dev *dev,\n {\n \tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n \tenum rte_filter_type filter_type = flow->filter_type;\n+\tstruct i40e_fdir_info *fdir_info = &pf->fdir;\n \tint ret = 0;\n \n \tswitch (filter_type) {\n@@ -5409,7 +5439,8 @@ i40e_flow_destroy(struct rte_eth_dev *dev,\n \t\tbreak;\n \tcase RTE_ETH_FILTER_FDIR:\n \t\tret = i40e_flow_add_del_fdir_filter(dev,\n-\t\t &((struct i40e_fdir_filter *)flow->rule)->fdir, 0);\n+\t\t\t\t&((struct i40e_fdir_filter *)flow->rule)->fdir,\n+\t\t\t\t0);\n \n \t\t/* If the last flow is destroyed, disable fdir. */\n \t\tif (!ret && TAILQ_EMPTY(&pf->fdir.fdir_list)) {\n@@ -5429,7 +5460,11 @@ i40e_flow_destroy(struct rte_eth_dev *dev,\n \n \tif (!ret) {\n \t\tTAILQ_REMOVE(&pf->flow_list, flow, node);\n-\t\trte_free(flow);\n+\t\tif (filter_type == RTE_ETH_FILTER_FDIR)\n+\t\t\ti40e_fdir_entry_pool_put(fdir_info, flow);\n+\t\telse\n+\t\t\trte_free(flow);\n+\n \t} else\n \t\trte_flow_error_set(error, -ret,\n \t\t\t\t RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n@@ -5583,6 +5618,7 @@ i40e_flow_flush_fdir_filter(struct i40e_pf *pf)\n \tstruct rte_flow *flow;\n \tvoid *temp;\n \tint ret;\n+\tuint32_t i = 0;\n \n \tret = i40e_fdir_flush(dev);\n \tif (!ret) {\n@@ -5598,13 +5634,23 @@ i40e_flow_flush_fdir_filter(struct i40e_pf *pf)\n \t\tTAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {\n \t\t\tif (flow->filter_type == RTE_ETH_FILTER_FDIR) {\n \t\t\t\tTAILQ_REMOVE(&pf->flow_list, flow, node);\n-\t\t\t\trte_free(flow);\n \t\t\t}\n \t\t}\n \n+\t\t/* reset bitmap */\n+\t\trte_bitmap_reset(fdir_info->fdir_flow_pool.bitmap);\n+\t\tfor (i = 0; i < fdir_info->fdir_space_size; i++) {\n+\t\t\tfdir_info->fdir_flow_pool.pool[i].idx = i;\n+\t\t\trte_bitmap_set(fdir_info->fdir_flow_pool.bitmap, i);\n+\t\t}\n+\n \t\tfdir_info->fdir_actual_cnt = 0;\n \t\tfdir_info->fdir_guarantee_free_space =\n \t\t\tfdir_info->fdir_guarantee_total_space;\n+\t\tmemset(fdir_info->fdir_filter_array,\n+\t\t\t0,\n+\t\t\tsizeof(struct i40e_fdir_filter) *\n+\t\t\tI40E_MAX_FDIR_FILTER_NUM);\n \n \t\tfor (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;\n \t\t pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++)\n", "prefixes": [ "v5", "2/4" ] }{ "id": 74292, "url": "