DPDK patches and discussions
 help / color / mirror / Atom feed
From: Itamar Gozlan <igozlan@nvidia.com>
To: <valex@nvidia.com>, <viacheslavo@nvidia.com>,
	<thomas@monjalon.net>, <suanmingm@nvidia.com>,
	Matan Azrad <matan@nvidia.com>, Ori Kam <orika@nvidia.com>
Cc: <dev@dpdk.org>
Subject: [PATCH 4/5] net/mlx5/hws: supporting default miss table in HWS
Date: Mon, 18 Sep 2023 15:07:04 +0300	[thread overview]
Message-ID: <20230918120705.265025-4-igozlan@nvidia.com> (raw)
In-Reply-To: <20230918120705.265025-1-igozlan@nvidia.com>

A default miss table is a way to define what happens to traffic that does
not match any rule in a specific table. In hws, this is done by connecting
the source table to the target table using the RTC.
This ensures that traffic that does not match any rule in the source table
is forwarded to the target table.
Issue: 3441251

Signed-off-by: Itamar Gozlan <igozlan@nvidia.com>
---
 drivers/common/mlx5/mlx5_prm.h        |   5 +-
 drivers/net/mlx5/hws/mlx5dr.h         |  12 ++
 drivers/net/mlx5/hws/mlx5dr_cmd.c     |   7 +-
 drivers/net/mlx5/hws/mlx5dr_cmd.h     |   1 +
 drivers/net/mlx5/hws/mlx5dr_debug.c   |   5 +-
 drivers/net/mlx5/hws/mlx5dr_matcher.c | 176 ++++++++++++---------
 drivers/net/mlx5/hws/mlx5dr_matcher.h |   5 +
 drivers/net/mlx5/hws/mlx5dr_table.c   | 218 +++++++++++++++++++++++++-
 drivers/net/mlx5/hws/mlx5dr_table.h   |  23 +++
 9 files changed, 366 insertions(+), 86 deletions(-)

diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 6df7ca20af..d46d4094b1 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -2085,7 +2085,10 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
 	u8 reparse[0x1];
 	u8 reserved_at_6b[0x1];
 	u8 cross_vhca_object[0x1];
-	u8 reserved_at_6d[0xb];
+	u8 reformat_l2_to_l3_audp_tunnel[0x1];
+	u8 reformat_l3_audp_tunnel_to_l2[0x1];
+	u8 ignore_flow_level_rtc_valid[0x1];
+	u8 reserved_at_70[0x8];
 	u8 log_max_ft_num[0x8];
 	u8 reserved_at_80[0x10];
 	u8 log_max_flow_counter[0x8];
diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index ec2230d136..54aa9fd6dd 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -237,6 +237,18 @@ mlx5dr_table_create(struct mlx5dr_context *ctx,
  */
 int mlx5dr_table_destroy(struct mlx5dr_table *tbl);
 
+/* Set default miss table for mlx5dr_table by using another mlx5dr_table
+ * Traffic which all table matchers miss will be forwarded to miss table.
+ *
+ * @param[in] tbl
+ *	source mlx5dr table
+ * @param[in] miss_tbl
+ *	target (miss) mlx5dr table, or NULL to remove current miss table
+ * @return zero on success non zero otherwise.
+ */
+int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl,
+				  struct mlx5dr_table *miss_tbl);
+
 /* Create new match template based on items mask, the match template
  * will be used for matcher creation.
  *
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.c b/drivers/net/mlx5/hws/mlx5dr_cmd.c
index 98d4b3bd3b..63b47f4617 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.c
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.c
@@ -581,7 +581,6 @@ mlx5dr_cmd_header_modify_pattern_create(struct ibv_context *ctx,
 		rte_errno = ENOMEM;
 		return NULL;
 	}
-
 	attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr);
 	MLX5_SET(general_obj_in_cmd_hdr,
 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
@@ -1032,6 +1031,12 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
 					capability.flow_table_nic_cap.
 					flow_table_properties_nic_receive.reparse);
 
+	caps->nic_ft.ignore_flow_level_rtc_valid =
+		MLX5_GET(query_hca_cap_out,
+			 out,
+			 capability.flow_table_nic_cap.
+			 flow_table_properties_nic_receive.ignore_flow_level_rtc_valid);
+
 	/* check cross-VHCA support in flow table properties */
 	res =
 	MLX5_GET(query_hca_cap_out, out,
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.h b/drivers/net/mlx5/hws/mlx5dr_cmd.h
index e57013c309..8a495db9b3 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.h
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.h
@@ -158,6 +158,7 @@ struct mlx5dr_cmd_allow_other_vhca_access_attr {
 struct mlx5dr_cmd_query_ft_caps {
 	uint8_t max_level;
 	uint8_t reparse;
+	uint8_t ignore_flow_level_rtc_valid;
 };
 
 struct mlx5dr_cmd_query_vport_caps {
diff --git a/drivers/net/mlx5/hws/mlx5dr_debug.c b/drivers/net/mlx5/hws/mlx5dr_debug.c
index 48810142a0..89529944a3 100644
--- a/drivers/net/mlx5/hws/mlx5dr_debug.c
+++ b/drivers/net/mlx5/hws/mlx5dr_debug.c
@@ -331,11 +331,12 @@ static int mlx5dr_debug_dump_table(FILE *f, struct mlx5dr_table *tbl)
 		}
 	}
 
-	ret = fprintf(f, ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 "\n",
+	ret = fprintf(f, ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 "\n",
 		      mlx5dr_debug_icm_to_idx(icm_addr_0),
 		      mlx5dr_debug_icm_to_idx(icm_addr_1),
 		      mlx5dr_debug_icm_to_idx(local_icm_addr_0),
-		      mlx5dr_debug_icm_to_idx(local_icm_addr_1));
+		      mlx5dr_debug_icm_to_idx(local_icm_addr_1),
+		      (uint64_t)(uintptr_t)tbl->default_miss.miss_tbl);
 	if (ret < 0)
 		goto out_err;
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c
index 1fe7ec1bc3..b704f85fba 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.c
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c
@@ -43,29 +43,21 @@ static void mlx5dr_matcher_destroy_end_ft(struct mlx5dr_matcher *matcher)
 	mlx5dr_table_destroy_default_ft(matcher->tbl, matcher->end_ft);
 }
 
-static int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
-					    uint32_t fw_ft_type,
-					    enum mlx5dr_table_type type,
-					    struct mlx5dr_devx_obj *devx_obj)
+int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
+				     uint32_t fw_ft_type,
+				     enum mlx5dr_table_type type,
+				     struct mlx5dr_devx_obj *devx_obj)
 {
-	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
 	int ret;
 
 	if (type != MLX5DR_TABLE_TYPE_FDB && !mlx5dr_context_shared_gvmi_used(ctx))
 		return 0;
 
-	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
-	ft_attr.type = fw_ft_type;
-	ft_attr.rtc_id_0 = 0;
-	ft_attr.rtc_id_1 = 0;
-
-	ret = mlx5dr_cmd_flow_table_modify(devx_obj, &ft_attr);
-	if (ret) {
+	ret = mlx5dr_table_ft_set_next_rtc(devx_obj, fw_ft_type, NULL, NULL);
+	if (ret)
 		DR_LOG(ERR, "Failed to disconnect previous RTC");
-		return ret;
-	}
 
-	return 0;
+	return ret;
 }
 
 static int mlx5dr_matcher_shared_point_end_ft(struct mlx5dr_matcher *matcher)
