Commit 7ee3f6d2 authored by Alex Vesker's avatar Alex Vesker Committed by Saeed Mahameed

net/mlx5: DR, Create multiple destination action from dr_create_fte

Until now it was possible to pass a packet to a single destination such
as vport or flow table. With the new support if multiple vports or multiple
tables are provided as destinations, fs_dr will create a multiple
destination table action, this action should replace other destination
actions provided to mlx5dr_create_rule.
Each vport destination can be provided with a reformat actions which
will be done before forwarding the packet to the vport.
Signed-off-by: default avatarAlex Vesker <valex@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent b8853c96
...@@ -206,6 +206,12 @@ static struct mlx5dr_action *create_action_push_vlan(struct mlx5dr_domain *domai ...@@ -206,6 +206,12 @@ static struct mlx5dr_action *create_action_push_vlan(struct mlx5dr_domain *domai
return mlx5dr_action_create_push_vlan(domain, htonl(vlan_hdr)); return mlx5dr_action_create_push_vlan(domain, htonl(vlan_hdr));
} }
static bool contain_vport_reformat_action(struct mlx5_flow_rule *dst)
{
return dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
dst->dest_attr.vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
}
#define MLX5_FLOW_CONTEXT_ACTION_MAX 20 #define MLX5_FLOW_CONTEXT_ACTION_MAX 20
static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
struct mlx5_flow_table *ft, struct mlx5_flow_table *ft,
...@@ -213,7 +219,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -213,7 +219,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
struct fs_fte *fte) struct fs_fte *fte)
{ {
struct mlx5dr_domain *domain = ns->fs_dr_domain.dr_domain; struct mlx5dr_domain *domain = ns->fs_dr_domain.dr_domain;
struct mlx5dr_action *term_action = NULL; struct mlx5dr_action_dest *term_actions;
struct mlx5dr_match_parameters params; struct mlx5dr_match_parameters params;
struct mlx5_core_dev *dev = ns->dev; struct mlx5_core_dev *dev = ns->dev;
struct mlx5dr_action **fs_dr_actions; struct mlx5dr_action **fs_dr_actions;
...@@ -223,6 +229,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -223,6 +229,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
struct mlx5dr_rule *rule; struct mlx5dr_rule *rule;
struct mlx5_flow_rule *dst; struct mlx5_flow_rule *dst;
int fs_dr_num_actions = 0; int fs_dr_num_actions = 0;
int num_term_actions = 0;
int num_actions = 0; int num_actions = 0;
size_t match_sz; size_t match_sz;
int err = 0; int err = 0;
...@@ -233,18 +240,38 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -233,18 +240,38 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX, sizeof(*actions), actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX, sizeof(*actions),
GFP_KERNEL); GFP_KERNEL);
if (!actions) if (!actions) {
return -ENOMEM; err = -ENOMEM;
goto out_err;
}
fs_dr_actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX, fs_dr_actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX,
sizeof(*fs_dr_actions), GFP_KERNEL); sizeof(*fs_dr_actions), GFP_KERNEL);
if (!fs_dr_actions) { if (!fs_dr_actions) {
kfree(actions); err = -ENOMEM;
return -ENOMEM; goto free_actions_alloc;
}
term_actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX,
sizeof(*term_actions), GFP_KERNEL);
if (!term_actions) {
err = -ENOMEM;
goto free_fs_dr_actions_alloc;
} }
match_sz = sizeof(fte->val); match_sz = sizeof(fte->val);
/* Drop reformat action bit if destination vport set with reformat */
if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
list_for_each_entry(dst, &fte->node.children, node.list) {
if (!contain_vport_reformat_action(dst))
continue;
fte->action.action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
break;
}
}
/* The order of the actions are must to be keep, only the following /* The order of the actions are must to be keep, only the following
* order is supported by SW steering: * order is supported by SW steering:
* TX: push vlan -> modify header -> encap * TX: push vlan -> modify header -> encap
...@@ -335,7 +362,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -335,7 +362,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
goto free_actions; goto free_actions;
} }
fs_dr_actions[fs_dr_num_actions++] = tmp_action; fs_dr_actions[fs_dr_num_actions++] = tmp_action;
term_action = tmp_action; term_actions[num_term_actions++].dest = tmp_action;
} }
if (fte->flow_context.flow_tag) { if (fte->flow_context.flow_tag) {
...@@ -354,7 +381,8 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -354,7 +381,8 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
enum mlx5_flow_destination_type type = dst->dest_attr.type; enum mlx5_flow_destination_type type = dst->dest_attr.type;
u32 id; u32 id;
if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX ||
num_term_actions >= MLX5_FLOW_CONTEXT_ACTION_MAX) {
err = -ENOSPC; err = -ENOSPC;
goto free_actions; goto free_actions;
} }
...@@ -379,7 +407,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -379,7 +407,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
goto free_actions; goto free_actions;
} }
fs_dr_actions[fs_dr_num_actions++] = tmp_action; fs_dr_actions[fs_dr_num_actions++] = tmp_action;
term_action = tmp_action; term_actions[num_term_actions++].dest = tmp_action;
break; break;
case MLX5_FLOW_DESTINATION_TYPE_VPORT: case MLX5_FLOW_DESTINATION_TYPE_VPORT:
tmp_action = create_vport_action(domain, dst); tmp_action = create_vport_action(domain, dst);
...@@ -388,7 +416,14 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -388,7 +416,14 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
goto free_actions; goto free_actions;
} }
fs_dr_actions[fs_dr_num_actions++] = tmp_action; fs_dr_actions[fs_dr_num_actions++] = tmp_action;
term_action = tmp_action; term_actions[num_term_actions].dest = tmp_action;
if (dst->dest_attr.vport.flags &
MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
term_actions[num_term_actions].reformat =
dst->dest_attr.vport.pkt_reformat->action.dr_action;
num_term_actions++;
break; break;
default: default:
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
...@@ -399,9 +434,22 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -399,9 +434,22 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
params.match_sz = match_sz; params.match_sz = match_sz;
params.match_buf = (u64 *)fte->val; params.match_buf = (u64 *)fte->val;
if (num_term_actions == 1) {
if (term_action) if (term_actions->reformat)
actions[num_actions++] = term_action; actions[num_actions++] = term_actions->reformat;
actions[num_actions++] = term_actions->dest;
} else if (num_term_actions > 1) {
tmp_action = mlx5dr_action_create_mult_dest_tbl(domain,
term_actions,
num_term_actions);
if (!tmp_action) {
err = -EOPNOTSUPP;
goto free_actions;
}
fs_dr_actions[fs_dr_num_actions++] = tmp_action;
actions[num_actions++] = tmp_action;
}
rule = mlx5dr_rule_create(group->fs_dr_matcher.dr_matcher, rule = mlx5dr_rule_create(group->fs_dr_matcher.dr_matcher,
&params, &params,
...@@ -412,7 +460,9 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -412,7 +460,9 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
goto free_actions; goto free_actions;
} }
kfree(term_actions);
kfree(actions); kfree(actions);
fte->fs_dr_rule.dr_rule = rule; fte->fs_dr_rule.dr_rule = rule;
fte->fs_dr_rule.num_actions = fs_dr_num_actions; fte->fs_dr_rule.num_actions = fs_dr_num_actions;
fte->fs_dr_rule.dr_actions = fs_dr_actions; fte->fs_dr_rule.dr_actions = fs_dr_actions;
...@@ -420,13 +470,18 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -420,13 +470,18 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
return 0; return 0;
free_actions: free_actions:
for (i = 0; i < fs_dr_num_actions; i++) /* Free in reverse order to handle action dependencies */
for (i = fs_dr_num_actions - 1; i >= 0; i--)
if (!IS_ERR_OR_NULL(fs_dr_actions[i])) if (!IS_ERR_OR_NULL(fs_dr_actions[i]))
mlx5dr_action_destroy(fs_dr_actions[i]); mlx5dr_action_destroy(fs_dr_actions[i]);
mlx5_core_err(dev, "Failed to create dr rule err(%d)\n", err); kfree(term_actions);
kfree(actions); free_fs_dr_actions_alloc:
kfree(fs_dr_actions); kfree(fs_dr_actions);
free_actions_alloc:
kfree(actions);
out_err:
mlx5_core_err(dev, "Failed to create dr rule err(%d)\n", err);
return err; return err;
} }
...@@ -533,7 +588,8 @@ static int mlx5_cmd_dr_delete_fte(struct mlx5_flow_root_namespace *ns, ...@@ -533,7 +588,8 @@ static int mlx5_cmd_dr_delete_fte(struct mlx5_flow_root_namespace *ns,
if (err) if (err)
return err; return err;
for (i = 0; i < rule->num_actions; i++) /* Free in reverse order to handle action dependencies */
for (i = rule->num_actions - 1; i >= 0; i--)
if (!IS_ERR_OR_NULL(rule->dr_actions[i])) if (!IS_ERR_OR_NULL(rule->dr_actions[i]))
mlx5dr_action_destroy(rule->dr_actions[i]); mlx5dr_action_destroy(rule->dr_actions[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment