net: qos offload add flow status with dropped count
This patch adds a drop frames counter to tc flower offloading. Reporting h/w dropped frames is necessary for some actions. Some actions like police action and the coming introduced stream gate action would produce dropped frames which is necessary for user. Status update shows how many filtered packets increasing and how many dropped in those packets. v2: Changes - Update commit comments suggest by Jiri Pirko. Signed-off-by: Po Liu <Po.Liu@nxp.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Reviewed-by: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7cc373db7e
commit
4b61d3e8d3
|
@ -771,7 +771,7 @@ int sja1105_vl_stats(struct sja1105_private *priv, int port,
|
|||
|
||||
pkts = timingerr + unreleased + lengtherr;
|
||||
|
||||
flow_stats_update(stats, 0, pkts - rule->vl.stats.pkts,
|
||||
flow_stats_update(stats, 0, pkts - rule->vl.stats.pkts, 0,
|
||||
jiffies - rule->vl.stats.lastused,
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
|
||||
|
|
|
@ -1638,7 +1638,7 @@ static int bnxt_tc_get_flow_stats(struct bnxt *bp,
|
|||
lastused = flow->lastused;
|
||||
spin_unlock(&flow->stats_lock);
|
||||
|
||||
flow_stats_update(&tc_flow_cmd->stats, stats.bytes, stats.packets,
|
||||
flow_stats_update(&tc_flow_cmd->stats, stats.bytes, stats.packets, 0,
|
||||
lastused, FLOW_ACTION_HW_STATS_DELAYED);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -902,7 +902,7 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
|
|||
if (ofld_stats->prev_packet_count != packets)
|
||||
ofld_stats->last_used = jiffies;
|
||||
flow_stats_update(&cls->stats, bytes - ofld_stats->byte_count,
|
||||
packets - ofld_stats->packet_count,
|
||||
packets - ofld_stats->packet_count, 0,
|
||||
ofld_stats->last_used,
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ int cxgb4_tc_matchall_stats(struct net_device *dev,
|
|||
flow_stats_update(&cls_matchall->stats,
|
||||
bytes - tc_port_matchall->ingress.bytes,
|
||||
packets - tc_port_matchall->ingress.packets,
|
||||
tc_port_matchall->ingress.last_used,
|
||||
0, tc_port_matchall->ingress.last_used,
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
|
||||
tc_port_matchall->ingress.packets = packets;
|
||||
|
|
|
@ -1291,12 +1291,15 @@ static int enetc_psfp_get_stats(struct enetc_ndev_priv *priv,
|
|||
|
||||
spin_lock(&epsfp.psfp_lock);
|
||||
stats.pkts = counters.matching_frames_count - filter->stats.pkts;
|
||||
stats.drops = counters.not_passing_frames_count -
|
||||
filter->stats.drops;
|
||||
stats.lastused = filter->stats.lastused;
|
||||
filter->stats.pkts += stats.pkts;
|
||||
filter->stats.drops += stats.drops;
|
||||
spin_unlock(&epsfp.psfp_lock);
|
||||
|
||||
flow_stats_update(&f->stats, 0x0, stats.pkts, stats.lastused,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops,
|
||||
stats.lastused, FLOW_ACTION_HW_STATS_DELAYED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -672,7 +672,7 @@ mlx5_tc_ct_block_flow_offload_stats(struct mlx5_ct_ft *ft,
|
|||
return -ENOENT;
|
||||
|
||||
mlx5_fc_query_cached(entry->counter, &bytes, &packets, &lastuse);
|
||||
flow_stats_update(&f->stats, bytes, packets, lastuse,
|
||||
flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -4828,7 +4828,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
|
|||
no_peer_counter:
|
||||
mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
|
||||
out:
|
||||
flow_stats_update(&f->stats, bytes, packets, lastuse,
|
||||
flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
trace_mlx5e_stats_flower(f);
|
||||
errout:
|
||||
|
@ -4946,7 +4946,7 @@ void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv,
|
|||
dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets;
|
||||
dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes;
|
||||
rpriv->prev_vf_vport_stats = cur_stats;
|
||||
flow_stats_update(&ma->stats, dbytes, dpkts, jiffies,
|
||||
flow_stats_update(&ma->stats, dbytes, dpkts, 0, jiffies,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
}
|
||||
|
||||
|
|
|
@ -633,7 +633,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
|
|||
if (err)
|
||||
goto err_rule_get_stats;
|
||||
|
||||
flow_stats_update(&f->stats, bytes, packets, lastuse, used_hw_stats);
|
||||
flow_stats_update(&f->stats, bytes, packets, 0, lastuse, used_hw_stats);
|
||||
|
||||
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
|
||||
return 0;
|
||||
|
|
|
@ -244,7 +244,7 @@ int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0,
|
||||
flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0, 0x0,
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1491,7 +1491,7 @@ nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
|
|||
nfp_flower_update_merge_stats(app, nfp_flow);
|
||||
|
||||
flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes,
|
||||
priv->stats[ctx_id].pkts, priv->stats[ctx_id].used,
|
||||
priv->stats[ctx_id].pkts, 0, priv->stats[ctx_id].used,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
|
||||
priv->stats[ctx_id].pkts = 0;
|
||||
|
|
|
@ -319,7 +319,7 @@ nfp_flower_stats_rate_limiter(struct nfp_app *app, struct net_device *netdev,
|
|||
prev_stats->bytes = curr_stats->bytes;
|
||||
spin_unlock_bh(&fl_priv->qos_stats_lock);
|
||||
|
||||
flow_stats_update(&flow->stats, diff_bytes, diff_pkts,
|
||||
flow_stats_update(&flow->stats, diff_bytes, diff_pkts, 0,
|
||||
repr_priv->qos_table.last_update,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
return 0;
|
||||
|
|
|
@ -106,7 +106,7 @@ struct tc_action_ops {
|
|||
struct netlink_callback *, int,
|
||||
const struct tc_action_ops *,
|
||||
struct netlink_ext_ack *);
|
||||
void (*stats_update)(struct tc_action *, u64, u32, u64, bool);
|
||||
void (*stats_update)(struct tc_action *, u64, u64, u64, u64, bool);
|
||||
size_t (*get_fill_size)(const struct tc_action *act);
|
||||
struct net_device *(*get_dev)(const struct tc_action *a,
|
||||
tc_action_priv_destructor *destructor);
|
||||
|
@ -232,8 +232,8 @@ static inline void tcf_action_inc_overlimit_qstats(struct tc_action *a)
|
|||
spin_unlock(&a->tcfa_lock);
|
||||
}
|
||||
|
||||
void tcf_action_update_stats(struct tc_action *a, u64 bytes, u32 packets,
|
||||
bool drop, bool hw);
|
||||
void tcf_action_update_stats(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, bool hw);
|
||||
int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
|
||||
|
||||
int tcf_action_check_ctrlact(int action, struct tcf_proto *tp,
|
||||
|
@ -244,13 +244,14 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
|
|||
#endif /* CONFIG_NET_CLS_ACT */
|
||||
|
||||
static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,
|
||||
u64 packets, u64 lastuse, bool hw)
|
||||
u64 packets, u64 drops,
|
||||
u64 lastuse, bool hw)
|
||||
{
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
if (!a->ops->stats_update)
|
||||
return;
|
||||
|
||||
a->ops->stats_update(a, bytes, packets, lastuse, hw);
|
||||
a->ops->stats_update(a, bytes, packets, drops, lastuse, hw);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -389,17 +389,20 @@ static inline bool flow_rule_match_key(const struct flow_rule *rule,
|
|||
struct flow_stats {
|
||||
u64 pkts;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 lastused;
|
||||
enum flow_action_hw_stats used_hw_stats;
|
||||
bool used_hw_stats_valid;
|
||||
};
|
||||
|
||||
static inline void flow_stats_update(struct flow_stats *flow_stats,
|
||||
u64 bytes, u64 pkts, u64 lastused,
|
||||
u64 bytes, u64 pkts,
|
||||
u64 drops, u64 lastused,
|
||||
enum flow_action_hw_stats used_hw_stats)
|
||||
{
|
||||
flow_stats->pkts += pkts;
|
||||
flow_stats->bytes += bytes;
|
||||
flow_stats->drops += drops;
|
||||
flow_stats->lastused = max_t(u64, flow_stats->lastused, lastused);
|
||||
|
||||
/* The driver should pass value with a maximum of one bit set.
|
||||
|
|
|
@ -262,7 +262,7 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts)
|
|||
|
||||
static inline void
|
||||
tcf_exts_stats_update(const struct tcf_exts *exts,
|
||||
u64 bytes, u64 packets, u64 lastuse,
|
||||
u64 bytes, u64 packets, u64 drops, u64 lastuse,
|
||||
u8 used_hw_stats, bool used_hw_stats_valid)
|
||||
{
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
|
@ -273,7 +273,8 @@ tcf_exts_stats_update(const struct tcf_exts *exts,
|
|||
for (i = 0; i < exts->nr_actions; i++) {
|
||||
struct tc_action *a = exts->actions[i];
|
||||
|
||||
tcf_action_stats_update(a, bytes, packets, lastuse, true);
|
||||
tcf_action_stats_update(a, bytes, packets, drops,
|
||||
lastuse, true);
|
||||
a->used_hw_stats = used_hw_stats;
|
||||
a->used_hw_stats_valid = used_hw_stats_valid;
|
||||
}
|
||||
|
|
|
@ -1059,14 +1059,13 @@ err:
|
|||
return err;
|
||||
}
|
||||
|
||||
void tcf_action_update_stats(struct tc_action *a, u64 bytes, u32 packets,
|
||||
bool drop, bool hw)
|
||||
void tcf_action_update_stats(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, bool hw)
|
||||
{
|
||||
if (a->cpu_bstats) {
|
||||
_bstats_cpu_update(this_cpu_ptr(a->cpu_bstats), bytes, packets);
|
||||
|
||||
if (drop)
|
||||
this_cpu_ptr(a->cpu_qstats)->drops += packets;
|
||||
this_cpu_ptr(a->cpu_qstats)->drops += drops;
|
||||
|
||||
if (hw)
|
||||
_bstats_cpu_update(this_cpu_ptr(a->cpu_bstats_hw),
|
||||
|
@ -1075,8 +1074,7 @@ void tcf_action_update_stats(struct tc_action *a, u64 bytes, u32 packets,
|
|||
}
|
||||
|
||||
_bstats_update(&a->tcfa_bstats, bytes, packets);
|
||||
if (drop)
|
||||
a->tcfa_qstats.drops += packets;
|
||||
a->tcfa_qstats.drops += drops;
|
||||
if (hw)
|
||||
_bstats_update(&a->tcfa_bstats_hw, bytes, packets);
|
||||
}
|
||||
|
|
|
@ -1450,12 +1450,12 @@ static int tcf_ct_search(struct net *net, struct tc_action **a, u32 index)
|
|||
return tcf_idr_search(tn, a, index);
|
||||
}
|
||||
|
||||
static void tcf_stats_update(struct tc_action *a, u64 bytes, u32 packets,
|
||||
u64 lastuse, bool hw)
|
||||
static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_ct *c = to_ct(a);
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
c->tcf_tm.lastuse = max_t(u64, c->tcf_tm.lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -171,14 +171,15 @@ static int tcf_gact_act(struct sk_buff *skb, const struct tc_action *a,
|
|||
return action;
|
||||
}
|
||||
|
||||
static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets,
|
||||
u64 lastuse, bool hw)
|
||||
static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_gact *gact = to_gact(a);
|
||||
int action = READ_ONCE(gact->tcf_action);
|
||||
struct tcf_t *tm = &gact->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, action == TC_ACT_SHOT, hw);
|
||||
tcf_action_update_stats(a, bytes, packets,
|
||||
action == TC_ACT_SHOT ? packets : drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -568,13 +568,13 @@ static int tcf_gate_walker(struct net *net, struct sk_buff *skb,
|
|||
return tcf_generic_walker(tn, skb, cb, type, ops, extack);
|
||||
}
|
||||
|
||||
static void tcf_gate_stats_update(struct tc_action *a, u64 bytes, u32 packets,
|
||||
u64 lastuse, bool hw)
|
||||
static void tcf_gate_stats_update(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_gate *gact = to_gate(a);
|
||||
struct tcf_t *tm = &gact->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -312,13 +312,13 @@ out:
|
|||
return retval;
|
||||
}
|
||||
|
||||
static void tcf_stats_update(struct tc_action *a, u64 bytes, u32 packets,
|
||||
u64 lastuse, bool hw)
|
||||
static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_mirred *m = to_mirred(a);
|
||||
struct tcf_t *tm = &m->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -409,13 +409,13 @@ done:
|
|||
return p->tcf_action;
|
||||
}
|
||||
|
||||
static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u32 packets,
|
||||
u64 lastuse, bool hw)
|
||||
static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_pedit *d = to_pedit(a);
|
||||
struct tcf_t *tm = &d->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -288,13 +288,13 @@ static void tcf_police_cleanup(struct tc_action *a)
|
|||
}
|
||||
|
||||
static void tcf_police_stats_update(struct tc_action *a,
|
||||
u64 bytes, u32 packets,
|
||||
u64 bytes, u64 packets, u64 drops,
|
||||
u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_police *police = to_police(a);
|
||||
struct tcf_t *tm = &police->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,12 +74,13 @@ err:
|
|||
}
|
||||
|
||||
static void tcf_skbedit_stats_update(struct tc_action *a, u64 bytes,
|
||||
u32 packets, u64 lastuse, bool hw)
|
||||
u64 packets, u64 drops,
|
||||
u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_skbedit *d = to_skbedit(a);
|
||||
struct tcf_t *tm = &d->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -302,13 +302,13 @@ static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
|
|||
return tcf_generic_walker(tn, skb, cb, type, ops, extack);
|
||||
}
|
||||
|
||||
static void tcf_vlan_stats_update(struct tc_action *a, u64 bytes, u32 packets,
|
||||
u64 lastuse, bool hw)
|
||||
static void tcf_vlan_stats_update(struct tc_action *a, u64 bytes, u64 packets,
|
||||
u64 drops, u64 lastuse, bool hw)
|
||||
{
|
||||
struct tcf_vlan *v = to_vlan(a);
|
||||
struct tcf_t *tm = &v->tcf_tm;
|
||||
|
||||
tcf_action_update_stats(a, bytes, packets, false, hw);
|
||||
tcf_action_update_stats(a, bytes, packets, drops, hw);
|
||||
tm->lastuse = max_t(u64, tm->lastuse, lastuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -491,6 +491,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f,
|
|||
|
||||
tcf_exts_stats_update(&f->exts, cls_flower.stats.bytes,
|
||||
cls_flower.stats.pkts,
|
||||
cls_flower.stats.drops,
|
||||
cls_flower.stats.lastused,
|
||||
cls_flower.stats.used_hw_stats,
|
||||
cls_flower.stats.used_hw_stats_valid);
|
||||
|
|
|
@ -338,7 +338,8 @@ static void mall_stats_hw_filter(struct tcf_proto *tp,
|
|||
tc_setup_cb_call(block, TC_SETUP_CLSMATCHALL, &cls_mall, false, true);
|
||||
|
||||
tcf_exts_stats_update(&head->exts, cls_mall.stats.bytes,
|
||||
cls_mall.stats.pkts, cls_mall.stats.lastused,
|
||||
cls_mall.stats.pkts, cls_mall.stats.drops,
|
||||
cls_mall.stats.lastused,
|
||||
cls_mall.stats.used_hw_stats,
|
||||
cls_mall.stats.used_hw_stats_valid);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue