aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_basic.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_basic.c')
-rw-r--r--net/sched/cls_basic.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 6a5dce8baf19..4a57fec6f306 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -18,6 +18,7 @@
18#include <linux/rtnetlink.h> 18#include <linux/rtnetlink.h>
19#include <linux/skbuff.h> 19#include <linux/skbuff.h>
20#include <linux/idr.h> 20#include <linux/idr.h>
21#include <linux/percpu.h>
21#include <net/netlink.h> 22#include <net/netlink.h>
22#include <net/act_api.h> 23#include <net/act_api.h>
23#include <net/pkt_cls.h> 24#include <net/pkt_cls.h>
@@ -35,6 +36,7 @@ struct basic_filter {
35 struct tcf_result res; 36 struct tcf_result res;
36 struct tcf_proto *tp; 37 struct tcf_proto *tp;
37 struct list_head link; 38 struct list_head link;
39 struct tc_basic_pcnt __percpu *pf;
38 struct rcu_work rwork; 40 struct rcu_work rwork;
39}; 41};
40 42
@@ -46,8 +48,10 @@ static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
46 struct basic_filter *f; 48 struct basic_filter *f;
47 49
48 list_for_each_entry_rcu(f, &head->flist, link) { 50 list_for_each_entry_rcu(f, &head->flist, link) {
51 __this_cpu_inc(f->pf->rcnt);
49 if (!tcf_em_tree_match(skb, &f->ematches, NULL)) 52 if (!tcf_em_tree_match(skb, &f->ematches, NULL))
50 continue; 53 continue;
54 __this_cpu_inc(f->pf->rhit);
51 *res = f->res; 55 *res = f->res;
52 r = tcf_exts_exec(skb, &f->exts, res); 56 r = tcf_exts_exec(skb, &f->exts, res);
53 if (r < 0) 57 if (r < 0)
@@ -89,6 +93,7 @@ static void __basic_delete_filter(struct basic_filter *f)
89 tcf_exts_destroy(&f->exts); 93 tcf_exts_destroy(&f->exts);
90 tcf_em_tree_destroy(&f->ematches); 94 tcf_em_tree_destroy(&f->ematches);
91 tcf_exts_put_net(&f->exts); 95 tcf_exts_put_net(&f->exts);
96 free_percpu(f->pf);
92 kfree(f); 97 kfree(f);
93} 98}
94 99
@@ -208,6 +213,11 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
208 if (err) 213 if (err)
209 goto errout; 214 goto errout;
210 fnew->handle = handle; 215 fnew->handle = handle;
216 fnew->pf = alloc_percpu(struct tc_basic_pcnt);
217 if (!fnew->pf) {
218 err = -ENOMEM;
219 goto errout;
220 }
211 221
212 err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr, 222 err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr,
213 extack); 223 extack);
@@ -231,6 +241,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
231 241
232 return 0; 242 return 0;
233errout: 243errout:
244 free_percpu(fnew->pf);
234 tcf_exts_destroy(&fnew->exts); 245 tcf_exts_destroy(&fnew->exts);
235 kfree(fnew); 246 kfree(fnew);
236 return err; 247 return err;
@@ -265,8 +276,10 @@ static void basic_bind_class(void *fh, u32 classid, unsigned long cl)
265static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, 276static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh,
266 struct sk_buff *skb, struct tcmsg *t) 277 struct sk_buff *skb, struct tcmsg *t)
267{ 278{
279 struct tc_basic_pcnt gpf = {};
268 struct basic_filter *f = fh; 280 struct basic_filter *f = fh;
269 struct nlattr *nest; 281 struct nlattr *nest;
282 int cpu;
270 283
271 if (f == NULL) 284 if (f == NULL)
272 return skb->len; 285 return skb->len;
@@ -281,6 +294,18 @@ static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh,
281 nla_put_u32(skb, TCA_BASIC_CLASSID, f->res.classid)) 294 nla_put_u32(skb, TCA_BASIC_CLASSID, f->res.classid))
282 goto nla_put_failure; 295 goto nla_put_failure;
283 296
297 for_each_possible_cpu(cpu) {
298 struct tc_basic_pcnt *pf = per_cpu_ptr(f->pf, cpu);
299
300 gpf.rcnt += pf->rcnt;
301 gpf.rhit += pf->rhit;
302 }
303
304 if (nla_put_64bit(skb, TCA_BASIC_PCNT,
305 sizeof(struct tc_basic_pcnt),
306 &gpf, TCA_BASIC_PAD))
307 goto nla_put_failure;
308
284 if (tcf_exts_dump(skb, &f->exts) < 0 || 309 if (tcf_exts_dump(skb, &f->exts) < 0 ||
285 tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0) 310 tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
286 goto nla_put_failure; 311 goto nla_put_failure;