blob: 6bbc9c621c495e58c1cf3d4ba4975b2b87765672 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
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
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -070030static void route_node_delete (struct route_node *);
31static void route_table_free (struct route_table *);
paul718e3742002-12-13 20:15:29 +000032
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070033
34/*
35 * route_table_init_with_delegate
36 */
paul718e3742002-12-13 20:15:29 +000037struct route_table *
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070038route_table_init_with_delegate (route_table_delegate_t *delegate)
paul718e3742002-12-13 20:15:29 +000039{
40 struct route_table *rt;
41
42 rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table));
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070043 rt->delegate = delegate;
paul718e3742002-12-13 20:15:29 +000044 return rt;
45}
46
47void
48route_table_finish (struct route_table *rt)
49{
50 route_table_free (rt);
51}
52
53/* Allocate new route node. */
paul8cc41982005-05-06 21:25:49 +000054static struct route_node *
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070055route_node_new (struct route_table *table)
paul718e3742002-12-13 20:15:29 +000056{
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070057 return table->delegate->create_node (table->delegate, table);
paul718e3742002-12-13 20:15:29 +000058}
59
60/* Allocate new route node with prefix set. */
paul8cc41982005-05-06 21:25:49 +000061static struct route_node *
paul718e3742002-12-13 20:15:29 +000062route_node_set (struct route_table *table, struct prefix *prefix)
63{
64 struct route_node *node;
65
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070066 node = route_node_new (table);
paul718e3742002-12-13 20:15:29 +000067
68 prefix_copy (&node->p, prefix);
69 node->table = table;
70
71 return node;
72}
73
74/* Free route node. */
paul8cc41982005-05-06 21:25:49 +000075static void
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070076route_node_free (struct route_table *table, struct route_node *node)
paul718e3742002-12-13 20:15:29 +000077{
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -070078 table->delegate->destroy_node (table->delegate, table, node);
paul718e3742002-12-13 20:15:29 +000079}
80
81/* Free route table. */
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -070082static void
paul718e3742002-12-13 20:15:29 +000083route_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
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -070093 /* 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. */
paul718e3742002-12-13 20:15:29 +000096 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
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700113 tmp_node->table->count--;
114 tmp_node->lock = 0; /* to cause assert if unlocked after this */
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -0700115 route_node_free (rt, tmp_node);
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700116
paul718e3742002-12-13 20:15:29 +0000117 if (node != NULL)
118 {
119 if (node->l_left == tmp_node)
120 node->l_left = NULL;
121 else
122 node->l_right = NULL;
paul718e3742002-12-13 20:15:29 +0000123 }
124 else
125 {
paul718e3742002-12-13 20:15:29 +0000126 break;
127 }
128 }
129
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700130 assert (rt->count == 0);
131
paul718e3742002-12-13 20:15:29 +0000132 XFREE (MTYPE_ROUTE_TABLE, rt);
133 return;
134}
135
136/* Utility mask array. */
Stephen Hemminger38cc00c2009-12-08 12:00:50 +0300137static const u_char maskbit[] =
paul718e3742002-12-13 20:15:29 +0000138{
139 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
140};
141
142/* Common prefix route genaration. */
143static void
144route_common (struct prefix *n, struct prefix *p, struct prefix *new)
145{
146 int i;
147 u_char diff;
148 u_char mask;
149
150 u_char *np = (u_char *)&n->u.prefix;
151 u_char *pp = (u_char *)&p->u.prefix;
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
paul718e3742002-12-13 20:15:29 +0000177static void
178set_link (struct route_node *node, struct route_node *new)
179{
Stephen Hemminger1352ef32009-12-09 14:43:17 +0300180 unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen);
paul718e3742002-12-13 20:15:29 +0000181
182 node->link[bit] = new;
183 new->parent = node;
184}
185
186/* Lock node. */
187struct route_node *
188route_lock_node (struct route_node *node)
189{
190 node->lock++;
191 return node;
192}
193
194/* Unlock node. */
195void
196route_unlock_node (struct route_node *node)
197{
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700198 assert (node->lock > 0);
paul718e3742002-12-13 20:15:29 +0000199 node->lock--;
200
201 if (node->lock == 0)
202 route_node_delete (node);
203}
204
paul718e3742002-12-13 20:15:29 +0000205/* Find matched prefix. */
206struct route_node *
Stephen Hemminger38cc00c2009-12-08 12:00:50 +0300207route_node_match (const struct route_table *table, const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000208{
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;
Paul Jakmaf8416812010-04-13 22:42:33 +0100222
223 if (node->p.prefixlen == p->prefixlen)
224 break;
225
Stephen Hemminger1352ef32009-12-09 14:43:17 +0300226 node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
paul718e3742002-12-13 20:15:29 +0000227 }
228
229 /* If matched route found, return it. */
230 if (matched)
231 return route_lock_node (matched);
232
233 return NULL;
234}
235
236struct route_node *
Stephen Hemminger38cc00c2009-12-08 12:00:50 +0300237route_node_match_ipv4 (const struct route_table *table,
238 const struct in_addr *addr)
paul718e3742002-12-13 20:15:29 +0000239{
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
251struct route_node *
Stephen Hemminger38cc00c2009-12-08 12:00:50 +0300252route_node_match_ipv6 (const struct route_table *table,
253 const struct in6_addr *addr)
paul718e3742002-12-13 20:15:29 +0000254{
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. */
267struct route_node *
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700268route_node_lookup (const struct route_table *table, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000269{
270 struct route_node *node;
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000271 u_char prefixlen = p->prefixlen;
272 const u_char *prefix = &p->u.prefix;
paul718e3742002-12-13 20:15:29 +0000273
274 node = table->top;
275
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000276 while (node && node->p.prefixlen <= prefixlen &&
paul718e3742002-12-13 20:15:29 +0000277 prefix_match (&node->p, p))
278 {
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000279 if (node->p.prefixlen == prefixlen)
Paul Jakmaf8416812010-04-13 22:42:33 +0100280 return node->info ? route_lock_node (node) : NULL;
paul718e3742002-12-13 20:15:29 +0000281
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000282 node = node->link[prefix_bit(prefix, node->p.prefixlen)];
paul718e3742002-12-13 20:15:29 +0000283 }
284
285 return NULL;
286}
287
288/* Add node to routing table. */
289struct route_node *
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700290route_node_get (struct route_table *const table, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000291{
292 struct route_node *new;
293 struct route_node *node;
294 struct route_node *match;
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000295 u_char prefixlen = p->prefixlen;
296 const u_char *prefix = &p->u.prefix;
paul718e3742002-12-13 20:15:29 +0000297
298 match = NULL;
299 node = table->top;
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000300 while (node && node->p.prefixlen <= prefixlen &&
paul718e3742002-12-13 20:15:29 +0000301 prefix_match (&node->p, p))
302 {
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000303 if (node->p.prefixlen == prefixlen)
Paul Jakmaf8416812010-04-13 22:42:33 +0100304 return route_lock_node (node);
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000305
paul718e3742002-12-13 20:15:29 +0000306 match = node;
Jorge Boncompte [DTI2]47d3b602012-05-07 16:53:11 +0000307 node = node->link[prefix_bit(prefix, node->p.prefixlen)];
paul718e3742002-12-13 20:15:29 +0000308 }
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 {
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -0700320 new = route_node_new (table);
paul718e3742002-12-13 20:15:29 +0000321 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);
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700336 table->count++;
paul718e3742002-12-13 20:15:29 +0000337 }
338 }
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700339 table->count++;
paul718e3742002-12-13 20:15:29 +0000340 route_lock_node (new);
341
342 return new;
343}
344
345/* Delete node from the routing table. */
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700346static void
paul718e3742002-12-13 20:15:29 +0000347route_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
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700378 node->table->count--;
379
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -0700380 route_node_free (node->table, node);
paul718e3742002-12-13 20:15:29 +0000381
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. */
389struct route_node *
390route_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. */
402struct route_node *
403route_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. */
443struct route_node *
444route_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}
Avneesh Sachdev3eb8ef32012-08-17 08:19:47 -0700482
483unsigned long
484route_table_count (const struct route_table *table)
485{
486 return table->count;
487}
Avneesh Sachdevf9c1b7b2012-08-17 08:19:48 -0700488
489/**
490 * route_node_create
491 *
492 * Default function for creating a route node.
493 */
494static struct route_node *
495route_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 */
508static void
509route_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 */
518static 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 */
526struct route_table *
527route_table_init (void)
528{
529 return route_table_init_with_delegate (&default_delegate);
530}