Skip to content

Commit 9d2e4e1

Browse files
committed
Merge branch 'net-allow-user-specify-TC-action-HW-stats-type'
Jiri Pirko says: ==================== net: allow user specify TC action HW stats type Currently, when user adds a TC action and the action gets offloaded, the user expects the HW stats to be counted and included in stats dump. However, since drivers may implement different types of counting, there is no way to specify which one the user is interested in. For example for mlx5, only delayed counters are available as the driver periodically polls for updated stats. In case of mlxsw, the counters are queried on dump time. However, the HW resources for this type of counters is quite limited (couple of thousands). This limits the amount of supported offloaded filters significantly. Without counter assigned, the HW is capable to carry millions of those. On top of that, mlxsw HW is able to support delayed counters as well in greater numbers. That is going to be added in a follow-up patch. This patchset allows user to specify one of the following types of HW stats for added action: immediate - queried during dump time delayed - polled from HW periodically or sent by HW in async manner disabled - no stats needed Note that if "hw_stats" option is not passed, user does not care about the type, just expects any type of stats. Examples: $ tc filter add dev enp0s16np28 ingress proto ip handle 1 pref 1 flower skip_sw dst_ip 192.168.1.1 action drop hw_stats disabled $ tc -s filter show dev enp0s16np28 ingress filter protocol ip pref 1 flower chain 0 filter protocol ip pref 1 flower chain 0 handle 0x1 eth_type ipv4 dst_ip 192.168.1.1 skip_sw in_hw in_hw_count 2 action order 1: gact action drop random type none pass val 0 index 1 ref 1 bind 1 installed 7 sec used 2 sec Action statistics: Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 hw_stats disabled $ tc filter add dev enp0s16np28 ingress proto ip handle 1 pref 1 flower skip_sw dst_ip 192.168.1.1 action drop hw_stats immediate $ tc -s filter show dev enp0s16np28 ingress filter protocol ip pref 1 flower chain 0 filter protocol ip pref 1 flower chain 0 handle 0x1 eth_type ipv4 dst_ip 192.168.1.1 skip_sw in_hw in_hw_count 2 action order 1: gact action drop random type none pass val 0 index 1 ref 1 bind 1 installed 11 sec used 4 sec Action statistics: Sent 102 bytes 1 pkt (dropped 1, overlimits 0 requeues 0) Sent software 0 bytes 0 pkt Sent hardware 102 bytes 1 pkt backlog 0b 0p requeues 0 hw_stats immediate ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents caf4838 + 44f8658 commit 9d2e4e1

File tree

19 files changed

+230
-26
lines changed

19 files changed

+230
-26
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions,
279279