@@ -200,12 +192,10 @@ static int mlx5dr_matcher_shared_update_local_ft(struct mlx5dr_table *tbl)
 
 static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
 {
-	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
 	struct mlx5dr_table *tbl = matcher->tbl;
 	struct mlx5dr_matcher *prev = NULL;
 	struct mlx5dr_matcher *next = NULL;
 	struct mlx5dr_matcher *tmp_matcher;
-	struct mlx5dr_devx_obj *ft;
 	int ret;
 
 	/* Find location in matcher list */
@@ -228,32 +218,30 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
 		LIST_INSERT_AFTER(prev, matcher, next);
 
 connect:
-	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
-	ft_attr.type = tbl->fw_ft_type;
-
-	/* Connect to next */
 	if (next) {
-		if (next->match_ste.rtc_0)
-			ft_attr.rtc_id_0 = next->match_ste.rtc_0->id;
-		if (next->match_ste.rtc_1)
-			ft_attr.rtc_id_1 = next->match_ste.rtc_1->id;
-
-		ret = mlx5dr_cmd_flow_table_modify(matcher->end_ft, &ft_attr);
+		/* Connect to next RTC */
+		ret = mlx5dr_table_ft_set_next_rtc(matcher->end_ft,
+						   tbl->fw_ft_type,
+						   next->match_ste.rtc_0,
+						   next->match_ste.rtc_1);
 		if (ret) {
 			DR_LOG(ERR, "Failed to connect new matcher to next RTC");
 			goto remove_from_list;
 		}
+	} else {
+		/* Connect last matcher to next miss_tbl if exists */
+		ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl);
+		if (ret) {
+			DR_LOG(ERR, "Failed connect new matcher to miss_tbl");
+			goto remove_from_list;
+		}
 	}
 
-	/* Connect to previous */
-	ft = prev ? prev->end_ft : tbl->ft;
-
-	if (matcher->match_ste.rtc_0)
-		ft_attr.rtc_id_0 = matcher->match_ste.rtc_0->id;
-	if (matcher->match_ste.rtc_1)
-		ft_attr.rtc_id_1 = matcher->match_ste.rtc_1->id;
-
-	ret = mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
+	/* Connect to previous FT */
+	ret = mlx5dr_table_ft_set_next_rtc(prev ? prev->end_ft : tbl->ft,
+					   tbl->fw_ft_type,
+					   matcher->match_ste.rtc_0,
+					   matcher->match_ste.rtc_1);
 	if (ret) {
 		DR_LOG(ERR, "Failed to connect new matcher to previous FT");
 		goto remove_from_list;
@@ -265,6 +253,22 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
 		goto remove_from_list;
 	}
 
+	if (prev) {
+		/* Reset next miss FT to default (drop refcount) */
+		ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev->end_ft);
+		if (ret) {
+			DR_LOG(ERR, "Failed to reset matcher ft default miss");
+			goto remove_from_list;
+		}
+	} else {
+		/* Update tables missing to current table */
+		ret = mlx5dr_table_update_connected_miss_tables(tbl);
+		if (ret) {
+			DR_LOG(ERR, "Fatal error, failed to update connected miss table");
+			goto remove_from_list;
+		}
+	}
+
 	return 0;
 
 remove_from_list:
@@ -272,81 +276,97 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
 	return ret;
 }
 
