]>
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.
39 #include "nest/bird.h"
40 #include "nest/route.h"
41 #include "lib/string.h"
43 #define HASH_DEF_ORDER 10
44 #define HASH_HI_MARK *4
45 #define HASH_HI_STEP 2
46 #define HASH_HI_MAX 16 /* Must be at most 16 */
47 #define HASH_LO_MARK /5
48 #define HASH_LO_STEP 2
49 #define HASH_LO_MIN 10
52 static inline void * fib_node_to_user(struct fib
*f
, struct fib_node
*e
)
53 { return (void *) ((char *) e
- f
->node_offset
); }
55 static inline struct fib_node
* fib_user_to_node(struct fib
*f
, void *e
)
56 { return (void *) ((char *) e
+ f
->node_offset
); }
59 fib_ht_alloc(struct fib
*f
)
61 f
->hash_size
= 1 << f
->hash_order
;
62 f
->hash_shift
= 16 - f
->hash_order
;
63 if (f
->hash_order
> HASH_HI_MAX
- HASH_HI_STEP
)
66 f
->entries_max
= f
->hash_size HASH_HI_MARK
;
67 if (f
->hash_order
< HASH_LO_MIN
+ HASH_LO_STEP
)
70 f
->entries_min
= f
->hash_size HASH_LO_MARK
;
71 DBG("Allocating FIB hash of order %d: %d entries, %d low, %d high\n",
72 f
->hash_order
, f
->hash_size
, f
->entries_min
, f
->entries_max
);
73 f
->hash_table
= mb_alloc(f
->fib_pool
, f
->hash_size
* sizeof(struct fib_node
*));
77 fib_ht_free(struct fib_node
**h
)
84 fib_hash(struct fib
*f
, net_addr
*a
);
87 * fib_init - initialize a new FIB
88 * @f: the FIB to be initialized (the structure itself being allocated by the caller)
89 * @p: pool to allocate the nodes in
90 * @node_size: node size to be used (each node consists of a standard header &fib_node
91 * followed by user data)
92 * @hash_order: initial hash order (a binary logarithm of hash table size), 0 to use default order
94 * @init: pointer a function to be called to initialize a newly created node
96 * This function initializes a newly allocated FIB and prepares it for use.
99 fib_init(struct fib
*f
, pool
*p
, uint addr_type
, uint node_size
, uint node_offset
, uint hash_order
, fib_init_fn init
)
101 uint addr_length
= net_addr_length
[addr_type
];
104 hash_order
= HASH_DEF_ORDER
;
106 f
->fib_slab
= addr_length
? sl_new(p
, node_size
+ addr_length
) : NULL
;
107 f
->addr_type
= addr_type
;
108 f
->node_size
= node_size
;
109 f
->node_offset
= node_offset
;
110 f
->hash_order
= hash_order
;
112 bzero(f
->hash_table
, f
->hash_size
* sizeof(struct fib_node
*));
119 fib_rehash(struct fib
*f
, int step
)
121 unsigned old
, new, oldn
, newn
, ni
, nh
;
122 struct fib_node
**n
, *e
, *x
, **t
, **m
, **h
;
127 m
= h
= f
->hash_table
;
128 DBG("Re-hashing FIB from order %d to %d\n", old
, new);
131 t
= n
= f
->hash_table
;
141 nh
= fib_hash(f
, e
->addr
);
161 #define CAST(t) (net_addr_##t *)
163 #define FIB_HASH(f,a,t) (net_hash_##t(CAST(t) a) >> f->hash_shift)
165 #define FIB_FIND(f,a,t) \
167 struct fib_node *e = f->hash_table[FIB_HASH(f, a, t)]; \
168 while (e && !net_equal_##t(CAST(t) e->addr, CAST(t) a)) \
170 fib_node_to_user(f, e); \
173 #define FIB_INSERT(f,a,e,t) \
175 u32 h = net_hash_##t(CAST(t) a); \
176 struct fib_node **ee = f->hash_table + (h >> f->hash_shift); \
177 struct fib_node *g; \
179 while ((g = *ee) && (net_hash_##t(CAST(t) g->addr) < h)) \
182 net_copy_##t(CAST(t) e->addr, CAST(t) a); \
189 fib_hash(struct fib
*f
, net_addr
*a
)
191 switch (f
->addr_type
)
193 case NET_IP4
: return FIB_HASH(f
, a
, ip4
);
194 case NET_IP6
: return FIB_HASH(f
, a
, ip6
);
195 case NET_VPN4
: return FIB_HASH(f
, a
, vpn4
);
196 case NET_VPN6
: return FIB_HASH(f
, a
, vpn6
);
197 default: bug("invalid type");
202 fib_find(struct fib
*f
, net_addr
*a
)
204 ASSERT(f
->addr_type
== a
->type
);
206 switch (f
->addr_type
)
208 case NET_IP4
: return FIB_FIND(f
, a
, ip4
);
209 case NET_IP6
: return FIB_FIND(f
, a
, ip6
);
210 case NET_VPN4
: return FIB_FIND(f
, a
, vpn4
);
211 case NET_VPN6
: return FIB_FIND(f
, a
, vpn6
);
212 default: bug("invalid type");
217 fib_insert(struct fib
*f
, net_addr
*a
, struct fib_node
*e
)
219 switch (f
->addr_type
)
221 case NET_IP4
: FIB_INSERT(f
, a
, e
, ip4
); return;
222 case NET_IP6
: FIB_INSERT(f
, a
, e
, ip6
); return;
223 case NET_VPN4
: FIB_INSERT(f
, a
, e
, vpn4
); return;
224 case NET_VPN6
: FIB_INSERT(f
, a
, e
, vpn6
); return;
225 default: bug("invalid type");
232 * fib_find - search for FIB node by prefix
233 * @f: FIB to search in
234 * @a: pointer to IP address of the prefix
235 * @len: prefix length
237 * Search for a FIB node corresponding to the given prefix, return
238 * a pointer to it or %NULL if no such node exists.
242 fib_find(struct fib *f, net_addr *a)
244 struct fib_node *e = f->hash_table[fib_hash(f, a)];
246 while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix)))
253 * fib_get - find or create a FIB node
254 * @f: FIB to work with
255 * @a: pointer to IP address of the prefix
256 * @len: prefix length
258 * Search for a FIB node corresponding to the given prefix and
259 * return a pointer to it. If no such node exists, create it.
262 fib_get(struct fib
*f
, net_addr
*a
)
264 char *b
= fib_find(f
, a
);
269 b
= sl_alloc(f
->fib_slab
);
271 b
= mb_alloc(f
->fib_pool
, f
->node_size
+ a
->length
);
273 struct fib_node
*e
= (void *) (b
+ f
->node_offset
);
279 memset(b
, 0, f
->node_offset
);
283 if (f
->entries
++ > f
->entries_max
)
284 fib_rehash(f
, HASH_HI_STEP
);
290 * fib_route - CIDR routing lookup
291 * @f: FIB to search in
292 * @a: pointer to IP address of the prefix
293 * @len: prefix length
295 * Search for a FIB node with longest prefix matching the given
296 * network, that is a node which a CIDR router would use for routing
301 fib_route(struct fib *f, ip_addr a, int len)
308 a0 = ipa_and(a, ipa_mkmask(len));
309 t = fib_find(f, &a0, len);
319 fib_merge_readers(struct fib_iterator
*i
, struct fib_node
*to
)
323 struct fib_iterator
*j
= to
->readers
;
328 i
->prev
= (struct fib_iterator
*) to
;
344 else /* No more nodes */
353 * fib_delete - delete a FIB node
354 * @f: FIB to delete from
355 * @E: entry to delete
357 * This function removes the given entry from the FIB,
358 * taking care of all the asynchronous readers by shifting
359 * them to the next node in the canonical reading order.
362 fib_delete(struct fib
*f
, void *E
)
364 struct fib_node
*e
= fib_user_to_node(f
, E
);
365 uint h
= fib_hash(f
, e
->addr
);
366 struct fib_node
**ee
= f
->hash_table
+ h
;
367 struct fib_iterator
*it
;
376 struct fib_node
*l
= e
->next
;
380 if (h
>= f
->hash_size
)
383 l
= f
->hash_table
[h
];
385 fib_merge_readers(it
, l
);
387 sl_free(f
->fib_slab
, e
);
388 if (f
->entries
-- < f
->entries_min
)
389 fib_rehash(f
, -HASH_LO_STEP
);
394 bug("fib_delete() called for invalid node");
398 * fib_free - delete a FIB
399 * @f: FIB to be deleted
401 * This function deletes a FIB -- it frees all memory associated
402 * with it and all its entries.
405 fib_free(struct fib
*f
)
407 fib_ht_free(f
->hash_table
);
412 fit_init(struct fib_iterator
*i
, struct fib
*f
)
418 for(h
=0; h
<f
->hash_size
; h
++)
419 if (n
= f
->hash_table
[h
])
421 i
->prev
= (struct fib_iterator
*) n
;
422 if (i
->next
= n
->readers
)
428 /* The fib is empty, nothing to do */
429 i
->prev
= i
->next
= NULL
;
434 fit_get(struct fib
*f
, struct fib_iterator
*i
)
437 struct fib_iterator
*j
, *k
;
441 /* We are at the end */
447 /* No node info available, we are a victim of merging. Try harder. */
449 while (j
->efef
== 0xff)
451 n
= (struct fib_node
*) j
;
457 i
->hash
= fib_hash(f
, n
->addr
);
462 fit_put(struct fib_iterator
*i
, struct fib_node
*n
)
464 struct fib_iterator
*j
;
471 i
->prev
= (struct fib_iterator
*) n
;
475 fit_put_next(struct fib
*f
, struct fib_iterator
*i
, struct fib_node
*n
, uint hpos
)
480 while (++hpos
< f
->hash_size
)
481 if (n
= f
->hash_table
[hpos
])
484 /* We are at the end */
485 i
->prev
= i
->next
= NULL
;
496 * fib_check - audit a FIB
497 * @f: FIB to be checked
499 * This debugging function audits a FIB by checking its internal consistency.
500 * Use when you suspect somebody of corrupting innocent data structures.
503 fib_check(struct fib
*f
)
505 uint i
, ec
, lo
, nulls
;
508 for(i
=0; i
<f
->hash_size
; i
++)
512 for(n
=f
->hash_table
[i
]; n
; n
=n
->next
)
514 struct fib_iterator
*j
, *j0
;
515 uint h0
= ipa_hash(n
->prefix
);
517 bug("fib_check: discord in hash chains");
519 if ((h0
>> f
->hash_shift
) != i
)
520 bug("fib_check: mishashed %x->%x (order %d)", h0
, i
, f
->hash_order
);
521 j0
= (struct fib_iterator
*) n
;
523 for(j
=n
->readers
; j
; j
=j
->next
)
526 bug("fib_check: iterator->prev mismatch");
531 bug("fib_check: iterator nullified");
532 else if (j
->node
!= n
)
533 bug("fib_check: iterator->node mismatch");
538 if (ec
!= f
->entries
)
539 bug("fib_check: invalid entry count (%d != %d)", ec
, f
->entries
);
544 fib_histogram(struct fib *f)
546 log(L_WARN "Histogram dump start %d %d", f->hash_size, f->entries);
551 for (i = 0; i < f->hash_size; i++)
554 for (e = f->hash_table[i]; e != NULL; e = e->next)
557 log(L_WARN "Histogram line %d: %d", i, j);
560 log(L_WARN "Histogram dump end");
568 #include "lib/resource.h"
576 debug("%s ... order=%d, size=%d, entries=%d\n", m
, f
.hash_order
, f
.hash_size
, f
.hash_size
);
577 for(i
=0; i
<f
.hash_size
; i
++)
580 struct fib_iterator
*j
;
581 for(n
=f
.hash_table
[i
]; n
; n
=n
->next
)
583 debug("%04x %08x %p %N", i
, ipa_hash(n
->prefix
), n
, n
->addr
);
584 for(j
=n
->readers
; j
; j
=j
->next
)
585 debug(" %p[%p]", j
, j
->node
);
593 void init(struct fib_node
*n
)
600 struct fib_iterator i
, j
;
604 log_init_debug(NULL
);
606 fib_init(&f
, &root_pool
, sizeof(struct fib_node
), 4, init
);
609 a
= ipa_from_u32(0x01020304); n
= fib_get(&f
, &a
, 32);
610 a
= ipa_from_u32(0x02030405); n
= fib_get(&f
, &a
, 32);
611 a
= ipa_from_u32(0x03040506); n
= fib_get(&f
, &a
, 32);
612 a
= ipa_from_u32(0x00000000); n
= fib_get(&f
, &a
, 32);
613 a
= ipa_from_u32(0x00000c01); n
= fib_get(&f
, &a
, 32);
614 a
= ipa_from_u32(0xffffffff); n
= fib_get(&f
, &a
, 32);
628 FIB_ITERATE_START(&f
, &i
, z
)
632 FIB_ITERATE_PUT(&i
, z
);
637 debug("got %p\n", z
);
649 fit_put(&i
, n
->next
);
652 a
= ipa_from_u32(0xffffffff); n
= fib_get(&f
, &a
, 32);