get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2407,
    "url": "https://patches.dpdk.org/api/patches/2407/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1421779267-18492-17-git-send-email-konstantin.ananyev@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1421779267-18492-17-git-send-email-konstantin.ananyev@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1421779267-18492-17-git-send-email-konstantin.ananyev@intel.com",
    "date": "2015-01-20T18:41:05",
    "name": "[dpdk-dev,v3,16/18] libte_acl: introduce max_size into rte_acl_config.",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "2d8713d6a4749ab434eacf98bb0959e05a4b8a41",
    "submitter": {
        "id": 33,
        "url": "https://patches.dpdk.org/api/people/33/?format=api",
        "name": "Ananyev, Konstantin",
        "email": "konstantin.ananyev@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1421779267-18492-17-git-send-email-konstantin.ananyev@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/2407/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/2407/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id DD9135AC8;\n\tTue, 20 Jan 2015 19:41:40 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 8A6AF5AA5\n\tfor <dev@dpdk.org>; Tue, 20 Jan 2015 19:41:24 +0100 (CET)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga103.fm.intel.com with ESMTP; 20 Jan 2015 10:35:43 -0800",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby FMSMGA003.fm.intel.com with ESMTP; 20 Jan 2015 10:28:05 -0800",
            "from sivswdev02.ir.intel.com (sivswdev02.ir.intel.com\n\t[10.237.217.46])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tt0KIfLTc029514; Tue, 20 Jan 2015 18:41:21 GMT",
            "from sivswdev02.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev02.ir.intel.com with ESMTP id t0KIfLOH018898;\n\tTue, 20 Jan 2015 18:41:21 GMT",
            "(from kananye1@localhost)\n\tby sivswdev02.ir.intel.com with  id t0KIfLpW018894;\n\tTue, 20 Jan 2015 18:41:21 GMT"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"4.97,862,1389772800\"; d=\"scan'208\";a=\"442827088\"",
        "From": "Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 20 Jan 2015 18:41:05 +0000",
        "Message-Id": "<1421779267-18492-17-git-send-email-konstantin.ananyev@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1421779267-18492-1-git-send-email-konstantin.ananyev@intel.com>",
        "References": "<1421779267-18492-1-git-send-email-konstantin.ananyev@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 16/18] libte_acl: introduce max_size into\n\trte_acl_config.",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "If at build phase we don't make any trie splitting,\nthen temporary build structures and resulting RT structure might be\nmuch bigger than current.\nFrom other side - having just one trie instead of multiple can speedup\nsearch quite significantly.\nFrom my measurements on rule-sets with ~10K rules:\nRT table up to 8 times bigger, classify() up to 80% faster\nthan current implementation.\nTo make it possible for the user to decide about performance/space trade-off -\nnew parameter for build config structure (max_size) is introduced.\nSetting it to the value greater than zero, instructs  rte_acl_build() to:\n- make sure that size of RT table wouldn't exceed given value.\n- attempt to minimise number of tries in the table.\nSetting it to zero maintains current behaviour.\nThat introduces a minor change in the public API, but I think the possible\nperformance gain is too big to ignore it.\n\nSigned-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\n---\n app/test-acl/main.c       |  33 ++++++++----\n examples/l3fwd-acl/main.c |   3 +-\n lib/librte_acl/acl.h      |   2 +-\n lib/librte_acl/acl_bld.c  | 134 +++++++++++++++++++++++++++++-----------------\n lib/librte_acl/acl_gen.c  |  22 +++++---\n lib/librte_acl/rte_acl.c  |   1 +\n lib/librte_acl/rte_acl.h  |   2 +\n 7 files changed, 131 insertions(+), 66 deletions(-)",
    "diff": "diff --git a/app/test-acl/main.c b/app/test-acl/main.c\nindex 52f43c6..5e8db04 100644\n--- a/app/test-acl/main.c\n+++ b/app/test-acl/main.c\n@@ -85,6 +85,7 @@\n #define\tOPT_SEARCH_ALG\t\t\"alg\"\n #define\tOPT_BLD_CATEGORIES\t\"bldcat\"\n #define\tOPT_RUN_CATEGORIES\t\"runcat\"\n+#define\tOPT_MAX_SIZE\t\t\"maxsize\"\n #define\tOPT_ITER_NUM\t\t\"iter\"\n #define\tOPT_VERBOSE\t\t\"verbose\"\n #define\tOPT_IPV6\t\t\"ipv6\"\n@@ -126,6 +127,7 @@ static struct {\n \tconst char         *prgname;\n \tconst char         *rule_file;\n \tconst char         *trace_file;\n+\tsize_t              max_size;\n \tuint32_t            bld_categories;\n \tuint32_t            run_categories;\n \tuint32_t            nb_rules;\n@@ -780,6 +782,8 @@ acx_init(void)\n \tFILE *f;\n \tstruct rte_acl_config cfg;\n \n+\tmemset(&cfg, 0, sizeof(cfg));\n+\n \t/* setup ACL build config. */\n \tif (config.ipv6) {\n \t\tcfg.num_fields = RTE_DIM(ipv6_defs);\n@@ -789,6 +793,7 @@ acx_init(void)\n \t\tmemcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs));\n \t}\n \tcfg.num_categories = config.bld_categories;\n+\tcfg.max_size = config.max_size;\n \n \t/* setup ACL creation parameters. */\n \tprm.rule_size = RTE_ACL_RULE_SZ(cfg.num_fields);\n@@ -899,8 +904,8 @@ search_ip5tuples(__attribute__((unused)) void *arg)\n \treturn 0;\n }\n \n-static uint32_t\n-get_uint32_opt(const char *opt, const char *name, uint32_t min, uint32_t max)\n+static unsigned long\n+get_ulong_opt(const char *opt, const char *name, size_t min, size_t max)\n {\n \tunsigned long val;\n \tchar *end;\n@@ -964,6 +969,9 @@ print_usage(const char *prgname)\n \t\t\t\"=<number of categories to run with> \"\n \t\t\t\"should be either 1 or multiple of %zu, \"\n \t\t\t\"but not greater then %u]\\n\"\n+\t\t\"[--\" OPT_MAX_SIZE\n+\t\t\t\"=<size limit (in bytes) for runtime ACL strucutures> \"\n+\t\t\t\"leave 0 for default behaviour]\\n\"\n \t\t\"[--\" OPT_ITER_NUM \"=<number of iterations to perform>]\\n\"\n \t\t\"[--\" OPT_VERBOSE \"=<verbose level>]\\n\"\n \t\t\"[--\" OPT_SEARCH_ALG \"=%s]\\n\"\n@@ -984,6 +992,7 @@ dump_config(FILE *f)\n \tfprintf(f, \"%s:%u\\n\", OPT_TRACE_STEP, config.trace_step);\n \tfprintf(f, \"%s:%u\\n\", OPT_BLD_CATEGORIES, config.bld_categories);\n \tfprintf(f, \"%s:%u\\n\", OPT_RUN_CATEGORIES, config.run_categories);\n+\tfprintf(f, \"%s:%zu\\n\", OPT_MAX_SIZE, config.max_size);\n \tfprintf(f, \"%s:%u\\n\", OPT_ITER_NUM, config.iter_num);\n \tfprintf(f, \"%s:%u\\n\", OPT_VERBOSE, config.verbose);\n \tfprintf(f, \"%s:%u(%s)\\n\", OPT_SEARCH_ALG, config.alg.alg,\n@@ -1010,6 +1019,7 @@ get_input_opts(int argc, char **argv)\n \t\t{OPT_TRACE_FILE, 1, 0, 0},\n \t\t{OPT_TRACE_NUM, 1, 0, 0},\n \t\t{OPT_RULE_NUM, 1, 0, 0},\n+\t\t{OPT_MAX_SIZE, 1, 0, 0},\n \t\t{OPT_TRACE_STEP, 1, 0, 0},\n \t\t{OPT_BLD_CATEGORIES, 1, 0, 0},\n \t\t{OPT_RUN_CATEGORIES, 1, 0, 0},\n@@ -1034,29 +1044,32 @@ get_input_opts(int argc, char **argv)\n \t\t} else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_FILE) == 0) {\n \t\t\tconfig.trace_file = optarg;\n \t\t} else if (strcmp(lgopts[opt_idx].name, OPT_RULE_NUM) == 0) {\n-\t\t\tconfig.nb_rules = get_uint32_opt(optarg,\n+\t\t\tconfig.nb_rules = get_ulong_opt(optarg,\n \t\t\t\tlgopts[opt_idx].name, 1, RTE_ACL_MAX_INDEX + 1);\n+\t\t} else if (strcmp(lgopts[opt_idx].name, OPT_MAX_SIZE) == 0) {\n+\t\t\tconfig.max_size = get_ulong_opt(optarg,\n+\t\t\t\tlgopts[opt_idx].name, 0, SIZE_MAX);\n \t\t} else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_NUM) == 0) {\n-\t\t\tconfig.nb_traces = get_uint32_opt(optarg,\n+\t\t\tconfig.nb_traces = get_ulong_opt(optarg,\n \t\t\t\tlgopts[opt_idx].name, 1, UINT32_MAX);\n \t\t} else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_STEP) == 0) {\n-\t\t\tconfig.trace_step = get_uint32_opt(optarg,\n+\t\t\tconfig.trace_step = get_ulong_opt(optarg,\n \t\t\t\tlgopts[opt_idx].name, 1, TRACE_STEP_MAX);\n \t\t} else if (strcmp(lgopts[opt_idx].name,\n \t\t\t\tOPT_BLD_CATEGORIES) == 0) {\n-\t\t\tconfig.bld_categories = get_uint32_opt(optarg,\n+\t\t\tconfig.bld_categories = get_ulong_opt(optarg,\n \t\t\t\tlgopts[opt_idx].name, 1,\n \t\t\t\tRTE_ACL_MAX_CATEGORIES);\n \t\t} else if (strcmp(lgopts[opt_idx].name,\n \t\t\t\tOPT_RUN_CATEGORIES) == 0) {\n-\t\t\tconfig.run_categories = get_uint32_opt(optarg,\n+\t\t\tconfig.run_categories = get_ulong_opt(optarg,\n \t\t\t\tlgopts[opt_idx].name, 1,\n \t\t\t\tRTE_ACL_MAX_CATEGORIES);\n \t\t} else if (strcmp(lgopts[opt_idx].name, OPT_ITER_NUM) == 0) {\n-\t\t\tconfig.iter_num = get_uint32_opt(optarg,\n-\t\t\t\tlgopts[opt_idx].name, 1, UINT16_MAX);\n+\t\t\tconfig.iter_num = get_ulong_opt(optarg,\n+\t\t\t\tlgopts[opt_idx].name, 1, INT32_MAX);\n \t\t} else if (strcmp(lgopts[opt_idx].name, OPT_VERBOSE) == 0) {\n-\t\t\tconfig.verbose = get_uint32_opt(optarg,\n+\t\t\tconfig.verbose = get_ulong_opt(optarg,\n \t\t\t\tlgopts[opt_idx].name, DUMP_NONE, DUMP_MAX);\n \t\t} else if (strcmp(lgopts[opt_idx].name,\n \t\t\t\tOPT_SEARCH_ALG) == 0) {\ndiff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c\nindex 022ccab..f1f7601 100644\n--- a/examples/l3fwd-acl/main.c\n+++ b/examples/l3fwd-acl/main.c\n@@ -1178,8 +1178,9 @@ setup_acl(struct rte_acl_rule *route_base,\n \t\t\trte_exit(EXIT_FAILURE, \"add rules failed\\n\");\n \n \t/* Perform builds */\n-\tacl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;\n+\tmemset(&acl_build_param, 0, sizeof(acl_build_param));\n \n+\tacl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;\n \tacl_build_param.num_fields = dim;\n \tmemcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs,\n \t\tipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs));\ndiff --git a/lib/librte_acl/acl.h b/lib/librte_acl/acl.h\nindex d33d7ad..61b849a 100644\n--- a/lib/librte_acl/acl.h\n+++ b/lib/librte_acl/acl.h\n@@ -180,7 +180,7 @@ struct rte_acl_ctx {\n \n int rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie,\n \tstruct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries,\n-\tuint32_t num_categories, uint32_t data_index_sz);\n+\tuint32_t num_categories, uint32_t data_index_sz, size_t max_size);\n \n typedef int (*rte_acl_classify_t)\n (const struct rte_acl_ctx *, const uint8_t **, uint32_t *, uint32_t, uint32_t);\ndiff --git a/lib/librte_acl/acl_bld.c b/lib/librte_acl/acl_bld.c\nindex 1fd59ee..1fe79fb 100644\n--- a/lib/librte_acl/acl_bld.c\n+++ b/lib/librte_acl/acl_bld.c\n@@ -41,10 +41,9 @@\n /* number of pointers per alloc */\n #define ACL_PTR_ALLOC\t32\n \n-/* variable for dividing rule sets */\n-#define NODE_MAX\t2500\n-#define NODE_PERCENTAGE\t(0.40)\n-#define RULE_PERCENTAGE\t(0.40)\n+/* macros for dividing rule sets heuristics */\n+#define NODE_MAX\t0x4000\n+#define NODE_MIN\t0x800\n \n /* TALLY are statistics per field */\n enum {\n@@ -97,6 +96,7 @@ struct acl_build_context {\n \tconst struct rte_acl_ctx *acx;\n \tstruct rte_acl_build_rule *build_rules;\n \tstruct rte_acl_config     cfg;\n+\tint32_t                   node_max;\n \tuint32_t                  node;\n \tuint32_t                  num_nodes;\n \tuint32_t                  category_mask;\n@@ -1447,7 +1447,7 @@ build_trie(struct acl_build_context *context, struct rte_acl_build_rule *head,\n \t\t\treturn NULL;\n \n \t\tnode_count = context->num_nodes - node_count;\n-\t\tif (node_count > NODE_MAX) {\n+\t\tif (node_count > context->node_max) {\n \t\t\t*last = prev;\n \t\t\treturn trie;\n \t\t}\n@@ -1628,6 +1628,9 @@ rule_cmp_wildness(struct rte_acl_build_rule *r1, struct rte_acl_build_rule *r2)\n \treturn 0;\n }\n \n+/*\n+ * Sort list of rules based on the rules wildness.\n+ */\n static struct rte_acl_build_rule *\n sort_rules(struct rte_acl_build_rule *head)\n {\n@@ -1636,21 +1639,22 @@ sort_rules(struct rte_acl_build_rule *head)\n \n \tnew_head = NULL;\n \twhile (head != NULL) {\n+\n+\t\t/* remove element from the head of the old list. */\n \t\tr = head;\n \t\thead = r->next;\n \t\tr->next = NULL;\n-\t\tif (new_head == NULL) {\n-\t\t\tnew_head = r;\n-\t\t} else {\n-\t\t\tfor (p = &new_head;\n-\t\t\t\t\t(l = *p) != NULL &&\n-\t\t\t\t\trule_cmp_wildness(l, r) >= 0;\n-\t\t\t\t\tp = &l->next)\n-\t\t\t\t;\n-\n-\t\t\tr->next = *p;\n-\t\t\t*p = r;\n-\t\t}\n+\n+\t\t/* walk through new sorted list to find a proper place. */\n+\t\tfor (p = &new_head;\n+\t\t\t\t(l = *p) != NULL &&\n+\t\t\t\trule_cmp_wildness(l, r) >= 0;\n+\t\t\t\tp = &l->next)\n+\t\t\t;\n+\n+\t\t/* insert element into the new sorted list. */\n+\t\tr->next = *p;\n+\t\t*p = r;\n \t}\n \n \treturn new_head;\n@@ -1789,9 +1793,11 @@ acl_build_log(const struct acl_build_context *ctx)\n \tuint32_t n;\n \n \tRTE_LOG(DEBUG, ACL, \"Build phase for ACL \\\"%s\\\":\\n\"\n+\t\t\"node limit for tree split: %u\\n\"\n \t\t\"nodes created: %u\\n\"\n \t\t\"memory consumed: %zu\\n\",\n \t\tctx->acx->name,\n+\t\tctx->node_max,\n \t\tctx->num_nodes,\n \t\tctx->pool.alloc);\n \n@@ -1868,11 +1874,48 @@ acl_set_data_indexes(struct rte_acl_ctx *ctx)\n \t}\n }\n \n+/*\n+ * Internal routine, performs 'build' phase of trie generation:\n+ * - setups build context.\n+ * - analizes given set of rules.\n+ * - builds internal tree(s).\n+ */\n+static int\n+acl_bld(struct acl_build_context *bcx, struct rte_acl_ctx *ctx,\n+\tconst struct rte_acl_config *cfg, uint32_t node_max)\n+{\n+\tint32_t rc;\n+\n+\t/* setup build context. */\n+\tmemset(bcx, 0, sizeof(*bcx));\n+\tbcx->acx = ctx;\n+\tbcx->pool.alignment = ACL_POOL_ALIGN;\n+\tbcx->pool.min_alloc = ACL_POOL_ALLOC_MIN;\n+\tbcx->cfg = *cfg;\n+\tbcx->category_mask = LEN2MASK(bcx->cfg.num_categories);\n+\tbcx->node_max = node_max;\n+\n+\t/* Create a build rules copy. */\n+\trc = acl_build_rules(bcx);\n+\tif (rc != 0)\n+\t\treturn rc;\n+\n+\t/* No rules to build for that context+config */\n+\tif (bcx->build_rules == NULL) {\n+\t\trc = -EINVAL;\n+\t} else {\n+\t\t/* build internal trie representation. */\n+\t\trc = acl_build_tries(bcx, bcx->build_rules);\n+\t}\n+\treturn rc;\n+}\n \n int\n rte_acl_build(struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg)\n {\n-\tint rc;\n+\tint32_t rc;\n+\tuint32_t n;\n+\tsize_t max_size;\n \tstruct acl_build_context bcx;\n \n \tif (ctx == NULL || cfg == NULL || cfg->num_categories == 0 ||\n@@ -1881,44 +1924,39 @@ rte_acl_build(struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg)\n \n \tacl_build_reset(ctx);\n \n-\tmemset(&bcx, 0, sizeof(bcx));\n-\tbcx.acx = ctx;\n-\tbcx.pool.alignment = ACL_POOL_ALIGN;\n-\tbcx.pool.min_alloc = ACL_POOL_ALLOC_MIN;\n-\tbcx.cfg = *cfg;\n-\tbcx.category_mask = LEN2MASK(bcx.cfg.num_categories);\n-\n-\n-\t/* Create a build rules copy. */\n-\trc = acl_build_rules(&bcx);\n-\tif (rc != 0)\n-\t\treturn rc;\n+\tif (cfg->max_size == 0) {\n+\t\tn = NODE_MIN;\n+\t\tmax_size = SIZE_MAX;\n+\t} else {\n+\t\tn = NODE_MAX;\n+\t\tmax_size = cfg->max_size;\n+\t}\n \n-\t/* No rules to build for that context+config */\n-\tif (bcx.build_rules == NULL) {\n-\t\trc = -EINVAL;\n+\tfor (rc = -ERANGE; n >= NODE_MIN && rc == -ERANGE; n /= 2) {\n \n-\t/* build internal trie representation. */\n-\t} else if ((rc = acl_build_tries(&bcx, bcx.build_rules)) == 0) {\n+\t\t/* perform build phase. */\n+\t\trc = acl_bld(&bcx, ctx, cfg, n);\n \n-\t\t/* allocate and fill run-time  structures. */\n-\t\trc = rte_acl_gen(ctx, bcx.tries, bcx.bld_tries,\n+\t\tif (rc == 0) {\n+\t\t\t/* allocate and fill run-time  structures. */\n+\t\t\trc = rte_acl_gen(ctx, bcx.tries, bcx.bld_tries,\n \t\t\t\tbcx.num_tries, bcx.cfg.num_categories,\n \t\t\t\tRTE_ACL_MAX_FIELDS * RTE_DIM(bcx.tries) *\n-\t\t\t\tsizeof(ctx->data_indexes[0]));\n-\t\tif (rc == 0) {\n+\t\t\t\tsizeof(ctx->data_indexes[0]), max_size);\n+\t\t\tif (rc == 0) {\n+\t\t\t\t/* set data indexes. */\n+\t\t\t\tacl_set_data_indexes(ctx);\n \n-\t\t\t/* set data indexes. */\n-\t\t\tacl_set_data_indexes(ctx);\n-\n-\t\t\t/* copy in build config. */\n-\t\t\tctx->config = *cfg;\n+\t\t\t\t/* copy in build config. */\n+\t\t\t\tctx->config = *cfg;\n+\t\t\t}\n \t\t}\n-\t}\n \n-\tacl_build_log(&bcx);\n+\t\tacl_build_log(&bcx);\n+\n+\t\t/* cleanup after build. */\n+\t\ttb_free_pool(&bcx.pool);\n+\t}\n \n-\t/* cleanup after build. */\n-\ttb_free_pool(&bcx.pool);\n \treturn rc;\n }\ndiff --git a/lib/librte_acl/acl_gen.c b/lib/librte_acl/acl_gen.c\nindex d3def66..ea557ab 100644\n--- a/lib/librte_acl/acl_gen.c\n+++ b/lib/librte_acl/acl_gen.c\n@@ -32,7 +32,6 @@\n  */\n \n #include <rte_acl.h>\n-#include \"acl_vect.h\"\n #include \"acl.h\"\n \n #define\tQRANGE_MIN\t((uint8_t)INT8_MIN)\n@@ -63,7 +62,8 @@ struct rte_acl_indices {\n static void\n acl_gen_log_stats(const struct rte_acl_ctx *ctx,\n \tconst struct acl_node_counters *counts,\n-\tconst struct rte_acl_indices *indices)\n+\tconst struct rte_acl_indices *indices,\n+\tsize_t max_size)\n {\n \tRTE_LOG(DEBUG, ACL, \"Gen phase for ACL \\\"%s\\\":\\n\"\n \t\t\"runtime memory footprint on socket %d:\\n\"\n@@ -71,7 +71,8 @@ acl_gen_log_stats(const struct rte_acl_ctx *ctx,\n \t\t\"quad nodes/vectors/bytes used: %d/%d/%zu\\n\"\n \t\t\"DFA nodes/group64/bytes used: %d/%d/%zu\\n\"\n \t\t\"match nodes/bytes used: %d/%zu\\n\"\n-\t\t\"total: %zu bytes\\n\",\n+\t\t\"total: %zu bytes\\n\"\n+\t\t\"max limit: %zu bytes\\n\",\n \t\tctx->name, ctx->socket_id,\n \t\tcounts->single, counts->single * sizeof(uint64_t),\n \t\tcounts->quad, counts->quad_vectors,\n@@ -80,7 +81,8 @@ acl_gen_log_stats(const struct rte_acl_ctx *ctx,\n \t\tindices->dfa_index * sizeof(uint64_t),\n \t\tcounts->match,\n \t\tcounts->match * sizeof(struct rte_acl_match_results),\n-\t\tctx->mem_sz);\n+\t\tctx->mem_sz,\n+\t\tmax_size);\n }\n \n static uint64_t\n@@ -474,7 +476,7 @@ acl_calc_counts_indices(struct acl_node_counters *counts,\n int\n rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie,\n \tstruct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries,\n-\tuint32_t num_categories, uint32_t data_index_sz)\n+\tuint32_t num_categories, uint32_t data_index_sz, size_t max_size)\n {\n \tvoid *mem;\n \tsize_t total_size;\n@@ -496,6 +498,14 @@ rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie,\n \t\t(counts.match + 1) * sizeof(struct rte_acl_match_results) +\n \t\tXMM_SIZE;\n \n+\tif (total_size > max_size) {\n+\t\tRTE_LOG(DEBUG, ACL,\n+\t\t\t\"Gen phase for ACL ctx \\\"%s\\\" exceeds max_size limit, \"\n+\t\t\t\"bytes required: %zu, allowed: %zu\\n\",\n+\t\t\tctx->name, total_size, max_size);\n+\t\treturn -ERANGE;\n+\t}\n+\n \tmem = rte_zmalloc_socket(ctx->name, total_size, RTE_CACHE_LINE_SIZE,\n \t\t\tctx->socket_id);\n \tif (mem == NULL) {\n@@ -546,6 +556,6 @@ rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie,\n \tctx->trans_table = node_array;\n \tmemcpy(ctx->trie, trie, sizeof(ctx->trie));\n \n-\tacl_gen_log_stats(ctx, &counts, &indices);\n+\tacl_gen_log_stats(ctx, &counts, &indices, max_size);\n \treturn 0;\n }\ndiff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c\nindex a9cd349..7d10301 100644\n--- a/lib/librte_acl/rte_acl.c\n+++ b/lib/librte_acl/rte_acl.c\n@@ -543,6 +543,7 @@ rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx,\n \tif (ctx == NULL || layout == NULL)\n \t\treturn -EINVAL;\n \n+\tmemset(&cfg, 0, sizeof(cfg));\n \tacl_ipv4vlan_config(&cfg, layout, num_categories);\n \treturn rte_acl_build(ctx, &cfg);\n }\ndiff --git a/lib/librte_acl/rte_acl.h b/lib/librte_acl/rte_acl.h\nindex 652a234..30aea03 100644\n--- a/lib/librte_acl/rte_acl.h\n+++ b/lib/librte_acl/rte_acl.h\n@@ -94,6 +94,8 @@ struct rte_acl_config {\n \tuint32_t num_fields;     /**< Number of field definitions. */\n \tstruct rte_acl_field_def defs[RTE_ACL_MAX_FIELDS];\n \t/**< array of field definitions. */\n+\tsize_t max_size;\n+\t/**< max memory limit for internal run-time structures. */\n };\n \n /**\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "16/18"
    ]
}