-static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
+static int mlx5dr_last_matcher_disconnect(struct mlx5dr_table *tbl,
+					  struct mlx5dr_devx_obj *prev_ft)
 {
 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
+
+	if (tbl->default_miss.miss_tbl) {
+		/* Connect new last matcher to next miss_tbl if exists */
+		return mlx5dr_table_connect_to_miss_table(tbl,
+							  tbl->default_miss.miss_tbl);
+	} else {
+		ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
+		ft_attr.type = tbl->fw_ft_type;
+		/* Matcher is last, point prev end FT to default miss */
+		mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx,
+						     tbl->fw_ft_type,
+						     tbl->type,
+						     &ft_attr);
+		return mlx5dr_cmd_flow_table_modify(prev_ft, &ft_attr);
+	}
+}
+
+static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
+{
+	struct mlx5dr_matcher *tmp_matcher, *prev_matcher;
 	struct mlx5dr_table *tbl = matcher->tbl;
-	struct mlx5dr_matcher *tmp_matcher;
 	struct mlx5dr_devx_obj *prev_ft;
 	struct mlx5dr_matcher *next;
 	int ret;
 
-	prev_ft = matcher->tbl->ft;
+	prev_ft = tbl->ft;
+	prev_matcher = LIST_FIRST(&tbl->head);
 	LIST_FOREACH(tmp_matcher, &tbl->head, next) {
 		if (tmp_matcher == matcher)
 			break;
 
 		prev_ft = tmp_matcher->end_ft;
+		prev_matcher = tmp_matcher;
 	}
 
 	next = matcher->next.le_next;
 
-	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
-	ft_attr.type = matcher->tbl->fw_ft_type;
+	LIST_REMOVE(matcher, next);
 
 	if (next) {
-		/* Connect previous end FT to next RTC if exists */
-		if (next->match_ste.rtc_0)
-			ft_attr.rtc_id_0 = next->match_ste.rtc_0->id;
-		if (next->match_ste.rtc_1)
-			ft_attr.rtc_id_1 = next->match_ste.rtc_1->id;
+		/* Connect previous end FT to next RTC */
+		ret = mlx5dr_table_ft_set_next_rtc(prev_ft,
+						   tbl->fw_ft_type,
+						   next->match_ste.rtc_0,
+						   next->match_ste.rtc_1);
+		if (ret) {
+			DR_LOG(ERR, "Failed to disconnect matcher");
+			goto matcher_reconnect;
+		}
 	} else {
-		/* Matcher is last, point prev end FT to default miss */
-		mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx,
-						     tbl->fw_ft_type,
-						     tbl->type,
-						     &ft_attr);
-	}
-
-	ret = mlx5dr_cmd_flow_table_modify(prev_ft, &ft_attr);
-	if (ret) {
-		DR_LOG(ERR, "Failed to disconnect matcher");
-		return ret;
-	}
-
-	LIST_REMOVE(matcher, next);
-
-	if (!next) {
-		/* ft no longer points to any RTC, drop refcount */
-		ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx,
-						       tbl->fw_ft_type,
-						       tbl->type,
-						       prev_ft);
+		ret = mlx5dr_last_matcher_disconnect(tbl, prev_ft);
 		if (ret) {
-			DR_LOG(ERR, "Failed to reset last RTC refcount");
-			return ret;
+			DR_LOG(ERR, "Failed to disconnect last matcher");
+			goto matcher_reconnect;
 		}
 	}
 
 	ret = mlx5dr_matcher_shared_update_local_ft(tbl);
 	if (ret) {
 		DR_LOG(ERR, "Failed to update local_ft in shared table");
-		return ret;
+		goto matcher_reconnect;
 	}
 
-	if (!next) {
-		/* ft no longer points to any RTC, drop refcount */
-		ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx,
-						       tbl->fw_ft_type,
-						       tbl->type,
-						       prev_ft);
+	/* Removing first matcher, update connected miss tables if exists */
+	if (prev_ft == tbl->ft) {
+		ret = mlx5dr_table_update_connected_miss_tables(tbl);
 		if (ret) {
-			DR_LOG(ERR, "Failed to reset last RTC refcount");
-			return ret;
+			DR_LOG(ERR, "Fatal error, failed to update connected miss table");
+			goto matcher_reconnect;
 		}
 	}
 
+	ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev_ft);
+	if (ret) {
+		DR_LOG(ERR, "Fatal error, failed to restore matcher ft default miss");
+		goto matcher_reconnect;
+	}
+
 	return 0;
