ip6_fib.c (05668381140309088443bf5dc53add4104610fbb) ip6_fib.c (c71099acce933455123ee505cc75964610a209ad)
1/*
2 * Linux INET6 implementation
3 * Forwarding Information Database
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * $Id: ip6_fib.c,v 1.25 2001/10/31 21:55:55 davem Exp $

--- 12 unchanged lines hidden (view full) ---

21 */
22#include <linux/errno.h>
23#include <linux/types.h>
24#include <linux/net.h>
25#include <linux/route.h>
26#include <linux/netdevice.h>
27#include <linux/in6.h>
28#include <linux/init.h>
1/*
2 * Linux INET6 implementation
3 * Forwarding Information Database
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * $Id: ip6_fib.c,v 1.25 2001/10/31 21:55:55 davem Exp $

--- 12 unchanged lines hidden (view full) ---

21 */
22#include <linux/errno.h>
23#include <linux/types.h>
24#include <linux/net.h>
25#include <linux/route.h>
26#include <linux/netdevice.h>
27#include <linux/in6.h>
28#include <linux/init.h>
29#include <linux/list.h>
29
30#ifdef CONFIG_PROC_FS
31#include <linux/proc_fs.h>
32#endif
33
34#include <net/ipv6.h>
35#include <net/ndisc.h>
36#include <net/addrconf.h>

--- 105 unchanged lines hidden (view full) ---

142}
143
144static __inline__ void rt6_release(struct rt6_info *rt)
145{
146 if (atomic_dec_and_test(&rt->rt6i_ref))
147 dst_free(&rt->u.dst);
148}
149
30
31#ifdef CONFIG_PROC_FS
32#include <linux/proc_fs.h>
33#endif
34
35#include <net/ipv6.h>
36#include <net/ndisc.h>
37#include <net/addrconf.h>

--- 105 unchanged lines hidden (view full) ---

143}
144
145static __inline__ void rt6_release(struct rt6_info *rt)
146{
147 if (atomic_dec_and_test(&rt->rt6i_ref))
148 dst_free(&rt->u.dst);
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};
150
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
271
151/*
152 * Routing Table
153 *
154 * return the appropriate node for a routing tree "add" operation
155 * by either creating and inserting or by returning an existing
156 * node.
157 */
158

--- 900 unchanged lines hidden (view full) ---

1059 c.w.func = fib6_clean_node;
1060 c.w.prune = prune;
1061 c.func = func;
1062 c.arg = arg;
1063
1064 fib6_walk(&c.w);
1065}
1066
272/*
273 * Routing Table
274 *
275 * return the appropriate node for a routing tree "add" operation
276 * by either creating and inserting or by returning an existing
277 * node.
278 */
279

--- 900 unchanged lines hidden (view full) ---

1180 c.w.func = fib6_clean_node;
1181 c.w.prune = prune;
1182 c.func = func;
1183 c.arg = arg;
1184
1185 fib6_walk(&c.w);
1186}
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)
1068{
1069 if (rt->rt6i_flags & RTF_CACHE) {
1070 RT6_TRACE("pruning clone %p\n", rt);
1071 return -1;
1072 }
1073
1074 return 0;

--- 62 unchanged lines hidden (view full) ---

1137 mod_timer(&ip6_fib_timer, jiffies + HZ);
1138 local_bh_enable();
1139 return;
1140 }
1141 gc_args.timeout = ip6_rt_gc_interval;
1142 }
1143 gc_args.more = 0;
1144
1204static int fib6_prune_clone(struct rt6_info *rt, void *arg)
1205{
1206 if (rt->rt6i_flags & RTF_CACHE) {
1207 RT6_TRACE("pruning clone %p\n", rt);
1208 return -1;
1209 }
1210
1211 return 0;

--- 62 unchanged lines hidden (view full) ---

1274 mod_timer(&ip6_fib_timer, jiffies + HZ);
1275 local_bh_enable();
1276 return;
1277 }
1278 gc_args.timeout = ip6_rt_gc_interval;
1279 }
1280 gc_args.more = 0;
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);
1149 write_unlock_bh(&rt6_lock);
1283 fib6_clean_all(fib6_age, 0, NULL);
1150
1151 if (gc_args.more)
1152 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
1153 else {
1154 del_timer(&ip6_fib_timer);
1155 ip6_fib_timer.expires = 0;
1156 }
1157 spin_unlock_bh(&fib6_gc_lock);
1158}
1159
1160void __init fib6_init(void)
1161{
1162 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1163 sizeof(struct fib6_node),
1164 0, SLAB_HWCACHE_ALIGN,
1165 NULL, NULL);
1166 if (!fib6_node_kmem)
1167 panic("cannot create fib6_nodes cache");
1284
1285 if (gc_args.more)
1286 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
1287 else {
1288 del_timer(&ip6_fib_timer);
1289 ip6_fib_timer.expires = 0;
1290 }
1291 spin_unlock_bh(&fib6_gc_lock);
1292}
1293
1294void __init fib6_init(void)
1295{
1296 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1297 sizeof(struct fib6_node),
1298 0, SLAB_HWCACHE_ALIGN,
1299 NULL, NULL);
1300 if (!fib6_node_kmem)
1301 panic("cannot create fib6_nodes cache");
1302
1303 fib6_tables_init();
1168}
1169
1170void fib6_gc_cleanup(void)
1171{
1172 del_timer(&ip6_fib_timer);
1173 kmem_cache_destroy(fib6_node_kmem);
1174}
1304}
1305
1306void fib6_gc_cleanup(void)
1307{
1308 del_timer(&ip6_fib_timer);
1309 kmem_cache_destroy(fib6_node_kmem);
1310}