get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/74086/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 74086,
    "url": "http://patches.dpdk.org/api/patches/74086/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200715195329.34699-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": "<20200715195329.34699-3-chenmin.sun@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200715195329.34699-3-chenmin.sun@intel.com",
    "date": "2020-07-15T19:53:27",
    "name": "[V4,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/20200715195329.34699-3-chenmin.sun@intel.com/mbox/",
    "series": [
        {
            "id": 11046,
            "url": "http://patches.dpdk.org/api/series/11046/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11046",
            "date": "2020-07-15T19:53:25",
            "name": "i40e FDIR update rate optimization",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/11046/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/74086/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/74086/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 1BD52A0545;\n\tWed, 15 Jul 2020 12:56:51 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 52D4B1BF3C;\n\tWed, 15 Jul 2020 12:56:41 +0200 (CEST)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n by dpdk.org (Postfix) with ESMTP id 73AA21BED7\n for <dev@dpdk.org>; Wed, 15 Jul 2020 12:56:38 +0200 (CEST)",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 15 Jul 2020 03:56:38 -0700",
            "from npg-dpdk-vpp-scm-1.sh.intel.com ([10.67.118.226])\n by orsmga005.jf.intel.com with ESMTP; 15 Jul 2020 03:56:36 -0700"
        ],
        "IronPort-SDR": [
            "\n J51V+Vvc/fite1uqYmEzJNczz5ZKE8u767VL05Sv4MGDu7HGhokbydI9t8SOr6UEyCgb0//3iq\n IVW8pwZZsXMQ==",
            "\n o+6ptnrCSlOgI4CCToS1gRgo6v8AuP8Sn5Fs31WAoCRj0+3hOtmZt1nSWBN+3g4ST/KLOMp9NF\n SJU76TJnH6QA=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9682\"; a=\"137249743\"",
            "E=Sophos;i=\"5.75,355,1589266800\"; d=\"scan'208\";a=\"137249743\"",
            "E=Sophos;i=\"5.75,355,1589266800\"; d=\"scan'208\";a=\"460026048\""
        ],
        "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": "Thu, 16 Jul 2020 03:53:27 +0800",
        "Message-Id": "<20200715195329.34699-3-chenmin.sun@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200715195329.34699-1-chenmin.sun@intel.com>",
        "References": "<20200713222321.2118-1-chenmin.sun@intel.com>\n <20200715195329.34699-1-chenmin.sun@intel.com>",
        "Subject": "[dpdk-dev] [PATCH V4 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": [
        "V4",
        "2/4"
    ]
}