Commit 08247066 authored by Ariel Levkovich's avatar Ariel Levkovich Committed by Saeed Mahameed

net/mlx5e: Split nic tc flow allocation and creation

For future support of CT offload with nic tc flows, where
the flow rule is not created immediately but rather following
a future event, the patch is splitting the nic rule creation
and deletion into 2 parts:
1. Creating/Deleting and setting the rule attributes.
2. Creating/Deleting the flow table and flow rule itself.

This way the attributes can be prepared and stored in the
flow handle when the tc flow is created but the rule can
actually be created at any point in the future, using these
pre allocated attributes.
Signed-off-by: default avatarAriel Levkovich <lariel@mellanox.com>
Reviewed-by: default avatarRoi Dayan <roid@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 6a064674
...@@ -891,39 +891,31 @@ static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv, ...@@ -891,39 +891,31 @@ static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv,
flow->hpe = NULL; flow->hpe = NULL;
} }
static int struct mlx5_flow_handle *
mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5_flow_spec *spec,
struct mlx5e_tc_flow *flow, struct mlx5_nic_flow_attr *attr)
struct netlink_ext_ack *extack)
{ {
struct mlx5_flow_context *flow_context = &parse_attr->spec.flow_context; struct mlx5_flow_context *flow_context = &spec->flow_context;
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
struct mlx5e_tc_table *tc = &priv->fs.tc; struct mlx5e_tc_table *tc = &priv->fs.tc;
struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_flow_destination dest[2] = {}; struct mlx5_flow_destination dest[2] = {};
struct mlx5_flow_act flow_act = { struct mlx5_flow_act flow_act = {
.action = attr->action, .action = attr->action,
.flags = FLOW_ACT_NO_APPEND, .flags = FLOW_ACT_NO_APPEND,
}; };
struct mlx5_fc *counter = NULL; struct mlx5_flow_handle *rule;
int err, dest_ix = 0; int dest_ix = 0;
flow_context->flags |= FLOW_CONTEXT_HAS_TAG; flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
flow_context->flow_tag = attr->flow_tag; flow_context->flow_tag = attr->flow_tag;
if (flow_flag_test(flow, HAIRPIN)) { if (attr->hairpin_ft) {
err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack);
if (err)
return err;
if (flow_flag_test(flow, HAIRPIN_RSS)) {
dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest[dest_ix].ft = attr->hairpin_ft; dest[dest_ix].ft = attr->hairpin_ft;
} else { dest_ix++;
} else if (attr->hairpin_tirn) {
dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_TIR; dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dest[dest_ix].tir_num = attr->hairpin_tirn; dest[dest_ix].tir_num = attr->hairpin_tirn;
}
dest_ix++; dest_ix++;
} else if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { } else if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
...@@ -931,24 +923,14 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, ...@@ -931,24 +923,14 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
dest_ix++; dest_ix++;
} }
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
counter = mlx5_fc_create(dev, true);
if (IS_ERR(counter))
return PTR_ERR(counter);
dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
dest[dest_ix].counter_id = mlx5_fc_id(counter); dest[dest_ix].counter_id = mlx5_fc_id(attr->counter);
dest_ix++; dest_ix++;
attr->counter = counter;
} }
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
flow_act.modify_hdr = attr->modify_hdr; flow_act.modify_hdr = attr->modify_hdr;
dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
if (err)
return err;
}
mutex_lock(&tc->t_lock); mutex_lock(&tc->t_lock);
if (IS_ERR_OR_NULL(tc->t)) { if (IS_ERR_OR_NULL(tc->t)) {
...@@ -958,35 +940,77 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, ...@@ -958,35 +940,77 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
if (IS_ERR(tc->t)) { if (IS_ERR(tc->t)) {
mutex_unlock(&tc->t_lock); mutex_unlock(&tc->t_lock);
NL_SET_ERR_MSG_MOD(extack,
"Failed to create tc offload table");
netdev_err(priv->netdev, netdev_err(priv->netdev,
"Failed to create tc offload table\n"); "Failed to create tc offload table\n");
return PTR_ERR(tc->t); return ERR_CAST(tc->t);
} }
} }
mutex_unlock(&tc->t_lock);
if (attr->match_level != MLX5_MATCH_NONE) if (attr->match_level != MLX5_MATCH_NONE)
parse_attr->spec.match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
flow->rule[0] = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec, rule = mlx5_add_flow_rules(tc->t, spec,
&flow_act, dest, dest_ix); &flow_act, dest, dest_ix);
mutex_unlock(&priv->fs.tc.t_lock); if (IS_ERR(rule))
return ERR_CAST(rule);
return rule;
}
static int
mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow,
struct netlink_ext_ack *extack)
{
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_fc *counter = NULL;
int err;
if (flow_flag_test(flow, HAIRPIN)) {
err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack);
if (err)
return err;
}
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
counter = mlx5_fc_create(dev, true);
if (IS_ERR(counter))
return PTR_ERR(counter);
attr->counter = counter;
}
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
if (err)
return err;
}
flow->rule[0] = mlx5e_add_offloaded_nic_rule(priv, &parse_attr->spec,
attr);
return PTR_ERR_OR_ZERO(flow->rule[0]); return PTR_ERR_OR_ZERO(flow->rule[0]);
} }
void mlx5e_del_offloaded_nic_rule(struct mlx5e_priv *priv,
struct mlx5_flow_handle *rule)
{
mlx5_del_flow_rules(rule);
}
static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow) struct mlx5e_tc_flow *flow)
{ {
struct mlx5_nic_flow_attr *attr = flow->nic_attr; struct mlx5_nic_flow_attr *attr = flow->nic_attr;
struct mlx5e_tc_table *tc = &priv->fs.tc; struct mlx5e_tc_table *tc = &priv->fs.tc;
struct mlx5_fc *counter = NULL;
counter = attr->counter;
if (!IS_ERR_OR_NULL(flow->rule[0])) if (!IS_ERR_OR_NULL(flow->rule[0]))
mlx5_del_flow_rules(flow->rule[0]); mlx5e_del_offloaded_nic_rule(priv, flow->rule[0]);
mlx5_fc_destroy(priv->mdev, counter); mlx5_fc_destroy(priv->mdev, attr->counter);
mutex_lock(&priv->fs.tc.t_lock); mutex_lock(&priv->fs.tc.t_lock);
if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) && if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) &&
......
...@@ -181,6 +181,13 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv); ...@@ -181,6 +181,13 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv);
int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data, int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
void *cb_priv); void *cb_priv);
struct mlx5_nic_flow_attr;
struct mlx5_flow_handle *
mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec,
struct mlx5_nic_flow_attr *attr);
void mlx5e_del_offloaded_nic_rule(struct mlx5e_priv *priv,
struct mlx5_flow_handle *rule);
#else /* CONFIG_MLX5_CLS_ACT */ #else /* CONFIG_MLX5_CLS_ACT */
static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; } static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; }
static inline void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) {} static inline void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) {}
......
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