diff options
Diffstat (limited to 'net/sched')
| -rw-r--r-- | net/sched/cls_basic.c | 25 |
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; |
| 233 | errout: | 243 | errout: |
| 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) | |||
| 265 | static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, | 276 | static 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; |
