From: Cristian Dumitrescu Date: Thu, 8 Jul 2021 10:11:29 +0000 (+0100) Subject: pipeline: support LPM lookup X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=a3ac0a4836b7f9f32388393fc8c5d079fdfc1cf0;p=dpdk.git pipeline: support LPM lookup Add support for the Longest Prefix Match (LPM) lookup to the SWX pipeline. Signed-off-by: Cristian Dumitrescu Signed-off-by: Churchill Khangar --- diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c index 4ee47df108..f1480bc27b 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 1ef8ac7de9..84505e2a45 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;