diff options
author | David S. Miller <davem@davemloft.net> | 2018-10-16 10:14:18 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-16 10:14:18 +0300 |
commit | 2c59f06cc0442862d589c36bd2f29667f96c35e7 (patch) | |
tree | eca4db1ca406c8c5d36daebbd92576ababdc4869 /net/ipv4/ipmr.c | |
parent | e85679511e48168b0f066b6ae585556b5e0d8f5b (diff) | |
parent | e4e92fb160d7bef689c6ad00108b4e52599ca05e (diff) | |
download | linux-2c59f06cc0442862d589c36bd2f29667f96c35e7.tar.xz |
Merge branch 'net-Kernel-side-filtering-for-route-dumps'
David Ahern says:
====================
net: Kernel side filtering for route dumps
Implement kernel side filtering of route dumps by protocol (e.g., which
routing daemon installed the route), route type (e.g., unicast), table
id and nexthop device.
iproute2 has been doing this filtering in userspace for years; pushing
the filters to the kernel side reduces the amount of data the kernel
sends and reduces wasted cycles on both sides processing unwanted data.
These initial options provide a huge improvement for efficiently
examining routes on large scale systems.
v2
- better handling of requests for a specific table. Rather than walking
the hash of all tables, lookup the specific table and dump it
- refactor mr_rtm_dumproute moving the loop over the table into a
helper that can be invoked directly
- add hook to return NLM_F_DUMP_FILTERED in DONE message to ensure
it is returned even when the dump returns nothing
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 91b0d5671649..7a3e2acda94c 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -2527,15 +2527,31 @@ errout_free: static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) { - if (cb->strict_check) { - int err = ip_valid_fib_dump_req(cb->nlh, cb->extack); + struct fib_dump_filter filter = {}; + int err; + if (cb->strict_check) { + err = ip_valid_fib_dump_req(sock_net(skb->sk), cb->nlh, + &filter, cb); if (err < 0) return err; } + if (filter.table_id) { + struct mr_table *mrt; + + mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id); + if (!mrt) { + NL_SET_ERR_MSG(cb->extack, "ipv4: MR table does not exist"); + return -ENOENT; + } + err = mr_table_dump(mrt, skb, cb, _ipmr_fill_mroute, + &mfc_unres_lock, &filter); + return skb->len ? : err; + } + return mr_rtm_dumproute(skb, cb, ipmr_mr_table_iter, - _ipmr_fill_mroute, &mfc_unres_lock); + _ipmr_fill_mroute, &mfc_unres_lock, &filter); } static const struct nla_policy rtm_ipmr_policy[RTA_MAX + 1] = { |