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 | |
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>
-rw-r--r-- | include/net/fib_rules.h | 3 | ||||
-rw-r--r-- | include/net/rtnetlink.h | 8 | ||||
-rw-r--r-- | net/core/fib_rules.c | 47 | ||||
-rw-r--r-- | net/decnet/dn_rules.c | 7 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 7 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 7 |
6 files changed, 45 insertions, 34 deletions
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index b2b9ccdf32d6..ff3029fe9656 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h | |||
@@ -98,7 +98,4 @@ extern int fib_rules_unregister(struct fib_rules_ops *); | |||
98 | extern int fib_rules_lookup(struct fib_rules_ops *, | 98 | extern int fib_rules_lookup(struct fib_rules_ops *, |
99 | struct flowi *, int flags, | 99 | struct flowi *, int flags, |
100 | struct fib_lookup_arg *); | 100 | struct fib_lookup_arg *); |
101 | |||
102 | extern int fib_rules_dump(struct sk_buff *, | ||
103 | struct netlink_callback *, int); | ||
104 | #endif | 101 | #endif |
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index dce7072bd28c..086fa9e89509 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h | |||
@@ -15,4 +15,12 @@ extern int rtnl_unregister(int protocol, int msgtype); | |||
15 | extern void rtnl_unregister_all(int protocol); | 15 | extern void rtnl_unregister_all(int protocol); |
16 | extern int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb); | 16 | extern int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb); |
17 | 17 | ||
18 | static inline int rtnl_msg_family(struct nlmsghdr *nlh) | ||
19 | { | ||
20 | if (nlmsg_len(nlh) >= sizeof(struct rtgenmsg)) | ||
21 | return ((struct rtgenmsg *) nlmsg_data(nlh))->rtgen_family; | ||
22 | else | ||
23 | return AF_UNSPEC; | ||
24 | } | ||
25 | |||
18 | #endif | 26 | #endif |
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 | } |
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index a7a7da9b35c3..fd0cc2aa316c 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c | |||
@@ -239,11 +239,6 @@ static u32 dn_fib_rule_default_pref(void) | |||
239 | return 0; | 239 | return 0; |
240 | } | 240 | } |
241 | 241 | ||
242 | static int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) | ||
243 | { | ||
244 | return fib_rules_dump(skb, cb, AF_DECnet); | ||
245 | } | ||
246 | |||
247 | static struct fib_rules_ops dn_fib_rules_ops = { | 242 | static struct fib_rules_ops dn_fib_rules_ops = { |
248 | .family = AF_DECnet, | 243 | .family = AF_DECnet, |
249 | .rule_size = sizeof(struct dn_fib_rule), | 244 | .rule_size = sizeof(struct dn_fib_rule), |
@@ -264,12 +259,10 @@ void __init dn_fib_rules_init(void) | |||
264 | { | 259 | { |
265 | list_add_tail(&default_rule.common.list, &dn_fib_rules); | 260 | list_add_tail(&default_rule.common.list, &dn_fib_rules); |
266 | fib_rules_register(&dn_fib_rules_ops); | 261 | fib_rules_register(&dn_fib_rules_ops); |
267 | rtnl_register(PF_DECnet, RTM_GETRULE, NULL, dn_fib_dump_rules); | ||
268 | } | 262 | } |
269 | 263 | ||
270 | void __exit dn_fib_rules_cleanup(void) | 264 | void __exit dn_fib_rules_cleanup(void) |
271 | { | 265 | { |
272 | rtnl_unregister(PF_DECnet, RTM_GETRULE); | ||
273 | fib_rules_unregister(&dn_fib_rules_ops); | 266 | fib_rules_unregister(&dn_fib_rules_ops); |
274 | } | 267 | } |
275 | 268 | ||
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index a7f931ddfaad..b021b3440ca3 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -274,11 +274,6 @@ nla_put_failure: | |||
274 | return -ENOBUFS; | 274 | return -ENOBUFS; |
275 | } | 275 | } |
276 | 276 | ||
277 | static int fib4_rule_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
278 | { | ||
279 | return fib_rules_dump(skb, cb, AF_INET); | ||
280 | } | ||
281 | |||
282 | static u32 fib4_rule_default_pref(void) | 277 | static u32 fib4_rule_default_pref(void) |
283 | { | 278 | { |
284 | struct list_head *pos; | 279 | struct list_head *pos; |
@@ -327,6 +322,4 @@ void __init fib4_rules_init(void) | |||
327 | list_add_tail(&default_rule.common.list, &fib4_rules); | 322 | list_add_tail(&default_rule.common.list, &fib4_rules); |
328 | 323 | ||
329 | fib_rules_register(&fib4_rules_ops); | 324 | fib_rules_register(&fib4_rules_ops); |
330 | |||
331 | rtnl_register(PF_INET, RTM_GETRULE, NULL, fib4_rule_dump); | ||
332 | } | 325 | } |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index c74da4b6dd2f..dd9720e700ef 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -216,11 +216,6 @@ nla_put_failure: | |||
216 | return -ENOBUFS; | 216 | return -ENOBUFS; |
217 | } | 217 | } |
218 | 218 | ||
219 | static int fib6_rules_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
220 | { | ||
221 | return fib_rules_dump(skb, cb, AF_INET6); | ||
222 | } | ||
223 | |||
224 | static u32 fib6_rule_default_pref(void) | 219 | static u32 fib6_rule_default_pref(void) |
225 | { | 220 | { |
226 | return 0x3FFF; | 221 | return 0x3FFF; |
@@ -255,11 +250,9 @@ void __init fib6_rules_init(void) | |||
255 | list_add_tail(&main_rule.common.list, &fib6_rules); | 250 | list_add_tail(&main_rule.common.list, &fib6_rules); |
256 | 251 | ||
257 | fib_rules_register(&fib6_rules_ops); | 252 | fib_rules_register(&fib6_rules_ops); |
258 | __rtnl_register(PF_INET6, RTM_GETRULE, NULL, fib6_rules_dump); | ||
259 | } | 253 | } |
260 | 254 | ||
261 | void fib6_rules_cleanup(void) | 255 | void fib6_rules_cleanup(void) |
262 | { | 256 | { |
263 | rtnl_unregister(PF_INET6, RTM_GETRULE); | ||
264 | fib_rules_unregister(&fib6_rules_ops); | 257 | fib_rules_unregister(&fib6_rules_ops); |
265 | } | 258 | } |