Annotation of embedaddon/quagga/lib/table.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Routing Table functions.
3: * Copyright (C) 1998 Kunihiro Ishiguro
4: *
5: * This file is part of GNU Zebra.
6: *
7: * GNU Zebra is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2, or (at your option) any
10: * later version.
11: *
12: * GNU Zebra is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with GNU Zebra; see the file COPYING. If not, write to the Free
19: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20: * 02111-1307, USA.
21: */
22:
23: #include <zebra.h>
24:
25: #include "prefix.h"
26: #include "table.h"
27: #include "memory.h"
28: #include "sockunion.h"
29:
1.1.1.2 misho 30: static void route_node_delete (struct route_node *);
31: static void route_table_free (struct route_table *);
1.1.1.3 ! misho 32:
1.1.1.2 misho 33:
34: /*
35: * route_table_init_with_delegate
36: */
1.1 misho 37: struct route_table *
1.1.1.2 misho 38: route_table_init_with_delegate (route_table_delegate_t *delegate)
1.1 misho 39: {
40: struct route_table *rt;
41:
42: rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table));
1.1.1.2 misho 43: rt->delegate = delegate;
1.1 misho 44: return rt;
45: }
46:
47: void
48: route_table_finish (struct route_table *rt)
49: {
50: route_table_free (rt);
51: }
52:
53: /* Allocate new route node. */
54: static struct route_node *
1.1.1.2 misho 55: route_node_new (struct route_table *table)
1.1 misho 56: {
1.1.1.2 misho 57: return table->delegate->create_node (table->delegate, table);
1.1 misho 58: }
59:
60: /* Allocate new route node with prefix set. */
61: static struct route_node *
1.1.1.3 ! misho 62: route_node_set (struct route_table *table, const struct prefix *prefix)
1.1 misho 63: {
64: struct route_node *node;
65:
1.1.1.2 misho 66: node = route_node_new (table);
1.1 misho 67:
68: prefix_copy (&node->p, prefix);
69: node->table = table;
70:
71: return node;
72: }
73:
74: /* Free route node. */
75: static void
1.1.1.2 misho 76: route_node_free (struct route_table *table, struct route_node *node)
1.1 misho 77: {
1.1.1.2 misho 78: table->delegate->destroy_node (table->delegate, table, node);
1.1 misho 79: }
80:
81: /* Free route table. */
1.1.1.2 misho 82: static void
1.1 misho 83: route_table_free (struct route_table *rt)
84: {
85: struct route_node *tmp_node;
86: struct route_node *node;
87:
88: if (rt == NULL)
89: return;
90:
91: node = rt->top;
92:
1.1.1.2 misho 93: /* Bulk deletion of nodes remaining in this table. This function is not
94: called until workers have completed their dependency on this table.
95: A final route_unlock_node() will not be called for these nodes. */
1.1 misho 96: while (node)
97: {
98: if (node->l_left)
99: {
100: node = node->l_left;
101: continue;
102: }
103:
104: if (node->l_right)
105: {
106: node = node->l_right;
107: continue;
108: }
109:
110: tmp_node = node;
111: node = node->parent;
112:
1.1.1.2 misho 113: tmp_node->table->count--;
114: tmp_node->lock = 0; /* to cause assert if unlocked after this */
115: route_node_free (rt, tmp_node);
116:
1.1 misho 117: if (node != NULL)
118: {
119: if (node->l_left == tmp_node)
120: node->l_left = NULL;
121: else
122: node->l_right = NULL;
123: }
124: else
125: {
126: break;
127: }
128: }
129:
1.1.1.2 misho 130: assert (rt->count == 0);
131:
1.1 misho 132: XFREE (MTYPE_ROUTE_TABLE, rt);
133: return;
134: }
135:
136: /* Utility mask array. */
137: static const u_char maskbit[] =
138: {
139: 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
140: };
141:
142: /* Common prefix route genaration. */
143: static void
1.1.1.3 ! misho 144: route_common (const struct prefix *n, const struct prefix *p, struct prefix *new)
1.1 misho 145: {
146: int i;
147: u_char diff;
148: u_char mask;
149:
1.1.1.3 ! misho 150: const u_char *np = (const u_char *)&n->u.prefix;
! 151: const u_char *pp = (const u_char *)&p->u.prefix;
1.1 misho 152: u_char *newp = (u_char *)&new->u.prefix;
153:
154: for (i = 0; i < p->prefixlen / 8; i++)
155: {
156: if (np[i] == pp[i])
157: newp[i] = np[i];
158: else
159: break;
160: }
161:
162: new->prefixlen = i * 8;
163:
164: if (new->prefixlen != p->prefixlen)
165: {
166: diff = np[i] ^ pp[i];
167: mask = 0x80;
168: while (new->prefixlen < p->prefixlen && !(mask & diff))
169: {
170: mask >>= 1;
171: new->prefixlen++;
172: }
173: newp[i] = np[i] & maskbit[new->prefixlen % 8];
174: }
175: }
176:
177: static void
178: set_link (struct route_node *node, struct route_node *new)
179: {
180: unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen);
181:
182: node->link[bit] = new;
183: new->parent = node;
184: }
185:
186: /* Lock node. */
187: struct route_node *
188: route_lock_node (struct route_node *node)
189: {
190: node->lock++;
191: return node;
192: }
193:
194: /* Unlock node. */
195: void
196: route_unlock_node (struct route_node *node)
197: {
1.1.1.2 misho 198: assert (node->lock > 0);
1.1 misho 199: node->lock--;
200:
201: if (node->lock == 0)
202: route_node_delete (node);
203: }
204:
205: /* Find matched prefix. */
206: struct route_node *
207: route_node_match (const struct route_table *table, const struct prefix *p)
208: {
209: struct route_node *node;
210: struct route_node *matched;
211:
212: matched = NULL;
213: node = table->top;
214:
215: /* Walk down tree. If there is matched route then store it to
216: matched. */
217: while (node && node->p.prefixlen <= p->prefixlen &&
218: prefix_match (&node->p, p))
219: {
220: if (node->info)
221: matched = node;
222:
223: if (node->p.prefixlen == p->prefixlen)
224: break;
225:
226: node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
227: }
228:
229: /* If matched route found, return it. */
230: if (matched)
231: return route_lock_node (matched);
232:
233: return NULL;
234: }
235:
236: struct route_node *
237: route_node_match_ipv4 (const struct route_table *table,
238: const struct in_addr *addr)
239: {
240: struct prefix_ipv4 p;
241:
242: memset (&p, 0, sizeof (struct prefix_ipv4));
243: p.family = AF_INET;
244: p.prefixlen = IPV4_MAX_PREFIXLEN;
245: p.prefix = *addr;
246:
247: return route_node_match (table, (struct prefix *) &p);
248: }
249:
250: #ifdef HAVE_IPV6
251: struct route_node *
252: route_node_match_ipv6 (const struct route_table *table,
253: const struct in6_addr *addr)
254: {
255: struct prefix_ipv6 p;
256:
257: memset (&p, 0, sizeof (struct prefix_ipv6));
258: p.family = AF_INET6;
259: p.prefixlen = IPV6_MAX_PREFIXLEN;
260: p.prefix = *addr;
261:
262: return route_node_match (table, (struct prefix *) &p);
263: }
264: #endif /* HAVE_IPV6 */
265:
266: /* Lookup same prefix node. Return NULL when we can't find route. */
267: struct route_node *
1.1.1.3 ! misho 268: route_node_lookup (const struct route_table *table, const struct prefix *p)
1.1 misho 269: {
270: struct route_node *node;
1.1.1.2 misho 271: u_char prefixlen = p->prefixlen;
272: const u_char *prefix = &p->u.prefix;
1.1 misho 273:
274: node = table->top;
275:
1.1.1.2 misho 276: while (node && node->p.prefixlen <= prefixlen &&
1.1 misho 277: prefix_match (&node->p, p))
278: {
1.1.1.2 misho 279: if (node->p.prefixlen == prefixlen)
1.1 misho 280: return node->info ? route_lock_node (node) : NULL;
281:
1.1.1.2 misho 282: node = node->link[prefix_bit(prefix, node->p.prefixlen)];
1.1 misho 283: }
284:
285: return NULL;
286: }
287:
288: /* Add node to routing table. */
289: struct route_node *
1.1.1.3 ! misho 290: route_node_get (struct route_table *const table, const struct prefix *p)
1.1 misho 291: {
292: struct route_node *new;
293: struct route_node *node;
294: struct route_node *match;
1.1.1.2 misho 295: u_char prefixlen = p->prefixlen;
296: const u_char *prefix = &p->u.prefix;
1.1 misho 297:
298: match = NULL;
299: node = table->top;
1.1.1.2 misho 300: while (node && node->p.prefixlen <= prefixlen &&
1.1 misho 301: prefix_match (&node->p, p))
302: {
1.1.1.2 misho 303: if (node->p.prefixlen == prefixlen)
1.1 misho 304: return route_lock_node (node);
1.1.1.2 misho 305:
1.1 misho 306: match = node;
1.1.1.2 misho 307: node = node->link[prefix_bit(prefix, node->p.prefixlen)];
1.1 misho 308: }
309:
310: if (node == NULL)
311: {
312: new = route_node_set (table, p);
313: if (match)
314: set_link (match, new);
315: else
316: table->top = new;
317: }
318: else
319: {
1.1.1.2 misho 320: new = route_node_new (table);
1.1 misho 321: route_common (&node->p, p, &new->p);
322: new->p.family = p->family;
323: new->table = table;
324: set_link (new, node);
325:
326: if (match)
327: set_link (match, new);
328: else
329: table->top = new;
330:
331: if (new->p.prefixlen != p->prefixlen)
332: {
333: match = new;
334: new = route_node_set (table, p);
335: set_link (match, new);
1.1.1.2 misho 336: table->count++;
1.1 misho 337: }
338: }
1.1.1.2 misho 339: table->count++;
1.1 misho 340: route_lock_node (new);
341:
342: return new;
343: }
344:
345: /* Delete node from the routing table. */
1.1.1.2 misho 346: static void
1.1 misho 347: route_node_delete (struct route_node *node)
348: {
349: struct route_node *child;
350: struct route_node *parent;
351:
352: assert (node->lock == 0);
353: assert (node->info == NULL);
354:
355: if (node->l_left && node->l_right)
356: return;
357:
358: if (node->l_left)
359: child = node->l_left;
360: else
361: child = node->l_right;
362:
363: parent = node->parent;
364:
365: if (child)
366: child->parent = parent;
367:
368: if (parent)
369: {
370: if (parent->l_left == node)
371: parent->l_left = child;
372: else
373: parent->l_right = child;
374: }
375: else
376: node->table->top = child;
377:
1.1.1.2 misho 378: node->table->count--;
379:
380: route_node_free (node->table, node);
1.1 misho 381:
382: /* If parent node is stub then delete it also. */
383: if (parent && parent->lock == 0)
384: route_node_delete (parent);
385: }
386:
387: /* Get fist node and lock it. This function is useful when one want
388: to lookup all the node exist in the routing table. */
389: struct route_node *
390: route_top (struct route_table *table)
391: {
392: /* If there is no node in the routing table return NULL. */
393: if (table->top == NULL)
394: return NULL;
395:
396: /* Lock the top node and return it. */
397: route_lock_node (table->top);
398: return table->top;
399: }
400:
401: /* Unlock current node and lock next node then return it. */
402: struct route_node *
403: route_next (struct route_node *node)
404: {
405: struct route_node *next;
406: struct route_node *start;
407:
408: /* Node may be deleted from route_unlock_node so we have to preserve
409: next node's pointer. */
410:
411: if (node->l_left)
412: {
413: next = node->l_left;
414: route_lock_node (next);
415: route_unlock_node (node);
416: return next;
417: }
418: if (node->l_right)
419: {
420: next = node->l_right;
421: route_lock_node (next);
422: route_unlock_node (node);
423: return next;
424: }
425:
426: start = node;
427: while (node->parent)
428: {
429: if (node->parent->l_left == node && node->parent->l_right)
430: {
431: next = node->parent->l_right;
432: route_lock_node (next);
433: route_unlock_node (start);
434: return next;
435: }
436: node = node->parent;
437: }
438: route_unlock_node (start);
439: return NULL;
440: }
441:
442: /* Unlock current node and lock next node until limit. */
443: struct route_node *
444: route_next_until (struct route_node *node, struct route_node *limit)
445: {
446: struct route_node *next;
447: struct route_node *start;
448:
449: /* Node may be deleted from route_unlock_node so we have to preserve
450: next node's pointer. */
451:
452: if (node->l_left)
453: {
454: next = node->l_left;
455: route_lock_node (next);
456: route_unlock_node (node);
457: return next;
458: }
459: if (node->l_right)
460: {
461: next = node->l_right;
462: route_lock_node (next);
463: route_unlock_node (node);
464: return next;
465: }
466:
467: start = node;
468: while (node->parent && node != limit)
469: {
470: if (node->parent->l_left == node && node->parent->l_right)
471: {
472: next = node->parent->l_right;
473: route_lock_node (next);
474: route_unlock_node (start);
475: return next;
476: }
477: node = node->parent;
478: }
479: route_unlock_node (start);
480: return NULL;
481: }
1.1.1.2 misho 482:
483: unsigned long
484: route_table_count (const struct route_table *table)
485: {
486: return table->count;
487: }
488:
489: /**
490: * route_node_create
491: *
492: * Default function for creating a route node.
493: */
494: static struct route_node *
495: route_node_create (route_table_delegate_t *delegate,
496: struct route_table *table)
497: {
498: struct route_node *node;
499: node = XCALLOC (MTYPE_ROUTE_NODE, sizeof (struct route_node));
500: return node;
501: }
502:
503: /**
504: * route_node_destroy
505: *
506: * Default function for destroying a route node.
507: */
508: static void
509: route_node_destroy (route_table_delegate_t *delegate,
510: struct route_table *table, struct route_node *node)
511: {
512: XFREE (MTYPE_ROUTE_NODE, node);
513: }
514:
515: /*
516: * Default delegate.
517: */
518: static route_table_delegate_t default_delegate = {
519: .create_node = route_node_create,
520: .destroy_node = route_node_destroy
521: };
522:
523: /*
524: * route_table_init
525: */
526: struct route_table *
527: route_table_init (void)
528: {
529: return route_table_init_with_delegate (&default_delegate);
530: }
531:
532: /**
533: * route_table_prefix_iter_cmp
534: *
535: * Compare two prefixes according to the order in which they appear in
536: * an iteration over a tree.
537: *
538: * @return -1 if p1 occurs before p2 (p1 < p2)
539: * 0 if the prefixes are identical (p1 == p2)
540: * +1 if p1 occurs after p2 (p1 > p2)
541: */
542: int
543: route_table_prefix_iter_cmp (struct prefix *p1, struct prefix *p2)
544: {
545: struct prefix common_space;
546: struct prefix *common = &common_space;
547:
548: if (p1->prefixlen <= p2->prefixlen)
549: {
550: if (prefix_match (p1, p2))
551: {
552:
553: /*
554: * p1 contains p2, or is equal to it.
555: */
556: return (p1->prefixlen == p2->prefixlen) ? 0 : -1;
557: }
558: }
559: else
560: {
561:
562: /*
563: * Check if p2 contains p1.
564: */
565: if (prefix_match (p2, p1))
566: return 1;
567: }
568:
569: route_common (p1, p2, common);
570: assert (common->prefixlen < p1->prefixlen);
571: assert (common->prefixlen < p2->prefixlen);
572:
573: /*
574: * Both prefixes are longer than the common prefix.
575: *
576: * We need to check the bit after the common prefixlen to determine
577: * which one comes later.
578: */
579: if (prefix_bit (&p1->u.prefix, common->prefixlen))
580: {
581:
582: /*
583: * We branch to the right to get to p1 from the common prefix.
584: */
585: assert (!prefix_bit (&p2->u.prefix, common->prefixlen));
586: return 1;
587: }
588:
589: /*
590: * We branch to the right to get to p2 from the common prefix.
591: */
592: assert (prefix_bit (&p2->u.prefix, common->prefixlen));
593: return -1;
594: }
595:
596: /*
597: * route_get_subtree_next
598: *
599: * Helper function that returns the first node that follows the nodes
600: * in the sub-tree under 'node' in iteration order.
601: */
602: static struct route_node *
603: route_get_subtree_next (struct route_node *node)
604: {
605: while (node->parent)
606: {
607: if (node->parent->l_left == node && node->parent->l_right)
608: return node->parent->l_right;
609:
610: node = node->parent;
611: }
612:
613: return NULL;
614: }
615:
616: /**
617: * route_table_get_next_internal
618: *
619: * Helper function to find the node that occurs after the given prefix in
620: * order of iteration.
621: *
622: * @see route_table_get_next
623: */
624: static struct route_node *
625: route_table_get_next_internal (const struct route_table *table,
626: struct prefix *p)
627: {
628: struct route_node *node, *tmp_node;
629: int cmp;
630:
631: node = table->top;
632:
633: while (node)
634: {
635: int match;
636:
637: if (node->p.prefixlen < p->prefixlen)
638: match = prefix_match (&node->p, p);
639: else
640: match = prefix_match (p, &node->p);
641:
642: if (match)
643: {
644: if (node->p.prefixlen == p->prefixlen)
645: {
646:
647: /*
648: * The prefix p exists in the tree, just return the next
649: * node.
650: */
651: route_lock_node (node);
652: node = route_next (node);
653: if (node)
654: route_unlock_node (node);
655:
656: return (node);
657: }
658:
659: if (node->p.prefixlen > p->prefixlen)
660: {
661:
662: /*
663: * Node is in the subtree of p, and hence greater than p.
664: */
665: return node;
666: }
667:
668: /*
669: * p is in the sub-tree under node.
670: */
671: tmp_node = node->link[prefix_bit (&p->u.prefix, node->p.prefixlen)];
672:
673: if (tmp_node)
674: {
675: node = tmp_node;
676: continue;
677: }
678:
679: /*
680: * There are no nodes in the direction where p should be. If
681: * node has a right child, then it must be greater than p.
682: */
683: if (node->l_right)
684: return node->l_right;
685:
686: /*
687: * No more children to follow, go upwards looking for the next
688: * node.
689: */
690: return route_get_subtree_next (node);
691: }
692:
693: /*
694: * Neither node prefix nor 'p' contains the other.
695: */
696: cmp = route_table_prefix_iter_cmp (&node->p, p);
697: if (cmp > 0)
698: {
699:
700: /*
701: * Node follows p in iteration order. Return it.
702: */
703: return node;
704: }
705:
706: assert (cmp < 0);
707:
708: /*
709: * Node and the subtree under it come before prefix p in
710: * iteration order. Prefix p and its sub-tree are not present in
711: * the tree. Go upwards and find the first node that follows the
712: * subtree. That node will also succeed p.
713: */
714: return route_get_subtree_next (node);
715: }
716:
717: return NULL;
718: }
719:
720: /**
721: * route_table_get_next
722: *
723: * Find the node that occurs after the given prefix in order of
724: * iteration.
725: */
726: struct route_node *
727: route_table_get_next (const struct route_table *table, struct prefix *p)
728: {
729: struct route_node *node;
730:
731: node = route_table_get_next_internal (table, p);
732: if (node)
733: {
734: assert (route_table_prefix_iter_cmp (&node->p, p) > 0);
735: route_lock_node (node);
736: }
737: return node;
738: }
739:
740: /*
741: * route_table_iter_init
742: */
743: void
744: route_table_iter_init (route_table_iter_t * iter, struct route_table *table)
745: {
746: memset (iter, 0, sizeof (*iter));
747: iter->state = RT_ITER_STATE_INIT;
748: iter->table = table;
749: }
750:
751: /*
752: * route_table_iter_pause
753: *
754: * Pause an iteration over the table. This allows the iteration to be
755: * resumed point after arbitrary additions/deletions from the table.
756: * An iteration can be resumed by just calling route_table_iter_next()
757: * on the iterator.
758: */
759: void
760: route_table_iter_pause (route_table_iter_t * iter)
761: {
762: switch (iter->state)
763: {
764:
765: case RT_ITER_STATE_INIT:
766: case RT_ITER_STATE_PAUSED:
767: case RT_ITER_STATE_DONE:
768: return;
769:
770: case RT_ITER_STATE_ITERATING:
771:
772: /*
773: * Save the prefix that we are currently at. The next call to
774: * route_table_iter_next() will return the node after this prefix
775: * in the tree.
776: */
777: prefix_copy (&iter->pause_prefix, &iter->current->p);
778: route_unlock_node (iter->current);
779: iter->current = NULL;
780: iter->state = RT_ITER_STATE_PAUSED;
781: return;
782:
783: default:
784: assert (0);
785: }
786:
787: }
788:
789: /*
790: * route_table_iter_cleanup
791: *
792: * Release any resources held by the iterator.
793: */
794: void
795: route_table_iter_cleanup (route_table_iter_t * iter)
796: {
797: if (iter->state == RT_ITER_STATE_ITERATING)
798: {
799: route_unlock_node (iter->current);
800: iter->current = NULL;
801: }
802: assert (!iter->current);
803:
804: /*
805: * Set the state to RT_ITER_STATE_DONE to make any
806: * route_table_iter_next() calls on this iterator return NULL.
807: */
808: iter->state = RT_ITER_STATE_DONE;
809: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>