Although matchall always matches packets, however, it still relies on a protocol match first. So it is still useful to have such a counter for matchall. Of course, unlike u32, every time we hit a matchall filter, it is always a success, so we don't have to distinguish them. Sample output: filter protocol 802.1Q pref 100 matchall chain 0 filter protocol 802.1Q pref 100 matchall chain 0 handle 0x1 not_in_hw (rule hit 10) action order 1: vlan pop continue index 1 ref 1 bind 1 installed 40 sec used 1 sec Action statistics: Sent 836 bytes 10 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0
Unified · Split
| @@ -527,11 +527,17 @@ enum { · 526 unmodified lines | ||
| 527 | 527 | |
| 528 | 528 | /* Match-all classifier */ |
| 529 | 529 | |
| 530 | +struct tc_matchall_pcnt { | |
| 531 | + __u64 rhit; | |
| 532 | +}; | |
| 533 | + | |
| 530 | 534 | enum { |
| 531 | 535 | TCA_MATCHALL_UNSPEC, |
| 532 | 536 | TCA_MATCHALL_CLASSID, |
| 533 | 537 | TCA_MATCHALL_ACT, |
| 534 | 538 | TCA_MATCHALL_FLAGS, |
| 539 | + TCA_MATCHALL_PCNT, | |
| 540 | + TCA_MATCHALL_PAD, | |
| 535 | 541 | __TCA_MATCHALL_MAX, |
| 536 | 542 | }; |
| 537 | 543 | |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/kernel.h> |
| 13 | 13 | #include <linux/init.h> |
| 14 | 14 | #include <linux/module.h> |
| 15 | +#include <linux/percpu.h> | |
| 15 | 16 | |
| 16 | 17 | #include <net/sch_generic.h> |
| 17 | 18 | #include <net/pkt_cls.h> |
| @@ -22,6 +23,7 @@ struct cls_mall_head { · 4 unmodified lines | ||
| 22 | 23 | u32 handle; |
| 23 | 24 | u32 flags; |
| 24 | 25 | unsigned int in_hw_count; |
| 26 | + struct tc_matchall_pcnt __percpu *pf; | |
| 25 | 27 | struct rcu_work rwork; |
| 26 | 28 | }; |
| 27 | 29 | |
| @@ -34,6 +36,7 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp, · 6 unmodified lines | ||
| 34 | 36 | return -1; |
| 35 | 37 | |
| 36 | 38 | *res = head->res; |
| 39 | + __this_cpu_inc(head->pf->rhit); | |
| 37 | 40 | return tcf_exts_exec(skb, &head->exts, res); |
| 38 | 41 | } |
| 39 | 42 | |
| @@ -46,6 +49,7 @@ static void __mall_destroy(struct cls_mall_head *head) · 6 unmodified lines | ||
| 46 | 49 | { |
| 47 | 50 | tcf_exts_destroy(&head->exts); |
| 48 | 51 | tcf_exts_put_net(&head->exts); |
| 52 | + free_percpu(head->pf); | |
| 49 | 53 | kfree(head); |
| 50 | 54 | } |
| 51 | 55 | |
| @@ -192,6 +196,11 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, · 140 unmodified lines | ||
| 192 | 196 | handle = 1; |
| 193 | 197 | new->handle = handle; |
| 194 | 198 | new->flags = flags; |
| 199 | + new->pf = alloc_percpu(struct tc_matchall_pcnt); | |
| 200 | + if (!new->pf) { | |
| 201 | + err = -ENOMEM; | |
| 202 | + goto err_alloc_percpu; | |
| 203 | + } | |
| 195 | 204 | |
| 196 | 205 | err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr, |
| 197 | 206 | extack); |
| @@ -214,6 +223,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, · 16 unmodified lines | ||
| 214 | 223 | |
| 215 | 224 | err_replace_hw_filter: |
| 216 | 225 | err_set_parms: |
| 226 | + free_percpu(new->pf); | |
| 227 | +err_alloc_percpu: | |
| 217 | 228 | tcf_exts_destroy(&new->exts); |
| 218 | 229 | err_exts_init: |
| 219 | 230 | kfree(new); |
| @@ -270,8 +281,10 @@ static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, · 50 unmodified lines | ||
| 270 | 281 | static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh, |
| 271 | 282 | struct sk_buff *skb, struct tcmsg *t) |
| 272 | 283 | { |
| 284 | + struct tc_matchall_pcnt gpf = {}; | |
| 273 | 285 | struct cls_mall_head *head = fh; |
| 274 | 286 | struct nlattr *nest; |
| 287 | + int cpu; | |
| 275 | 288 | |
| 276 | 289 | if (!head) |
| 277 | 290 | return skb->len; |
| @@ -289,6 +302,17 @@ static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh, · 11 unmodified lines | ||
| 289 | 302 | if (head->flags && nla_put_u32(skb, TCA_MATCHALL_FLAGS, head->flags)) |
| 290 | 303 | goto nla_put_failure; |
| 291 | 304 | |
| 305 | + for_each_possible_cpu(cpu) { | |
| 306 | + struct tc_matchall_pcnt *pf = per_cpu_ptr(head->pf, cpu); | |
| 307 | + | |
| 308 | + gpf.rhit += pf->rhit; | |
| 309 | + } | |
| 310 | + | |
| 311 | + if (nla_put_64bit(skb, TCA_MATCHALL_PCNT, | |
| 312 | + sizeof(struct tc_matchall_pcnt), | |
| 313 | + &gpf, TCA_MATCHALL_PAD)) | |
| 314 | + goto nla_put_failure; | |
| 315 | + | |
| 292 | 316 | if (tcf_exts_dump(skb, &head->exts)) |
| 293 | 317 | goto nla_put_failure; |
| 294 | 318 | |