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.
355 lines
11 KiB
355 lines
11 KiB
4 years ago
|
From ff78c16e4544e8a6e60b243d7ddd8d5c8d677fc4 Mon Sep 17 00:00:00 2001
|
||
|
From: Alaa Hleihel <ahleihel@redhat.com>
|
||
|
Date: Tue, 12 May 2020 10:54:07 -0400
|
||
|
Subject: [PATCH 147/312] [netdrv] net/mlx5: DR, Modify set action limitation
|
||
|
extension
|
||
|
|
||
|
Message-id: <20200512105530.4207-42-ahleihel@redhat.com>
|
||
|
Patchwork-id: 306912
|
||
|
Patchwork-instance: patchwork
|
||
|
O-Subject: [RHEL8.3 BZ 1789382 041/124] net/mlx5: DR, Modify set action limitation extension
|
||
|
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 a51dcc10a04ac476240befb875b0a21388a429cd
|
||
|
Author: Hamdan Igbaria <hamdani@mellanox.com>
|
||
|
Date: Tue Dec 24 18:07:41 2019 +0200
|
||
|
|
||
|
net/mlx5: DR, Modify set action limitation extension
|
||
|
|
||
|
Modify set actions are not supported on both tx
|
||
|
and rx, added a check for that.
|
||
|
Also refactored the code in a way that every modify
|
||
|
action has his own functions, this needed so in the
|
||
|
future we could add copy action more smoothly.
|
||
|
|
||
|
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 | 226 +++++++++++++++------
|
||
|
1 file changed, 165 insertions(+), 61 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 9359eed10889..ad32b88a83dc 100644
|
||
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
|
||
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
|
||
|
@@ -1314,58 +1314,85 @@ dr_action_modify_get_hw_info(u16 sw_field)
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
+dr_action_modify_sw_to_hw_add(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 *hw_action_info;
|
||
|
- u8 offset, length, max_length, action;
|
||
|
+ u8 max_length;
|
||
|
u16 sw_field;
|
||
|
- u8 hw_opcode;
|
||
|
u32 data;
|
||
|
|
||
|
/* Get SW modify action data */
|
||
|
- action = MLX5_GET(set_action_in, sw_action, action_type);
|
||
|
- length = MLX5_GET(set_action_in, sw_action, length);
|
||
|
- offset = MLX5_GET(set_action_in, sw_action, offset);
|
||
|
sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||
|
data = MLX5_GET(set_action_in, sw_action, data);
|
||
|
|
||
|
/* Convert SW data to HW modify action format */
|
||
|
hw_action_info = dr_action_modify_get_hw_info(sw_field);
|
||
|
if (!hw_action_info) {
|
||
|
- mlx5dr_dbg(dmn, "Modify action invalid field given\n");
|
||
|
+ mlx5dr_dbg(dmn, "Modify add action invalid field given\n");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
max_length = hw_action_info->end - hw_action_info->start + 1;
|
||
|
|
||
|
- switch (action) {
|
||
|
- case MLX5_ACTION_TYPE_SET:
|
||
|
- hw_opcode = MLX5DR_ACTION_MDFY_HW_OP_SET;
|
||
|
- /* PRM defines that length zero specific length of 32bits */
|
||
|
- if (!length)
|
||
|
- length = 32;
|
||
|
+ MLX5_SET(dr_action_hw_set, hw_action,
|
||
|
+ opcode, MLX5DR_ACTION_MDFY_HW_OP_ADD);
|
||
|
|
||
|
- if (length + offset > max_length) {
|
||
|
- mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n");
|
||
|
- return -EINVAL;
|
||
|
- }
|
||
|
- break;
|
||
|
+ MLX5_SET(dr_action_hw_set, hw_action, destination_field_code,
|
||
|
+ hw_action_info->hw_field);
|
||
|
|
||
|
- case MLX5_ACTION_TYPE_ADD:
|
||
|
- hw_opcode = MLX5DR_ACTION_MDFY_HW_OP_ADD;
|
||
|
- offset = 0;
|
||
|
- length = max_length;
|
||
|
- break;
|
||
|
+ MLX5_SET(dr_action_hw_set, hw_action, destination_left_shifter,
|
||
|
+ hw_action_info->start);
|
||
|
|
||
|
- default:
|
||
|
- mlx5dr_info(dmn, "Unsupported action_type for modify action\n");
|
||
|
- return -EOPNOTSUPP;
|
||
|
+ /* PRM defines that length zero specific length of 32bits */
|
||
|
+ MLX5_SET(dr_action_hw_set, hw_action, destination_length,
|
||
|
+ max_length == 32 ? 0 : max_length);
|
||
|
+
|
||
|
+ MLX5_SET(dr_action_hw_set, hw_action, inline_data, data);
|
||
|
+
|
||
|
+ *ret_hw_info = hw_action_info;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+dr_action_modify_sw_to_hw_set(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 *hw_action_info;
|
||
|
+ u8 offset, length, max_length;
|
||
|
+ u16 sw_field;
|
||
|
+ u32 data;
|
||
|
+
|
||
|
+ /* Get SW modify action data */
|
||
|
+ length = MLX5_GET(set_action_in, sw_action, length);
|
||
|
+ offset = MLX5_GET(set_action_in, sw_action, offset);
|
||
|
+ sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||
|
+ data = MLX5_GET(set_action_in, sw_action, data);
|
||
|
+
|
||
|
+ /* Convert SW data to HW modify action format */
|
||
|
+ hw_action_info = dr_action_modify_get_hw_info(sw_field);
|
||
|
+ if (!hw_action_info) {
|
||
|
+ mlx5dr_dbg(dmn, "Modify set action invalid field given\n");
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
|
||
|
- MLX5_SET(dr_action_hw_set, hw_action, opcode, hw_opcode);
|
||
|
+ /* PRM defines that length zero specific length of 32bits */
|
||
|
+ length = length ? length : 32;
|
||
|
+
|
||
|
+ max_length = hw_action_info->end - hw_action_info->start + 1;
|
||
|
+
|
||
|
+ if (length + offset > max_length) {
|
||
|
+ mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ MLX5_SET(dr_action_hw_set, hw_action,
|
||
|
+ opcode, MLX5DR_ACTION_MDFY_HW_OP_SET);
|
||
|
|
||
|
MLX5_SET(dr_action_hw_set, hw_action, destination_field_code,
|
||
|
hw_action_info->hw_field);
|
||
|
@@ -1384,48 +1411,120 @@ dr_action_modify_sw_to_hw(struct mlx5dr_domain *dmn,
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-dr_action_modify_check_field_limitation(struct mlx5dr_domain *dmn,
|
||
|
- const __be64 *sw_action)
|
||
|
+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)
|
||
|
{
|
||
|
- u16 sw_field;
|
||
|
u8 action;
|
||
|
+ int ret;
|
||
|
|
||
|
- sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||
|
+ *hw_action = 0;
|
||
|
+
|
||
|
+ /* Get SW modify action type */
|
||
|
action = MLX5_GET(set_action_in, sw_action, action_type);
|
||
|
|
||
|
- /* Check if SW field is supported in current domain (RX/TX) */
|
||
|
- if (action == MLX5_ACTION_TYPE_SET) {
|
||
|
- if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
|
||
|
- if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
|
||
|
- mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
|
||
|
- sw_field);
|
||
|
- return -EINVAL;
|
||
|
- }
|
||
|
- }
|
||
|
+ switch (action) {
|
||
|
+ case MLX5_ACTION_TYPE_SET:
|
||
|
+ ret = dr_action_modify_sw_to_hw_set(dmn, sw_action,
|
||
|
+ hw_action,
|
||
|
+ ret_hw_info);
|
||
|
+ break;
|
||
|
|
||
|
- if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
|
||
|
- if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
|
||
|
- mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
|
||
|
- sw_field);
|
||
|
- return -EINVAL;
|
||
|
- }
|
||
|
+ case MLX5_ACTION_TYPE_ADD:
|
||
|
+ ret = dr_action_modify_sw_to_hw_add(dmn, sw_action,
|
||
|
+ hw_action,
|
||
|
+ ret_hw_info);
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ mlx5dr_info(dmn, "Unsupported action_type for modify action\n");
|
||
|
+ ret = -EOPNOTSUPP;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action,
|
||
|
+ const __be64 *sw_action)
|
||
|
+{
|
||
|
+ u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||
|
+ struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||
|
+
|
||
|
+ if (sw_field == 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_field);
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
- } else if (action == MLX5_ACTION_TYPE_ADD) {
|
||
|
- if (sw_field != MLX5_ACTION_IN_FIELD_OUT_IP_TTL &&
|
||
|
- sw_field != MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT &&
|
||
|
- sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM &&
|
||
|
- sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM) {
|
||
|
- mlx5dr_dbg(dmn, "Unsupported field %d for add action\n", sw_field);
|
||
|
+ } else if (sw_field == 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_field);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
- } else {
|
||
|
- mlx5dr_info(dmn, "Unsupported action %d modify action\n", action);
|
||
|
- return -EOPNOTSUPP;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!action->rewrite.allow_rx && !action->rewrite.allow_tx) {
|
||
|
+ mlx5dr_dbg(dmn, "Modify SET actions not supported on both RX and TX\n");
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+dr_action_modify_check_add_field_limitation(struct mlx5dr_action *action,
|
||
|
+ const __be64 *sw_action)
|
||
|
+{
|
||
|
+ u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||
|
+ struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||
|
+
|
||
|
+ if (sw_field != MLX5_ACTION_IN_FIELD_OUT_IP_TTL &&
|
||
|
+ sw_field != MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT &&
|
||
|
+ sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM &&
|
||
|
+ sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM) {
|
||
|
+ mlx5dr_dbg(dmn, "Unsupported field %d for add action\n",
|
||
|
+ sw_field);
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+dr_action_modify_check_field_limitation(struct mlx5dr_action *action,
|
||
|
+ const __be64 *sw_action)
|
||
|
+{
|
||
|
+ struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||
|
+ u8 action_type;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ action_type = MLX5_GET(set_action_in, sw_action, action_type);
|
||
|
+
|
||
|
+ switch (action_type) {
|
||
|
+ case MLX5_ACTION_TYPE_SET:
|
||
|
+ ret = dr_action_modify_check_set_field_limitation(action,
|
||
|
+ sw_action);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case MLX5_ACTION_TYPE_ADD:
|
||
|
+ ret = dr_action_modify_check_add_field_limitation(action,
|
||
|
+ sw_action);
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ mlx5dr_info(dmn, "Unsupported action %d modify action\n",
|
||
|
+ action_type);
|
||
|
+ ret = -EOPNOTSUPP;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
static bool
|
||
|
dr_action_modify_check_is_ttl_modify(const u64 *sw_action)
|
||
|
{
|
||
|
@@ -1434,7 +1533,7 @@ dr_action_modify_check_is_ttl_modify(const u64 *sw_action)
|
||
|
return sw_field == MLX5_ACTION_IN_FIELD_OUT_IP_TTL;
|
||
|
}
|
||
|
|
||
|
-static int dr_actions_convert_modify_header(struct mlx5dr_domain *dmn,
|
||
|
+static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
|
||
|
u32 max_hw_actions,
|
||
|
u32 num_sw_actions,
|
||
|
__be64 sw_actions[],
|
||
|
@@ -1446,16 +1545,21 @@ static int dr_actions_convert_modify_header(struct mlx5dr_domain *dmn,
|
||
|
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;
|
||
|
+ struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||
|
int ret, i, hw_idx = 0;
|
||
|
__be64 *sw_action;
|
||
|
__be64 hw_action;
|
||
|
|
||
|
*modify_ttl = false;
|
||
|
|
||
|
+ action->rewrite.allow_rx = 1;
|
||
|
+ action->rewrite.allow_tx = 1;
|
||
|
+
|
||
|
for (i = 0; i < num_sw_actions; i++) {
|
||
|
sw_action = &sw_actions[i];
|
||
|
|
||
|
- ret = dr_action_modify_check_field_limitation(dmn, sw_action);
|
||
|
+ ret = dr_action_modify_check_field_limitation(action,
|
||
|
+ sw_action);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
@@ -1544,7 +1648,7 @@ static int dr_action_create_modify_action(struct mlx5dr_domain *dmn,
|
||
|
goto free_chunk;
|
||
|
}
|
||
|
|
||
|
- ret = dr_actions_convert_modify_header(dmn,
|
||
|
+ ret = dr_actions_convert_modify_header(action,
|
||
|
max_hw_actions,
|
||
|
num_sw_actions,
|
||
|
actions,
|
||
|
--
|
||
|
2.13.6
|
||
|
|