aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_fib.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r--net/ipv6/ip6_fib.c144
1 files changed, 140 insertions, 4 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 764221220afd..fcd7da830aca 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -26,6 +26,7 @@
26#include <linux/netdevice.h> 26#include <linux/netdevice.h>
27#include <linux/in6.h> 27#include <linux/in6.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/list.h>
29 30
30#ifdef CONFIG_PROC_FS 31#ifdef CONFIG_PROC_FS
31#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
@@ -147,6 +148,126 @@ static __inline__ void rt6_release(struct rt6_info *rt)
147 dst_free(&rt->u.dst); 148 dst_free(&rt->u.dst);
148} 149}
149 150
151static struct fib6_table fib6_main_tbl = {
152 .tb6_id = RT6_TABLE_MAIN,
153 .tb6_lock = RW_LOCK_UNLOCKED,
154 .tb6_root = {
155 .leaf = &ip6_null_entry,
156 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
157 },
158};
159
160#ifdef CONFIG_IPV6_MULTIPLE_TABLES
161
162#define FIB_TABLE_HASHSZ 256
163static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
164
165static struct fib6_table *fib6_alloc_table(u32 id)
166{
167 struct fib6_table *table;
168
169 table = kzalloc(sizeof(*table), GFP_ATOMIC);
170 if (table != NULL) {
171 table->tb6_id = id;
172 table->tb6_lock = RW_LOCK_UNLOCKED;
173 table->tb6_root.leaf = &ip6_null_entry;
174 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
175 }
176
177 return table;
178}
179
180static void fib6_link_table(struct fib6_table *tb)
181{
182 unsigned int h;
183
184 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
185
186 /*
187 * No protection necessary, this is the only list mutatation
188 * operation, tables never disappear once they exist.
189 */
190 hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
191}
192
193struct fib6_table *fib6_new_table(u32 id)
194{
195 struct fib6_table *tb;
196
197 if (id == 0)
198 id = RT6_TABLE_MAIN;
199 tb = fib6_get_table(id);
200 if (tb)
201 return tb;
202
203 tb = fib6_alloc_table(id);
204 if (tb != NULL)
205 fib6_link_table(tb);
206
207 return tb;
208}
209
210struct fib6_table *fib6_get_table(u32 id)
211{
212 struct fib6_table *tb;
213 struct hlist_node *node;
214 unsigned int h;
215
216 if (id == 0)
217 id = RT6_TABLE_MAIN;
218 h = id & (FIB_TABLE_HASHSZ - 1);
219 rcu_read_lock();
220 hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
221 if (tb->tb6_id == id) {
222 rcu_read_unlock();
223 return tb;
224 }
225 }
226 rcu_read_unlock();
227
228 return NULL;
229}
230
231struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
232 pol_lookup_t lookup)
233{
234 /*
235 * TODO: Add rule lookup
236 */
237 struct fib6_table *table = fib6_get_table(RT6_TABLE_MAIN);
238
239 return (struct dst_entry *) lookup(table, fl, flags);
240}
241
242static void __init fib6_tables_init(void)
243{
244 fib6_link_table(&fib6_main_tbl);
245}
246
247#else
248
249struct fib6_table *fib6_new_table(u32 id)
250{
251 return fib6_get_table(id);
252}
253
254struct fib6_table *fib6_get_table(u32 id)
255{
256 return &fib6_main_tbl;
257}
258
259struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
260 pol_lookup_t lookup)
261{
262 return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
263}
264
265static void __init fib6_tables_init(void)
266{
267}
268
269#endif
270
150 271
151/* 272/*
152 * Routing Table 273 * Routing Table
@@ -1064,6 +1185,22 @@ void fib6_clean_tree(struct fib6_node *root,
1064 fib6_walk(&c.w); 1185 fib6_walk(&c.w);
1065} 1186}
1066 1187
1188void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
1189 int prune, void *arg)
1190{
1191 int i;
1192 struct fib6_table *table;
1193
1194 for (i = FIB6_TABLE_MIN; i <= FIB6_TABLE_MAX; i++) {
1195 table = fib6_get_table(i);
1196 if (table != NULL) {
1197 write_lock_bh(&table->tb6_lock);
1198 fib6_clean_tree(&table->tb6_root, func, prune, arg);
1199 write_unlock_bh(&table->tb6_lock);
1200 }
1201 }
1202}
1203
1067static int fib6_prune_clone(struct rt6_info *rt, void *arg) 1204static int fib6_prune_clone(struct rt6_info *rt, void *arg)
1068{ 1205{
1069 if (rt->rt6i_flags & RTF_CACHE) { 1206 if (rt->rt6i_flags & RTF_CACHE) {
@@ -1142,11 +1279,8 @@ void fib6_run_gc(unsigned long dummy)
1142 } 1279 }
1143 gc_args.more = 0; 1280 gc_args.more = 0;
1144 1281
1145
1146 write_lock_bh(&rt6_lock);
1147 ndisc_dst_gc(&gc_args.more); 1282 ndisc_dst_gc(&gc_args.more);
1148 fib6_clean_tree(&ip6_routing_table, fib6_age, 0, NULL); 1283 fib6_clean_all(fib6_age, 0, NULL);
1149 write_unlock_bh(&rt6_lock);
1150 1284
1151 if (gc_args.more) 1285 if (gc_args.more)
1152 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval); 1286 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
@@ -1165,6 +1299,8 @@ void __init fib6_init(void)
1165 NULL, NULL); 1299 NULL, NULL);
1166 if (!fib6_node_kmem) 1300 if (!fib6_node_kmem)
1167 panic("cannot create fib6_nodes cache"); 1301 panic("cannot create fib6_nodes cache");
1302
1303 fib6_tables_init();
1168} 1304}
1169 1305
1170void fib6_gc_cleanup(void) 1306void fib6_gc_cleanup(void)