[dpdk-dev] [PATCH] pipeline: add support for LPM lookup

Cristian Dumitrescu cristian.dumitrescu at intel.com
Wed Jul 7 22:48:04 CEST 2021


Add support for the Longest Prefix Match (LPM) lookup to the SWX
pipeline.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu at intel.com>
Signed-off-by: Churchill Khangar <churchill.khangar at intel.com>
---
 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;
-- 
2.17.1



More information about the dev mailing list