[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>
This commit is contained in:
committed by
David S. Miller
parent
687ad8cc64
commit
c454673da7
@@ -393,19 +393,15 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
|
||||
static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
|
||||
struct fib_rules_ops *ops)
|
||||
{
|
||||
int idx = 0;
|
||||
struct fib_rule *rule;
|
||||
struct fib_rules_ops *ops;
|
||||
|
||||
ops = lookup_rules_ops(family);
|
||||
if (ops == NULL)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(rule, ops->rules_list, list) {
|
||||
if (idx < cb->args[0])
|
||||
if (idx < cb->args[1])
|
||||
goto skip;
|
||||
|
||||
if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid,
|
||||
@@ -416,13 +412,44 @@ skip:
|
||||
idx++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
cb->args[0] = idx;
|
||||
cb->args[1] = idx;
|
||||
rules_ops_put(ops);
|
||||
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(fib_rules_dump);
|
||||
static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct fib_rules_ops *ops;
|
||||
int idx = 0, family;
|
||||
|
||||
family = rtnl_msg_family(cb->nlh);
|
||||
if (family != AF_UNSPEC) {
|
||||
/* Protocol specific dump request */
|
||||
ops = lookup_rules_ops(family);
|
||||
if (ops == NULL)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
return dump_rules(skb, cb, ops);
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(ops, &rules_ops, list) {
|
||||
if (idx < cb->args[0] || !try_module_get(ops->owner))
|
||||
goto skip;
|
||||
|
||||
if (dump_rules(skb, cb, ops) < 0)
|
||||
break;
|
||||
|
||||
cb->args[1] = 0;
|
||||
skip:
|
||||
idx++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
cb->args[0] = idx;
|
||||
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static void notify_rule_change(int event, struct fib_rule *rule,
|
||||
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
|
||||
@@ -503,7 +530,7 @@ static int __init fib_rules_init(void)
|
||||
{
|
||||
rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
|
||||
rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
|
||||
rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, rtnl_dump_all);
|
||||
rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
|
||||
|
||||
return register_netdevice_notifier(&fib_rules_notifier);
|
||||
}
|
||||
|
Reference in New Issue
Block a user