mirror of https://gitee.com/openkylin/linux.git
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: Alex Vesker <valex@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
parent
b8853c969f
commit
7ee3f6d248
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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_actions->reformat)
|
||||||
|
actions[num_actions++] = term_actions->reformat;
|
||||||
|
|
||||||
if (term_action)
|
actions[num_actions++] = term_actions->dest;
|
||||||
actions[num_actions++] = term_action;
|
} 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,
|
||||||
¶ms,
|
¶ms,
|
||||||
|
@ -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,
|
||||||
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,
|
||||||
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]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue