From patchwork Fri Aug 19 19:52:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 115302 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 08B13A034C; Fri, 19 Aug 2022 21:53:08 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 937C14282D; Fri, 19 Aug 2022 21:52:37 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by mails.dpdk.org (Postfix) with ESMTP id 79F0041614 for ; Fri, 19 Aug 2022 21:52:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1660938753; x=1692474753; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=X52X70mQvKkL1hVaWWowYAFkBoV+k//xGEZUpKrdNUw=; b=Y5q3re6l0ptaZLkktWK1gJPZ5B47o7PyPRxvfuzVcbsqoV9wHWB7XZGr vsDZhsA7crx7wx+Xm4zlPiqXL7KUpAlySA2NQpWwJYkvA5l5Wsda4vjdy EOIdpfEGub/T6hpE/mWHp6kgrLKdrvGv+OXHeU3dUQhbAx/94JGpZ1cw6 UDGb1T6mI6zr1ySompiLUTfI4bx9F2+NiLc3AtEU7z0v9ETre02lh3lMO omNO2TbtdS3Dw+XXZ7n23thN/nVHviUYxohyaxrB4B2kQZyPPRj4FpPuq /YaeDxLF5WV7I9ArKscXnYUU51s0SvbhWlsb+Lq1n2Y7Td5rwihS0XjDG A==; X-IronPort-AV: E=McAfee;i="6500,9779,10444"; a="280047530" X-IronPort-AV: E=Sophos;i="5.93,249,1654585200"; d="scan'208";a="280047530" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2022 12:52:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,248,1654585200"; d="scan'208";a="604695971" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com.) ([10.237.223.157]) by orsmga007.jf.intel.com with ESMTP; 19 Aug 2022 12:52:32 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Cc: "Kamalakannan R ." Subject: [PATCH V2 6/6] pipeline: configure the hash function for learner tables Date: Fri, 19 Aug 2022 19:52:25 +0000 Message-Id: <20220819195225.1483020-7-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220819195225.1483020-1-cristian.dumitrescu@intel.com> References: <20220818114449.1408226-1-cristian.dumitrescu@intel.com> <20220819195225.1483020-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Make the hash function configurable for the learner pipeline tables. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R. --- lib/pipeline/rte_swx_pipeline.c | 78 +++++++++++++++++++++--- lib/pipeline/rte_swx_pipeline.h | 6 ++ lib/pipeline/rte_swx_pipeline_internal.h | 1 + lib/pipeline/rte_swx_pipeline_spec.c | 41 ++++++++++++- lib/pipeline/rte_swx_pipeline_spec.h | 1 + 5 files changed, 116 insertions(+), 11 deletions(-) diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 0b21adacbc..1c49622be7 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -8789,31 +8789,55 @@ learner_match_fields_check(struct rte_swx_pipeline *p, { struct header *h0 = NULL; struct field *hf, *mf; - uint32_t i; + uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i; + int status = 0; /* Return if no match fields. */ if (!params->n_fields || !params->field_names) return -EINVAL; + /* Memory allocation. */ + offset = calloc(params->n_fields, sizeof(uint32_t)); + n_bits = calloc(params->n_fields, sizeof(uint32_t)); + if (!offset || !n_bits) { + status = -ENOMEM; + goto end; + } + /* Check that all the match fields either belong to the same header * or are all meta-data fields. */ hf = header_field_parse(p, params->field_names[0], &h0); mf = metadata_field_parse(p, params->field_names[0]); - if (!hf && !mf) - return -EINVAL; + if ((!hf && !mf) || (hf && hf->var_size)) { + status = -EINVAL; + goto end; + } + + offset[0] = h0 ? hf->offset : mf->offset; + n_bits[0] = h0 ? hf->n_bits : mf->n_bits; for (i = 1; i < params->n_fields; i++) if (h0) { struct header *h; hf = header_field_parse(p, params->field_names[i], &h); - if (!hf || (h->id != h0->id)) - return -EINVAL; + if (!hf || (h->id != h0->id) || hf->var_size) { + status = -EINVAL; + goto end; + } + + offset[i] = hf->offset; + n_bits[i] = hf->n_bits; } else { mf = metadata_field_parse(p, params->field_names[i]); - if (!mf) - return -EINVAL; + if (!mf) { + status = -EINVAL; + goto end; + } + + offset[i] = mf->offset; + n_bits[i] = mf->n_bits; } /* Check that there are no duplicated match fields. */ @@ -8822,15 +8846,37 @@ learner_match_fields_check(struct rte_swx_pipeline *p, uint32_t j; for (j = i + 1; j < params->n_fields; j++) - if (!strcmp(params->field_names[j], field_name)) - return -EINVAL; + if (!strcmp(params->field_names[j], field_name)) { + status = -EINVAL; + goto end; + } + } + + /* Check that the match fields are contiguous. */ + for (i = 0; i < params->n_fields; i++) { + uint32_t offset_next = offset[i] + n_bits[i]; + uint32_t j; + + for (j = 0; j < params->n_fields; j++) + if (offset[j] == offset_next) { + n_fields_with_valid_next++; + break; + } + } + + if (n_fields_with_valid_next != params->n_fields - 1) { + status = -EINVAL; + goto end; } /* Return. */ if (header) *header = h0; - return 0; +end: + free(offset); + free(n_bits); + return status; } static int @@ -8919,6 +8965,7 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, struct learner *l = NULL; struct action *default_action; struct header *header = NULL; + struct hash_func *hf = NULL; uint32_t action_data_size_max = 0, i; int status = 0; @@ -8981,6 +9028,12 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, CHECK((default_action->st && params->default_action_args) || !params->default_action_args, EINVAL); + /* Hash function checks. */ + if (params->hash_func_name) { + hf = hash_func_find(p, params->hash_func_name); + CHECK(hf, EINVAL); + } + /* Any other checks. */ CHECK(size, EINVAL); CHECK(timeout, EINVAL); @@ -9069,6 +9122,8 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, l->action_data_size_max = action_data_size_max; + l->hf = hf; + l->size = size; for (i = 0; i < n_timeouts; i++) @@ -9158,6 +9213,9 @@ learner_params_get(struct learner *l) /* Action data size. */ params->action_data_size = l->action_data_size_max; + /* Hash function. */ + params->hash_func = l->hf ? l->hf->func : NULL; + /* Maximum number of keys. */ params->n_keys_max = l->size; diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h index 09c75180f8..2c9cc6ee44 100644 --- a/lib/pipeline/rte_swx_pipeline.h +++ b/lib/pipeline/rte_swx_pipeline.h @@ -829,6 +829,12 @@ struct rte_swx_pipeline_learner_params { * list. */ int default_action_is_const; + + /** Hash function name. When not set to NULL, it must point to one of + * the hash functions that were registered for the current pipeline. + * When NULL, the default hash function will be used. + */ + const char *hash_func_name; }; /** diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h index ee579c6656..ef60288dca 100644 --- a/lib/pipeline/rte_swx_pipeline_internal.h +++ b/lib/pipeline/rte_swx_pipeline_internal.h @@ -900,6 +900,7 @@ struct learner { int *action_is_for_table_entries; int *action_is_for_default_entry; + struct hash_func *hf; uint32_t size; uint32_t timeout[RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX]; uint32_t n_timeouts; diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c index e9fde4f241..9116f38ed2 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.c +++ b/lib/pipeline/rte_swx_pipeline_spec.c @@ -1350,7 +1350,7 @@ selector_block_parse(struct selector_spec *s, static void learner_spec_free(struct learner_spec *s) { - uintptr_t default_action_name, default_action_args; + uintptr_t default_action_name, default_action_args, hash_func_name; uint32_t i; if (!s) @@ -1397,6 +1397,10 @@ learner_spec_free(struct learner_spec *s) s->params.default_action_is_const = 0; + hash_func_name = (uintptr_t)s->params.hash_func_name; + free((void *)hash_func_name); + s->params.hash_func_name = NULL; + s->size = 0; free(s->timeout); @@ -1853,6 +1857,35 @@ learner_block_parse(struct learner_spec *s, err_line, err_msg); + if (!strcmp(tokens[0], "hash")) { + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid hash statement."; + return -EINVAL; + } + + if (s->params.hash_func_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Duplicate hash statement."; + return -EINVAL; + } + + s->params.hash_func_name = strdup(tokens[1]); + if (!s->params.hash_func_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + return 0; + } + if (!strcmp(tokens[0], "size")) { char *p = tokens[1]; @@ -2692,6 +2725,12 @@ pipeline_spec_codegen(FILE *f, fprintf(f, "\t\t\t.default_action_is_const = %d,\n", learner_spec->params.default_action_is_const); + if (learner_spec->params.hash_func_name) + fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n", + learner_spec->params.hash_func_name); + else + fprintf(f, "\t\t\t.hash_func_name = NULL,\n"); + fprintf(f, "\t\t},\n"); fprintf(f, "\t\t.size = %u,\n", learner_spec->size); diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h index dbe1b40adc..123e175f8b 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.h +++ b/lib/pipeline/rte_swx_pipeline_spec.h @@ -134,6 +134,7 @@ struct selector_spec { * ... * } * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ] + * hash HASH_FUNCTION_NAME * size SIZE * timeout { * TIMEOUT_IN_SECONDS