+
+matcher_reconnect:
+	if (LIST_EMPTY(&tbl->head))
+		LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
+	else
+		LIST_INSERT_AFTER(prev_matcher, matcher, next);
+
+	return ret;
 }
 
 static bool mlx5dr_matcher_supp_fw_wqe(struct mlx5dr_matcher *matcher)
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.h b/drivers/net/mlx5/hws/mlx5dr_matcher.h
index 4759068ab4..363a61fd41 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.h
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.h
@@ -115,4 +115,9 @@ static inline bool mlx5dr_matcher_is_insert_by_idx(struct mlx5dr_matcher *matche
 	return matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX;
 }
 
+int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
+				     uint32_t fw_ft_type,
+				     enum mlx5dr_table_type type,
+				     struct mlx5dr_devx_obj *devx_obj);
+
 #endif /* MLX5DR_MATCHER_H_ */
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.c b/drivers/net/mlx5/hws/mlx5dr_table.c
index f91f04d924..e1150cd75d 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.c
+++ b/drivers/net/mlx5/hws/mlx5dr_table.c
@@ -90,7 +90,7 @@ mlx5dr_table_connect_to_default_miss_tbl(struct mlx5dr_table *tbl,
 	ret = mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
 	if (ret) {
 		DR_LOG(ERR, "Failed to connect FT to default FDB FT");
-		return errno;
+		return ret;
 	}
 
 	return 0;
@@ -396,7 +396,7 @@ struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx,
 		return NULL;
 	}
 
-	tbl = simple_malloc(sizeof(*tbl));
+	tbl = simple_calloc(1, sizeof(*tbl));
 	if (!tbl) {
 		rte_errno = ENOMEM;
 		return NULL;
@@ -405,7 +405,6 @@ struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx,
 	tbl->ctx = ctx;
 	tbl->type = attr->type;
 	tbl->level = attr->level;
-	LIST_INIT(&tbl->head);
 
 	ret = mlx5dr_table_init(tbl);
 	if (ret) {
@@ -427,12 +426,223 @@ struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx,
 int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
 {
 	struct mlx5dr_context *ctx = tbl->ctx;
-
 	pthread_spin_lock(&ctx->ctrl_lock);
+	if (!LIST_EMPTY(&tbl->head)) {
+		DR_LOG(ERR, "Cannot destroy table containing matchers");
+		rte_errno = EBUSY;
+		goto unlock_err;
+	}
+
+	if (!LIST_EMPTY(&tbl->default_miss.head)) {
+		DR_LOG(ERR, "Cannot destroy table pointed by default miss");
+		rte_errno = EBUSY;
+		goto unlock_err;
+	}
+
 	LIST_REMOVE(tbl, next);
 	pthread_spin_unlock(&ctx->ctrl_lock);
 	mlx5dr_table_uninit(tbl);
 	simple_free(tbl);
 
 	return 0;
+
+unlock_err:
+	pthread_spin_unlock(&ctx->ctrl_lock);
+	return -rte_errno;
+}
+
+static struct mlx5dr_devx_obj *
+mlx5dr_table_get_last_ft(struct mlx5dr_table *tbl)
+{
+	struct mlx5dr_devx_obj *last_ft = tbl->ft;
+	struct mlx5dr_matcher *matcher;
+
+	LIST_FOREACH(matcher, &tbl->head, next)
+		last_ft = matcher->end_ft;
+
+	return last_ft;
+}
+
+int mlx5dr_table_ft_set_default_next_ft(struct mlx5dr_table *tbl,
+					struct mlx5dr_devx_obj *ft_obj)
+{
+	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
+	int ret;
+
+	/* Due to FW limitation, resetting the flow table to default action will
+	 * disconnect RTC when ignore_flow_level_rtc_valid is not supported.
+	 */
+	if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid)
+		return 0;
+
+	if (tbl->type == MLX5DR_TABLE_TYPE_FDB)
+		return mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj);
+
+	ft_attr.type = tbl->fw_ft_type;
+	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
+	ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_DEFAULT;
+
+	ret = mlx5dr_cmd_flow_table_modify(ft_obj, &ft_attr);
+	if (ret) {
+		DR_LOG(ERR, "Failed to set FT default miss action");
+		return ret;
+	}
+
+	return 0;
+}
+
+int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft,
+				 uint32_t fw_ft_type,
+				 struct mlx5dr_devx_obj *rtc_0,
+				 struct mlx5dr_devx_obj *rtc_1)
+{
+	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
+
+	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
+	ft_attr.type = fw_ft_type;
+	ft_attr.rtc_id_0 = rtc_0 ? rtc_0->id : 0;
+	ft_attr.rtc_id_1 = rtc_1 ? rtc_1->id : 0;
+
+	return mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
+}
+
+static int mlx5dr_table_ft_set_next_ft(struct mlx5dr_devx_obj *ft,
+				       uint32_t fw_ft_type,
+				       uint32_t next_ft_id)
+{
+	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
+
+	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
+	ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
+	ft_attr.type = fw_ft_type;
+	ft_attr.table_miss_id = next_ft_id;
+
+	return mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
+}
+
+int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
+{
+	struct mlx5dr_table *src_tbl;
+	int ret;
+
+	if (LIST_EMPTY(&dst_tbl->default_miss.head))
+		return 0;
+
+	LIST_FOREACH(src_tbl, &dst_tbl->default_miss.head, default_miss.next) {
+		ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl);
+		if (ret) {
+			DR_LOG(ERR, "Failed to update source miss table, unexpected behavior");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
+				       struct mlx5dr_table *dst_tbl)
+{
+	struct mlx5dr_devx_obj *last_ft;
+	struct mlx5dr_matcher *matcher;
+	int ret;
+
+	last_ft = mlx5dr_table_get_last_ft(src_tbl);
+
+	if (dst_tbl) {
+		if (LIST_EMPTY(&dst_tbl->head)) {
+			/* Connect src_tbl last_ft to dst_tbl start anchor */
+			ret = mlx5dr_table_ft_set_next_ft(last_ft,
+							  src_tbl->fw_ft_type,
+							  dst_tbl->ft->id);
+			if (ret)
+				return ret;
+
+			/* Reset last_ft RTC to default RTC */
+			ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+							   src_tbl->fw_ft_type,
+							   NULL, NULL);
+			if (ret)
+				return ret;
+		} else {
+			/* Connect src_tbl last_ft to first matcher RTC */
+			matcher = LIST_FIRST(&dst_tbl->head);
+			ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+							   src_tbl->fw_ft_type,
+							   matcher->match_ste.rtc_0,
+							   matcher->match_ste.rtc_1);
+			if (ret)
+				return ret;
+
+			/* Reset next miss FT to default */
+			ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, last_ft);
+			if (ret)
+				return ret;
+		}
+	} else {
+		/* Reset next miss FT to default */
+		ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, last_ft);
+		if (ret)
+			return ret;
+
+		/* Reset last_ft RTC to default RTC */
+		ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+						   src_tbl->fw_ft_type,
+						   NULL, NULL);
+		if (ret)
+			return ret;
+	}
+
+	src_tbl->default_miss.miss_tbl = dst_tbl;
+
+	return 0;
+}
+
+static int mlx5dr_table_set_default_miss_not_valid(struct mlx5dr_table *tbl,
+						   struct mlx5dr_table *miss_tbl)
+{
+	if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid ||
+	    mlx5dr_context_shared_gvmi_used(tbl->ctx)) {
+		DR_LOG(ERR, "Default miss table is not supported");
+		rte_errno = EOPNOTSUPP;
+		return -rte_errno;
+	}
+
+	if (mlx5dr_table_is_root(tbl) ||
+	    (miss_tbl && mlx5dr_table_is_root(miss_tbl)) ||
+	    (miss_tbl && miss_tbl->type != tbl->type) ||
+	    (miss_tbl && tbl->default_miss.miss_tbl)) {
+		DR_LOG(ERR, "Invalid arguments");
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl,
+				  struct mlx5dr_table *miss_tbl)
+{
+	struct mlx5dr_context *ctx = tbl->ctx;
+	int ret;
+
+	ret = mlx5dr_table_set_default_miss_not_valid(tbl, miss_tbl);
+	if (ret)
+		return ret;
+
+	pthread_spin_lock(&ctx->ctrl_lock);
+
+	ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl);
+	if (ret)
+		goto out;
+
+	if (miss_tbl)
+		LIST_INSERT_HEAD(&miss_tbl->default_miss.head, tbl, default_miss.next);
+	else
+		LIST_REMOVE(tbl, default_miss.next);
+
+	pthread_spin_unlock(&ctx->ctrl_lock);
+	return 0;
+out:
+	pthread_spin_unlock(&ctx->ctrl_lock);
+	return -ret;
 }
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.h b/drivers/net/mlx5/hws/mlx5dr_table.h
index 362d8a9048..b2fbb47416 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.h
+++ b/drivers/net/mlx5/hws/mlx5dr_table.h
@@ -7,6 +7,14 @@
 
 #define MLX5DR_ROOT_LEVEL 0
 
