1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Routing Table functions.
4 * Copyright (C) 1998 Kunihiro Ishiguro
7 #define FRR_COMPILING_TABLE_C
14 #include "sockunion.h"
15 #include "libfrr_trace.h"
17 DEFINE_MTYPE_STATIC(LIB
, ROUTE_TABLE
, "Route table");
18 DEFINE_MTYPE(LIB
, ROUTE_NODE
, "Route node");
20 static void route_table_free(struct route_table
*);
22 static int route_table_hash_cmp(const struct route_node
*a
,
23 const struct route_node
*b
)
25 return prefix_cmp(&a
->p
, &b
->p
);
28 DECLARE_HASH(rn_hash_node
, struct route_node
, nodehash
, route_table_hash_cmp
,
31 * route_table_init_with_delegate
34 route_table_init_with_delegate(route_table_delegate_t
*delegate
)
36 struct route_table
*rt
;
38 rt
= XCALLOC(MTYPE_ROUTE_TABLE
, sizeof(struct route_table
));
39 rt
->delegate
= delegate
;
40 rn_hash_node_init(&rt
->hash
);
44 void route_table_finish(struct route_table
*rt
)
49 /* Allocate new route node. */
50 static struct route_node
*route_node_new(struct route_table
*table
)
52 return table
->delegate
->create_node(table
->delegate
, table
);
55 /* Allocate new route node with prefix set. */
56 static struct route_node
*route_node_set(struct route_table
*table
,
57 const struct prefix
*prefix
)
59 struct route_node
*node
;
61 node
= route_node_new(table
);
63 prefix_copy(&node
->p
, prefix
);
66 rn_hash_node_add(&node
->table
->hash
, node
);
71 /* Free route node. */
72 static void route_node_free(struct route_table
*table
, struct route_node
*node
)
75 table
->cleanup(table
, node
);
76 table
->delegate
->destroy_node(table
->delegate
, table
, node
);
79 /* Free route table. */
80 static void route_table_free(struct route_table
*rt
)
82 struct route_node
*tmp_node
;
83 struct route_node
*node
;
90 /* Bulk deletion of nodes remaining in this table. This function is not
91 called until workers have completed their dependency on this table.
92 A final route_unlock_node() will not be called for these nodes. */
100 node
= node
->l_right
;
107 tmp_node
->table
->count
--;
109 0; /* to cause assert if unlocked after this */
110 rn_hash_node_del(&rt
->hash
, tmp_node
);
111 route_node_free(rt
, tmp_node
);
114 if (node
->l_left
== tmp_node
)
117 node
->l_right
= NULL
;
123 assert(rt
->count
== 0);
125 rn_hash_node_fini(&rt
->hash
);
126 XFREE(MTYPE_ROUTE_TABLE
, rt
);
130 /* Utility mask array. */
131 static const uint8_t maskbit
[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
132 0xf8, 0xfc, 0xfe, 0xff};
134 /* Common prefix route genaration. */
135 static void route_common(const struct prefix
*n
, const struct prefix
*p
,
145 if (n
->family
== AF_FLOWSPEC
)
146 return prefix_copy(new, p
);
147 np
= (const uint8_t *)&n
->u
.prefix
;
148 pp
= (const uint8_t *)&p
->u
.prefix
;
150 newp
= &new->u
.prefix
;
152 for (i
= 0; i
< p
->prefixlen
/ 8; i
++) {
159 new->prefixlen
= i
* 8;
161 if (new->prefixlen
!= p
->prefixlen
) {
162 diff
= np
[i
] ^ pp
[i
];
164 while (new->prefixlen
< p
->prefixlen
&& !(mask
& diff
)) {
168 newp
[i
] = np
[i
] & maskbit
[new->prefixlen
% 8];
172 static void set_link(struct route_node
*node
, struct route_node
*new)
174 unsigned int bit
= prefix_bit(&new->p
.u
.prefix
, node
->p
.prefixlen
);
176 node
->link
[bit
] = new;
180 /* Find matched prefix. */
181 struct route_node
*route_node_match(struct route_table
*table
,
182 union prefixconstptr pu
)
184 const struct prefix
*p
= pu
.p
;
185 struct route_node
*node
;
186 struct route_node
*matched
;
191 /* Walk down tree. If there is matched route then store it to
193 while (node
&& node
->p
.prefixlen
<= p
->prefixlen
194 && prefix_match(&node
->p
, p
)) {
198 if (node
->p
.prefixlen
== p
->prefixlen
)
201 node
= node
->link
[prefix_bit(&p
->u
.prefix
, node
->p
.prefixlen
)];
204 /* If matched route found, return it. */
206 return route_lock_node(matched
);
211 struct route_node
*route_node_match_ipv4(struct route_table
*table
,
212 const struct in_addr
*addr
)
214 struct prefix_ipv4 p
;
216 memset(&p
, 0, sizeof(p
));
218 p
.prefixlen
= IPV4_MAX_BITLEN
;
221 return route_node_match(table
, (struct prefix
*)&p
);
224 struct route_node
*route_node_match_ipv6(struct route_table
*table
,
225 const struct in6_addr
*addr
)
227 struct prefix_ipv6 p
;
229 memset(&p
, 0, sizeof(p
));
231 p
.prefixlen
= IPV6_MAX_BITLEN
;
234 return route_node_match(table
, &p
);
237 /* Lookup same prefix node. Return NULL when we can't find route. */
238 struct route_node
*route_node_lookup(struct route_table
*table
,
239 union prefixconstptr pu
)
241 struct route_node rn
, *node
;
242 prefix_copy(&rn
.p
, pu
.p
);
245 node
= rn_hash_node_find(&table
->hash
, &rn
);
246 return (node
&& node
->info
) ? route_lock_node(node
) : NULL
;
249 /* Lookup same prefix node. Return NULL when we can't find route. */
250 struct route_node
*route_node_lookup_maynull(struct route_table
*table
,
251 union prefixconstptr pu
)
253 struct route_node rn
, *node
;
254 prefix_copy(&rn
.p
, pu
.p
);
257 node
= rn_hash_node_find(&table
->hash
, &rn
);
258 return node
? route_lock_node(node
) : NULL
;
261 /* Add node to routing table. */
262 struct route_node
*route_node_get(struct route_table
*table
,
263 union prefixconstptr pu
)
265 if (frrtrace_enabled(frr_libfrr
, route_node_get
)) {
266 char buf
[PREFIX2STR_BUFFER
];
267 prefix2str(pu
, buf
, sizeof(buf
));
268 frrtrace(2, frr_libfrr
, route_node_get
, table
, buf
);
271 struct route_node search
;
272 struct prefix
*p
= &search
.p
;
274 prefix_copy(p
, pu
.p
);
277 struct route_node
*new;
278 struct route_node
*node
;
279 struct route_node
*match
;
280 uint16_t prefixlen
= p
->prefixlen
;
281 const uint8_t *prefix
= &p
->u
.prefix
;
283 node
= rn_hash_node_find(&table
->hash
, &search
);
284 if (node
&& node
->info
)
285 return route_lock_node(node
);
289 while (node
&& node
->p
.prefixlen
<= prefixlen
290 && prefix_match(&node
->p
, p
)) {
291 if (node
->p
.prefixlen
== prefixlen
)
292 return route_lock_node(node
);
295 node
= node
->link
[prefix_bit(prefix
, node
->p
.prefixlen
)];
299 new = route_node_set(table
, p
);
301 set_link(match
, new);
305 new = route_node_new(table
);
306 route_common(&node
->p
, p
, &new->p
);
307 new->p
.family
= p
->family
;
310 rn_hash_node_add(&table
->hash
, new);
313 set_link(match
, new);
317 if (new->p
.prefixlen
!= p
->prefixlen
) {
319 new = route_node_set(table
, p
);
320 set_link(match
, new);
325 route_lock_node(new);
330 /* Delete node from the routing table. */
331 void route_node_delete(struct route_node
*node
)
333 struct route_node
*child
;
334 struct route_node
*parent
;
336 assert(node
->lock
== 0);
337 assert(node
->info
== NULL
);
339 if (node
->l_left
&& node
->l_right
)
343 child
= node
->l_left
;
345 child
= node
->l_right
;
347 parent
= node
->parent
;
350 child
->parent
= parent
;
353 if (parent
->l_left
== node
)
354 parent
->l_left
= child
;
356 parent
->l_right
= child
;
358 node
->table
->top
= child
;
360 node
->table
->count
--;
362 rn_hash_node_del(&node
->table
->hash
, node
);
364 /* WARNING: FRAGILE CODE!
365 * route_node_free may have the side effect of free'ing the entire
367 * this is permitted only if table->count got decremented to zero above,
368 * because in that case parent will also be NULL, so that we won't try
370 * delete a now-stale parent below.
372 * cf. srcdest_srcnode_destroy() in zebra/zebra_rib.c */
374 route_node_free(node
->table
, node
);
376 /* If parent node is stub then delete it also. */
377 if (parent
&& parent
->lock
== 0)
378 route_node_delete(parent
);
381 /* Get first node and lock it. This function is useful when one wants
382 to lookup all the node exist in the routing table. */
383 struct route_node
*route_top(struct route_table
*table
)
385 /* If there is no node in the routing table return NULL. */
386 if (table
->top
== NULL
)
389 /* Lock the top node and return it. */
390 route_lock_node(table
->top
);
394 /* Unlock current node and lock next node then return it. */
395 struct route_node
*route_next(struct route_node
*node
)
397 struct route_node
*next
;
398 struct route_node
*start
;
400 /* Node may be deleted from route_unlock_node so we have to preserve
401 next node's pointer. */
405 route_lock_node(next
);
406 route_unlock_node(node
);
410 next
= node
->l_right
;
411 route_lock_node(next
);
412 route_unlock_node(node
);
417 while (node
->parent
) {
418 if (node
->parent
->l_left
== node
&& node
->parent
->l_right
) {
419 next
= node
->parent
->l_right
;
420 route_lock_node(next
);
421 route_unlock_node(start
);
426 route_unlock_node(start
);
430 /* Unlock current node and lock next node until limit. */
431 struct route_node
*route_next_until(struct route_node
*node
,
432 const struct route_node
*limit
)
434 struct route_node
*next
;
435 struct route_node
*start
;
437 /* Node may be deleted from route_unlock_node so we have to preserve
438 next node's pointer. */
442 route_lock_node(next
);
443 route_unlock_node(node
);
447 next
= node
->l_right
;
448 route_lock_node(next
);
449 route_unlock_node(node
);
454 while (node
->parent
&& node
!= limit
) {
455 if (node
->parent
->l_left
== node
&& node
->parent
->l_right
) {
456 next
= node
->parent
->l_right
;
457 route_lock_node(next
);
458 route_unlock_node(start
);
463 route_unlock_node(start
);
467 unsigned long route_table_count(struct route_table
*table
)
475 * Default function for creating a route node.
477 struct route_node
*route_node_create(route_table_delegate_t
*delegate
,
478 struct route_table
*table
)
480 struct route_node
*node
;
481 node
= XCALLOC(MTYPE_ROUTE_NODE
, sizeof(struct route_node
));
488 * Default function for destroying a route node.
490 void route_node_destroy(route_table_delegate_t
*delegate
,
491 struct route_table
*table
, struct route_node
*node
)
493 XFREE(MTYPE_ROUTE_NODE
, node
);
499 static route_table_delegate_t default_delegate
= {
500 .create_node
= route_node_create
,
501 .destroy_node
= route_node_destroy
};
503 route_table_delegate_t
*route_table_get_default_delegate(void)
505 return &default_delegate
;
511 struct route_table
*route_table_init(void)
513 return route_table_init_with_delegate(&default_delegate
);
517 * route_table_prefix_iter_cmp
519 * Compare two prefixes according to the order in which they appear in
520 * an iteration over a tree.
522 * @return -1 if p1 occurs before p2 (p1 < p2)
523 * 0 if the prefixes are identical (p1 == p2)
524 * +1 if p1 occurs after p2 (p1 > p2)
526 int route_table_prefix_iter_cmp(const struct prefix
*p1
,
527 const struct prefix
*p2
)
529 struct prefix common_space
;
530 struct prefix
*common
= &common_space
;
532 if (p1
->prefixlen
<= p2
->prefixlen
) {
533 if (prefix_match(p1
, p2
)) {
536 * p1 contains p2, or is equal to it.
538 return (p1
->prefixlen
== p2
->prefixlen
) ? 0 : -1;
543 * Check if p2 contains p1.
545 if (prefix_match(p2
, p1
))
549 route_common(p1
, p2
, common
);
550 assert(common
->prefixlen
< p1
->prefixlen
);
551 assert(common
->prefixlen
< p2
->prefixlen
);
554 * Both prefixes are longer than the common prefix.
556 * We need to check the bit after the common prefixlen to determine
557 * which one comes later.
559 if (prefix_bit(&p1
->u
.prefix
, common
->prefixlen
)) {
562 * We branch to the right to get to p1 from the common prefix.
564 assert(!prefix_bit(&p2
->u
.prefix
, common
->prefixlen
));
569 * We branch to the right to get to p2 from the common prefix.
571 assert(prefix_bit(&p2
->u
.prefix
, common
->prefixlen
));
576 * route_get_subtree_next
578 * Helper function that returns the first node that follows the nodes
579 * in the sub-tree under 'node' in iteration order.
581 static struct route_node
*route_get_subtree_next(struct route_node
*node
)
583 while (node
->parent
) {
584 if (node
->parent
->l_left
== node
&& node
->parent
->l_right
)
585 return node
->parent
->l_right
;
594 * route_table_get_next_internal
596 * Helper function to find the node that occurs after the given prefix in
597 * order of iteration.
599 * @see route_table_get_next
601 static struct route_node
*
602 route_table_get_next_internal(struct route_table
*table
,
603 const struct prefix
*p
)
605 struct route_node
*node
, *tmp_node
;
613 if (node
->p
.prefixlen
< p
->prefixlen
)
614 match
= prefix_match(&node
->p
, p
);
616 match
= prefix_match(p
, &node
->p
);
619 if (node
->p
.prefixlen
== p
->prefixlen
) {
622 * The prefix p exists in the tree, just return
626 route_lock_node(node
);
627 node
= route_next(node
);
629 route_unlock_node(node
);
634 if (node
->p
.prefixlen
> p
->prefixlen
) {
637 * Node is in the subtree of p, and hence
644 * p is in the sub-tree under node.
646 tmp_node
= node
->link
[prefix_bit(&p
->u
.prefix
,
655 * There are no nodes in the direction where p should
657 * node has a right child, then it must be greater than
661 return node
->l_right
;
664 * No more children to follow, go upwards looking for
668 return route_get_subtree_next(node
);
672 * Neither node prefix nor 'p' contains the other.
674 cmp
= route_table_prefix_iter_cmp(&node
->p
, p
);
678 * Node follows p in iteration order. Return it.
686 * Node and the subtree under it come before prefix p in
687 * iteration order. Prefix p and its sub-tree are not present in
688 * the tree. Go upwards and find the first node that follows the
689 * subtree. That node will also succeed p.
691 return route_get_subtree_next(node
);
698 * route_table_get_next
700 * Find the node that occurs after the given prefix in order of
703 struct route_node
*route_table_get_next(struct route_table
*table
,
704 union prefixconstptr pu
)
706 const struct prefix
*p
= pu
.p
;
707 struct route_node
*node
;
709 node
= route_table_get_next_internal(table
, p
);
711 assert(route_table_prefix_iter_cmp(&node
->p
, p
) > 0);
712 route_lock_node(node
);
718 * route_table_iter_init
720 void route_table_iter_init(route_table_iter_t
*iter
, struct route_table
*table
)
722 memset(iter
, 0, sizeof(*iter
));
723 iter
->state
= RT_ITER_STATE_INIT
;
728 * route_table_iter_pause
730 * Pause an iteration over the table. This allows the iteration to be
731 * resumed point after arbitrary additions/deletions from the table.
732 * An iteration can be resumed by just calling route_table_iter_next()
735 void route_table_iter_pause(route_table_iter_t
*iter
)
737 switch (iter
->state
) {
739 case RT_ITER_STATE_INIT
:
740 case RT_ITER_STATE_PAUSED
:
741 case RT_ITER_STATE_DONE
:
744 case RT_ITER_STATE_ITERATING
:
747 * Save the prefix that we are currently at. The next call to
748 * route_table_iter_next() will return the node after this
752 prefix_copy(&iter
->pause_prefix
, &iter
->current
->p
);
753 route_unlock_node(iter
->current
);
754 iter
->current
= NULL
;
755 iter
->state
= RT_ITER_STATE_PAUSED
;
764 * route_table_iter_cleanup
766 * Release any resources held by the iterator.
768 void route_table_iter_cleanup(route_table_iter_t
*iter
)
770 if (iter
->state
== RT_ITER_STATE_ITERATING
) {
771 route_unlock_node(iter
->current
);
772 iter
->current
= NULL
;
774 assert(!iter
->current
);
777 * Set the state to RT_ITER_STATE_DONE to make any
778 * route_table_iter_next() calls on this iterator return NULL.
780 iter
->state
= RT_ITER_STATE_DONE
;