From patchwork Fri Aug 19 19:52:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 115300 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 35AAAA034C; Fri, 19 Aug 2022 21:52:54 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8D6AD427F6; Fri, 19 Aug 2022 21:52:35 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by mails.dpdk.org (Postfix) with ESMTP id ADFE141614 for ; Fri, 19 Aug 2022 21:52:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1660938752; x=1692474752; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vguaOuw5SvAbd26k6AzG+VohkW5iEeyA04ZXJPwHIbE=; b=CAEhtKQMz/zkPjqfF4yi5CyPJjL5kYCHZqJF4hmuzn+bOyKHmaXZ3fDx 14Fb0NgszRjWpH3VeOwMTsScYmRjbJ3uJS5sgtBB3eFh1yoAdNOU8Ubwg 0nLX0BdN95y2sDPKZ7swmFaqMNmGrLJ3qO4C8gHgvaR1wWtLr/KEADvtL 9wSGHCCGiR8lw22kHDHVjyclWKzijQ2p0aDmtajhFBO+LdA12xTY7+EDy QmseEtzJY4nb/VTFIBdLhv08Lg6uDWmUFw4JG8t8vENgzV58FFIp2KPTi VviKp33YOEEiHUrLwx9f54+2Mkn5wXeOlBjNhfIcJPTF7t7hsBrBd5Diz w==; X-IronPort-AV: E=McAfee;i="6500,9779,10444"; a="280047523" X-IronPort-AV: E=Sophos;i="5.93,249,1654585200"; d="scan'208";a="280047523" 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:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,248,1654585200"; d="scan'208";a="604695954" 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:30 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Cc: "Kamalakannan R ." Subject: [PATCH V2 4/6] pipeline: configure the hash function for regular tables Date: Fri, 19 Aug 2022 19:52:23 +0000 Message-Id: <20220819195225.1483020-5-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 regular pipeline tables. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R. --- lib/pipeline/rte_swx_ctl.c | 1 + lib/pipeline/rte_swx_ctl.h | 3 ++ lib/pipeline/rte_swx_pipeline.c | 56 +++++++++++++++++++----- lib/pipeline/rte_swx_pipeline.h | 24 +++------- lib/pipeline/rte_swx_pipeline_internal.h | 1 + lib/pipeline/rte_swx_pipeline_spec.c | 42 +++++++++++++++++- lib/pipeline/rte_swx_pipeline_spec.h | 1 + 7 files changed, 100 insertions(+), 28 deletions(-) diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c index bdbcd8f50a..b6449f5f0c 100644 --- a/lib/pipeline/rte_swx_ctl.c +++ b/lib/pipeline/rte_swx_ctl.c @@ -272,6 +272,7 @@ table_params_get(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id) table->params.key_offset = key_offset; table->params.key_mask0 = key_mask; table->params.action_data_size = action_data_size; + table->params.hash_func = table->info.hash_func; table->params.n_keys_max = table->info.size; table->mf_first = first; diff --git a/lib/pipeline/rte_swx_ctl.h b/lib/pipeline/rte_swx_ctl.h index 63ee479e47..0694df557a 100644 --- a/lib/pipeline/rte_swx_ctl.h +++ b/lib/pipeline/rte_swx_ctl.h @@ -236,6 +236,9 @@ struct rte_swx_ctl_table_info { */ int default_action_is_const; + /** Hash function. */ + rte_swx_hash_func_t hash_func; + /** Table size parameter. */ uint32_t size; }; diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 2cac4caa95..0b21adacbc 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -7866,6 +7866,7 @@ rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p, static int table_match_type_resolve(struct rte_swx_match_field_params *fields, uint32_t n_fields, + int contiguous_fields, enum rte_swx_table_match_type *match_type) { uint32_t n_fields_em = 0, n_fields_lpm = 0, i; @@ -7884,7 +7885,7 @@ table_match_type_resolve(struct rte_swx_match_field_params *fields, (n_fields_lpm && (n_fields_em != n_fields - 1))) return -EINVAL; - *match_type = (n_fields_em == n_fields) ? + *match_type = ((n_fields_em == n_fields) && contiguous_fields) ? RTE_SWX_TABLE_MATCH_EXACT : RTE_SWX_TABLE_MATCH_WILDCARD; @@ -7894,11 +7895,12 @@ table_match_type_resolve(struct rte_swx_match_field_params *fields, static int table_match_fields_check(struct rte_swx_pipeline *p, struct rte_swx_pipeline_table_params *params, - struct header **header) + struct header **header, + int *contiguous_fields) { struct header *h0 = NULL; struct field *hf, *mf; - uint32_t *offset = NULL, i; + uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i; int status = 0; /* Return if no match fields. */ @@ -7911,12 +7913,16 @@ table_match_fields_check(struct rte_swx_pipeline *p, if (header) *header = NULL; + if (contiguous_fields) + *contiguous_fields = 0; + return 0; } /* Memory allocation. */ offset = calloc(params->n_fields, sizeof(uint32_t)); - if (!offset) { + n_bits = calloc(params->n_fields, sizeof(uint32_t)); + if (!offset || !n_bits) { status = -ENOMEM; goto end; } @@ -7932,6 +7938,7 @@ table_match_fields_check(struct rte_swx_pipeline *p, } 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) { @@ -7944,6 +7951,7 @@ table_match_fields_check(struct rte_swx_pipeline *p, } offset[i] = hf->offset; + n_bits[i] = hf->n_bits; } else { mf = metadata_field_parse(p, params->fields[i].name); if (!mf) { @@ -7952,6 +7960,7 @@ table_match_fields_check(struct rte_swx_pipeline *p, } offset[i] = mf->offset; + n_bits[i] = mf->n_bits; } /* Check that there are no duplicated match fields. */ @@ -7965,12 +7974,28 @@ table_match_fields_check(struct rte_swx_pipeline *p, } } + /* Detect if the match fields are contiguous or not. */ + 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; + } + } + /* Return. */ if (header) *header = h0; + if (contiguous_fields) + *contiguous_fields = (n_fields_with_valid_next == params->n_fields - 1) ? 1 : 0; + end: free(offset); + free(n_bits); return status; } @@ -7982,12 +8007,13 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, const char *args, uint32_t size) { - struct table_type *type; + struct table_type *type = NULL; struct table *t = 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; + int contiguous_fields = 0, status = 0; CHECK(p, EINVAL); @@ -7999,7 +8025,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, CHECK(params, EINVAL); /* Match checks. */ - status = table_match_fields_check(p, params, &header); + status = table_match_fields_check(p, params, &header, &contiguous_fields); if (status) return status; @@ -8042,6 +8068,12 @@ rte_swx_pipeline_table_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); + } + /* Table type checks. */ if (recommended_table_type_name) CHECK_NAME(recommended_table_type_name, EINVAL); @@ -8049,14 +8081,15 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, if (params->n_fields) { enum rte_swx_table_match_type match_type; - status = table_match_type_resolve(params->fields, params->n_fields, &match_type); + status = table_match_type_resolve(params->fields, + params->n_fields, + contiguous_fields, + &match_type); if (status) return status; type = table_type_resolve(p, recommended_table_type_name, match_type); CHECK(type, EINVAL); - } else { - type = NULL; } /* Memory allocation. */ @@ -8141,6 +8174,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, t->default_action_is_const = params->default_action_is_const; t->action_data_size_max = action_data_size_max; + t->hf = hf; t->size = size; t->id = p->n_tables; @@ -8227,6 +8261,7 @@ table_params_get(struct table *table) params->key_offset = key_offset; params->key_mask0 = key_mask; params->action_data_size = action_data_size; + params->hash_func = table->hf ? table->hf->func : NULL; params->n_keys_max = table->size; return params; @@ -10265,6 +10300,7 @@ rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p, table->n_match_fields = t->n_fields; table->n_actions = t->n_actions; table->default_action_is_const = t->default_action_is_const; + table->hash_func = t->hf ? t->hf->func : NULL; table->size = t->size; return 0; } diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h index 9c629d4118..09c75180f8 100644 --- a/lib/pipeline/rte_swx_pipeline.h +++ b/lib/pipeline/rte_swx_pipeline.h @@ -331,23 +331,6 @@ rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p, * Hash function. */ -/** - * Hash function prototype - * - * @param[in] key - * Key to hash. Must be non-NULL. - * @param[in] length - * Key length in bytes. - * @param[in] seed - * Hash seed. - * @return - * Hash value. - */ -typedef uint32_t -(*rte_swx_hash_func_t)(const void *key, - uint32_t length, - uint32_t seed); - /** * Pipeline hash function register * @@ -699,6 +682,13 @@ struct rte_swx_pipeline_table_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. + * Ignored by the table implementation when not needed. When needed but + * NULL, the table implementation will select the hash function to use. + */ + const char *hash_func_name; }; /** diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h index 6d65b635c6..ee579c6656 100644 --- a/lib/pipeline/rte_swx_pipeline_internal.h +++ b/lib/pipeline/rte_swx_pipeline_internal.h @@ -828,6 +828,7 @@ struct table { int *action_is_for_table_entries; int *action_is_for_default_entry; + struct hash_func *hf; uint32_t size; uint32_t id; }; diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c index 1b4183ef55..e9fde4f241 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.c +++ b/lib/pipeline/rte_swx_pipeline_spec.c @@ -509,7 +509,7 @@ action_block_parse(struct action_spec *s, static void table_spec_free(struct table_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) @@ -556,6 +556,10 @@ table_spec_free(struct table_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; + free(s->recommended_table_type_name); s->recommended_table_type_name = NULL; @@ -935,6 +939,35 @@ table_block_parse(struct table_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], "instanceof")) { if (n_tokens != 2) { if (err_line) @@ -2419,6 +2452,13 @@ pipeline_spec_codegen(FILE *f, fprintf(f, "\t\t\t.default_action_is_const = %d,\n", table_spec->params.default_action_is_const); + + if (table_spec->params.hash_func_name) + fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n", + table_spec->params.hash_func_name); + else + fprintf(f, "\t\t\t.hash_func_name = NULL,\n"); + fprintf(f, "\t\t},\n"); if (table_spec->recommended_table_type_name) diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h index 62ac4ecfc4..dbe1b40adc 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.h +++ b/lib/pipeline/rte_swx_pipeline_spec.h @@ -88,6 +88,7 @@ struct action_spec { * ... * } * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ] + * hash HASH_FUNCTION_NAME * instanceof TABLE_TYPE_NAME * pragma ARGS * size SIZE