From patchwork Wed Jul 7 20:48:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 95518 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 69EF7A0C49; Wed, 7 Jul 2021 22:48:09 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1B768413DB; Wed, 7 Jul 2021 22:48:09 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mails.dpdk.org (Postfix) with ESMTP id 443F3413B6 for ; Wed, 7 Jul 2021 22:48:07 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10037"; a="209202000" X-IronPort-AV: E=Sophos;i="5.84,221,1620716400"; d="scan'208";a="209202000" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jul 2021 13:48:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.84,221,1620716400"; d="scan'208";a="491845515" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by orsmga001.jf.intel.com with ESMTP; 07 Jul 2021 13:48:05 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Churchill Khangar Date: Wed, 7 Jul 2021 21:48:04 +0100 Message-Id: <20210707204804.16848-1-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dpdk-dev] [PATCH] pipeline: add support for LPM lookup 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 Sender: "dev" Add support for the Longest Prefix Match (LPM) lookup to the SWX pipeline. Signed-off-by: Cristian Dumitrescu Signed-off-by: Churchill Khangar --- lib/pipeline/rte_swx_ctl.c | 99 ++++++++++++++++++++++----------- lib/pipeline/rte_swx_pipeline.c | 78 +++++++++----------------- 2 files changed, 93 insertions(+), 84 deletions(-) diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c index 4ee47df10..f1480bc27 100644 --- a/lib/pipeline/rte_swx_ctl.c +++ b/lib/pipeline/rte_swx_ctl.c @@ -218,9 +218,6 @@ table_params_get(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id) if (n_match_fields_em == table->info.n_match_fields) match_type = RTE_SWX_TABLE_MATCH_EXACT; - else if ((n_match_fields_em == table->info.n_match_fields - 1) && - (last->match_type == RTE_SWX_TABLE_MATCH_LPM)) - match_type = RTE_SWX_TABLE_MATCH_LPM; /* key_offset. */ key_offset = first->offset / 8; @@ -347,35 +344,15 @@ table_entry_check(struct rte_swx_ctl_pipeline *ctl, CHECK(entry, EINVAL); - if (key_check) { - if (table->is_stub) { - /* key. */ - CHECK(!entry->key, EINVAL); - - /* key_mask. */ - CHECK(!entry->key_mask, EINVAL); - } else { - /* key. */ - CHECK(entry->key, EINVAL); - - /* key_mask. */ - switch (table->params.match_type) { - case RTE_SWX_TABLE_MATCH_WILDCARD: - break; - - case RTE_SWX_TABLE_MATCH_LPM: - /* TBD Check that key mask is prefix. */ - break; - - case RTE_SWX_TABLE_MATCH_EXACT: - status = table_entry_key_check_em(table, entry); - if (status) - return status; - break; + if (key_check && !table->is_stub) { + /* key. */ + CHECK(entry->key, EINVAL); - default: - CHECK(0, EINVAL); - } + /* key_mask. */ + if (table->params.match_type == RTE_SWX_TABLE_MATCH_EXACT) { + status = table_entry_key_check_em(table, entry); + if (status) + return status; } } @@ -2207,6 +2184,45 @@ rte_swx_ctl_pipeline_abort(struct rte_swx_ctl_pipeline *ctl) selector_abort(ctl, i); } +static int +mask_to_prefix(uint64_t mask, uint32_t mask_length, uint32_t *prefix_length) +{ + uint32_t n_trailing_zeros = 0, n_ones = 0, i; + + if (!mask) { + *prefix_length = 0; + return 0; + } + + /* Count trailing zero bits. */ + for (i = 0; i < 64; i++) { + if (mask & (1LLU << i)) + break; + + n_trailing_zeros++; + } + + /* Count the one bits that follow. */ + for ( ; i < 64; i++) { + if (!(mask & (1LLU << i))) + break; + + n_ones++; + } + + /* Check that no more one bits are present */ + for ( ; i < 64; i++) + if (mask & (1LLU << i)) + return -EINVAL; + + /* Check that the input mask is a prefix or the right length. */ + if (n_ones + n_trailing_zeros != mask_length) + return -EINVAL; + + *prefix_length = n_ones; + return 0; +} + static int token_is_comment(const char *token) { @@ -2231,8 +2247,8 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl, struct action *action; struct rte_swx_table_entry *entry = NULL; char *s0 = NULL, *s; - uint32_t n_tokens = 0, arg_offset = 0, i; - int blank_or_comment = 0; + uint32_t n_tokens = 0, arg_offset = 0, lpm_prefix_length_max = 0, lpm_prefix_length = 0, i; + int lpm = 0, blank_or_comment = 0; /* Check input arguments. */ if (!ctl) @@ -2307,6 +2323,19 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl, if (mf_mask[0]) goto error; + /* LPM. */ + if (mf->match_type == RTE_SWX_TABLE_MATCH_LPM) { + int status; + + lpm = 1; + + lpm_prefix_length_max = mf->n_bits; + + status = mask_to_prefix(mask, mf->n_bits, &lpm_prefix_length); + if (status) + goto error; + } + /* Endianness conversion. */ if (mf->is_header) mask = field_hton(mask, mf->n_bits); @@ -2361,6 +2390,10 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl, n_tokens -= 2; } + /* LPM. */ + if (lpm) + entry->key_priority = lpm_prefix_length_max - lpm_prefix_length; + /* * Action. */ diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 22c860f28..85db45d48 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -9199,37 +9199,42 @@ rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p, return 0; } -static enum rte_swx_table_match_type +static int table_match_type_resolve(struct rte_swx_match_field_params *fields, uint32_t n_fields, - uint32_t max_offset_field_id) + enum rte_swx_table_match_type *match_type) { - uint32_t n_fields_em = 0, i; + uint32_t n_fields_em = 0, n_fields_lpm = 0, i; + + for (i = 0; i < n_fields; i++) { + struct rte_swx_match_field_params *f = &fields[i]; - for (i = 0; i < n_fields; i++) - if (fields[i].match_type == RTE_SWX_TABLE_MATCH_EXACT) + if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT) n_fields_em++; - if (n_fields_em == n_fields) - return RTE_SWX_TABLE_MATCH_EXACT; + if (f->match_type == RTE_SWX_TABLE_MATCH_LPM) + n_fields_lpm++; + } + + if ((n_fields_lpm > 1) || + (n_fields_lpm && (n_fields_em != n_fields - 1))) + return -EINVAL; - if ((n_fields_em == n_fields - 1) && - (fields[max_offset_field_id].match_type == RTE_SWX_TABLE_MATCH_LPM)) - return RTE_SWX_TABLE_MATCH_LPM; + *match_type = (n_fields_em == n_fields) ? + RTE_SWX_TABLE_MATCH_EXACT : + RTE_SWX_TABLE_MATCH_WILDCARD; - return RTE_SWX_TABLE_MATCH_WILDCARD; + return 0; } static int table_match_fields_check(struct rte_swx_pipeline *p, struct rte_swx_pipeline_table_params *params, - struct header **header, - uint32_t *min_offset_field_id, - uint32_t *max_offset_field_id) + struct header **header) { struct header *h0 = NULL; struct field *hf, *mf; - uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i; + uint32_t *offset = NULL, i; int status = 0; /* Return if no match fields. */ @@ -9293,34 +9298,10 @@ table_match_fields_check(struct rte_swx_pipeline *p, } } - /* Find the min and max offset fields. */ - min_offset = offset[0]; - max_offset = offset[0]; - min_offset_pos = 0; - max_offset_pos = 0; - - for (i = 1; i < params->n_fields; i++) { - if (offset[i] < min_offset) { - min_offset = offset[i]; - min_offset_pos = i; - } - - if (offset[i] > max_offset) { - max_offset = offset[i]; - max_offset_pos = i; - } - } - /* Return. */ if (header) *header = h0; - if (min_offset_field_id) - *min_offset_field_id = min_offset_pos; - - if (max_offset_field_id) - *max_offset_field_id = max_offset_pos; - end: free(offset); return status; @@ -9338,7 +9319,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, struct table *t; struct action *default_action; struct header *header = NULL; - uint32_t action_data_size_max = 0, min_offset_field_id = 0, max_offset_field_id = 0, i; + uint32_t action_data_size_max = 0, i; int status = 0; CHECK(p, EINVAL); @@ -9350,11 +9331,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, CHECK(params, EINVAL); /* Match checks. */ - status = table_match_fields_check(p, - params, - &header, - &min_offset_field_id, - &max_offset_field_id); + status = table_match_fields_check(p, params, &header); if (status) return status; @@ -9393,12 +9370,11 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, if (params->n_fields) { enum rte_swx_table_match_type match_type; - match_type = table_match_type_resolve(params->fields, - params->n_fields, - max_offset_field_id); - type = table_type_resolve(p, - recommended_table_type_name, - match_type); + status = table_match_type_resolve(params->fields, params->n_fields, &match_type); + if (status) + return status; + + type = table_type_resolve(p, recommended_table_type_name, match_type); CHECK(type, EINVAL); } else { type = NULL;