Drivers that support per-action stats should implement TC_ACTION_STATS rather than TC_CLSFLOWER_STATS/TC_CLSMATCHALL_STATS.
Signed-off-by: Edward Cree <ec...@solarflare.com> --- include/net/act_api.h | 5 +++++ include/net/flow_offload.h | 1 + net/sched/act_api.c | 3 ++- net/sched/cls_api.c | 1 + net/sched/cls_flower.c | 6 ++++++ net/sched/cls_matchall.c | 5 +++++ 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 38d1769f279b..76054524a2de 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -187,6 +187,11 @@ int tcf_action_check_ctrlact(int action, struct tcf_proto *tp, struct netlink_ext_ack *newchain); struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action, struct tcf_chain *newchain); +void tcf_action_update_stats(struct tc_action *a); +#else /* CONFIG_NET_CLS_ACT */ +static inline void tcf_action_update_stats(struct tc_action *a) +{ +} #endif /* CONFIG_NET_CLS_ACT */ static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes, diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index d526696958f6..813a91ae9d9a 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -140,6 +140,7 @@ enum flow_action_mangle_base { struct flow_action_entry { enum flow_action_id id; + bool want_stats; unsigned long cookie; union { u32 chain_index; /* FLOW_ACTION_GOTO */ diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 239fc28456d9..82f9c1f1acd6 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -754,7 +754,7 @@ tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref) return a->ops->dump(skb, a, bind, ref); } -static void tcf_action_update_stats(struct tc_action *a) +void tcf_action_update_stats(struct tc_action *a) { struct tc_action_block_binding *bind; struct tc_action_offload offl = {}; @@ -767,6 +767,7 @@ static void tcf_action_update_stats(struct tc_action *a) tcf_action_stats_update(a, offl.stats.bytes, offl.stats.pkts, offl.stats.lastused, true); } +EXPORT_SYMBOL(tcf_action_update_stats); int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 5411cec17af5..bb9b0d7ec1c0 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3195,6 +3195,7 @@ int tc_setup_flow_action(struct flow_action *flow_action, struct flow_action_entry *entry; entry = &flow_action->entries[j]; + entry->want_stats = act->ops && act->ops->stats_update; entry->cookie = (unsigned long)act; if (is_tcf_gact_ok(act)) { entry->id = FLOW_ACTION_ACCEPT; diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 252d102702bb..fcd5615ca2bc 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -477,6 +477,8 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f, { struct tc_cls_flower_offload cls_flower = {}; struct tcf_block *block = tp->chain->block; + struct tc_action *act; + int i; if (!rtnl_held) rtnl_lock(); @@ -492,6 +494,10 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f, cls_flower.stats.pkts, cls_flower.stats.lastused); + tcf_exts_for_each_action(i, act, &f->exts) + if (act->ops && act->ops->stats_update) + tcf_action_update_stats(act); + if (!rtnl_held) rtnl_unlock(); } diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c index 5cb4832d1b3b..c51beed83b1e 100644 --- a/net/sched/cls_matchall.c +++ b/net/sched/cls_matchall.c @@ -338,6 +338,8 @@ static void mall_stats_hw_filter(struct tcf_proto *tp, { struct tc_cls_matchall_offload cls_mall = {}; struct tcf_block *block = tp->chain->block; + struct tc_action *act; + int i; tc_cls_common_offload_init(&cls_mall.common, tp, head->flags, NULL); cls_mall.command = TC_CLSMATCHALL_STATS; @@ -347,6 +349,9 @@ static void mall_stats_hw_filter(struct tcf_proto *tp, tcf_exts_stats_update(&head->exts, cls_mall.stats.bytes, cls_mall.stats.pkts, cls_mall.stats.lastused); + tcf_exts_for_each_action(i, act, &head->exts) + if (act->ops && act->ops->stats_update) + tcf_action_update_stats(act); } static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh,