Skip to content

Commit

Permalink
Merge branch 'net-allow-user-specify-TC-action-HW-stats-type'
Browse files Browse the repository at this point in the history
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 <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 9, 2020
2 parents caf4838 + 44f8658 commit 9d2e4e1
Show file tree
Hide file tree
Showing 19 changed files with 230 additions and 26 deletions.
9 changes: 7 additions & 2 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions,

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

if (!flow_action_basic_hw_stats_types_check(flow_action, extack))
return -EOPNOTSUPP;

flow_action_for_each(i, act, flow_action) {
switch (act->id) {
case FLOW_ACTION_DROP:
Expand Down Expand Up @@ -491,7 +495,8 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
flow->tun_mask.tp_src = match.mask->src;
}

return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action);
return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action,
tc_flow_cmd->common.extack);
}

static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,
Expand Down
8 changes: 6 additions & 2 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,14 +544,18 @@ static bool valid_pedit_action(struct net_device *dev,
}

int cxgb4_validate_flow_actions(struct net_device *dev,
struct flow_action *actions)
struct flow_action *actions,
struct netlink_ext_ack *extack)
{
struct flow_action_entry *act;
bool act_redir = false;
bool act_pedit = false;
bool act_vlan = false;
int i;

if (!flow_action_basic_hw_stats_types_check(actions, extack))
return -EOPNOTSUPP;

flow_action_for_each(i, act, actions) {
switch (act->id) {
case FLOW_ACTION_ACCEPT:
Expand Down Expand Up @@ -642,7 +646,7 @@ int cxgb4_tc_flower_replace(struct net_device *dev,
struct filter_ctx ctx;
int fidx, ret;

if (cxgb4_validate_flow_actions(dev, &rule->action))
if (cxgb4_validate_flow_actions(dev, &rule->action, extack))
return -EOPNOTSUPP;

if (cxgb4_validate_flow_match(dev, cls))
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ void cxgb4_process_flow_actions(struct net_device *in,
struct flow_action *actions,
struct ch_filter_specification *fs);
int cxgb4_validate_flow_actions(struct net_device *dev,
struct flow_action *actions);
struct flow_action *actions,
struct netlink_ext_ack *extack);

int cxgb4_tc_flower_replace(struct net_device *dev,
struct flow_cls_offload *cls);
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ int cxgb4_tc_matchall_replace(struct net_device *dev,
}

ret = cxgb4_validate_flow_actions(dev,
&cls_matchall->rule->action);
&cls_matchall->rule->action,
extack);
if (ret)
return ret;

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,9 @@ static int mvpp2_port_c2_tcam_rule_add(struct mvpp2_port *port,
u8 qh, ql, pmap;
int index, ctx;

if (!flow_action_basic_hw_stats_types_check(&rule->flow->action, NULL))
return -EOPNOTSUPP;

memset(&c2, 0, sizeof(c2));

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

if (!flow_action_basic_hw_stats_types_check(&rule->flow->action, NULL))
return -EOPNOTSUPP;

act = &flow->action.entries[0];
if (act->id != FLOW_ACTION_QUEUE && act->id != FLOW_ACTION_DROP)
return -EOPNOTSUPP;
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2878,6 +2878,10 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
if (!flow_action_has_entries(flow_action))
return -EINVAL;

if (!flow_action_hw_stats_types_check(flow_action, extack,
FLOW_ACTION_HW_STATS_TYPE_DELAYED))
return -EOPNOTSUPP;

attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;

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

if (!flow_action_hw_stats_types_check(flow_action, extack,
FLOW_ACTION_HW_STATS_TYPE_DELAYED))
return -EOPNOTSUPP;

flow_action_for_each(i, act, flow_action) {
switch (act->id) {
case FLOW_ACTION_DROP:
Expand Down Expand Up @@ -4148,6 +4156,9 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
return -EOPNOTSUPP;
}

if (!flow_action_basic_hw_stats_types_check(flow_action, extack))
return -EOPNOTSUPP;

flow_action_for_each(i, act, flow_action) {
switch (act->id) {
case FLOW_ACTION_POLICE:
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,8 @@ struct mlxsw_sp_acl_rule_info {
struct mlxsw_afa_block *act_block;
u8 action_created:1,
ingress_bind_blocker:1,
egress_bind_blocker:1;
egress_bind_blocker:1,
counter_valid:1;
unsigned int counter_index;
};

Expand Down
26 changes: 17 additions & 9 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,14 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
struct netlink_ext_ack *extack)
{
return mlxsw_afa_block_append_counter(rulei->act_block,
&rulei->counter_index, extack);
int err;

err = mlxsw_afa_block_append_counter(rulei->act_block,
&rulei->counter_index, extack);
if (err)
return err;
rulei->counter_valid = true;
return 0;
}

int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
Expand Down Expand Up @@ -857,16 +863,18 @@ int mlxsw_sp_acl_rule_get_stats(struct mlxsw_sp *mlxsw_sp,

{
struct mlxsw_sp_acl_rule_info *rulei;
u64 current_packets;
u64 current_bytes;
u64 current_packets = 0;
u64 current_bytes = 0;
int err;

rulei = mlxsw_sp_acl_rule_rulei(rule);
err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
&current_packets, &current_bytes);
if (err)
return err;

if (rulei->counter_valid) {
err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
&current_packets,
&current_bytes);
if (err)
return err;
}
*packets = current_packets - rule->last_packets;
*bytes = current_bytes - rule->last_bytes;
*last_use = rule->last_used;
Expand Down
17 changes: 13 additions & 4 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,20 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,

if (!flow_action_has_entries(flow_action))
return 0;
if (!flow_action_mixed_hw_stats_types_check(flow_action, extack))
return -EOPNOTSUPP;

/* Count action is inserted first */
err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack);
if (err)
return err;
act = flow_action_first_entry_get(flow_action);
if (act->hw_stats_type == FLOW_ACTION_HW_STATS_TYPE_ANY ||
act->hw_stats_type == FLOW_ACTION_HW_STATS_TYPE_IMMEDIATE) {
/* Count action is inserted first */
err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack);
if (err)
return err;
} else if (act->hw_stats_type != FLOW_ACTION_HW_STATS_TYPE_DISABLED) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type");
return -EOPNOTSUPP;
}

flow_action_for_each(i, act, flow_action) {
switch (act->id) {
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/ethernet/mscc/ocelot_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
const struct flow_action_entry *a;
int i;

if (f->rule->action.num_entries != 1)
if (!flow_offload_has_one_action(&f->rule->action))
return -EOPNOTSUPP;

if (!flow_action_basic_hw_stats_types_check(&f->rule->action,
f->common.extack))
return -EOPNOTSUPP;

flow_action_for_each(i, a, &f->rule->action) {
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,10 @@ int nfp_flower_compile_action(struct nfp_app *app,
bool pkt_host = false;
u32 csum_updated = 0;

if (!flow_action_basic_hw_stats_types_check(&flow->rule->action,
extack))
return -EOPNOTSUPP;

memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ);
nfp_flow->meta.act_len = 0;
tun_type = NFP_FL_TUNNEL_NONE;
Expand Down
10 changes: 7 additions & 3 deletions drivers/net/ethernet/qlogic/qede/qede_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1746,7 +1746,8 @@ int qede_get_arfs_filter_count(struct qede_dev *edev)
}

static int qede_parse_actions(struct qede_dev *edev,
struct flow_action *flow_action)
struct flow_action *flow_action,
struct netlink_ext_ack *extack)
{
const struct flow_action_entry *act;
int i;
Expand All @@ -1756,6 +1757,9 @@ static int qede_parse_actions(struct qede_dev *edev,
return -EINVAL;
}

if (!flow_action_basic_hw_stats_types_check(flow_action, extack))
return -EOPNOTSUPP;

flow_action_for_each(i, act, flow_action) {
switch (act->id) {
case FLOW_ACTION_DROP:
Expand Down Expand Up @@ -1970,7 +1974,7 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
}

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

if (qede_flow_find_fltr(edev, &t)) {
Expand Down Expand Up @@ -2038,7 +2042,7 @@ static int qede_flow_spec_validate(struct qede_dev *edev,
return -EINVAL;
}

if (qede_parse_actions(edev, flow_action))
if (qede_parse_actions(edev, flow_action, NULL))
return -EINVAL;

return 0;
Expand Down
9 changes: 7 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,14 +367,18 @@ static int tc_setup_cbs(struct stmmac_priv *priv,

static int tc_parse_flow_actions(struct stmmac_priv *priv,
struct flow_action *action,
struct stmmac_flow_entry *entry)
struct stmmac_flow_entry *entry,
struct netlink_ext_ack *extack)
{
struct flow_action_entry *act;
int i;

if (!flow_action_has_entries(action))
return -EINVAL;

if (!flow_action_basic_hw_stats_types_check(action, extack))
return -EOPNOTSUPP;

flow_action_for_each(i, act, action) {
switch (act->id) {
case FLOW_ACTION_DROP:
Expand Down Expand Up @@ -530,7 +534,8 @@ static int tc_add_flow(struct stmmac_priv *priv,
return -ENOENT;
}

ret = tc_parse_flow_actions(priv, &rule->action, entry);
ret = tc_parse_flow_actions(priv, &rule->action, entry,
cls->common.extack);
if (ret)
return ret;

Expand Down
4 changes: 4 additions & 0 deletions include/net/act_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct tc_action {
struct tc_cookie __rcu *act_cookie;
struct tcf_chain __rcu *goto_chain;
u32 tcfa_flags;
u8 hw_stats_type;
};
#define tcf_index common.tcfa_index
#define tcf_refcnt common.tcfa_refcnt
Expand All @@ -52,6 +53,9 @@ struct tc_action {
#define tcf_rate_est common.tcfa_rate_est
#define tcf_lock common.tcfa_lock

#define TCA_ACT_HW_STATS_TYPE_ANY (TCA_ACT_HW_STATS_TYPE_IMMEDIATE | \
TCA_ACT_HW_STATS_TYPE_DELAYED)

/* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice.
*/
Expand Down
Loading

0 comments on commit 9d2e4e1

Please sign in to comment.