Annotation of embedaddon/quagga/lib/table.c, revision 1.1.1.1
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:
30: void route_node_delete (struct route_node *);
31: void route_table_free (struct route_table *);
32:
33: struct route_table *
34: route_table_init (void)
35: {
36: struct route_table *rt;
37:
38: rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table));
39: return rt;
40: }
41:
42: void
43: route_table_finish (struct route_table *rt)
44: {
45: route_table_free (rt);
46: }
47:
48: /* Allocate new route node. */
49: static struct route_node *
50: route_node_new (void)
51: {
52: struct route_node *node;
53: node = XCALLOC (MTYPE_ROUTE_NODE, sizeof (struct route_node));
54: return node;
55: }
56:
57: /* Allocate new route node with prefix set. */
58: static struct route_node *
59: route_node_set (struct route_table *table, struct prefix *prefix)
60: {
61: struct route_node *node;
62:
63: node = route_node_new ();
64:
65: prefix_copy (&node->p, prefix);
66: node->table = table;
67:
68: return node;
69: }
70:
71: /* Free route node. */
72: static void
73: route_node_free (struct route_node *node)
74: {
75: XFREE (MTYPE_ROUTE_NODE, node);
76: }
77:
78: /* Free route table. */
79: void
80: route_table_free (struct route_table *rt)
81: {
82: struct route_node *tmp_node;
83: struct route_node *node;
84:
85: if (rt == NULL)
86: return;
87:
88: node = rt->top;
89:
90: while (node)
91: {
92: if (node->l_left)
93: {
94: node = node->l_left;
95: continue;
96: }
97:
98: if (node->l_right)
99: {
100: node = node->l_right;
101: continue;
102: }
103:
104: tmp_node = node;
105: node = node->parent;
106:
107: if (node != NULL)
108: {
109: if (node->l_left == tmp_node)
110: node->l_left = NULL;
111: else
112: node->l_right = NULL;
113:
114: route_node_free (tmp_node);
115: }
116: else
117: {
118: route_node_free (tmp_node);
119: break;
120: }
121: }
122:
123: XFREE (MTYPE_ROUTE_TABLE, rt);
124: return;
125: }
126:
127: /* Utility mask array. */
128: static const u_char maskbit[] =
129: {
130: 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
131: };
132:
133: /* Common prefix route genaration. */
134: static void
135: route_common (struct prefix *n, struct prefix *p, struct prefix *new)
136: {
137: int i;
138: u_char diff;
139: u_char mask;
140:
141: u_char *np = (u_char *)&n->u.prefix;
142: u_char *pp = (u_char *)&p->u.prefix;
143: u_char *newp = (u_char *)&new->u.prefix;
144:
145: for (i = 0; i < p->prefixlen / 8; i++)
146: {
147: if (np[i] == pp[i])
148: newp[i] = np[i];
149: else
150: break;
151: }
152:
153: new->prefixlen = i * 8;
154:
155: if (new->prefixlen != p->prefixlen)
156: {
157: diff = np[i] ^ pp[i];
158: mask = 0x80;
159: while (new->prefixlen < p->prefixlen && !(mask & diff))
160: {
161: mask >>= 1;
162: new->prefixlen++;
163: }
164: newp[i] = np[i] & maskbit[new->prefixlen % 8];
165: }
166: }
167:
168: static void
169: set_link (struct route_node *node, struct route_node *new)
170: {
171: unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen);
172:
173: node->link[bit] = new;
174: new->parent = node;
175: }
176:
177: /* Lock node. */
178: struct route_node *
179: route_lock_node (struct route_node *node)
180: {
181: node->lock++;
182: return node;
183: }
184:
185: /* Unlock node. */
186: void
187: route_unlock_node (struct route_node *node)
188: {
189: node->lock--;
190:
191: if (node->lock == 0)
192: route_node_delete (node);
193: }
194:
195: /* Find matched prefix. */
196: struct route_node *
197: route_node_match (const struct route_table *table, const struct prefix *p)
198: {
199: struct route_node *node;
200: struct route_node *matched;
201:
202: matched = NULL;
203: node = table->top;
204:
205: /* Walk down tree. If there is matched route then store it to
206: matched. */
207: while (node && node->p.prefixlen <= p->prefixlen &&
208: prefix_match (&node->p, p))
209: {
210: if (node->info)
211: matched = node;
212:
213: if (node->p.prefixlen == p->prefixlen)
214: break;
215:
216: node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
217: }
218:
219: /* If matched route found, return it. */
220: if (matched)
221: return route_lock_node (matched);
222:
223: return NULL;
224: }
225:
226: struct route_node *
227: route_node_match_ipv4 (const struct route_table *table,
228: const struct in_addr *addr)
229: {
230: struct prefix_ipv4 p;
231:
232: memset (&p, 0, sizeof (struct prefix_ipv4));
233: p.family = AF_INET;
234: p.prefixlen = IPV4_MAX_PREFIXLEN;
235: p.prefix = *addr;
236:
237: return route_node_match (table, (struct prefix *) &p);
238: }
239:
240: #ifdef HAVE_IPV6
241: struct route_node *
242: route_node_match_ipv6 (const struct route_table *table,
243: const struct in6_addr *addr)
244: {
245: struct prefix_ipv6 p;
246:
247: memset (&p, 0, sizeof (struct prefix_ipv6));
248: p.family = AF_INET6;
249: p.prefixlen = IPV6_MAX_PREFIXLEN;
250: p.prefix = *addr;
251:
252: return route_node_match (table, (struct prefix *) &p);
253: }
254: #endif /* HAVE_IPV6 */
255:
256: /* Lookup same prefix node. Return NULL when we can't find route. */
257: struct route_node *
258: route_node_lookup (struct route_table *table, struct prefix *p)
259: {
260: struct route_node *node;
261:
262: node = table->top;
263:
264: while (node && node->p.prefixlen <= p->prefixlen &&
265: prefix_match (&node->p, p))
266: {
267: if (node->p.prefixlen == p->prefixlen)
268: return node->info ? route_lock_node (node) : NULL;
269:
270: node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
271: }
272:
273: return NULL;
274: }
275:
276: /* Add node to routing table. */
277: struct route_node *
278: route_node_get (struct route_table *table, struct prefix *p)
279: {
280: struct route_node *new;
281: struct route_node *node;
282: struct route_node *match;
283:
284: match = NULL;
285: node = table->top;
286: while (node && node->p.prefixlen <= p->prefixlen &&
287: prefix_match (&node->p, p))
288: {
289: if (node->p.prefixlen == p->prefixlen)
290: return route_lock_node (node);
291:
292: match = node;
293: node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
294: }
295:
296: if (node == NULL)
297: {
298: new = route_node_set (table, p);
299: if (match)
300: set_link (match, new);
301: else
302: table->top = new;
303: }
304: else
305: {
306: new = route_node_new ();
307: route_common (&node->p, p, &new->p);
308: new->p.family = p->family;
309: new->table = table;
310: set_link (new, node);
311:
312: if (match)
313: set_link (match, new);
314: else
315: table->top = new;
316:
317: if (new->p.prefixlen != p->prefixlen)
318: {
319: match = new;
320: new = route_node_set (table, p);
321: set_link (match, new);
322: }
323: }
324: route_lock_node (new);
325:
326: return new;
327: }
328:
329: /* Delete node from the routing table. */
330: void
331: route_node_delete (struct route_node *node)
332: {
333: struct route_node *child;
334: struct route_node *parent;
335:
336: assert (node->lock == 0);
337: assert (node->info == NULL);
338:
339: if (node->l_left && node->l_right)
340: return;
341:
342: if (node->l_left)
343: child = node->l_left;
344: else
345: child = node->l_right;
346:
347: parent = node->parent;
348:
349: if (child)
350: child->parent = parent;
351:
352: if (parent)
353: {
354: if (parent->l_left == node)
355: parent->l_left = child;
356: else
357: parent->l_right = child;
358: }
359: else
360: node->table->top = child;
361:
362: route_node_free (node);
363:
364: /* If parent node is stub then delete it also. */
365: if (parent && parent->lock == 0)
366: route_node_delete (parent);
367: }
368:
369: /* Get fist node and lock it. This function is useful when one want
370: to lookup all the node exist in the routing table. */
371: struct route_node *
372: route_top (struct route_table *table)
373: {
374: /* If there is no node in the routing table return NULL. */
375: if (table->top == NULL)
376: return NULL;
377:
378: /* Lock the top node and return it. */
379: route_lock_node (table->top);
380: return table->top;
381: }
382:
383: /* Unlock current node and lock next node then return it. */
384: struct route_node *
385: route_next (struct route_node *node)
386: {
387: struct route_node *next;
388: struct route_node *start;
389:
390: /* Node may be deleted from route_unlock_node so we have to preserve
391: next node's pointer. */
392:
393: if (node->l_left)
394: {
395: next = node->l_left;
396: route_lock_node (next);
397: route_unlock_node (node);
398: return next;
399: }
400: if (node->l_right)
401: {
402: next = node->l_right;
403: route_lock_node (next);
404: route_unlock_node (node);
405: return next;
406: }
407:
408: start = node;
409: while (node->parent)
410: {
411: if (node->parent->l_left == node && node->parent->l_right)
412: {
413: next = node->parent->l_right;
414: route_lock_node (next);
415: route_unlock_node (start);
416: return next;
417: }
418: node = node->parent;
419: }
420: route_unlock_node (start);
421: return NULL;
422: }
423:
424: /* Unlock current node and lock next node until limit. */
425: struct route_node *
426: route_next_until (struct route_node *node, struct route_node *limit)
427: {
428: struct route_node *next;
429: struct route_node *start;
430:
431: /* Node may be deleted from route_unlock_node so we have to preserve
432: next node's pointer. */
433:
434: if (node->l_left)
435: {
436: next = node->l_left;
437: route_lock_node (next);
438: route_unlock_node (node);
439: return next;
440: }
441: if (node->l_right)
442: {
443: next = node->l_right;
444: route_lock_node (next);
445: route_unlock_node (node);
446: return next;
447: }
448:
449: start = node;
450: while (node->parent && node != limit)
451: {
452: if (node->parent->l_left == node && node->parent->l_right)
453: {
454: next = node->parent->l_right;
455: route_lock_node (next);
456: route_unlock_node (start);
457: return next;
458: }
459: node = node->parent;
460: }
461: route_unlock_node (start);
462: return NULL;
463: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>