aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_api.c
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2017-05-17 05:07:55 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-17 15:22:13 -0400
commit6529eaba33f0465fc6d228e1d05b1745f7d0e8c9 (patch)
treed0caf42e125d3554262bd7c2fb66f232a5a7c90a /net/sched/cls_api.c
parent87d83093bfc2f4938ff21524ebb50ecf53c15a64 (diff)
net: sched: introduce tcf block infractructure
Currently, the filter chains are direcly put into the private structures of qdiscs. In order to be able to have multiple chains per qdisc and to allow filter chains sharing among qdiscs, there is a need for common object that would hold the chains. This introduces such object and calls it "tcf_block". Helpers to get and put the blocks are provided to be called from individual qdisc code. Also, the original filter_list pointers are left in qdisc privs to allow the entry into tcf_block processing without any added overhead of possible multiple pointer dereference on fast path. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_api.c')
-rw-r--r--net/sched/cls_api.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index af58bbef6610..d30116f77156 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -129,7 +129,8 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
129} 129}
130 130
131static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol, 131static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
132 u32 prio, u32 parent, struct Qdisc *q) 132 u32 prio, u32 parent, struct Qdisc *q,
133 struct tcf_block *block)
133{ 134{
134 struct tcf_proto *tp; 135 struct tcf_proto *tp;
135 int err; 136 int err;
@@ -165,6 +166,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
165 tp->prio = prio; 166 tp->prio = prio;
166 tp->classid = parent; 167 tp->classid = parent;
167 tp->q = q; 168 tp->q = q;
169 tp->block = block;
168 170
169 err = tp->ops->init(tp); 171 err = tp->ops->init(tp);
170 if (err) { 172 if (err) {
@@ -185,7 +187,7 @@ static void tcf_proto_destroy(struct tcf_proto *tp)
185 kfree_rcu(tp, rcu); 187 kfree_rcu(tp, rcu);
186} 188}
187 189
188void tcf_destroy_chain(struct tcf_proto __rcu **fl) 190static void tcf_destroy_chain(struct tcf_proto __rcu **fl)
189{ 191{
190 struct tcf_proto *tp; 192 struct tcf_proto *tp;
191 193
@@ -194,7 +196,28 @@ void tcf_destroy_chain(struct tcf_proto __rcu **fl)
194 tcf_proto_destroy(tp); 196 tcf_proto_destroy(tp);
195 } 197 }
196} 198}
197EXPORT_SYMBOL(tcf_destroy_chain); 199
200int tcf_block_get(struct tcf_block **p_block,
201 struct tcf_proto __rcu **p_filter_chain)
202{
203 struct tcf_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
204
205 if (!block)
206 return -ENOMEM;
207 block->p_filter_chain = p_filter_chain;
208 *p_block = block;
209 return 0;
210}
211EXPORT_SYMBOL(tcf_block_get);
212
213void tcf_block_put(struct tcf_block *block)
214{
215 if (!block)
216 return;
217 tcf_destroy_chain(block->p_filter_chain);
218 kfree(block);
219}
220EXPORT_SYMBOL(tcf_block_put);
198 221
199/* Main classifier routine: scans classifier chain attached 222/* Main classifier routine: scans classifier chain attached
200 * to this qdisc, (optionally) tests for protocol and asks 223 * to this qdisc, (optionally) tests for protocol and asks
@@ -260,6 +283,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
260 struct Qdisc *q; 283 struct Qdisc *q;
261 struct tcf_proto __rcu **back; 284 struct tcf_proto __rcu **back;
262 struct tcf_proto __rcu **chain; 285 struct tcf_proto __rcu **chain;
286 struct tcf_block *block;
263 struct tcf_proto *next; 287 struct tcf_proto *next;
264 struct tcf_proto *tp; 288 struct tcf_proto *tp;
265 const struct Qdisc_class_ops *cops; 289 const struct Qdisc_class_ops *cops;
@@ -328,7 +352,7 @@ replay:
328 if (!cops) 352 if (!cops)
329 return -EINVAL; 353 return -EINVAL;
330 354
331 if (cops->tcf_chain == NULL) 355 if (!cops->tcf_block)
332 return -EOPNOTSUPP; 356 return -EOPNOTSUPP;
333 357
334 /* Do we search for filter, attached to class? */ 358 /* Do we search for filter, attached to class? */
@@ -339,11 +363,13 @@ replay:
339 } 363 }
340 364
341 /* And the last stroke */ 365 /* And the last stroke */
342 chain = cops->tcf_chain(q, cl); 366 block = cops->tcf_block(q, cl);
343 if (chain == NULL) { 367 if (!block) {
344 err = -EINVAL; 368 err = -EINVAL;
345 goto errout; 369 goto errout;
346 } 370 }
371 chain = block->p_filter_chain;
372
347 if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) { 373 if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) {
348 tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER); 374 tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER);
349 tcf_destroy_chain(chain); 375 tcf_destroy_chain(chain);
@@ -387,7 +413,7 @@ replay:
387 nprio = TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back))); 413 nprio = TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back)));
388 414
389 tp = tcf_proto_create(nla_data(tca[TCA_KIND]), 415 tp = tcf_proto_create(nla_data(tca[TCA_KIND]),
390 protocol, nprio, parent, q); 416 protocol, nprio, parent, q, block);
391 if (IS_ERR(tp)) { 417 if (IS_ERR(tp)) {
392 err = PTR_ERR(tp); 418 err = PTR_ERR(tp);
393 goto errout; 419 goto errout;
@@ -556,6 +582,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
556 int s_t; 582 int s_t;
557 struct net_device *dev; 583 struct net_device *dev;
558 struct Qdisc *q; 584 struct Qdisc *q;
585 struct tcf_block *block;
559 struct tcf_proto *tp, __rcu **chain; 586 struct tcf_proto *tp, __rcu **chain;
560 struct tcmsg *tcm = nlmsg_data(cb->nlh); 587 struct tcmsg *tcm = nlmsg_data(cb->nlh);
561 unsigned long cl = 0; 588 unsigned long cl = 0;
@@ -577,16 +604,17 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
577 cops = q->ops->cl_ops; 604 cops = q->ops->cl_ops;
578 if (!cops) 605 if (!cops)
579 goto errout; 606 goto errout;
580 if (cops->tcf_chain == NULL) 607 if (!cops->tcf_block)
581 goto errout; 608 goto errout;
582 if (TC_H_MIN(tcm->tcm_parent)) { 609 if (TC_H_MIN(tcm->tcm_parent)) {
583 cl = cops->get(q, tcm->tcm_parent); 610 cl = cops->get(q, tcm->tcm_parent);
584 if (cl == 0) 611 if (cl == 0)
585 goto errout; 612 goto errout;
586 } 613 }
587 chain = cops->tcf_chain(q, cl); 614 block = cops->tcf_block(q, cl);
588 if (chain == NULL) 615 if (!block)
589 goto errout; 616 goto errout;
617 chain = block->p_filter_chain;
590 618
591 s_t = cb->args[0]; 619 s_t = cb->args[0];
592 620