diff options
author | Thomas Graf <tgraf@suug.ch> | 2007-03-26 02:24:24 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:27:17 -0400 |
commit | c454673da7c1d6533f40ec2f788023df9af56ebf (patch) | |
tree | 004d329e049f3bdef09ff20623e24cba9f1fac12 /net/core | |
parent | 687ad8cc640fd1f1619cc44a9ab274dabd48c758 (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.c | 47 |
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 | ||
396 | int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) | 396 | static 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 | ||
425 | EXPORT_SYMBOL_GPL(fib_rules_dump); | 421 | static 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 | ||
427 | static void notify_rule_change(int event, struct fib_rule *rule, | 454 | static 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 | } |