You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
307 lines
10 KiB
307 lines
10 KiB
From 2b68292318b04855edb2ad274d8acc3d34a066aa Mon Sep 17 00:00:00 2001
|
|
From: Alaa Hleihel <ahleihel@redhat.com>
|
|
Date: Tue, 12 May 2020 10:54:08 -0400
|
|
Subject: [PATCH 148/312] [netdrv] net/mlx5: DR, Modify header copy support
|
|
|
|
Message-id: <20200512105530.4207-43-ahleihel@redhat.com>
|
|
Patchwork-id: 306914
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.3 BZ 1789382 042/124] net/mlx5: DR, Modify header copy support
|
|
Bugzilla: 1789384 1789382
|
|
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
|
|
RH-Acked-by: Kamal Heib <kheib@redhat.com>
|
|
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
|
|
Bugzilla: http://bugzilla.redhat.com/1789382
|
|
Bugzilla: http://bugzilla.redhat.com/1789384
|
|
Upstream: v5.6-rc1
|
|
|
|
commit c21a49b360e16657f42f1a9269c3aa714738fec7
|
|
Author: Hamdan Igbaria <hamdani@mellanox.com>
|
|
Date: Thu Jan 9 13:27:16 2020 +0200
|
|
|
|
net/mlx5: DR, Modify header copy support
|
|
|
|
Modify header supports ADD/SET and from this patch
|
|
also COPY. Copy allows to copy header fields and
|
|
metadata.
|
|
|
|
Signed-off-by: Hamdan Igbaria <hamdani@mellanox.com>
|
|
Signed-off-by: Alex Vesker <valex@mellanox.com>
|
|
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
|
|
|
|
Signed-off-by: Alaa Hleihel <ahleihel@redhat.com>
|
|
Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
|
|
---
|
|
.../mellanox/mlx5/core/steering/dr_action.c | 150 ++++++++++++++++++---
|
|
.../mellanox/mlx5/core/steering/mlx5_ifc_dr.h | 16 +++
|
|
2 files changed, 151 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
|
|
index ad32b88a83dc..286fcec5eff2 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
|
|
@@ -1411,15 +1411,82 @@ dr_action_modify_sw_to_hw_set(struct mlx5dr_domain *dmn,
|
|
}
|
|
|
|
static int
|
|
+dr_action_modify_sw_to_hw_copy(struct mlx5dr_domain *dmn,
|
|
+ __be64 *sw_action,
|
|
+ __be64 *hw_action,
|
|
+ const struct dr_action_modify_field_conv **ret_dst_hw_info,
|
|
+ const struct dr_action_modify_field_conv **ret_src_hw_info)
|
|
+{
|
|
+ u8 src_offset, dst_offset, src_max_length, dst_max_length, length;
|
|
+ const struct dr_action_modify_field_conv *hw_dst_action_info;
|
|
+ const struct dr_action_modify_field_conv *hw_src_action_info;
|
|
+ u16 src_field, dst_field;
|
|
+
|
|
+ /* Get SW modify action data */
|
|
+ src_field = MLX5_GET(copy_action_in, sw_action, src_field);
|
|
+ dst_field = MLX5_GET(copy_action_in, sw_action, dst_field);
|
|
+ src_offset = MLX5_GET(copy_action_in, sw_action, src_offset);
|
|
+ dst_offset = MLX5_GET(copy_action_in, sw_action, dst_offset);
|
|
+ length = MLX5_GET(copy_action_in, sw_action, length);
|
|
+
|
|
+ /* Convert SW data to HW modify action format */
|
|
+ hw_src_action_info = dr_action_modify_get_hw_info(src_field);
|
|
+ hw_dst_action_info = dr_action_modify_get_hw_info(dst_field);
|
|
+ if (!hw_src_action_info || !hw_dst_action_info) {
|
|
+ mlx5dr_dbg(dmn, "Modify copy action invalid field given\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* PRM defines that length zero specific length of 32bits */
|
|
+ length = length ? length : 32;
|
|
+
|
|
+ src_max_length = hw_src_action_info->end -
|
|
+ hw_src_action_info->start + 1;
|
|
+ dst_max_length = hw_dst_action_info->end -
|
|
+ hw_dst_action_info->start + 1;
|
|
+
|
|
+ if (length + src_offset > src_max_length ||
|
|
+ length + dst_offset > dst_max_length) {
|
|
+ mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ MLX5_SET(dr_action_hw_copy, hw_action,
|
|
+ opcode, MLX5DR_ACTION_MDFY_HW_OP_COPY);
|
|
+
|
|
+ MLX5_SET(dr_action_hw_copy, hw_action, destination_field_code,
|
|
+ hw_dst_action_info->hw_field);
|
|
+
|
|
+ MLX5_SET(dr_action_hw_copy, hw_action, destination_left_shifter,
|
|
+ hw_dst_action_info->start + dst_offset);
|
|
+
|
|
+ MLX5_SET(dr_action_hw_copy, hw_action, destination_length,
|
|
+ length == 32 ? 0 : length);
|
|
+
|
|
+ MLX5_SET(dr_action_hw_copy, hw_action, source_field_code,
|
|
+ hw_src_action_info->hw_field);
|
|
+
|
|
+ MLX5_SET(dr_action_hw_copy, hw_action, source_left_shifter,
|
|
+ hw_src_action_info->start + dst_offset);
|
|
+
|
|
+ *ret_dst_hw_info = hw_dst_action_info;
|
|
+ *ret_src_hw_info = hw_src_action_info;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
dr_action_modify_sw_to_hw(struct mlx5dr_domain *dmn,
|
|
__be64 *sw_action,
|
|
__be64 *hw_action,
|
|
- const struct dr_action_modify_field_conv **ret_hw_info)
|
|
+ const struct dr_action_modify_field_conv **ret_dst_hw_info,
|
|
+ const struct dr_action_modify_field_conv **ret_src_hw_info)
|
|
{
|
|
u8 action;
|
|
int ret;
|
|
|
|
*hw_action = 0;
|
|
+ *ret_src_hw_info = NULL;
|
|
|
|
/* Get SW modify action type */
|
|
action = MLX5_GET(set_action_in, sw_action, action_type);
|
|
@@ -1428,13 +1495,20 @@ dr_action_modify_sw_to_hw(struct mlx5dr_domain *dmn,
|
|
case MLX5_ACTION_TYPE_SET:
|
|
ret = dr_action_modify_sw_to_hw_set(dmn, sw_action,
|
|
hw_action,
|
|
- ret_hw_info);
|
|
+ ret_dst_hw_info);
|
|
break;
|
|
|
|
case MLX5_ACTION_TYPE_ADD:
|
|
ret = dr_action_modify_sw_to_hw_add(dmn, sw_action,
|
|
hw_action,
|
|
- ret_hw_info);
|
|
+ ret_dst_hw_info);
|
|
+ break;
|
|
+
|
|
+ case MLX5_ACTION_TYPE_COPY:
|
|
+ ret = dr_action_modify_sw_to_hw_copy(dmn, sw_action,
|
|
+ hw_action,
|
|
+ ret_dst_hw_info,
|
|
+ ret_src_hw_info);
|
|
break;
|
|
|
|
default:
|
|
@@ -1496,6 +1570,43 @@ dr_action_modify_check_add_field_limitation(struct mlx5dr_action *action,
|
|
}
|
|
|
|
static int
|
|
+dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
|
|
+ const __be64 *sw_action)
|
|
+{
|
|
+ struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
|
+ u16 sw_fields[2];
|
|
+ int i;
|
|
+
|
|
+ sw_fields[0] = MLX5_GET(copy_action_in, sw_action, src_field);
|
|
+ sw_fields[1] = MLX5_GET(copy_action_in, sw_action, dst_field);
|
|
+
|
|
+ for (i = 0; i < 2; i++) {
|
|
+ if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
|
|
+ action->rewrite.allow_rx = 0;
|
|
+ if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
|
|
+ mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
|
|
+ sw_fields[i]);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ } else if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
|
|
+ action->rewrite.allow_tx = 0;
|
|
+ if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
|
|
+ mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
|
|
+ sw_fields[i]);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!action->rewrite.allow_rx && !action->rewrite.allow_tx) {
|
|
+ mlx5dr_dbg(dmn, "Modify copy actions not supported on both RX and TX\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
dr_action_modify_check_field_limitation(struct mlx5dr_action *action,
|
|
const __be64 *sw_action)
|
|
{
|
|
@@ -1516,6 +1627,11 @@ dr_action_modify_check_field_limitation(struct mlx5dr_action *action,
|
|
sw_action);
|
|
break;
|
|
|
|
+ case MLX5_ACTION_TYPE_COPY:
|
|
+ ret = dr_action_modify_check_copy_field_limitation(action,
|
|
+ sw_action);
|
|
+ break;
|
|
+
|
|
default:
|
|
mlx5dr_info(dmn, "Unsupported action %d modify action\n",
|
|
action_type);
|
|
@@ -1541,7 +1657,8 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
|
|
u32 *num_hw_actions,
|
|
bool *modify_ttl)
|
|
{
|
|
- const struct dr_action_modify_field_conv *hw_action_info;
|
|
+ const struct dr_action_modify_field_conv *hw_dst_action_info;
|
|
+ const struct dr_action_modify_field_conv *hw_src_action_info;
|
|
u16 hw_field = MLX5DR_ACTION_MDFY_HW_FLD_RESERVED;
|
|
u32 l3_type = MLX5DR_ACTION_MDFY_HW_HDR_L3_NONE;
|
|
u32 l4_type = MLX5DR_ACTION_MDFY_HW_HDR_L4_NONE;
|
|
@@ -1570,32 +1687,35 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
|
|
ret = dr_action_modify_sw_to_hw(dmn,
|
|
sw_action,
|
|
&hw_action,
|
|
- &hw_action_info);
|
|
+ &hw_dst_action_info,
|
|
+ &hw_src_action_info);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* Due to a HW limitation we cannot modify 2 different L3 types */
|
|
- if (l3_type && hw_action_info->l3_type &&
|
|
- hw_action_info->l3_type != l3_type) {
|
|
+ if (l3_type && hw_dst_action_info->l3_type &&
|
|
+ hw_dst_action_info->l3_type != l3_type) {
|
|
mlx5dr_dbg(dmn, "Action list can't support two different L3 types\n");
|
|
return -EINVAL;
|
|
}
|
|
- if (hw_action_info->l3_type)
|
|
- l3_type = hw_action_info->l3_type;
|
|
+ if (hw_dst_action_info->l3_type)
|
|
+ l3_type = hw_dst_action_info->l3_type;
|
|
|
|
/* Due to a HW limitation we cannot modify two different L4 types */
|
|
- if (l4_type && hw_action_info->l4_type &&
|
|
- hw_action_info->l4_type != l4_type) {
|
|
+ if (l4_type && hw_dst_action_info->l4_type &&
|
|
+ hw_dst_action_info->l4_type != l4_type) {
|
|
mlx5dr_dbg(dmn, "Action list can't support two different L4 types\n");
|
|
return -EINVAL;
|
|
}
|
|
- if (hw_action_info->l4_type)
|
|
- l4_type = hw_action_info->l4_type;
|
|
+ if (hw_dst_action_info->l4_type)
|
|
+ l4_type = hw_dst_action_info->l4_type;
|
|
|
|
/* HW reads and executes two actions at once this means we
|
|
* need to create a gap if two actions access the same field
|
|
*/
|
|
- if ((hw_idx % 2) && hw_field == hw_action_info->hw_field) {
|
|
+ if ((hw_idx % 2) && (hw_field == hw_dst_action_info->hw_field ||
|
|
+ (hw_src_action_info &&
|
|
+ hw_field == hw_src_action_info->hw_field))) {
|
|
/* Check if after gap insertion the total number of HW
|
|
* modify actions doesn't exceeds the limit
|
|
*/
|
|
@@ -1605,7 +1725,7 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
- hw_field = hw_action_info->hw_field;
|
|
+ hw_field = hw_dst_action_info->hw_field;
|
|
|
|
hw_actions[hw_idx] = hw_action;
|
|
hw_idx++;
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h
|
|
index 1722f4668269..e01c3766c7de 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h
|
|
@@ -32,6 +32,7 @@ enum {
|
|
};
|
|
|
|
enum {
|
|
+ MLX5DR_ACTION_MDFY_HW_OP_COPY = 0x1,
|
|
MLX5DR_ACTION_MDFY_HW_OP_SET = 0x2,
|
|
MLX5DR_ACTION_MDFY_HW_OP_ADD = 0x3,
|
|
};
|
|
@@ -625,4 +626,19 @@ struct mlx5_ifc_dr_action_hw_set_bits {
|
|
u8 inline_data[0x20];
|
|
};
|
|
|
|
+struct mlx5_ifc_dr_action_hw_copy_bits {
|
|
+ u8 opcode[0x8];
|
|
+ u8 destination_field_code[0x8];
|
|
+ u8 reserved_at_10[0x2];
|
|
+ u8 destination_left_shifter[0x6];
|
|
+ u8 reserved_at_18[0x2];
|
|
+ u8 destination_length[0x6];
|
|
+
|
|
+ u8 reserved_at_20[0x8];
|
|
+ u8 source_field_code[0x8];
|
|
+ u8 reserved_at_30[0x2];
|
|
+ u8 source_left_shifter[0x6];
|
|
+ u8 reserved_at_38[0x8];
|
|
+};
|
|
+
|
|
#endif /* MLX5_IFC_DR_H */
|
|
--
|
|
2.13.6
|
|
|