Skip to content

Commit 7d1a5ce

Browse files
roidayanSaeed Mahameed
authored andcommitted
net/mlx5e: TC, Support tc action api for police
Add support for tc action api for police. Offloading standalone police action without a tc rule and reporting stats. Signed-off-by: Roi Dayan <[email protected]> Reviewed-by: Jianbo Liu <[email protected]> Reviewed-by: Oz Shlomo <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent f8e9d41 commit 7d1a5ce

File tree

5 files changed

+239
-8
lines changed

5 files changed

+239
-8
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "en/tc/sample.h"
2222
#include "en_accel/ipsec_rxtx.h"
2323
#include "en/tc/int_port.h"
24+
#include "en/tc/act/act.h"
2425

2526
struct mlx5e_rep_indr_block_priv {
2627
struct net_device *netdev;
@@ -511,14 +512,128 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev, struct Qdisc *sch,
511512
return 0;
512513
}
513514

515+
static int
516+
mlx5e_rep_indr_replace_act(struct mlx5e_rep_priv *rpriv,
517+
struct flow_offload_action *fl_act)
518+
519+
{
520+
struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
521+
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
522+
enum mlx5_flow_namespace_type ns_type;
523+
struct flow_action_entry *action;
524+
struct mlx5e_tc_act *act;
525+
bool add = false;
526+
int i;
527+
528+
/* There is no use case currently for more than one action (e.g. pedit).
529+
* when there will be, need to handle cleaning multiple actions on err.
530+
*/
531+
if (!flow_offload_has_one_action(&fl_act->action))
532+
return -EOPNOTSUPP;
533+
534+
if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
535+
ns_type = MLX5_FLOW_NAMESPACE_FDB;
536+
else
537+
ns_type = MLX5_FLOW_NAMESPACE_KERNEL;
538+
539+
flow_action_for_each(i, action, &fl_act->action) {
540+
act = mlx5e_tc_act_get(action->id, ns_type);
541+
if (!act)
542+
continue;
543+
544+
if (!act->offload_action)
545+
continue;
546+
547+
if (!act->offload_action(priv, fl_act, action))
548+
add = true;
549+
}
550+
551+
return add ? 0 : -EOPNOTSUPP;
552+
}
553+
554+
static int
555+
mlx5e_rep_indr_destroy_act(struct mlx5e_rep_priv *rpriv,
556+
struct flow_offload_action *fl_act)
557+
{
558+
struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
559+
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
560+
enum mlx5_flow_namespace_type ns_type;
561+
struct mlx5e_tc_act *act;
562+
563+
if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
564+
ns_type = MLX5_FLOW_NAMESPACE_FDB;
565+
else
566+
ns_type = MLX5_FLOW_NAMESPACE_KERNEL;
567+
568+
act = mlx5e_tc_act_get(fl_act->id, ns_type);
569+
if (!act || !act->destroy_action)
570+
return -EOPNOTSUPP;
571+
572+
return act->destroy_action(priv, fl_act);
573+
}
574+
575+
static int
576+
mlx5e_rep_indr_stats_act(struct mlx5e_rep_priv *rpriv,
577+
struct flow_offload_action *fl_act)
578+
579+
{
580+
struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
581+
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
582+
enum mlx5_flow_namespace_type ns_type;
583+
struct mlx5e_tc_act *act;
584+
585+
if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
586+
ns_type = MLX5_FLOW_NAMESPACE_FDB;
587+
else
588+
ns_type = MLX5_FLOW_NAMESPACE_KERNEL;
589+
590+
act = mlx5e_tc_act_get(fl_act->id, ns_type);
591+
if (!act || !act->stats_action)
592+
return -EOPNOTSUPP;
593+
594+
return act->stats_action(priv, fl_act);
595+
}
596+
597+
static int
598+
mlx5e_rep_indr_setup_act(struct mlx5e_rep_priv *rpriv,
599+
struct flow_offload_action *fl_act)
600+
{
601+
switch (fl_act->command) {
602+
case FLOW_ACT_REPLACE:
603+
return mlx5e_rep_indr_replace_act(rpriv, fl_act);
604+
case FLOW_ACT_DESTROY:
605+
return mlx5e_rep_indr_destroy_act(rpriv, fl_act);
606+
case FLOW_ACT_STATS:
607+
return mlx5e_rep_indr_stats_act(rpriv, fl_act);
608+
default:
609+
return -EOPNOTSUPP;
610+
}
611+
}
612+
613+
static int
614+
mlx5e_rep_indr_no_dev_setup(struct mlx5e_rep_priv *rpriv,
615+
enum tc_setup_type type,
616+
void *data)
617+
{
618+
if (!data)
619+
return -EOPNOTSUPP;
620+
621+
switch (type) {
622+
case TC_SETUP_ACT:
623+
return mlx5e_rep_indr_setup_act(rpriv, data);
624+
default:
625+
return -EOPNOTSUPP;
626+
}
627+
}
628+
514629
static
515630
int mlx5e_rep_indr_setup_cb(struct net_device *netdev, struct Qdisc *sch, void *cb_priv,
516631
enum tc_setup_type type, void *type_data,
517632
void *data,
518633
void (*cleanup)(struct flow_block_cb *block_cb))
519634
{
520635
if (!netdev)
521-
return -EOPNOTSUPP;
636+
return mlx5e_rep_indr_no_dev_setup(cb_priv, type, data);
522637

523638
switch (type) {
524639
case TC_SETUP_BLOCK:

drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ struct mlx5e_tc_act {
5050
bool (*is_multi_table_act)(struct mlx5e_priv *priv,
5151
const struct flow_action_entry *act,
5252
struct mlx5_flow_attr *attr);
53+
54+
int (*offload_action)(struct mlx5e_priv *priv,
55+
struct flow_offload_action *fl_act,
56+
struct flow_action_entry *act);
57+
58+
int (*destroy_action)(struct mlx5e_priv *priv,
59+
struct flow_offload_action *fl_act);
60+
61+
int (*stats_action)(struct mlx5e_priv *priv,
62+
struct flow_offload_action *fl_act);
5363
};
5464

5565
struct mlx5e_tc_flow_action {

drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,9 @@ tc_act_can_offload_police(struct mlx5e_tc_act_parse_state *parse_state,
2424
}
2525

2626
static int
27-
tc_act_parse_police(struct mlx5e_tc_act_parse_state *parse_state,
28-
const struct flow_action_entry *act,
29-
struct mlx5e_priv *priv,
30-
struct mlx5_flow_attr *attr)
27+
fill_meter_params_from_act(const struct flow_action_entry *act,
28+
struct mlx5e_flow_meter_params *params)
3129
{
32-
struct mlx5e_flow_meter_params *params;
33-
34-
params = &attr->meter_attr.params;
3530
params->index = act->hw_index;
3631
if (act->police.rate_bytes_ps) {
3732
params->mode = MLX5_RATE_LIMIT_BPS;
@@ -46,6 +41,21 @@ tc_act_parse_police(struct mlx5e_tc_act_parse_state *parse_state,
4641
return -EOPNOTSUPP;
4742
}
4843

44+
return 0;
45+
}
46+
47+
static int
48+
tc_act_parse_police(struct mlx5e_tc_act_parse_state *parse_state,
49+
const struct flow_action_entry *act,
50+
struct mlx5e_priv *priv,
51+
struct mlx5_flow_attr *attr)
52+
{
53+
int err;
54+
55+
err = fill_meter_params_from_act(act, &attr->meter_attr.params);
56+
if (err)
57+
return err;
58+
4959
attr->action |= MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO;
5060
attr->exe_aso_type = MLX5_EXE_ASO_FLOW_METER;
5161

@@ -60,8 +70,84 @@ tc_act_is_multi_table_act_police(struct mlx5e_priv *priv,
6070
return true;
6171
}
6272

73+
static int
74+
tc_act_police_offload(struct mlx5e_priv *priv,
75+
struct flow_offload_action *fl_act,
76+
struct flow_action_entry *act)
77+
{
78+
struct mlx5e_flow_meter_params params = {};
79+
struct mlx5e_flow_meter_handle *meter;
80+
int err = 0;
81+
82+
err = fill_meter_params_from_act(act, &params);
83+
if (err)
84+
return err;
85+
86+
meter = mlx5e_tc_meter_get(priv->mdev, &params);
87+
if (IS_ERR(meter) && PTR_ERR(meter) == -ENOENT) {
88+
meter = mlx5e_tc_meter_replace(priv->mdev, &params);
89+
} else if (!IS_ERR(meter)) {
90+
err = mlx5e_tc_meter_update(meter, &params);
91+
mlx5e_tc_meter_put(meter);
92+
}
93+
94+
if (IS_ERR(meter)) {
95+
NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
96+
mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
97+
err = PTR_ERR(meter);
98+
}
99+
100+
return err;
101+
}
102+
103+
static int
104+
tc_act_police_destroy(struct mlx5e_priv *priv,
105+
struct flow_offload_action *fl_act)
106+
{
107+
struct mlx5e_flow_meter_params params = {};
108+
struct mlx5e_flow_meter_handle *meter;
109+
110+
params.index = fl_act->index;
111+
meter = mlx5e_tc_meter_get(priv->mdev, &params);
112+
if (IS_ERR(meter)) {
113+
NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
114+
mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
115+
return PTR_ERR(meter);
116+
}
117+
/* first put for the get and second for cleanup */
118+
mlx5e_tc_meter_put(meter);
119+
mlx5e_tc_meter_put(meter);
120+
return 0;
121+
}
122+
123+
static int
124+
tc_act_police_stats(struct mlx5e_priv *priv,
125+
struct flow_offload_action *fl_act)
126+
{
127+
struct mlx5e_flow_meter_params params = {};
128+
struct mlx5e_flow_meter_handle *meter;
129+
u64 bytes, packets, drops, lastuse;
130+
131+
params.index = fl_act->index;
132+
meter = mlx5e_tc_meter_get(priv->mdev, &params);
133+
if (IS_ERR(meter)) {
134+
NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
135+
mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
136+
return PTR_ERR(meter);
137+
}
138+
139+
mlx5e_tc_meter_get_stats(meter, &bytes, &packets, &drops, &lastuse);
140+
flow_stats_update(&fl_act->stats, bytes, packets, drops, lastuse,
141+
FLOW_ACTION_HW_STATS_DELAYED);
142+
mlx5e_tc_meter_put(meter);
143+
return 0;
144+
}
145+
63146
struct mlx5e_tc_act mlx5e_tc_act_police = {
64147
.can_offload = tc_act_can_offload_police,
65148
.parse_action = tc_act_parse_police,
66149
.is_multi_table_act = tc_act_is_multi_table_act_police,
150+
.offload_action = tc_act_police_offload,
151+
.destroy_action = tc_act_police_destroy,
152+
.stats_action = tc_act_police_stats,
67153
};

drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,19 @@ mlx5e_flow_meters_cleanup(struct mlx5e_flow_meters *flow_meters)
561561
mlx5_core_dealloc_pd(flow_meters->mdev, flow_meters->pdn);
562562
kfree(flow_meters);
563563
}
564+
565+
void
566+
mlx5e_tc_meter_get_stats(struct mlx5e_flow_meter_handle *meter,
567+
u64 *bytes, u64 *packets, u64 *drops, u64 *lastuse)
568+
{
569+
u64 bytes1, packets1, lastuse1;
570+
u64 bytes2, packets2, lastuse2;
571+
572+
mlx5_fc_query_cached(meter->green_counter, &bytes1, &packets1, &lastuse1);
573+
mlx5_fc_query_cached(meter->red_counter, &bytes2, &packets2, &lastuse2);
574+
575+
*bytes = bytes1 + bytes2;
576+
*packets = packets1 + packets2;
577+
*drops = packets2;
578+
*lastuse = max_t(u64, lastuse1, lastuse2);
579+
}

drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,8 @@ mlx5e_flow_meters_init(struct mlx5e_priv *priv,
6767
void
6868
mlx5e_flow_meters_cleanup(struct mlx5e_flow_meters *flow_meters);
6969

70+
void
71+
mlx5e_tc_meter_get_stats(struct mlx5e_flow_meter_handle *meter,
72+
u64 *bytes, u64 *packets, u64 *drops, u64 *lastuse);
73+
7074
#endif /* __MLX5_EN_FLOW_METER_H__ */

0 commit comments

Comments
 (0)