aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2007-03-26 02:24:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:27:17 -0400
commitc454673da7c1d6533f40ec2f788023df9af56ebf (patch)
tree004d329e049f3bdef09ff20623e24cba9f1fac12 /net/core
parent687ad8cc640fd1f1619cc44a9ab274dabd48c758 (diff)
[NET] rules: Unified rules dumping
Implements a unified, protocol independant rules dumping function which is capable of both, dumping a specific protocol family or all of them. This speeds up dumping as less lookups are required. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/fib_rules.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index bf45f24cfea2..fdf05af16ba5 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -393,19 +393,15 @@ nla_put_failure:
393 return -EMSGSIZE; 393 return -EMSGSIZE;
394} 394}
395 395
396int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) 396static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
397 struct fib_rules_ops *ops)
397{ 398{
398 int idx = 0; 399 int idx = 0;
399 struct fib_rule *rule; 400 struct fib_rule *rule;
400 struct fib_rules_ops *ops;
401
402 ops = lookup_rules_ops(family);
403 if (ops == NULL)
404 return -EAFNOSUPPORT;
405 401
406 rcu_read_lock(); 402 rcu_read_lock();
407 list_for_each_entry_rcu(rule, ops->rules_list, list) { 403 list_for_each_entry_rcu(rule, ops->rules_list, list) {
408 if (idx < cb->args[0]) 404 if (idx < cb->args[1])
409 goto skip; 405 goto skip;
410 406
411 if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid, 407 if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid,
@@ -416,13 +412,44 @@ skip:
416 idx++; 412 idx++;
417 } 413 }
418 rcu_read_unlock(); 414 rcu_read_unlock();
419 cb->args[0] = idx; 415 cb->args[1] = idx;
420 rules_ops_put(ops); 416 rules_ops_put(ops);
421 417
422 return skb->len; 418 return skb->len;
423} 419}
424 420
425EXPORT_SYMBOL_GPL(fib_rules_dump); 421static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
422{
423 struct fib_rules_ops *ops;
424 int idx = 0, family;
425
426 family = rtnl_msg_family(cb->nlh);
427 if (family != AF_UNSPEC) {
428 /* Protocol specific dump request */
429 ops = lookup_rules_ops(family);
430 if (ops == NULL)
431 return -EAFNOSUPPORT;
432
433 return dump_rules(skb, cb, ops);
434 }
435
436 rcu_read_lock();
437 list_for_each_entry_rcu(ops, &rules_ops, list) {
438 if (idx < cb->args[0] || !try_module_get(ops->owner))
439 goto skip;
440
441 if (dump_rules(skb, cb, ops) < 0)
442 break;
443
444 cb->args[1] = 0;
445 skip:
446 idx++;
447 }
448 rcu_read_unlock();
449 cb->args[0] = idx;
450
451 return skb->len;
452}
426 453
427static void notify_rule_change(int event, struct fib_rule *rule, 454static void notify_rule_change(int event, struct fib_rule *rule,
428 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 455 struct fib_rules_ops *ops, struct nlmsghdr *nlh,
@@ -503,7 +530,7 @@ static int __init fib_rules_init(void)
503{ 530{
504 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL); 531 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
505 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL); 532 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
506 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, rtnl_dump_all); 533 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
507 534
508 return register_netdevice_notifier(&fib_rules_notifier); 535 return register_netdevice_notifier(&fib_rules_notifier);
509} 536}