[7/8] net/mlx5/hws: fix NAT64 csum issue

Message ID 20240709123103.2101902-8-igozlan@nvidia.com (mailing list archive)
State Awaiting Upstream
Delegated to: Raslan Darawsheh
Headers
Series HW steering team updates |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Itamar Gozlan July 9, 2024, 12:31 p.m. UTC
  From: Erez Shitrit <erezsh@nvidia.com>

Due to HW limitation we got two csum's that were not correct, udp and
ip, both of them were not calculated correctly by the HW.
By adding the next W/A we allow the HW to collect it well:
Separate the protocol field and zero all the addresses before fixed the
UDP csum.
We saw that the IP csum by the HW didn't take the ipv4 version as part
of the csum because the way it was inserted into the packet, in order to
solve that we added a prefix that takes into account the real csum for
the ip version and from that point the HW calculating the csum correctly.

Fixes: 06d969a8c5b8 ("net/mlx5/hws: support NAT64 flow action")
Cc: erezsh@nvidia.com
Cc: stable@dpdk.org

Signed-off-by: Erez Shitrit <erezsh@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr_action.c | 136 ++++++++++++++++++++++-----
 drivers/net/mlx5/hws/mlx5dr_action.h |  15 ++-
 2 files changed, 123 insertions(+), 28 deletions(-)
  

Patch

diff --git a/drivers/net/mlx5/hws/mlx5dr_action.c b/drivers/net/mlx5/hws/mlx5dr_action.c
index 0d90280a7d..8d3d0033e5 100644
--- a/drivers/net/mlx5/hws/mlx5dr_action.c
+++ b/drivers/net/mlx5/hws/mlx5dr_action.c
@@ -249,6 +249,62 @@  static void mlx5dr_action_put_shared_stc(struct mlx5dr_action *action,
 		mlx5dr_action_put_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_FDB);
 }
 