280280
static int bnxt_tc_parse_actions(struct bnxt *bp,
281281
struct bnxt_tc_actions *actions,
282-
struct flow_action *flow_action)
282+
struct flow_action *flow_action,
283+
struct netlink_ext_ack *extack)
283284
{
284285
/* Used to store the L2 rewrite mask for dmac (6 bytes) followed by
285286
* smac (6 bytes) if rewrite of both is specified, otherwise either
@@ -299,6 +300,9 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
299300
return -EINVAL;
300301
}
301302

303+
if (!flow_action_basic_hw_stats_types_check(flow_action, extack))
304+
return -EOPNOTSUPP;
305+
302306
flow_action_for_each(i, act, flow_action) {
303307
switch (act->id) {
304308
case FLOW_ACTION_DROP:
@@ -491,7 +495,8 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
491495
flow->tun_mask.tp_src = match.mask->src;
492496
}
493497

494-
return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action);
498+
return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action,
499+
tc_flow_cmd->common.extack);
495500
}
496501

497502
static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,14 +544,18 @@ static bool valid_pedit_action(struct net_device *dev,
544544
}
545545

546546
int cxgb4_validate_flow_actions(struct net_device *dev,
547-
struct flow_action *actions)
547+
struct flow_action *actions,
548+
struct netlink_ext_ack *extack)
548549
{
549550
struct flow_action_entry *act;
550551
bool act_redir = false;
551552
bool act_pedit = false;
552553
bool act_vlan = false;
553554
int i;
554555

556+
if (!flow_action_basic_hw_stats_types_check(actions, extack))
557+
return -EOPNOTSUPP;
558+
555559
flow_action_for_each(i, act, actions) {
556560
switch (act->id) {
557561
case FLOW_ACTION_ACCEPT:
@@ -642,7 +646,7 @@ int cxgb4_tc_flower_replace(struct net_device *dev,
642646
struct filter_ctx ctx;
643647
int fidx, ret;
644648

645-
if (cxgb4_validate_flow_actions(dev, &rule->action))
649+
if (cxgb4_validate_flow_actions(dev, &rule->action, extack))
646650
return -EOPNOTSUPP;
647651

648652
if (cxgb4_validate_flow_match(dev, cls))

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ void cxgb4_process_flow_actions(struct net_device *in,
112112
struct flow_action *actions,
113113
struct ch_filter_specification *fs);
114114
int cxgb4_validate_flow_actions(struct net_device *dev,
115-
struct flow_action *actions);
115+
struct flow_action *actions,
116+
struct netlink_ext_ack *extack);
116117

117118
int cxgb4_tc_flower_replace(struct net_device *dev,
118119
struct flow_cls_offload *cls);

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,8 @@ int cxgb4_tc_matchall_replace(struct net_device *dev,
286286
}
287287

288288
ret = cxgb4_validate_flow_actions(dev,
289-
&cls_matchall->rule->action);
289+
&cls_matchall->rule->action,
290+
extack);
290291
if (ret)
291292
return ret;
292293

drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,9 @@ static int mvpp2_port_c2_tcam_rule_add(struct mvpp2_port *port,
10821082
u8 qh, ql, pmap;
10831083
int index, ctx;
10841084

1085+
if (!flow_action_basic_hw_stats_types_check(&rule->flow->action, NULL))
1086+
return -EOPNOTSUPP;
1087+
10851088
memset(&c2, 0, sizeof(c2));
10861089

10871090
index = mvpp2_cls_c2_port_flow_index(port, rule->loc);
@@ -1305,6 +1308,9 @@ static int mvpp2_cls_rfs_parse_rule(struct mvpp2_rfs_rule *rule)
13051308
struct flow_rule *flow = rule->flow;
13061309
struct flow_action_entry *act;
13071310

1311+
if (!flow_action_basic_hw_stats_types_check(&rule->flow->action, NULL))
1312+
return -EOPNOTSUPP;
1313+
13081314
act = &flow->action.entries[0];
13091315
if (act->id != FLOW_ACTION_QUEUE && act->id != FLOW_ACTION_DROP)
13101316
return -EOPNOTSUPP;

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,6 +2878,10 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
28782878
if (!flow_action_has_entries(flow_action))
28792879
return -EINVAL;
28802880

2881+
if (!flow_action_hw_stats_types_check(flow_action, extack,
2882+
FLOW_ACTION_HW_STATS_TYPE_DELAYED))
2883+
return -EOPNOTSUPP;
2884+
28812885
attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
28822886

28832887
flow_action_for_each(i, act, flow_action) {
@@ -3330,6 +3334,10 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
33303334
if (!flow_action_has_entries(flow_action))
33313335
return -EINVAL;
33323336

3337+
if (!flow_action_hw_stats_types_check(flow_action, extack,
3338+
FLOW_ACTION_HW_STATS_TYPE_DELAYED))
3339+
return -EOPNOTSUPP;
3340+
33333341
flow_action_for_each(i, act, flow_action) {
33343342
switch (act->id) {
33353343
case FLOW_ACTION_DROP:
@@ -4148,6 +4156,9 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
41484156
return -EOPNOTSUPP;
41494157
}
41504158

4159+
if (!flow_action_basic_hw_stats_types_check(flow_action, extack))
4160+
return -EOPNOTSUPP;
4161+
41514162
flow_action_for_each(i, act, flow_action) {
41524163
switch (act->id) {
41534164
case FLOW_ACTION_POLICE:

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,8 @@ struct mlxsw_sp_acl_rule_info {
641641
struct mlxsw_afa_block *act_block;
642642
u8 action_created:1,
643643
ingress_bind_blocker:1,
644-
egress_bind_blocker:1;
644+
egress_bind_blocker:1,
645+
counter_valid:1;
645646
unsigned int counter_index;
646647
};
647648

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,14 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
642642
struct mlxsw_sp_acl_rule_info *rulei,
643643
struct netlink_ext_ack *extack)
644644
{
645-
return mlxsw_afa_block_append_counter(rulei->act_block,
646-
&rulei->counter_index, extack);
645+
int err;
646+
647+
err = mlxsw_afa_block_append_counter(rulei->act_block,
648+
&rulei->counter_index, extack);
649+
if (err)
650+
return err;
651+
rulei->counter_valid = true;
652+
return 0;
647653
}
648654

649655
int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
@@ -857,16 +863,18 @@ int mlxsw_sp_acl_rule_get_stats(struct mlxsw_sp *mlxsw_sp,
857863

858864
{
859865
struct mlxsw_sp_acl_rule_info *rulei;
860-
u64 current_packets;
861-
u64 current_bytes;
866+
u64 current_packets = 0;
867+
u64 current_bytes = 0;
862868
int err;
863869

864870
rulei = mlxsw_sp_acl_rule_rulei(rule);
865-
err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
866-
&current_packets, &current_bytes);
867-
if (err)
868-
return err;
869-
871+
if (rulei->counter_valid) {
872+
err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
873+
&current_packets,
874+
&current_bytes);
875+
if (err)
876+
return err;
877+
}
870878
*packets = current_packets - rule->last_packets;
871879
*bytes = current_bytes - rule->last_bytes;
872880
*last_use = rule->last_used;

drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,20 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
2626

2727
if (!flow_action_has_entries(flow_action))
2828
return 0;
29+
if (!flow_action_mixed_hw_stats_types_check(flow_action, extack))
30+
return -EOPNOTSUPP;
2931

30-
/* Count action is inserted first */
31-
err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack);
32-
if (err)
33-
return err;
32+
act = flow_action_first_entry_get(flow_action);
33+
if (act->hw_stats_type == FLOW_ACTION_HW_STATS_TYPE_ANY ||
34+
act->hw_stats_type == FLOW_ACTION_HW_STATS_TYPE_IMMEDIATE) {
35+
/* Count action is inserted first */
36+
err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack);
37+
if (err)
38+
return err;
39+
} else if (act->hw_stats_type != FLOW_ACTION_HW_STATS_TYPE_DISABLED) {
40+
NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type");
41+
return -EOPNOTSUPP;
42+
}
3443

