aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-08-11 02:11:17 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:54:27 -0400
commit1b43af5480c351dbcb2eef478bafe179cbeb6e83 (patch)
treec69adf005f89c7f5147ad338f1e7243aebc14008 /net/ipv6/route.c
parent1af5a8c4a11cfed0c9a7f30fcfb689981750599c (diff)
[IPV6]: Increase number of possible routing tables to 2^32
Increase number of possible routing tables to 2^32 by replacing iterations over all possible table IDs by hash table walking. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c128
1 files changed, 1 insertions, 127 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 843c5509fced..9ce28277f47f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1874,12 +1874,6 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1874 rtm_get_table(arg, r->rtm_table)); 1874 rtm_get_table(arg, r->rtm_table));
1875} 1875}
1876 1876
1877struct rt6_rtnl_dump_arg
1878{
1879 struct sk_buff *skb;
1880 struct netlink_callback *cb;
1881};
1882
1883static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, 1877static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1884 struct in6_addr *dst, struct in6_addr *src, 1878 struct in6_addr *dst, struct in6_addr *src,
1885 int iif, int type, u32 pid, u32 seq, 1879 int iif, int type, u32 pid, u32 seq,
@@ -1976,7 +1970,7 @@ rtattr_failure:
1976 return -1; 1970 return -1;
1977} 1971}
1978 1972
1979static int rt6_dump_route(struct rt6_info *rt, void *p_arg) 1973int rt6_dump_route(struct rt6_info *rt, void *p_arg)
1980{ 1974{
1981 struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; 1975 struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
1982 int prefix; 1976 int prefix;
@@ -1992,126 +1986,6 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
1992 prefix, NLM_F_MULTI); 1986 prefix, NLM_F_MULTI);
1993} 1987}
1994 1988
1995static int fib6_dump_node(struct fib6_walker_t *w)
1996{
1997 int res;
1998 struct rt6_info *rt;
1999
2000 for (rt = w->leaf; rt; rt = rt->u.next) {
2001 res = rt6_dump_route(rt, w->args);
2002 if (res < 0) {
2003 /* Frame is full, suspend walking */
2004 w->leaf = rt;
2005 return 1;
2006 }
2007 BUG_TRAP(res!=0);
2008 }
2009 w->leaf = NULL;
2010 return 0;
2011}
2012
2013static void fib6_dump_end(struct netlink_callback *cb)
2014{
2015 struct fib6_walker_t *w = (void*)cb->args[0];
2016
2017 if (w) {
2018 cb->args[0] = 0;
2019 kfree(w);
2020 }
2021 cb->done = (void*)cb->args[1];
2022 cb->args[1] = 0;
2023}
2024
2025static int fib6_dump_done(struct netlink_callback *cb)
2026{
2027 fib6_dump_end(cb);
2028 return cb->done ? cb->done(cb) : 0;
2029}
2030
2031int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
2032{
2033 struct fib6_table *table;
2034 struct rt6_rtnl_dump_arg arg;
2035 struct fib6_walker_t *w;
2036 int i, res = 0;
2037
2038 arg.skb = skb;
2039 arg.cb = cb;
2040
2041 /*
2042 * cb->args[0] = pointer to walker structure
2043 * cb->args[1] = saved cb->done() pointer
2044 * cb->args[2] = current table being dumped
2045 */
2046
2047 w = (void*)cb->args[0];
2048 if (w == NULL) {
2049 /* New dump:
2050 *
2051 * 1. hook callback destructor.
2052 */
2053 cb->args[1] = (long)cb->done;
2054 cb->done = fib6_dump_done;
2055
2056 /*
2057 * 2. allocate and initialize walker.
2058 */
2059 w = kzalloc(sizeof(*w), GFP_ATOMIC);
2060 if (w == NULL)
2061 return -ENOMEM;
2062 w->func = fib6_dump_node;
2063 w->args = &arg;
2064 cb->args[0] = (long)w;
2065 cb->args[2] = FIB6_TABLE_MIN;
2066 } else {
2067 w->args = &arg;
2068 i = cb->args[2];
2069 if (i > FIB6_TABLE_MAX)
2070 goto end;
2071
2072 table = fib6_get_table(i);
2073 if (table != NULL) {
2074 read_lock_bh(&table->tb6_lock);
2075 w->root = &table->tb6_root;
2076 res = fib6_walk_continue(w);
2077 read_unlock_bh(&table->tb6_lock);
2078 if (res != 0) {
2079 if (res < 0)
2080 fib6_walker_unlink(w);
2081 goto end;
2082 }
2083 }
2084
2085 fib6_walker_unlink(w);
2086 cb->args[2] = ++i;
2087 }
2088
2089 for (i = cb->args[2]; i <= FIB6_TABLE_MAX; i++) {
2090 table = fib6_get_table(i);
2091 if (table == NULL)
2092 continue;
2093
2094 read_lock_bh(&table->tb6_lock);
2095 w->root = &table->tb6_root;
2096 res = fib6_walk(w);
2097 read_unlock_bh(&table->tb6_lock);
2098 if (res)
2099 break;
2100 }
2101end:
2102 cb->args[2] = i;
2103
2104 res = res < 0 ? res : skb->len;
2105 /* res < 0 is an error. (really, impossible)
2106 res == 0 means that dump is complete, but skb still can contain data.
2107 res > 0 dump is not complete, but frame is full.
2108 */
2109 /* Destroy walker, if dump of this table is complete. */
2110 if (res <= 0)
2111 fib6_dump_end(cb);
2112 return res;
2113}
2114
2115int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) 1989int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
2116{ 1990{
2117 struct rtattr **rta = arg; 1991 struct rtattr **rta = arg;