Merge branch 'mlx5-Support-tc-police-jump-conform-exceed-attribute'
Saeed Mahameed says: ==================== Support tc police jump conform-exceed attribute The tc police action conform-exceed option defines how to handle packets which exceed or conform to the configured bandwidth limit. One of the possible conform-exceed values is jump, which skips over a specified number of actions. This series adds support for conform-exceed jump action. The series adds platform support for branching actions by providing true/false flow attributes to the branching action. This is necessary for supporting police jump, as each branch may execute a different action list. The first five patches are preparation patches: - Patches 1 and 2 add support for actions with no destinations (e.g. drop) - Patch 3 refactor the code for subsequent function reuse - Patch 4 defines an abstract way for identifying terminating actions - Patch 5 updates action list validations logic considering branching actions The following three patches introduce an interface for abstracting branching actions: - Patch 6 introduces an abstract api for defining branching actions - Patch 7 generically instantiates the branching flow attributes using the abstract API Patch 8 adds the platform support for jump actions, by executing the following sequence: a. Store the jumping flow attr b. Identify the jump target action while iterating the actions list. c. Instantiate a new flow attribute after the jump target action. This is the flow attribute that the branching action should jump to. d. Set the target post action id on: d.1. The jumping attribute, thus realizing the jump functionality. d.2. The attribute preceding the target jump attr, if not terminating. The next patches apply the platform's branching attributes to the police action: - Patch 9 is a refactor patch - Patch 10 initializes the post meter table with the red/green flow attributes, as were initialized by the platform - Patch 11 enables the offload of meter actions using jump conform-exceed value. ==================== Link: https://lore.kernel.org/all/20221203221337.29267-1-saeed@kernel.org/ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
ddda6326ee
|
@ -28,4 +28,5 @@ tc_act_parse_accept(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
struct mlx5e_tc_act mlx5e_tc_act_accept = {
|
||||
.can_offload = tc_act_can_offload_accept,
|
||||
.parse_action = tc_act_parse_accept,
|
||||
.is_terminating_action = true,
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = {
|
|||
[FLOW_ACTION_DROP] = &mlx5e_tc_act_drop,
|
||||
[FLOW_ACTION_TRAP] = &mlx5e_tc_act_trap,
|
||||
[FLOW_ACTION_GOTO] = &mlx5e_tc_act_goto,
|
||||
[FLOW_ACTION_REDIRECT] = &mlx5e_tc_act_mirred,
|
||||
[FLOW_ACTION_REDIRECT] = &mlx5e_tc_act_redirect,
|
||||
[FLOW_ACTION_MIRRED] = &mlx5e_tc_act_mirred,
|
||||
[FLOW_ACTION_REDIRECT_INGRESS] = &mlx5e_tc_act_redirect_ingress,
|
||||
[FLOW_ACTION_VLAN_PUSH] = &mlx5e_tc_act_vlan,
|
||||
|
|
|
@ -32,6 +32,11 @@ struct mlx5e_tc_act_parse_state {
|
|||
struct mlx5_tc_ct_priv *ct_priv;
|
||||
};
|
||||
|
||||
struct mlx5e_tc_act_branch_ctrl {
|
||||
enum flow_action_id act_id;
|
||||
u32 extval;
|
||||
};
|
||||
|
||||
struct mlx5e_tc_act {
|
||||
bool (*can_offload)(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
const struct flow_action_entry *act,
|
||||
|
@ -60,6 +65,12 @@ struct mlx5e_tc_act {
|
|||
|
||||
int (*stats_action)(struct mlx5e_priv *priv,
|
||||
struct flow_offload_action *fl_act);
|
||||
|
||||
bool (*get_branch_ctrl)(const struct flow_action_entry *act,
|
||||
struct mlx5e_tc_act_branch_ctrl *cond_true,
|
||||
struct mlx5e_tc_act_branch_ctrl *cond_false);
|
||||
|
||||
bool is_terminating_action;
|
||||
};
|
||||
|
||||
struct mlx5e_tc_flow_action {
|
||||
|
@ -81,6 +92,7 @@ extern struct mlx5e_tc_act mlx5e_tc_act_vlan_mangle;
|
|||
extern struct mlx5e_tc_act mlx5e_tc_act_mpls_push;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_mpls_pop;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_mirred;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_redirect;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_mirred_nic;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_ct;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_sample;
|
||||
|
|
|
@ -27,4 +27,5 @@ tc_act_parse_drop(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
struct mlx5e_tc_act mlx5e_tc_act_drop = {
|
||||
.can_offload = tc_act_can_offload_drop,
|
||||
.parse_action = tc_act_parse_drop,
|
||||
.is_terminating_action = true,
|
||||
};
|
||||
|
|
|
@ -121,4 +121,5 @@ struct mlx5e_tc_act mlx5e_tc_act_goto = {
|
|||
.can_offload = tc_act_can_offload_goto,
|
||||
.parse_action = tc_act_parse_goto,
|
||||
.post_parse = tc_act_post_parse_goto,
|
||||
.is_terminating_action = true,
|
||||
};
|
||||
|
|
|
@ -334,4 +334,11 @@ tc_act_parse_mirred(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
struct mlx5e_tc_act mlx5e_tc_act_mirred = {
|
||||
.can_offload = tc_act_can_offload_mirred,
|
||||
.parse_action = tc_act_parse_mirred,
|
||||
.is_terminating_action = false,
|
||||
};
|
||||
|
||||
struct mlx5e_tc_act mlx5e_tc_act_redirect = {
|
||||
.can_offload = tc_act_can_offload_mirred,
|
||||
.parse_action = tc_act_parse_mirred,
|
||||
.is_terminating_action = true,
|
||||
};
|
||||
|
|
|
@ -48,4 +48,5 @@ tc_act_parse_mirred_nic(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
struct mlx5e_tc_act mlx5e_tc_act_mirred_nic = {
|
||||
.can_offload = tc_act_can_offload_mirred_nic,
|
||||
.parse_action = tc_act_parse_mirred_nic,
|
||||
.is_terminating_action = true,
|
||||
};
|
||||
|
|
|
@ -4,20 +4,54 @@
|
|||
#include "act.h"
|
||||
#include "en/tc_priv.h"
|
||||
|
||||
static bool police_act_validate_control(enum flow_action_id act_id,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act_id != FLOW_ACTION_PIPE &&
|
||||
act_id != FLOW_ACTION_ACCEPT &&
|
||||
act_id != FLOW_ACTION_JUMP &&
|
||||
act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform-exceed action is not pipe, ok, jump or drop");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int police_act_validate(const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (!police_act_validate_control(act->police.exceed.act_id, extack) ||
|
||||
!police_act_validate_control(act->police.notexceed.act_id, extack))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when peakrate/avrate/overhead is configured");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_act_can_offload_police(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
const struct flow_action_entry *act,
|
||||
int act_index,
|
||||
struct mlx5_flow_attr *attr)
|
||||
{
|
||||
if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
|
||||
act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
|
||||
NL_SET_ERR_MSG_MOD(parse_state->extack,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return false;
|
||||
}
|
||||
if (mlx5e_policer_validate(parse_state->flow_action, act,
|
||||
parse_state->extack))
|
||||
int err;
|
||||
|
||||
err = police_act_validate(act, parse_state->extack);
|
||||
if (err)
|
||||
return false;
|
||||
|
||||
return !!mlx5e_get_flow_meters(parse_state->flow->priv->mdev);
|
||||
|
@ -79,7 +113,7 @@ tc_act_police_offload(struct mlx5e_priv *priv,
|
|||
struct mlx5e_flow_meter_handle *meter;
|
||||
int err = 0;
|
||||
|
||||
err = mlx5e_policer_validate(&fl_act->action, act, fl_act->extack);
|
||||
err = police_act_validate(act, fl_act->extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -147,6 +181,19 @@ tc_act_police_stats(struct mlx5e_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_act_police_get_branch_ctrl(const struct flow_action_entry *act,
|
||||
struct mlx5e_tc_act_branch_ctrl *cond_true,
|
||||
struct mlx5e_tc_act_branch_ctrl *cond_false)
|
||||
{
|
||||
cond_true->act_id = act->police.notexceed.act_id;
|
||||
cond_true->extval = act->police.notexceed.extval;
|
||||
|
||||
cond_false->act_id = act->police.exceed.act_id;
|
||||
cond_false->extval = act->police.exceed.extval;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct mlx5e_tc_act mlx5e_tc_act_police = {
|
||||
.can_offload = tc_act_can_offload_police,
|
||||
.parse_action = tc_act_parse_police,
|
||||
|
@ -154,4 +201,5 @@ struct mlx5e_tc_act mlx5e_tc_act_police = {
|
|||
.offload_action = tc_act_police_offload,
|
||||
.destroy_action = tc_act_police_destroy,
|
||||
.stats_action = tc_act_police_stats,
|
||||
.get_branch_ctrl = tc_act_police_get_branch_ctrl,
|
||||
};
|
||||
|
|
|
@ -257,16 +257,16 @@ __mlx5e_flow_meter_alloc(struct mlx5e_flow_meters *flow_meters)
|
|||
counter = mlx5_fc_create(mdev, true);
|
||||
if (IS_ERR(counter)) {
|
||||
err = PTR_ERR(counter);
|
||||
goto err_red_counter;
|
||||
goto err_drop_counter;
|
||||
}
|
||||
meter->red_counter = counter;
|
||||
meter->drop_counter = counter;
|
||||
|
||||
counter = mlx5_fc_create(mdev, true);
|
||||
if (IS_ERR(counter)) {
|
||||
err = PTR_ERR(counter);
|
||||
goto err_green_counter;
|
||||
goto err_act_counter;
|
||||
}
|
||||
meter->green_counter = counter;
|
||||
meter->act_counter = counter;
|
||||
|
||||
meters_obj = list_first_entry_or_null(&flow_meters->partial_list,
|
||||
struct mlx5e_flow_meter_aso_obj,
|
||||
|
@ -313,10 +313,10 @@ __mlx5e_flow_meter_alloc(struct mlx5e_flow_meters *flow_meters)
|
|||
err_mem:
|
||||
mlx5e_flow_meter_destroy_aso_obj(mdev, id);
|
||||
err_create:
|
||||
mlx5_fc_destroy(mdev, meter->green_counter);
|
||||
err_green_counter:
|
||||
mlx5_fc_destroy(mdev, meter->red_counter);
|
||||
err_red_counter:
|
||||
mlx5_fc_destroy(mdev, meter->act_counter);
|
||||
err_act_counter:
|
||||
mlx5_fc_destroy(mdev, meter->drop_counter);
|
||||
err_drop_counter:
|
||||
kfree(meter);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
@ -329,8 +329,8 @@ __mlx5e_flow_meter_free(struct mlx5e_flow_meter_handle *meter)
|
|||
struct mlx5e_flow_meter_aso_obj *meters_obj;
|
||||
int n, pos;
|
||||
|
||||
mlx5_fc_destroy(mdev, meter->green_counter);
|
||||
mlx5_fc_destroy(mdev, meter->red_counter);
|
||||
mlx5_fc_destroy(mdev, meter->act_counter);
|
||||
mlx5_fc_destroy(mdev, meter->drop_counter);
|
||||
|
||||
meters_obj = meter->meters_obj;
|
||||
pos = (meter->obj_id - meters_obj->base_id) * 2 + meter->idx;
|
||||
|
@ -575,8 +575,8 @@ mlx5e_tc_meter_get_stats(struct mlx5e_flow_meter_handle *meter,
|
|||
u64 bytes1, packets1, lastuse1;
|
||||
u64 bytes2, packets2, lastuse2;
|
||||
|
||||
mlx5_fc_query_cached(meter->green_counter, &bytes1, &packets1, &lastuse1);
|
||||
mlx5_fc_query_cached(meter->red_counter, &bytes2, &packets2, &lastuse2);
|
||||
mlx5_fc_query_cached(meter->act_counter, &bytes1, &packets1, &lastuse1);
|
||||
mlx5_fc_query_cached(meter->drop_counter, &bytes2, &packets2, &lastuse2);
|
||||
|
||||
*bytes = bytes1 + bytes2;
|
||||
*packets = packets1 + packets2;
|
||||
|
|
|
@ -32,8 +32,8 @@ struct mlx5e_flow_meter_handle {
|
|||
struct hlist_node hlist;
|
||||
struct mlx5e_flow_meter_params params;
|
||||
|
||||
struct mlx5_fc *green_counter;
|
||||
struct mlx5_fc *red_counter;
|
||||
struct mlx5_fc *act_counter;
|
||||
struct mlx5_fc *drop_counter;
|
||||
};
|
||||
|
||||
struct mlx5e_meter_attr {
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
struct mlx5e_post_meter_priv {
|
||||
struct mlx5_flow_table *ft;
|
||||
struct mlx5_flow_group *fg;
|
||||
struct mlx5_flow_handle *fwd_green_rule;
|
||||
struct mlx5_flow_handle *drop_red_rule;
|
||||
struct mlx5_flow_handle *green_rule;
|
||||
struct mlx5_flow_attr *green_attr;
|
||||
struct mlx5_flow_handle *red_rule;
|
||||
struct mlx5_flow_attr *red_attr;
|
||||
};
|
||||
|
||||
struct mlx5_flow_table *
|
||||
|
@ -81,15 +83,48 @@ mlx5e_post_meter_fg_create(struct mlx5e_priv *priv,
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct mlx5_flow_handle *
|
||||
mlx5e_post_meter_add_rule(struct mlx5e_priv *priv,
|
||||
struct mlx5e_post_meter_priv *post_meter,
|
||||
struct mlx5_flow_spec *spec,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct mlx5_fc *act_counter,
|
||||
struct mlx5_fc *drop_counter)
|
||||
{
|
||||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||
struct mlx5_flow_handle *ret;
|
||||
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_DROP)
|
||||
attr->counter = drop_counter;
|
||||
else
|
||||
attr->counter = act_counter;
|
||||
|
||||
attr->ft = post_meter->ft;
|
||||
attr->flags |= MLX5_ATTR_FLAG_NO_IN_PORT;
|
||||
attr->outer_match_level = MLX5_MATCH_NONE;
|
||||
attr->chain = 0;
|
||||
attr->prio = 0;
|
||||
|
||||
ret = mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
|
||||
|
||||
/* We did not create the counter, so we can't delete it.
|
||||
* Avoid freeing the counter when the attr is deleted in free_branching_attr
|
||||
*/
|
||||
attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5e_post_meter_rules_create(struct mlx5e_priv *priv,
|
||||
struct mlx5e_post_meter_priv *post_meter,
|
||||
struct mlx5e_post_act *post_act,
|
||||
struct mlx5_fc *green_counter,
|
||||
struct mlx5_fc *red_counter)
|
||||
struct mlx5_fc *act_counter,
|
||||
struct mlx5_fc *drop_counter,
|
||||
struct mlx5_flow_attr *green_attr,
|
||||
struct mlx5_flow_attr *red_attr)
|
||||
{
|
||||
struct mlx5_flow_destination dest[2] = {};
|
||||
struct mlx5_flow_act flow_act = {};
|
||||
struct mlx5_flow_handle *rule;
|
||||
struct mlx5_flow_spec *spec;
|
||||
int err;
|
||||
|
@ -100,52 +135,45 @@ mlx5e_post_meter_rules_create(struct mlx5e_priv *priv,
|
|||
|
||||
mlx5e_tc_match_to_reg_match(spec, PACKET_COLOR_TO_REG,
|
||||
MLX5_FLOW_METER_COLOR_RED, MLX5_PACKET_COLOR_MASK);
|
||||
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP |
|
||||
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
|
||||
dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
|
||||
dest[0].counter_id = mlx5_fc_id(red_counter);
|
||||
|
||||
rule = mlx5_add_flow_rules(post_meter->ft, spec, &flow_act, dest, 1);
|
||||
rule = mlx5e_post_meter_add_rule(priv, post_meter, spec, red_attr,
|
||||
act_counter, drop_counter);
|
||||
if (IS_ERR(rule)) {
|
||||
mlx5_core_warn(priv->mdev, "Failed to create post_meter flow drop rule\n");
|
||||
mlx5_core_warn(priv->mdev, "Failed to create post_meter exceed rule\n");
|
||||
err = PTR_ERR(rule);
|
||||
goto err_red;
|
||||
}
|
||||
post_meter->drop_red_rule = rule;
|
||||
post_meter->red_rule = rule;
|
||||
post_meter->red_attr = red_attr;
|
||||
|
||||
mlx5e_tc_match_to_reg_match(spec, PACKET_COLOR_TO_REG,
|
||||
MLX5_FLOW_METER_COLOR_GREEN, MLX5_PACKET_COLOR_MASK);
|
||||
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
||||
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
dest[0].ft = mlx5e_tc_post_act_get_ft(post_act);
|
||||
dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
|
||||
dest[1].counter_id = mlx5_fc_id(green_counter);
|
||||
|
||||
rule = mlx5_add_flow_rules(post_meter->ft, spec, &flow_act, dest, 2);
|
||||
rule = mlx5e_post_meter_add_rule(priv, post_meter, spec, green_attr,
|
||||
act_counter, drop_counter);
|
||||
if (IS_ERR(rule)) {
|
||||
mlx5_core_warn(priv->mdev, "Failed to create post_meter flow fwd rule\n");
|
||||
mlx5_core_warn(priv->mdev, "Failed to create post_meter notexceed rule\n");
|
||||
err = PTR_ERR(rule);
|
||||
goto err_green;
|
||||
}
|
||||
post_meter->fwd_green_rule = rule;
|
||||
post_meter->green_rule = rule;
|
||||
post_meter->green_attr = green_attr;
|
||||
|
||||
kvfree(spec);
|
||||
return 0;
|
||||
|
||||
err_green:
|
||||
mlx5_del_flow_rules(post_meter->drop_red_rule);
|
||||
mlx5_del_flow_rules(post_meter->red_rule);
|
||||
err_red:
|
||||
kvfree(spec);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5e_post_meter_rules_destroy(struct mlx5e_post_meter_priv *post_meter)
|
||||
mlx5e_post_meter_rules_destroy(struct mlx5_eswitch *esw,
|
||||
struct mlx5e_post_meter_priv *post_meter)
|
||||
{
|
||||
mlx5_del_flow_rules(post_meter->drop_red_rule);
|
||||
mlx5_del_flow_rules(post_meter->fwd_green_rule);
|
||||
mlx5_eswitch_del_offloaded_rule(esw, post_meter->red_rule, post_meter->red_attr);
|
||||
mlx5_eswitch_del_offloaded_rule(esw, post_meter->green_rule, post_meter->green_attr);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -164,8 +192,10 @@ struct mlx5e_post_meter_priv *
|
|||
mlx5e_post_meter_init(struct mlx5e_priv *priv,
|
||||
enum mlx5_flow_namespace_type ns_type,
|
||||
struct mlx5e_post_act *post_act,
|
||||
struct mlx5_fc *green_counter,
|
||||
struct mlx5_fc *red_counter)
|
||||
struct mlx5_fc *act_counter,
|
||||
struct mlx5_fc *drop_counter,
|
||||
struct mlx5_flow_attr *branch_true,
|
||||
struct mlx5_flow_attr *branch_false)
|
||||
{
|
||||
struct mlx5e_post_meter_priv *post_meter;
|
||||
int err;
|
||||
|
@ -182,8 +212,8 @@ mlx5e_post_meter_init(struct mlx5e_priv *priv,
|
|||
if (err)
|
||||
goto err_fg;
|
||||
|
||||
err = mlx5e_post_meter_rules_create(priv, post_meter, post_act, green_counter,
|
||||
red_counter);
|
||||
err = mlx5e_post_meter_rules_create(priv, post_meter, post_act, act_counter,
|
||||
drop_counter, branch_true, branch_false);
|
||||
if (err)
|
||||
goto err_rules;
|
||||
|
||||
|
@ -199,9 +229,9 @@ err_ft:
|
|||
}
|
||||
|
||||
void
|
||||
mlx5e_post_meter_cleanup(struct mlx5e_post_meter_priv *post_meter)
|
||||
mlx5e_post_meter_cleanup(struct mlx5_eswitch *esw, struct mlx5e_post_meter_priv *post_meter)
|
||||
{
|
||||
mlx5e_post_meter_rules_destroy(post_meter);
|
||||
mlx5e_post_meter_rules_destroy(esw, post_meter);
|
||||
mlx5e_post_meter_fg_destroy(post_meter);
|
||||
mlx5e_post_meter_table_destroy(post_meter);
|
||||
kfree(post_meter);
|
||||
|
|
|
@ -21,9 +21,11 @@ struct mlx5e_post_meter_priv *
|
|||
mlx5e_post_meter_init(struct mlx5e_priv *priv,
|
||||
enum mlx5_flow_namespace_type ns_type,
|
||||
struct mlx5e_post_act *post_act,
|
||||
struct mlx5_fc *green_counter,
|
||||
struct mlx5_fc *red_counter);
|
||||
struct mlx5_fc *act_counter,
|
||||
struct mlx5_fc *drop_counter,
|
||||
struct mlx5_flow_attr *branch_true,
|
||||
struct mlx5_flow_attr *branch_false);
|
||||
void
|
||||
mlx5e_post_meter_cleanup(struct mlx5e_post_meter_priv *post_meter);
|
||||
mlx5e_post_meter_cleanup(struct mlx5_eswitch *esw, struct mlx5e_post_meter_priv *post_meter);
|
||||
|
||||
#endif /* __MLX5_EN_POST_METER_H__ */
|
||||
|
|
|
@ -211,8 +211,4 @@ struct mlx5e_flow_meters *mlx5e_get_flow_meters(struct mlx5_core_dev *dev);
|
|||
void *mlx5e_get_match_headers_value(u32 flags, struct mlx5_flow_spec *spec);
|
||||
void *mlx5e_get_match_headers_criteria(u32 flags, struct mlx5_flow_spec *spec);
|
||||
|
||||
int mlx5e_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
#endif /* __MLX5_EN_TC_PRIV_H__ */
|
||||
|
|
|
@ -132,6 +132,15 @@ struct mlx5e_tc_attr_to_reg_mapping mlx5e_tc_attr_to_reg_mappings[] = {
|
|||
[PACKET_COLOR_TO_REG] = packet_color_to_reg,
|
||||
};
|
||||
|
||||
struct mlx5e_tc_jump_state {
|
||||
u32 jump_count;
|
||||
bool jump_target;
|
||||
struct mlx5_flow_attr *jumping_attr;
|
||||
|
||||
enum flow_action_id last_id;
|
||||
u32 last_index;
|
||||
};
|
||||
|
||||
struct mlx5e_tc_table *mlx5e_tc_table_alloc(void)
|
||||
{
|
||||
struct mlx5e_tc_table *tc;
|
||||
|
@ -160,6 +169,7 @@ static struct lock_class_key tc_ht_lock_key;
|
|||
|
||||
static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow);
|
||||
static void free_flow_post_acts(struct mlx5e_tc_flow *flow);
|
||||
static void mlx5_free_flow_attr(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr);
|
||||
|
||||
void
|
||||
mlx5e_tc_match_to_reg_match(struct mlx5_flow_spec *spec,
|
||||
|
@ -412,8 +422,9 @@ mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv,
|
|||
}
|
||||
|
||||
ns_type = mlx5e_tc_meter_get_namespace(meter->flow_meters);
|
||||
post_meter = mlx5e_post_meter_init(priv, ns_type, post_act, meter->green_counter,
|
||||
meter->red_counter);
|
||||
post_meter = mlx5e_post_meter_init(priv, ns_type, post_act,
|
||||
meter->act_counter, meter->drop_counter,
|
||||
attr->branch_true, attr->branch_false);
|
||||
if (IS_ERR(post_meter)) {
|
||||
mlx5_core_err(priv->mdev, "Failed to init post meter\n");
|
||||
goto err_meter_init;
|
||||
|
@ -432,9 +443,9 @@ err_meter_init:
|
|||
}
|
||||
|
||||
static void
|
||||
mlx5e_tc_del_flow_meter(struct mlx5_flow_attr *attr)
|
||||
mlx5e_tc_del_flow_meter(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr)
|
||||
{
|
||||
mlx5e_post_meter_cleanup(attr->meter_attr.post_meter);
|
||||
mlx5e_post_meter_cleanup(esw, attr->meter_attr.post_meter);
|
||||
mlx5e_tc_meter_put(attr->meter_attr.meter);
|
||||
}
|
||||
|
||||
|
@ -495,7 +506,7 @@ mlx5e_tc_rule_unoffload(struct mlx5e_priv *priv,
|
|||
mlx5_eswitch_del_offloaded_rule(esw, rule, attr);
|
||||
|
||||
if (attr->meter_attr.meter)
|
||||
mlx5e_tc_del_flow_meter(attr);
|
||||
mlx5e_tc_del_flow_meter(esw, attr);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -606,6 +617,12 @@ int mlx5e_get_flow_namespace(struct mlx5e_tc_flow *flow)
|
|||
MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL;
|
||||
}
|
||||
|
||||
static struct mlx5_core_dev *
|
||||
get_flow_counter_dev(struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
return mlx5e_is_eswitch_flow(flow) ? flow->attr->esw_attr->counter_dev : flow->priv->mdev;
|
||||
}
|
||||
|
||||
static struct mod_hdr_tbl *
|
||||
get_mod_hdr_table(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
|
@ -1718,6 +1735,90 @@ clean_encap_dests(struct mlx5e_priv *priv,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
verify_attr_actions(u32 actions, struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (!(actions &
|
||||
(MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Rule must have at least one forward/drop action");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!(~actions &
|
||||
(MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Rule cannot support forward+drop action");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
|
||||
actions & MLX5_FLOW_CONTEXT_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Drop with modify header action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
post_process_attr(struct mlx5e_tc_flow *flow,
|
||||
struct mlx5_flow_attr *attr,
|
||||
bool is_post_act_attr,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch;
|
||||
bool vf_tun;
|
||||
int err = 0;
|
||||
|
||||
err = verify_attr_actions(attr->action, extack);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = set_encap_dests(flow->priv, flow, attr, extack, &vf_tun);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
if (mlx5e_is_eswitch_flow(flow)) {
|
||||
err = mlx5_eswitch_add_vlan_action(esw, attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
if (vf_tun || is_post_act_attr) {
|
||||
err = mlx5e_tc_add_flow_mod_hdr(flow->priv, flow, attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
} else {
|
||||
err = mlx5e_attach_mod_hdr(flow->priv, flow, attr->parse_attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr->branch_true &&
|
||||
attr->branch_true->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
err = mlx5e_tc_add_flow_mod_hdr(flow->priv, flow, attr->branch_true);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (attr->branch_false &&
|
||||
attr->branch_false->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
err = mlx5e_tc_add_flow_mod_hdr(flow->priv, flow, attr->branch_false);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
|
||||
err = alloc_flow_attr_counter(get_flow_counter_dev(flow), attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
|
||||
struct mlx5e_tc_flow *flow,
|
||||
|
@ -1728,7 +1829,6 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
|
|||
struct mlx5_flow_attr *attr = flow->attr;
|
||||
struct mlx5_esw_flow_attr *esw_attr;
|
||||
u32 max_prio, max_chain;
|
||||
bool vf_tun;
|
||||
int err = 0;
|
||||
|
||||
parse_attr = attr->parse_attr;
|
||||
|
@ -1818,32 +1918,10 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
|
|||
esw_attr->int_port = int_port;
|
||||
}
|
||||
|
||||
err = set_encap_dests(priv, flow, attr, extack, &vf_tun);
|
||||
err = post_process_attr(flow, attr, false, extack);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = mlx5_eswitch_add_vlan_action(esw, attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
if (vf_tun) {
|
||||
err = mlx5e_tc_add_flow_mod_hdr(priv, flow, attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
} else {
|
||||
err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
|
||||
err = alloc_flow_attr_counter(esw_attr->counter_dev, attr);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* we get here if one of the following takes place:
|
||||
* (1) there's no error
|
||||
* (2) there's an encap action and we don't have valid neigh
|
||||
|
@ -1879,6 +1957,16 @@ static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow)
|
|||
return !!geneve_tlv_opt_0_data;
|
||||
}
|
||||
|
||||
static void free_branch_attr(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr)
|
||||
{
|
||||
if (!attr)
|
||||
return;
|
||||
|
||||
mlx5_free_flow_attr(flow, attr);
|
||||
kvfree(attr->parse_attr);
|
||||
kfree(attr);
|
||||
}
|
||||
|
||||
static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
|
||||
struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
|
@ -1934,6 +2022,8 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
|
|||
mlx5e_detach_decap(priv, flow);
|
||||
|
||||
free_flow_post_acts(flow);
|
||||
free_branch_attr(flow, attr->branch_true);
|
||||
free_branch_attr(flow, attr->branch_false);
|
||||
|
||||
if (flow->attr->lag.count)
|
||||
mlx5_lag_del_mpesw_rule(esw->dev);
|
||||
|
@ -3507,36 +3597,6 @@ actions_match_supported(struct mlx5e_priv *priv,
|
|||
ct_clear = flow->attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR;
|
||||
ct_flow = flow_flag_test(flow, CT) && !ct_clear;
|
||||
|
||||
if (!(actions &
|
||||
(MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Rule must have at least one forward/drop action");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(~actions &
|
||||
(MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Rule cannot support forward+drop action");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
|
||||
actions & MLX5_FLOW_CONTEXT_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Drop with modify header action is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(~actions &
|
||||
(MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Rule cannot support forward+drop action");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
|
||||
actions & MLX5_FLOW_CONTEXT_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Drop with modify header action is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
|
||||
!modify_header_match_supported(priv, &parse_attr->spec, flow_action,
|
||||
actions, ct_flow, ct_clear, extack))
|
||||
|
@ -3636,15 +3696,12 @@ mlx5e_clone_flow_attr_for_post_act(struct mlx5_flow_attr *attr,
|
|||
attr2->esw_attr->split_count = 0;
|
||||
}
|
||||
|
||||
attr2->branch_true = NULL;
|
||||
attr2->branch_false = NULL;
|
||||
attr2->jumping_attr = NULL;
|
||||
return attr2;
|
||||
}
|
||||
|
||||
static struct mlx5_core_dev *
|
||||
get_flow_counter_dev(struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
return mlx5e_is_eswitch_flow(flow) ? flow->attr->esw_attr->counter_dev : flow->priv->mdev;
|
||||
}
|
||||
|
||||
struct mlx5_flow_attr *
|
||||
mlx5e_tc_get_encap_attr(struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
|
@ -3680,28 +3737,15 @@ mlx5e_tc_unoffload_flow_post_acts(struct mlx5e_tc_flow *flow)
|
|||
static void
|
||||
free_flow_post_acts(struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow);
|
||||
struct mlx5e_post_act *post_act = get_post_action(flow->priv);
|
||||
struct mlx5_flow_attr *attr, *tmp;
|
||||
bool vf_tun;
|
||||
|
||||
list_for_each_entry_safe(attr, tmp, &flow->attrs, list) {
|
||||
if (list_is_last(&attr->list, &flow->attrs))
|
||||
break;
|
||||
|
||||
if (attr->post_act_handle)
|
||||
mlx5e_tc_post_act_del(post_act, attr->post_act_handle);
|
||||
|
||||
clean_encap_dests(flow->priv, flow, attr, &vf_tun);
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
|
||||
mlx5_fc_destroy(counter_dev, attr->counter);
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
mlx5e_mod_hdr_dealloc(&attr->parse_attr->mod_hdr_acts);
|
||||
if (attr->modify_hdr)
|
||||
mlx5_modify_header_dealloc(flow->priv->mdev, attr->modify_hdr);
|
||||
}
|
||||
mlx5_free_flow_attr(flow, attr);
|
||||
free_branch_attr(flow, attr->branch_true);
|
||||
free_branch_attr(flow, attr->branch_false);
|
||||
|
||||
list_del(&attr->list);
|
||||
kvfree(attr->parse_attr);
|
||||
|
@ -3754,7 +3798,6 @@ alloc_flow_post_acts(struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack)
|
|||
struct mlx5e_post_act *post_act = get_post_action(flow->priv);
|
||||
struct mlx5_flow_attr *attr, *next_attr = NULL;
|
||||
struct mlx5e_post_act_handle *handle;
|
||||
bool vf_tun;
|
||||
int err;
|
||||
|
||||
/* This is going in reverse order as needed.
|
||||
|
@ -3764,7 +3807,9 @@ alloc_flow_post_acts(struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack)
|
|||
if (!next_attr) {
|
||||
/* Set counter action on last post act rule. */
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (next_attr && !(attr->flags & MLX5_ATTR_FLAG_TERMINATING)) {
|
||||
err = mlx5e_tc_act_set_next_post_act(flow, attr, next_attr);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
@ -3776,25 +3821,13 @@ alloc_flow_post_acts(struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack)
|
|||
if (list_is_last(&attr->list, &flow->attrs))
|
||||
break;
|
||||
|
||||
err = set_encap_dests(flow->priv, flow, attr, extack, &vf_tun);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
err = actions_prepare_mod_hdr_actions(flow->priv, flow, attr, extack);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
err = mlx5e_tc_add_flow_mod_hdr(flow->priv, flow, attr);
|
||||
if (err)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
|
||||
err = alloc_flow_attr_counter(get_flow_counter_dev(flow), attr);
|
||||
if (err)
|
||||
goto out_free;
|
||||
}
|
||||
err = post_process_attr(flow, attr, true, extack);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
handle = mlx5e_tc_post_act_add(post_act, attr);
|
||||
if (IS_ERR(handle)) {
|
||||
|
@ -3803,6 +3836,13 @@ alloc_flow_post_acts(struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack)
|
|||
}
|
||||
|
||||
attr->post_act_handle = handle;
|
||||
|
||||
if (attr->jumping_attr) {
|
||||
err = mlx5e_tc_act_set_next_post_act(flow, attr->jumping_attr, attr);
|
||||
if (err)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
next_attr = attr;
|
||||
}
|
||||
|
||||
|
@ -3821,6 +3861,138 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_branch_attr(struct mlx5e_tc_flow *flow,
|
||||
struct mlx5e_tc_act_branch_ctrl *cond,
|
||||
struct mlx5_flow_attr **cond_attr,
|
||||
u32 *jump_count,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_flow_attr *attr;
|
||||
int err = 0;
|
||||
|
||||
*cond_attr = mlx5e_clone_flow_attr_for_post_act(flow->attr,
|
||||
mlx5e_get_flow_namespace(flow));
|
||||
if (!(*cond_attr))
|
||||
return -ENOMEM;
|
||||
|
||||
attr = *cond_attr;
|
||||
|
||||
switch (cond->act_id) {
|
||||
case FLOW_ACTION_DROP:
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
|
||||
break;
|
||||
case FLOW_ACTION_ACCEPT:
|
||||
case FLOW_ACTION_PIPE:
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
attr->dest_ft = mlx5e_tc_post_act_get_ft(get_post_action(flow->priv));
|
||||
break;
|
||||
case FLOW_ACTION_JUMP:
|
||||
if (*jump_count) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Cannot offload flows with nested jumps");
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_err;
|
||||
}
|
||||
*jump_count = cond->extval;
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
attr->dest_ft = mlx5e_tc_post_act_get_ft(get_post_action(flow->priv));
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return err;
|
||||
out_err:
|
||||
kfree(*cond_attr);
|
||||
*cond_attr = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
dec_jump_count(struct flow_action_entry *act, struct mlx5e_tc_act *tc_act,
|
||||
struct mlx5_flow_attr *attr, struct mlx5e_priv *priv,
|
||||
struct mlx5e_tc_jump_state *jump_state)
|
||||
{
|
||||
if (!jump_state->jump_count)
|
||||
return;
|
||||
|
||||
/* Single tc action can instantiate multiple offload actions (e.g. pedit)
|
||||
* Jump only over a tc action
|
||||
*/
|
||||
if (act->id == jump_state->last_id && act->hw_index == jump_state->last_index)
|
||||
return;
|
||||
|
||||
jump_state->last_id = act->id;
|
||||
jump_state->last_index = act->hw_index;
|
||||
|
||||
/* nothing to do for intermediate actions */
|
||||
if (--jump_state->jump_count > 1)
|
||||
return;
|
||||
|
||||
if (jump_state->jump_count == 1) { /* last action in the jump action list */
|
||||
|
||||
/* create a new attribute after this action */
|
||||
jump_state->jump_target = true;
|
||||
|
||||
if (tc_act->is_terminating_action) { /* the branch ends here */
|
||||
attr->flags |= MLX5_ATTR_FLAG_TERMINATING;
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
} else { /* the branch continues executing the rest of the actions */
|
||||
struct mlx5e_post_act *post_act;
|
||||
|
||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
post_act = get_post_action(priv);
|
||||
attr->dest_ft = mlx5e_tc_post_act_get_ft(post_act);
|
||||
}
|
||||
} else if (jump_state->jump_count == 0) { /* first attr after the jump action list */
|
||||
/* This is the post action for the jumping attribute (either red or green)
|
||||
* Use the stored jumping_attr to set the post act id on the jumping attribute
|
||||
*/
|
||||
attr->jumping_attr = jump_state->jumping_attr;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
parse_branch_ctrl(struct flow_action_entry *act, struct mlx5e_tc_act *tc_act,
|
||||
struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr,
|
||||
struct mlx5e_tc_jump_state *jump_state,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5e_tc_act_branch_ctrl cond_true, cond_false;
|
||||
u32 jump_count = jump_state->jump_count;
|
||||
int err;
|
||||
|
||||
if (!tc_act->get_branch_ctrl)
|
||||
return 0;
|
||||
|
||||
tc_act->get_branch_ctrl(act, &cond_true, &cond_false);
|
||||
|
||||
err = alloc_branch_attr(flow, &cond_true,
|
||||
&attr->branch_true, &jump_count, extack);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
if (jump_count)
|
||||
jump_state->jumping_attr = attr->branch_true;
|
||||
|
||||
err = alloc_branch_attr(flow, &cond_false,
|
||||
&attr->branch_false, &jump_count, extack);
|
||||
if (err)
|
||||
goto err_branch_false;
|
||||
|
||||
if (jump_count && !jump_state->jumping_attr)
|
||||
jump_state->jumping_attr = attr->branch_false;
|
||||
|
||||
jump_state->jump_count = jump_count;
|
||||
return 0;
|
||||
|
||||
err_branch_false:
|
||||
free_branch_attr(flow, attr->branch_true);
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
struct flow_action *flow_action)
|
||||
|
@ -3828,6 +4000,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
struct netlink_ext_ack *extack = parse_state->extack;
|
||||
struct mlx5e_tc_flow_action flow_action_reorder;
|
||||
struct mlx5e_tc_flow *flow = parse_state->flow;
|
||||
struct mlx5e_tc_jump_state jump_state = {};
|
||||
struct mlx5_flow_attr *attr = flow->attr;
|
||||
enum mlx5_flow_namespace_type ns_type;
|
||||
struct mlx5e_priv *priv = flow->priv;
|
||||
|
@ -3847,6 +4020,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
list_add(&attr->list, &flow->attrs);
|
||||
|
||||
flow_action_for_each(i, _act, &flow_action_reorder) {
|
||||
jump_state.jump_target = false;
|
||||
act = *_act;
|
||||
tc_act = mlx5e_tc_act_get(act->id, ns_type);
|
||||
if (!tc_act) {
|
||||
|
@ -3864,12 +4038,19 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
dec_jump_count(act, tc_act, attr, priv, &jump_state);
|
||||
|
||||
err = parse_branch_ctrl(act, tc_act, flow, attr, &jump_state, extack);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
parse_state->actions |= attr->action;
|
||||
|
||||
/* Split attr for multi table act if not the last act. */
|
||||
if (tc_act->is_multi_table_act &&
|
||||
if (jump_state.jump_target ||
|
||||
(tc_act->is_multi_table_act &&
|
||||
tc_act->is_multi_table_act(priv, act, attr) &&
|
||||
i < flow_action_reorder.num_entries - 1) {
|
||||
i < flow_action_reorder.num_entries - 1)) {
|
||||
err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
@ -3951,6 +4132,10 @@ parse_tc_nic_actions(struct mlx5e_priv *priv,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = verify_attr_actions(attr->action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!actions_match_supported(priv, flow_action, parse_state->actions,
|
||||
parse_attr, flow, extack))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -4188,6 +4373,30 @@ mlx5_alloc_flow_attr(enum mlx5_flow_namespace_type type)
|
|||
return attr;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_free_flow_attr(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr)
|
||||
{
|
||||
struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow);
|
||||
bool vf_tun;
|
||||
|
||||
if (!attr)
|
||||
return;
|
||||
|
||||
if (attr->post_act_handle)
|
||||
mlx5e_tc_post_act_del(get_post_action(flow->priv), attr->post_act_handle);
|
||||
|
||||
clean_encap_dests(flow->priv, flow, attr, &vf_tun);
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
|
||||
mlx5_fc_destroy(counter_dev, attr->counter);
|
||||
|
||||
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
|
||||
mlx5e_mod_hdr_dealloc(&attr->parse_attr->mod_hdr_acts);
|
||||
if (attr->modify_hdr)
|
||||
mlx5_modify_header_dealloc(flow->priv->mdev, attr->modify_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
|
||||
struct flow_cls_offload *f, unsigned long flow_flags,
|
||||
|
@ -4730,10 +4939,17 @@ static int apply_police_params(struct mlx5e_priv *priv, u64 rate,
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
static int
|
||||
tc_matchall_police_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.notexceed.act_id != FLOW_ACTION_CONTINUE) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is not continue");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when exceed action is not drop");
|
||||
|
@ -4784,13 +5000,7 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
|
|||
flow_action_for_each(i, act, flow_action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_POLICE:
|
||||
if (act->police.notexceed.act_id != FLOW_ACTION_CONTINUE) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is not continue");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = mlx5e_policer_validate(flow_action, act, extack);
|
||||
err = tc_matchall_police_validate(flow_action, act, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -95,6 +95,9 @@ struct mlx5_flow_attr {
|
|||
*/
|
||||
bool count;
|
||||
} lag;
|
||||
struct mlx5_flow_attr *branch_true;
|
||||
struct mlx5_flow_attr *branch_false;
|
||||
struct mlx5_flow_attr *jumping_attr;
|
||||
/* keep this union last */
|
||||
union {
|
||||
DECLARE_FLEX_ARRAY(struct mlx5_esw_flow_attr, esw_attr);
|
||||
|
@ -110,6 +113,7 @@ enum {
|
|||
MLX5_ATTR_FLAG_SAMPLE = BIT(4),
|
||||
MLX5_ATTR_FLAG_ACCEPT = BIT(5),
|
||||
MLX5_ATTR_FLAG_CT = BIT(6),
|
||||
MLX5_ATTR_FLAG_TERMINATING = BIT(7),
|
||||
};
|
||||
|
||||
/* Returns true if any of the flags that require skipping further TC/NF processing are set. */
|
||||
|
|
|
@ -640,6 +640,11 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
|
|||
goto err_esw_get;
|
||||
}
|
||||
|
||||
if (!i) {
|
||||
kfree(dest);
|
||||
dest = NULL;
|
||||
}
|
||||
|
||||
if (mlx5_eswitch_termtbl_required(esw, attr, &flow_act, spec))
|
||||
rule = mlx5_eswitch_add_termtbl_rule(esw, fdb, spec, esw_attr,
|
||||
&flow_act, dest, i);
|
||||
|
|
|
@ -1962,6 +1962,9 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
|
|||
if (flow_act->fg && ft->autogroup.active)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (dest && dest_num <= 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
for (i = 0; i < dest_num; i++) {
|
||||
if (!dest_is_valid(&dest[i], flow_act, ft))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
Загрузка…
Ссылка в новой задаче