+struct mlx5dr_default_miss {
+	/* My miss table */
+	struct mlx5dr_table *miss_tbl;
+	LIST_ENTRY(mlx5dr_table) next;
+	/* Tables missing to my table */
+	LIST_HEAD(miss_table_head, mlx5dr_table) head;
+};
+
 struct mlx5dr_table {
 	struct mlx5dr_context *ctx;
 	struct mlx5dr_devx_obj *ft;
@@ -16,6 +24,7 @@ struct mlx5dr_table {
 	uint32_t level;
 	LIST_HEAD(matcher_head, mlx5dr_matcher) head;
 	LIST_ENTRY(mlx5dr_table) next;
+	struct mlx5dr_default_miss default_miss;
 };
 
 static inline
@@ -43,4 +52,18 @@ struct mlx5dr_devx_obj *mlx5dr_table_create_default_ft(struct ibv_context *ibv,
 
 void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
 				     struct mlx5dr_devx_obj *ft_obj);
+
+int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
+				       struct mlx5dr_table *dst_tbl);
+
+int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl);
+
+int mlx5dr_table_ft_set_default_next_ft(struct mlx5dr_table *tbl,
+					struct mlx5dr_devx_obj *ft_obj);
+
+int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft,
+				 uint32_t fw_ft_type,
+				 struct mlx5dr_devx_obj *rtc_0,
+				 struct mlx5dr_devx_obj *rtc_1);
+
 #endif /* MLX5DR_TABLE_H_ */
-- 
2.38.1


  parent reply	other threads:[~2023-09-18 12:08 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-18 12:07 [PATCH 1/5] net/mlx5/hws: add support for matching on bth_a bit Itamar Gozlan
2023-09-18 12:07 ` [PATCH 2/5] net/mlx5/hws: support additional 4 C registers Itamar Gozlan
2023-09-18 12:07 ` [PATCH 3/5] net/mlx5/hws: supporting add_field action Itamar Gozlan
2023-09-18 12:07 ` Itamar Gozlan [this message]
2023-10-29 16:02   ` [PATCH 4/5] net/mlx5/hws: supporting default miss table in HWS Ori Kam
2023-09-18 12:07 ` [PATCH 5/5] net/mlx5/hws: fix field copy bind Itamar Gozlan
2023-10-09  7:57 ` [PATCH 1/5] net/mlx5/hws: add support for matching on bth_a bit Matan Azrad
2023-10-10  9:33 ` Raslan Darawsheh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230918120705.265025-4-igozlan@nvidia.com \
    --to=igozlan@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=matan@nvidia.com \
    --cc=orika@nvidia.com \
    --cc=suanmingm@nvidia.com \
    --cc=thomas@monjalon.net \
    --cc=valex@nvidia.com \
    --cc=viacheslavo@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).