+static void
+mlx5dr_action_create_nat64_zero_all_addr(uint8_t **action_ptr, bool is_v4_to_v6)
+{
+	if (is_v4_to_v6) {
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_SIPV4);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_DIPV4);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+	} else {
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_SIPV6_127_96);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_SIPV6_95_64);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_SIPV6_63_32);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_SIPV6_31_0);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_DIPV6_127_96);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_DIPV6_95_64);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_DIPV6_63_32);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+		MLX5_SET(set_action_in, *action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
+		MLX5_SET(set_action_in, *action_ptr, field, MLX5_MODI_OUT_DIPV6_31_0);
+		MLX5_SET(set_action_in, *action_ptr, data, 0);
+		*action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+	}
+}
+
 static struct mlx5dr_action *
 mlx5dr_action_create_nat64_copy_state(struct mlx5dr_context *ctx,
 				      struct mlx5dr_action_nat64_attr *attr,
@@ -329,17 +385,7 @@  mlx5dr_action_create_nat64_copy_state(struct mlx5dr_context *ctx,
 	action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
 
 	/* set sip and dip to 0, in order to have new csum */
-	if (is_v4_to_v6) {
-		MLX5_SET(set_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
-		MLX5_SET(set_action_in, action_ptr, field, MLX5_MODI_OUT_SIPV4);
-		MLX5_SET(set_action_in, action_ptr, data, 0);
-		action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
-
-		MLX5_SET(set_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_SET);
-		MLX5_SET(set_action_in, action_ptr, field, MLX5_MODI_OUT_DIPV4);
-		MLX5_SET(set_action_in, action_ptr, data, 0);
-		action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
-	}
+	mlx5dr_action_create_nat64_zero_all_addr(&action_ptr, is_v4_to_v6);
 
 	pat[0].data = modify_action_data;
 	pat[0].sz = (action_ptr - (uint8_t *)modify_action_data);
@@ -383,9 +429,14 @@  mlx5dr_action_create_nat64_repalce_state(struct mlx5dr_context *ctx,
 		memcpy(address_prefix, nat64_well_known_pref,
 		       MLX5DR_ACTION_NAT64_HEADER_MINUS_ONE * sizeof(uint32_t));
 	} else {
+		/* In order to fix HW csum issue, make the prefix ready */
+		uint32_t ipv4_pref[] = {0x0, 0xffba0000, 0x0, 0x0, 0x0};
+
 		header_size_in_dw = MLX5DR_ACTION_NAT64_IPV4_HEADER;
 		ip_ver = MLX5DR_ACTION_NAT64_IPV4_VER;
 		eth_type = RTE_ETHER_TYPE_IPV4;
+		memcpy(address_prefix, ipv4_pref,
+		       MLX5DR_ACTION_NAT64_IPV4_HEADER * sizeof(uint32_t));
 	}
 
 	memset(modify_action_data, 0, sizeof(modify_action_data));
@@ -441,6 +492,46 @@  mlx5dr_action_create_nat64_repalce_state(struct mlx5dr_context *ctx,
 	return action;
 }
 
+static struct mlx5dr_action *
+mlx5dr_action_create_nat64_copy_proto_state(struct mlx5dr_context *ctx,
+					    struct mlx5dr_action_nat64_attr *attr,
+					    uint32_t flags)
+{
+	__be64 modify_action_data[MLX5DR_ACTION_NAT64_MAX_MODIFY_ACTIONS];
+	struct mlx5dr_action_mh_pattern pat[2];
+	struct mlx5dr_action *action;
+	uint8_t *action_ptr;
+
+	memset(modify_action_data, 0, sizeof(modify_action_data));
+	action_ptr = (uint8_t *)modify_action_data;
+
+	MLX5_SET(copy_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_COPY);
+	MLX5_SET(copy_action_in, action_ptr, src_field,
+		 attr->registers[MLX5DR_ACTION_NAT64_REG_CONTROL]);
+	MLX5_SET(copy_action_in, action_ptr, dst_field,
+		 MLX5_MODI_OUT_IP_PROTOCOL);
+	MLX5_SET(copy_action_in, action_ptr, src_offset, 16);
+	MLX5_SET(copy_action_in, action_ptr, dst_offset, 0);
+	MLX5_SET(copy_action_in, action_ptr, length, 8);
+	action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+	MLX5_SET(copy_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_NOP);
+	action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
+
+	pat[0].data = modify_action_data;
+	pat[0].sz = action_ptr - (uint8_t *)modify_action_data;
+
+	action = mlx5dr_action_create_modify_header_reparse(ctx, 1, pat, 0, flags,
+							    MLX5DR_ACTION_STC_REPARSE_ON);
+	if (!action) {
+		DR_LOG(ERR, "Failed to create action: action_sz: %zu, flags: 0x%x\n",
+		       pat[0].sz, flags);
+		return NULL;
+	}
+
+	return action;
+}
+
 static struct mlx5dr_action *
 mlx5dr_action_create_nat64_copy_back_state(struct mlx5dr_context *ctx,
 					   struct mlx5dr_action_nat64_attr *attr,
@@ -490,16 +581,6 @@  mlx5dr_action_create_nat64_copy_back_state(struct mlx5dr_context *ctx,
 	MLX5_SET(copy_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_NOP);
 	action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
 
-	MLX5_SET(copy_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_COPY);
-	MLX5_SET(copy_action_in, action_ptr, src_field,
-		 attr->registers[MLX5DR_ACTION_NAT64_REG_CONTROL]);
-	MLX5_SET(copy_action_in, action_ptr, dst_field,
-		 MLX5_MODI_OUT_IP_PROTOCOL);
-	MLX5_SET(copy_action_in, action_ptr, src_offset, 16);
-	MLX5_SET(copy_action_in, action_ptr, dst_offset, 0);
-	MLX5_SET(copy_action_in, action_ptr, length, 8);
-	action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
-
 	MLX5_SET(copy_action_in, action_ptr, action_type, MLX5_MODIFICATION_TYPE_NOP);
 	action_ptr += MLX5DR_ACTION_DOUBLE_SIZE;
 
@@ -2051,7 +2132,7 @@  mlx5dr_action_create_modify_header_hws(struct mlx5dr_action *action,
 	return rte_errno;
 }
 
-static struct mlx5dr_action *
+struct mlx5dr_action *
 mlx5dr_action_create_modify_header_reparse(struct mlx5dr_context *ctx,
 					   uint8_t num_of_patterns,
 					   struct mlx5dr_action_mh_pattern *patterns,
@@ -2927,17 +3008,24 @@  mlx5dr_action_create_nat64(struct mlx5dr_context *ctx,
 		DR_LOG(ERR, "Nat64 failed creating replace state");
 		goto free_copy;
 	}
+	action->nat64.stages[MLX5DR_ACTION_NAT64_STAGE_COPY_PROTOCOL] =
+		mlx5dr_action_create_nat64_copy_proto_state(ctx, attr, flags);
+	if (!action->nat64.stages[MLX5DR_ACTION_NAT64_STAGE_COPY_PROTOCOL]) {
+		DR_LOG(ERR, "Nat64 failed creating copy protocol state");
+		goto free_replace;
+	}
 
 	action->nat64.stages[MLX5DR_ACTION_NAT64_STAGE_COPYBACK] =
 		mlx5dr_action_create_nat64_copy_back_state(ctx, attr, flags);
 	if (!action->nat64.stages[MLX5DR_ACTION_NAT64_STAGE_COPYBACK]) {
 		DR_LOG(ERR, "Nat64 failed creating copyback state");
-		goto free_replace;
+		goto free_copy_proto;
 	}
 
 	return action;
 
-
+free_copy_proto:
+	mlx5dr_action_destroy(action->nat64.stages[MLX5DR_ACTION_NAT64_STAGE_COPY_PROTOCOL]);
 free_replace:
 	mlx5dr_action_destroy(action->nat64.stages[MLX5DR_ACTION_NAT64_STAGE_REPLACE]);
 free_copy:
diff --git a/drivers/net/mlx5/hws/mlx5dr_action.h b/drivers/net/mlx5/hws/mlx5dr_action.h
index 57e059a572..faea6bb1f4 100644
--- a/drivers/net/mlx5/hws/mlx5dr_action.h
+++ b/drivers/net/mlx5/hws/mlx5dr_action.h
@@ -11,9 +11,6 @@ 
 /* Max number of internal subactions of ipv6_ext */
 #define MLX5DR_ACTION_IPV6_EXT_MAX_SA 4
 
-/* Number of MH in NAT64 */
-#define MLX5DR_ACTION_NAT64_STAGES 3
-
 enum mlx5dr_action_stc_idx {
 	MLX5DR_ACTION_STC_IDX_CTRL = 0,
 	MLX5DR_ACTION_STC_IDX_HIT = 1,
@@ -88,7 +85,10 @@  enum {
 enum mlx5dr_action_nat64_stages {
 	MLX5DR_ACTION_NAT64_STAGE_COPY = 0,
 	MLX5DR_ACTION_NAT64_STAGE_REPLACE = 1,
-	MLX5DR_ACTION_NAT64_STAGE_COPYBACK = 2,
+	MLX5DR_ACTION_NAT64_STAGE_COPY_PROTOCOL = 2,
+	MLX5DR_ACTION_NAT64_STAGE_COPYBACK = 3,
+	/* Number of MH in NAT64 */
+	MLX5DR_ACTION_NAT64_STAGES = 4,
 };
 
 /* Registers for keeping data from stage to stage */
@@ -256,6 +256,13 @@  int mlx5dr_action_alloc_single_stc(struct mlx5dr_context *ctx,
 void mlx5dr_action_free_single_stc(struct mlx5dr_context *ctx,
 				   uint32_t table_type,
 				   struct mlx5dr_pool_chunk *stc);
+struct mlx5dr_action *
+mlx5dr_action_create_modify_header_reparse(struct mlx5dr_context *ctx,
+					   uint8_t num_of_patterns,
+					   struct mlx5dr_action_mh_pattern *patterns,
+					   uint32_t log_bulk_size,
+					   uint32_t flags, uint32_t reparse);
+
 
 static inline void
 mlx5dr_action_setter_default_single(struct mlx5dr_actions_apply_data *apply,