]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-fib.c
2 * BIRD -- Forwarding Information Base -- Data Structures
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
10 * DOC: Forwarding Information Base
12 * FIB is a data structure designed for storage of routes indexed by their
13 * network prefixes. It supports insertion, deletion, searching by prefix,
14 * `routing' (in CIDR sense, that is searching for a longest prefix matching
15 * a given IP address) and (which makes the structure very tricky to implement)
16 * asynchronous reading, that is enumerating the contents of a FIB while other
17 * modules add, modify or remove entries.
19 * Internally, each FIB is represented as a collection of nodes of type &fib_node
20 * indexed using a sophisticated hashing mechanism.
21 * We use two-stage hashing where we calculate a 16-bit primary hash key independent
22 * on hash table size and then we just divide the primary keys modulo table size
23 * to get a real hash key used for determining the bucket containing the node.
24 * The lists of nodes in each bucket are sorted according to the primary hash
25 * key, hence if we keep the total number of buckets to be a power of two,
26 * re-hashing of the structure keeps the relative order of the nodes.
28 * To get the asynchronous reading consistent over node deletions, we need to
29 * keep a list of readers for each node. When a node gets deleted, its readers
30 * are automatically moved to the next node in the table.
32 * Basic FIB operations are performed by functions defined by this module,
33 * enumerating of FIB contents is accomplished by using the FIB_WALK() macro
34 * or FIB_ITERATE_START() if you want to do it asynchronously.
36 * For simple iteration just place the body of the loop between FIB_WALK() and
37 * FIB_WALK_END(). You can't modify the FIB during the iteration (you can modify
38 * data in the node, but not add or remove nodes).
40 * If you need more freedom, you can use the FIB_ITERATE_*() group of macros.
41 * First, you initialize an iterator with FIB_ITERATE_INIT(). Then you can put
42 * the loop body in between FIB_ITERATE_START() and FIB_ITERATE_END(). In
43 * addition, the iteration can be suspended by calling FIB_ITERATE_PUT().
44 * This'll link the iterator inside the FIB. While suspended, you may modify the
45 * FIB, exit the current function, etc. To resume the iteration, enter the loop
46 * again. You can use FIB_ITERATE_UNLINK() to unlink the iterator (while
47 * iteration is suspended) in cases like premature end of FIB iteration.
49 * Note that the iterator must not be destroyed when the iteration is suspended,
50 * the FIB would then contain a pointer to invalid memory. Therefore, after each
51 * FIB_ITERATE_INIT() or FIB_ITERATE_PUT() there must be either
52 * FIB_ITERATE_START() or FIB_ITERATE_UNLINK() before the iterator is destroyed.
57 #include "nest/bird.h"
58 #include "nest/route.h"
59 #include "lib/string.h"
61 #define HASH_DEF_ORDER 10
62 #define HASH_HI_MARK *4
63 #define HASH_HI_STEP 2
64 #define HASH_HI_MAX 16 /* Must be at most 16 */
65 #define HASH_LO_MARK /5
66 #define HASH_LO_STEP 2
67 #define HASH_LO_MIN 10
70 fib_ht_alloc(struct fib
*f
)
72 f
->hash_size
= 1 << f
->hash_order
;
73 f
->hash_shift
= 16 - f
->hash_order
;
74 if (f
->hash_order
> HASH_HI_MAX
- HASH_HI_STEP
)
77 f
->entries_max
= f
->hash_size HASH_HI_MARK
;
78 if (f
->hash_order
< HASH_LO_MIN
+ HASH_LO_STEP
)
81 f
->entries_min
= f
->hash_size HASH_LO_MARK
;
82 DBG("Allocating FIB hash of order %d: %d entries, %d low, %d high\n",
83 f
->hash_order
, f
->hash_size
, f
->entries_min
, f
->entries_max
);
84 f
->hash_table
= mb_alloc(f
->fib_pool
, f
->hash_size
* sizeof(struct fib_node
*));
88 fib_ht_free(struct fib_node
**h
)
93 static inline unsigned
94 fib_hash(struct fib
*f
, ip_addr
*a
)
96 return ipa_hash(*a
) >> f
->hash_shift
;
100 fib_dummy_init(struct fib_node
*dummy UNUSED
)
105 * fib_init - initialize a new FIB
106 * @f: the FIB to be initialized (the structure itself being allocated by the caller)
107 * @p: pool to allocate the nodes in
108 * @node_size: node size to be used (each node consists of a standard header &fib_node
109 * followed by user data)
110 * @hash_order: initial hash order (a binary logarithm of hash table size), 0 to use default order
112 * @init: pointer a function to be called to initialize a newly created node
114 * This function initializes a newly allocated FIB and prepares it for use.
117 fib_init(struct fib
*f
, pool
*p
, unsigned node_size
, unsigned hash_order
, fib_init_func init
)
120 hash_order
= HASH_DEF_ORDER
;
122 f
->fib_slab
= sl_new(p
, node_size
);
123 f
->hash_order
= hash_order
;
125 bzero(f
->hash_table
, f
->hash_size
* sizeof(struct fib_node
*));
128 f
->init
= init
? : fib_dummy_init
;
132 fib_rehash(struct fib
*f
, int step
)
134 unsigned old
, new, oldn
, newn
, ni
, nh
;
135 struct fib_node
**n
, *e
, *x
, **t
, **m
, **h
;
140 m
= h
= f
->hash_table
;
141 DBG("Re-hashing FIB from order %d to %d\n", old
, new);
144 t
= n
= f
->hash_table
;
154 nh
= fib_hash(f
, &e
->prefix
);
175 * fib_find - search for FIB node by prefix
176 * @f: FIB to search in
177 * @a: pointer to IP address of the prefix
178 * @len: prefix length
180 * Search for a FIB node corresponding to the given prefix, return
181 * a pointer to it or %NULL if no such node exists.
184 fib_find(struct fib
*f
, ip_addr
*a
, int len
)
186 struct fib_node
*e
= f
->hash_table
[fib_hash(f
, a
)];
188 while (e
&& (e
->pxlen
!= len
|| !ipa_equal(*a
, e
->prefix
)))
195 fib_histogram(struct fib *f)
197 log(L_WARN "Histogram dump start %d %d", f->hash_size, f->entries);
202 for (i = 0; i < f->hash_size; i++)
205 for (e = f->hash_table[i]; e != NULL; e = e->next)
208 log(L_WARN "Histogram line %d: %d", i, j);
211 log(L_WARN "Histogram dump end");
216 * fib_get - find or create a FIB node
217 * @f: FIB to work with
218 * @a: pointer to IP address of the prefix
219 * @len: prefix length
221 * Search for a FIB node corresponding to the given prefix and
222 * return a pointer to it. If no such node exists, create it.
225 fib_get(struct fib
*f
, ip_addr
*a
, int len
)
227 uint h
= ipa_hash(*a
);
228 struct fib_node
**ee
= f
->hash_table
+ (h
>> f
->hash_shift
);
229 struct fib_node
*g
, *e
= *ee
;
232 while (e
&& (e
->pxlen
!= len
|| !ipa_equal(*a
, e
->prefix
)))
237 if (len
< 0 || len
> BITS_PER_IP_ADDRESS
|| !ip_is_prefix(*a
,len
))
238 bug("fib_get() called for invalid address");
241 while ((g
= *ee
) && g
->uid
< uid
)
243 while ((g
= *ee
) && g
->uid
== uid
)
249 if ((uid
>> 16) != h
)
250 log(L_ERR
"FIB hash table chains are too long");
252 // log (L_WARN "FIB_GET %I %x %x", *a, h, uid);
254 e
= sl_alloc(f
->fib_slab
);
262 if (f
->entries
++ > f
->entries_max
)
263 fib_rehash(f
, HASH_HI_STEP
);
269 * fib_route - CIDR routing lookup
270 * @f: FIB to search in
271 * @a: pointer to IP address of the prefix
272 * @len: prefix length
274 * Search for a FIB node with longest prefix matching the given
275 * network, that is a node which a CIDR router would use for routing
279 fib_route(struct fib
*f
, ip_addr a
, int len
)
286 a0
= ipa_and(a
, ipa_mkmask(len
));
287 t
= fib_find(f
, &a0
, len
);
296 fib_merge_readers(struct fib_iterator
*i
, struct fib_node
*to
)
300 struct fib_iterator
*j
= to
->readers
;
305 i
->prev
= (struct fib_iterator
*) to
;
321 else /* No more nodes */
330 * fib_delete - delete a FIB node
331 * @f: FIB to delete from
332 * @E: entry to delete
334 * This function removes the given entry from the FIB,
335 * taking care of all the asynchronous readers by shifting
336 * them to the next node in the canonical reading order.
339 fib_delete(struct fib
*f
, void *E
)
341 struct fib_node
*e
= E
;
342 uint h
= fib_hash(f
, &e
->prefix
);
343 struct fib_node
**ee
= f
->hash_table
+ h
;
344 struct fib_iterator
*it
;
353 struct fib_node
*l
= e
->next
;
357 if (h
>= f
->hash_size
)
360 l
= f
->hash_table
[h
];
362 fib_merge_readers(it
, l
);
364 sl_free(f
->fib_slab
, e
);
365 if (f
->entries
-- < f
->entries_min
)
366 fib_rehash(f
, -HASH_LO_STEP
);
371 bug("fib_delete() called for invalid node");
375 * fib_free - delete a FIB
376 * @f: FIB to be deleted
378 * This function deletes a FIB -- it frees all memory associated
379 * with it and all its entries.
382 fib_free(struct fib
*f
)
384 fib_ht_free(f
->hash_table
);
389 fit_init(struct fib_iterator
*i
, struct fib
*f
)
395 for(h
=0; h
<f
->hash_size
; h
++)
396 if (n
= f
->hash_table
[h
])
398 i
->prev
= (struct fib_iterator
*) n
;
399 if (i
->next
= n
->readers
)
405 /* The fib is empty, nothing to do */
406 i
->prev
= i
->next
= NULL
;
411 fit_get(struct fib
*f
, struct fib_iterator
*i
)
414 struct fib_iterator
*j
, *k
;
418 /* We are at the end */
424 /* No node info available, we are a victim of merging. Try harder. */
426 while (j
->efef
== 0xff)
428 n
= (struct fib_node
*) j
;
434 i
->hash
= fib_hash(f
, &n
->prefix
);
439 fit_put(struct fib_iterator
*i
, struct fib_node
*n
)
441 struct fib_iterator
*j
;
448 i
->prev
= (struct fib_iterator
*) n
;
452 fit_put_next(struct fib
*f
, struct fib_iterator
*i
, struct fib_node
*n
, uint hpos
)
457 while (++hpos
< f
->hash_size
)
458 if (n
= f
->hash_table
[hpos
])
461 /* We are at the end */
462 i
->prev
= i
->next
= NULL
;
473 * fib_check - audit a FIB
474 * @f: FIB to be checked
476 * This debugging function audits a FIB by checking its internal consistency.
477 * Use when you suspect somebody of corrupting innocent data structures.
480 fib_check(struct fib
*f
)
482 uint i
, ec
, lo
, nulls
;
485 for(i
=0; i
<f
->hash_size
; i
++)
489 for(n
=f
->hash_table
[i
]; n
; n
=n
->next
)
491 struct fib_iterator
*j
, *j0
;
492 uint h0
= ipa_hash(n
->prefix
);
494 bug("fib_check: discord in hash chains");
496 if ((h0
>> f
->hash_shift
) != i
)
497 bug("fib_check: mishashed %x->%x (order %d)", h0
, i
, f
->hash_order
);
498 j0
= (struct fib_iterator
*) n
;
500 for(j
=n
->readers
; j
; j
=j
->next
)
503 bug("fib_check: iterator->prev mismatch");
508 bug("fib_check: iterator nullified");
509 else if (j
->node
!= n
)
510 bug("fib_check: iterator->node mismatch");
515 if (ec
!= f
->entries
)
516 bug("fib_check: invalid entry count (%d != %d)", ec
, f
->entries
);
523 #include "lib/resource.h"
531 debug("%s ... order=%d, size=%d, entries=%d\n", m
, f
.hash_order
, f
.hash_size
, f
.hash_size
);
532 for(i
=0; i
<f
.hash_size
; i
++)
535 struct fib_iterator
*j
;
536 for(n
=f
.hash_table
[i
]; n
; n
=n
->next
)
538 debug("%04x %04x %p %I/%2d", i
, ipa_hash(n
->prefix
), n
, n
->prefix
, n
->pxlen
);
539 for(j
=n
->readers
; j
; j
=j
->next
)
540 debug(" %p[%p]", j
, j
->node
);
548 void init(struct fib_node
*n
)
555 struct fib_iterator i
, j
;
559 log_init_debug(NULL
);
561 fib_init(&f
, &root_pool
, sizeof(struct fib_node
), 4, init
);
564 a
= ipa_from_u32(0x01020304); n
= fib_get(&f
, &a
, 32);
565 a
= ipa_from_u32(0x02030405); n
= fib_get(&f
, &a
, 32);
566 a
= ipa_from_u32(0x03040506); n
= fib_get(&f
, &a
, 32);
567 a
= ipa_from_u32(0x00000000); n
= fib_get(&f
, &a
, 32);
568 a
= ipa_from_u32(0x00000c01); n
= fib_get(&f
, &a
, 32);
569 a
= ipa_from_u32(0xffffffff); n
= fib_get(&f
, &a
, 32);
583 FIB_ITERATE_START(&f
, &i
, z
)
587 FIB_ITERATE_PUT(&i
, z
);
592 debug("got %p\n", z
);
604 fit_put(&i
, n
->next
);
607 a
= ipa_from_u32(0xffffffff); n
= fib_get(&f
, &a
, 32);