Skip to content

Commit

Permalink
net/mlx5e: TC, Support offloading police action
Browse files Browse the repository at this point in the history
Add parsing support by implementing struct mlx5e_tc_act for police
action.

TC rule with police actions is broken down into several rules in
different tables. One rule with the original match in the original
flow table, which set fte_id, do metering, and jump to the post_meter
table. If there are more police actions, more rules are created for
each of them. Besides, a last rule is created in the end.

In post_meter table, there are two pre-defined rules, one is to drop
packet if its packet color is RED, the other is to jump back to
post_act table. As fte_id is updated before jumping, the rule for next
meter is matched to do another round of metering (if there are
multiple meters in the flow rule). Otherwise, last fte_id is matched
and do the original actions.

Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Reviewed-by: Ariel Levkovich <lariel@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
  • Loading branch information
Jianbo Liu authored and Saeed Mahameed committed Jul 2, 2022
1 parent 03a92a9 commit a8d52b0
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 5 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/a
en/tc/act/vlan.o en/tc/act/vlan_mangle.o en/tc/act/mpls.o \
en/tc/act/mirred.o en/tc/act/mirred_nic.o \
en/tc/act/ct.o en/tc/act/sample.o en/tc/act/ptype.o \
en/tc/act/redirect_ingress.o
en/tc/act/redirect_ingress.o en/tc/act/police.o

ifneq ($(CONFIG_MLX5_TC_CT),)
mlx5_core-y += en/tc_ct.o en/tc/ct_fs_dmfs.o
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = {
NULL, /* FLOW_ACTION_WAKE, */
NULL, /* FLOW_ACTION_QUEUE, */
&mlx5e_tc_act_sample,
NULL, /* FLOW_ACTION_POLICE, */
&mlx5e_tc_act_police,
&mlx5e_tc_act_ct,
NULL, /* FLOW_ACTION_CT_METADATA, */
&mlx5e_tc_act_mpls_push,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ extern struct mlx5e_tc_act mlx5e_tc_act_ct;
extern struct mlx5e_tc_act mlx5e_tc_act_sample;
extern struct mlx5e_tc_act mlx5e_tc_act_ptype;
extern struct mlx5e_tc_act mlx5e_tc_act_redirect_ingress;
extern struct mlx5e_tc_act mlx5e_tc_act_police;

struct mlx5e_tc_act *
mlx5e_tc_act_get(enum flow_action_id act_id,
Expand Down
61 changes: 61 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.

#include "act.h"
#include "en/tc_priv.h"

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 (mlx5e_policer_validate(parse_state->flow_action, act,
parse_state->extack))
return false;

return !!mlx5e_get_flow_meters(parse_state->flow->priv->mdev);
}

static int
tc_act_parse_police(struct mlx5e_tc_act_parse_state *parse_state,
const struct flow_action_entry *act,
struct mlx5e_priv *priv,
struct mlx5_flow_attr *attr)
{
struct mlx5e_flow_meter_params *params;

params = &attr->meter_attr.params;
params->index = act->hw_index;
if (act->police.rate_bytes_ps) {
params->mode = MLX5_RATE_LIMIT_BPS;
/* change rate to bits per second */
params->rate = act->police.rate_bytes_ps << 3;
params->burst = act->police.burst;
} else if (act->police.rate_pkt_ps) {
params->mode = MLX5_RATE_LIMIT_PPS;
params->rate = act->police.rate_pkt_ps;
params->burst = act->police.burst_pkt;
} else {
return -EOPNOTSUPP;
}

attr->action |= MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO;
attr->exe_aso_type = MLX5_EXE_ASO_FLOW_METER;

return 0;
}

static bool
tc_act_is_multi_table_act_police(struct mlx5e_priv *priv,
const struct flow_action_entry *act,
struct mlx5_flow_attr *attr)
{
return true;
}

struct mlx5e_tc_act mlx5e_tc_act_police = {
.can_offload = tc_act_can_offload_police,
.parse_action = tc_act_parse_police,
.is_multi_table_act = tc_act_is_multi_table_act_police,
};
6 changes: 6 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,12 @@ mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter)
mutex_unlock(&flow_meters->sync_lock);
}

struct mlx5_flow_table *
mlx5e_tc_meter_get_post_meter_ft(struct mlx5e_flow_meters *flow_meters)
{
return mlx5e_post_meter_get_ft(flow_meters->post_meter);
}

struct mlx5e_flow_meters *
mlx5e_flow_meters_init(struct mlx5e_priv *priv,
enum mlx5_flow_namespace_type ns_type,
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

struct mlx5e_flow_meter_aso_obj;
struct mlx5e_flow_meters;
struct mlx5_flow_attr;

enum mlx5e_flow_meter_mode {
MLX5_RATE_LIMIT_BPS,
Expand All @@ -31,6 +32,11 @@ struct mlx5e_flow_meter_handle {
struct mlx5e_flow_meter_params params;
};

struct mlx5e_meter_attr {
struct mlx5e_flow_meter_params params;
struct mlx5e_flow_meter_handle *meter;
};

int
mlx5e_tc_meter_modify(struct mlx5_core_dev *mdev,
struct mlx5e_flow_meter_handle *meter,
Expand All @@ -41,6 +47,9 @@ mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *p
void
mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter);

struct mlx5_flow_table *
mlx5e_tc_meter_get_post_meter_ft(struct mlx5e_flow_meters *flow_meters);

struct mlx5e_flow_meters *
mlx5e_flow_meters_init(struct mlx5e_priv *priv,
enum mlx5_flow_namespace_type ns_type,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,8 @@ 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__ */
42 changes: 39 additions & 3 deletions drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,39 @@ mlx5_tc_rule_delete(struct mlx5e_priv *priv,
mlx5e_del_offloaded_nic_rule(priv, rule, attr);
}

static bool
is_flow_meter_action(struct mlx5_flow_attr *attr)
{
return ((attr->action & MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO) &&
(attr->exe_aso_type == MLX5_EXE_ASO_FLOW_METER));
}

static int
mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv,
struct mlx5_flow_attr *attr)
{
struct mlx5e_flow_meter_handle *meter;

meter = mlx5e_tc_meter_get(priv->mdev, &attr->meter_attr.params);
if (IS_ERR(meter)) {
mlx5_core_err(priv->mdev, "Failed to get flow meter\n");
return PTR_ERR(meter);
}

attr->meter_attr.meter = meter;
attr->dest_ft = mlx5e_tc_meter_get_post_meter_ft(meter->flow_meters);
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;

return 0;
}

struct mlx5_flow_handle *
mlx5e_tc_rule_offload(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec,
struct mlx5_flow_attr *attr)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
int err;

if (attr->flags & MLX5_ATTR_FLAG_CT) {
struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts =
Expand All @@ -367,6 +394,12 @@ mlx5e_tc_rule_offload(struct mlx5e_priv *priv,
if (attr->flags & MLX5_ATTR_FLAG_SAMPLE)
return mlx5e_tc_sample_offload(get_sample_priv(priv), spec, attr);

if (is_flow_meter_action(attr)) {
err = mlx5e_tc_add_flow_meter(priv, attr);
if (err)
return ERR_PTR(err);
}

return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
}

Expand All @@ -393,6 +426,9 @@ mlx5e_tc_rule_unoffload(struct mlx5e_priv *priv,
}

mlx5_eswitch_del_offloaded_rule(esw, rule, attr);

if (attr->meter_attr.meter)
mlx5e_tc_meter_put(attr->meter_attr.meter);
}

int
Expand Down Expand Up @@ -4545,9 +4581,9 @@ static int apply_police_params(struct mlx5e_priv *priv, u64 rate,
return err;
}

static int mlx5e_policer_validate(const struct flow_action *action,
const struct flow_action_entry *act,
struct netlink_ext_ack *extack)
int mlx5e_policer_validate(const struct flow_action *action,
const struct flow_action_entry *act,
struct netlink_ext_ack *extack)
{
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
NL_SET_ERR_MSG_MOD(extack,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct mlx5_flow_attr {
struct mlx5_modify_hdr *modify_hdr;
struct mlx5_ct_attr ct_attr;
struct mlx5e_sample_attr sample_attr;
struct mlx5e_meter_attr meter_attr;
struct mlx5e_tc_flow_parse_attr *parse_attr;
u32 chain;
u16 prio;
Expand All @@ -84,6 +85,7 @@ struct mlx5_flow_attr {
u8 tun_ip_version;
int tunnel_id; /* mapped tunnel id */
u32 flags;
u32 exe_aso_type;
struct list_head list;
struct mlx5e_post_act_handle *post_act_handle;
struct {
Expand Down

0 comments on commit a8d52b0

Please sign in to comment.