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 | /* Match-all classifier */ | 528 | /* Match-all classifier */ |
| 529 | 529 | ||
| 530 | struct tc_matchall_pcnt { | ||
| 531 | __u64 rhit; | ||
| 532 | }; | ||
| 533 | |||
| 530 | enum { | 534 | enum { |
| 531 | TCA_MATCHALL_UNSPEC, | 535 | TCA_MATCHALL_UNSPEC, |
| 532 | TCA_MATCHALL_CLASSID, | 536 | TCA_MATCHALL_CLASSID, |
| 533 | TCA_MATCHALL_ACT, | 537 | TCA_MATCHALL_ACT, |
| 534 | TCA_MATCHALL_FLAGS, | 538 | TCA_MATCHALL_FLAGS, |
| 539 | TCA_MATCHALL_PCNT, | ||
| 540 | TCA_MATCHALL_PAD, | ||
| 535 | __TCA_MATCHALL_MAX, | 541 | __TCA_MATCHALL_MAX, |
| 536 | }; | 542 | }; |
| 537 | 543 | ||
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/percpu.h> | ||
| 15 | 16 | ||
| 16 | #include <net/sch_generic.h> | 17 | #include <net/sch_generic.h> |
| 17 | #include <net/pkt_cls.h> | 18 | #include <net/pkt_cls.h> |
| @@ -22,6 +23,7 @@ struct cls_mall_head { · 4 unmodified lines | |||
| 22 | u32 handle; | 23 | u32 handle; |
| 23 | u32 flags; | 24 | u32 flags; |
| 24 | unsigned int in_hw_count; | 25 | unsigned int in_hw_count; |
| 26 | struct tc_matchall_pcnt __percpu *pf; | ||
| 25 | struct rcu_work rwork; | 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 | return -1; | 36 | return -1; |
| 35 | 37 | ||
| 36 | *res = head->res; | 38 | *res = head->res; |
| 39 | __this_cpu_inc(head->pf->rhit); | ||
| 37 | return tcf_exts_exec(skb, &head->exts, res); | 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 | tcf_exts_destroy(&head->exts); | 50 | tcf_exts_destroy(&head->exts); |
| 48 | tcf_exts_put_net(&head->exts); | 51 | tcf_exts_put_net(&head->exts); |
| 52 | free_percpu(head->pf); | ||
| 49 | kfree(head); | 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 | handle = 1; | 196 | handle = 1; |
| 193 | new->handle = handle; | 197 | new->handle = handle; |
| 194 | new->flags = flags; | 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 | err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr, | 205 | err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr, |
| 197 | extack); | 206 | extack); |
| @@ -214,6 +223,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, · 16 unmodified lines | |||
| 214 | 223 | ||
| 215 | err_replace_hw_filter: | 224 | err_replace_hw_filter: |
| 216 | err_set_parms: | 225 | err_set_parms: |
| 226 | free_percpu(new->pf); | ||
| 227 | err_alloc_percpu: | ||
| 217 | tcf_exts_destroy(&new->exts); | 228 | tcf_exts_destroy(&new->exts); |
| 218 | err_exts_init: | 229 | err_exts_init: |
| 219 | kfree(new); | 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 | static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh, | 281 | static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh, |
| 271 | struct sk_buff *skb, struct tcmsg *t) | 282 | struct sk_buff *skb, struct tcmsg *t) |
| 272 | { | 283 | { |
| 284 | struct tc_matchall_pcnt gpf = {}; | ||
| 273 | struct cls_mall_head *head = fh; | 285 | struct cls_mall_head *head = fh; |
| 274 | struct nlattr *nest; | 286 | struct nlattr *nest; |
| 287 | int cpu; | ||
| 275 | 288 | ||
| 276 | if (!head) | 289 | if (!head) |
| 277 | return skb->len; | 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 | if (head->flags && nla_put_u32(skb, TCA_MATCHALL_FLAGS, head->flags)) | 302 | if (head->flags && nla_put_u32(skb, TCA_MATCHALL_FLAGS, head->flags)) |
| 290 | goto nla_put_failure; | 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 | if (tcf_exts_dump(skb, &head->exts)) | 316 | if (tcf_exts_dump(skb, &head->exts)) |
| 293 | goto nla_put_failure; | 317 | goto nla_put_failure; |
| 294 | 318 | ||