net_sched: add hit counter for matchall
authorCong Wang <xiyou.wangcong@gmail.com>
Thu, 17 Jan 2019 20:44:25 +0000 (12:44 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Jan 2019 22:13:50 +0000 (14:13 -0800)
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

Reported-by: Martin Olsson <martin.olsson+netdev@sentorsecurity.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/pkt_cls.h
net/sched/cls_matchall.c

index 95d0db2a8350dffb1dd20816591f3b179913fb2e..32a3416b51c3f0e9737dcad6d57fc3a6a242c2b5 100644 (file)
@@ -527,11 +527,17 @@ enum {
 
 /* Match-all classifier */
 
+struct tc_matchall_pcnt {
+       __u64 rhit;
+};
+
 enum {
        TCA_MATCHALL_UNSPEC,
        TCA_MATCHALL_CLASSID,
        TCA_MATCHALL_ACT,
        TCA_MATCHALL_FLAGS,
+       TCA_MATCHALL_PCNT,
+       TCA_MATCHALL_PAD,
        __TCA_MATCHALL_MAX,
 };
 
index 0e408ee9dcec67994fff827b77befe8755007146..a1b803fd372eb7ba3bf13a64c0c6b5684b9350ea 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/percpu.h>
 
 #include <net/sch_generic.h>
 #include <net/pkt_cls.h>
@@ -22,6 +23,7 @@ struct cls_mall_head {
        u32 handle;
        u32 flags;
        unsigned int in_hw_count;
+       struct tc_matchall_pcnt __percpu *pf;
        struct rcu_work rwork;
 };
 
@@ -34,6 +36,7 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                return -1;
 
        *res = head->res;
+       __this_cpu_inc(head->pf->rhit);
        return tcf_exts_exec(skb, &head->exts, res);
 }
 
@@ -46,6 +49,7 @@ static void __mall_destroy(struct cls_mall_head *head)
 {
        tcf_exts_destroy(&head->exts);
        tcf_exts_put_net(&head->exts);
+       free_percpu(head->pf);
        kfree(head);
 }
 
@@ -192,6 +196,11 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
                handle = 1;
        new->handle = handle;
        new->flags = flags;
+       new->pf = alloc_percpu(struct tc_matchall_pcnt);
+       if (!new->pf) {
+               err = -ENOMEM;
+               goto err_alloc_percpu;
+       }
 
        err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr,
                             extack);
@@ -214,6 +223,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
 
 err_replace_hw_filter:
 err_set_parms:
+       free_percpu(new->pf);
+err_alloc_percpu:
        tcf_exts_destroy(&new->exts);
 err_exts_init:
        kfree(new);
@@ -270,8 +281,10 @@ static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
 static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh,
                     struct sk_buff *skb, struct tcmsg *t)
 {
+       struct tc_matchall_pcnt gpf = {};
        struct cls_mall_head *head = fh;
        struct nlattr *nest;
+       int cpu;
 
        if (!head)
                return skb->len;
@@ -289,6 +302,17 @@ static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh,
        if (head->flags && nla_put_u32(skb, TCA_MATCHALL_FLAGS, head->flags))
                goto nla_put_failure;
 
+       for_each_possible_cpu(cpu) {
+               struct tc_matchall_pcnt *pf = per_cpu_ptr(head->pf, cpu);
+
+               gpf.rhit += pf->rhit;
+       }
+
+       if (nla_put_64bit(skb, TCA_MATCHALL_PCNT,
+                         sizeof(struct tc_matchall_pcnt),
+                         &gpf, TCA_MATCHALL_PAD))
+               goto nla_put_failure;
+
        if (tcf_exts_dump(skb, &head->exts))
                goto nla_put_failure;