3544
flow_action_for_each(i, act, flow_action) {
3645
switch (act->id) {

drivers/net/ethernet/mscc/ocelot_flower.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
1414
const struct flow_action_entry *a;
1515
int i;
1616

17-
if (f->rule->action.num_entries != 1)
17+
if (!flow_offload_has_one_action(&f->rule->action))
18+
return -EOPNOTSUPP;
19+
20+
if (!flow_action_basic_hw_stats_types_check(&f->rule->action,
21+
f->common.extack))
1822
return -EOPNOTSUPP;
1923

2024
flow_action_for_each(i, a, &f->rule->action) {

drivers/net/ethernet/netronome/nfp/flower/action.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,10 @@ int nfp_flower_compile_action(struct nfp_app *app,
12071207
bool pkt_host = false;
12081208
u32 csum_updated = 0;
12091209

1210+
if (!flow_action_basic_hw_stats_types_check(&flow->rule->action,
1211+
extack))
1212+
return -EOPNOTSUPP;
1213+
12101214
memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ);
12111215
nfp_flow->meta.act_len = 0;
12121216
tun_type = NFP_FL_TUNNEL_NONE;

drivers/net/ethernet/qlogic/qede/qede_filter.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,7 +1746,8 @@ int qede_get_arfs_filter_count(struct qede_dev *edev)
17461746
}
17471747

17481748
static int qede_parse_actions(struct qede_dev *edev,
1749-
struct flow_action *flow_action)
1749+
struct flow_action *flow_action,
1750+
struct netlink_ext_ack *extack)
17501751
{
17511752
const struct flow_action_entry *act;
17521753
int i;
@@ -1756,6 +1757,9 @@ static int qede_parse_actions(struct qede_dev *edev,
17561757
return -EINVAL;
17571758
}
17581759

1760+
if (!flow_action_basic_hw_stats_types_check(flow_action, extack))
1761+
return -EOPNOTSUPP;
1762+
17591763
flow_action_for_each(i, act, flow_action) {
17601764
switch (act->id) {
17611765
case FLOW_ACTION_DROP:
@@ -1970,7 +1974,7 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
19701974
}
19711975

19721976
/* parse tc actions and get the vf_id */
1973-
if (qede_parse_actions(edev, &f->rule->action))
1977+
if (qede_parse_actions(edev, &f->rule->action, f->common.extack))
19741978
goto unlock;
19751979

19761980
if (qede_flow_find_fltr(edev, &t)) {
@@ -2038,7 +2042,7 @@ static int qede_flow_spec_validate(struct qede_dev *edev,
20382042
return -EINVAL;
20392043
}
20402044

2041-
if (qede_parse_actions(edev, flow_action))
2045+
if (qede_parse_actions(edev, flow_action, NULL))
20422046
return -EINVAL;
20432047

20442048
return 0;

drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,18 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
367367

368368
static int tc_parse_flow_actions(struct stmmac_priv *priv,
369369
struct flow_action *action,
370-
struct stmmac_flow_entry *entry)
370+
struct stmmac_flow_entry *entry,
371+
struct netlink_ext_ack *extack)
371372
{
372373
struct flow_action_entry *act;
373374
int i;
374375

375376
if (!flow_action_has_entries(action))
376377
return -EINVAL;
377378

379+
if (!flow_action_basic_hw_stats_types_check(action, extack))
380+
return -EOPNOTSUPP;
381+
378382
flow_action_for_each(i, act, action) {
379383
switch (act->id) {
380384
case FLOW_ACTION_DROP:
@@ -530,7 +534,8 @@ static int tc_add_flow(struct stmmac_priv *priv,
530534
return -ENOENT;
531535
}
532536

533-
ret = tc_parse_flow_actions(priv, &rule->action, entry);
537+
ret = tc_parse_flow_actions(priv, &rule->action, entry,
538+
cls->common.extack);
534539
if (ret)
535540
return ret;
536541

include/net/act_api.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct tc_action {
4141
struct tc_cookie __rcu *act_cookie;
4242
struct tcf_chain __rcu *goto_chain;
4343
u32 tcfa_flags;
44+
u8 hw_stats_type;
4445
};
4546
#define tcf_index common.tcfa_index
4647
#define tcf_refcnt common.tcfa_refcnt
@@ -52,6 +53,9 @@ struct tc_action {
5253
#define tcf_rate_est common.tcfa_rate_est
5354
#define tcf_lock common.tcfa_lock
5455

56+
#define TCA_ACT_HW_STATS_TYPE_ANY (TCA_ACT_HW_STATS_TYPE_IMMEDIATE | \
57+
TCA_ACT_HW_STATS_TYPE_DELAYED)
58+
5559
/* Update lastuse only if needed, to avoid dirtying a cache line.
5660
* We use a temp variable to avoid fetching jiffies twice.
5761
*/

0 commit comments

Comments
 (0)