]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_table.c
2005-06-28 Paul Jakma <paul.jakma@sun.com>
[mirror_frr.git] / bgpd / bgp_table.c
CommitLineData
718e3744 1/* BGP routing table
2 Copyright (C) 1998, 2001 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "memory.h"
25#include "sockunion.h"
26#include "vty.h"
27
28#include "bgpd/bgpd.h"
29#include "bgpd/bgp_table.h"
30
31void bgp_node_delete (struct bgp_node *);
32void bgp_table_free (struct bgp_table *);
33\f
34struct bgp_table *
35bgp_table_init (void)
36{
37 struct bgp_table *rt;
38
39 rt = XMALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
40 memset (rt, 0, sizeof (struct bgp_table));
fee0f4c6 41
42 rt->type = BGP_TABLE_MAIN;
43
718e3744 44 return rt;
45}
46
47void
48bgp_table_finish (struct bgp_table *rt)
49{
50 bgp_table_free (rt);
51}
52
53struct bgp_node *
54bgp_node_create ()
55{
56 struct bgp_node *rn;
57
58 rn = (struct bgp_node *) XMALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node));
59 memset (rn, 0, sizeof (struct bgp_node));
60 return rn;
61}
62
63/* Allocate new route node with prefix set. */
64struct bgp_node *
65bgp_node_set (struct bgp_table *table, struct prefix *prefix)
66{
67 struct bgp_node *node;
68
69 node = bgp_node_create ();
70
71 prefix_copy (&node->p, prefix);
72 node->table = table;
73
74 return node;
75}
76
77/* Free route node. */
78void
79bgp_node_free (struct bgp_node *node)
80{
81 XFREE (MTYPE_BGP_NODE, node);
82}
83
84/* Free route table. */
85void
86bgp_table_free (struct bgp_table *rt)
87{
88 struct bgp_node *tmp_node;
89 struct bgp_node *node;
90
91 if (rt == NULL)
92 return;
93
94 node = rt->top;
95
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
113 if (node != NULL)
114 {
115 if (node->l_left == tmp_node)
116 node->l_left = NULL;
117 else
118 node->l_right = NULL;
119
120 bgp_node_free (tmp_node);
121 }
122 else
123 {
124 bgp_node_free (tmp_node);
125 break;
126 }
127 }
128
129 XFREE (MTYPE_BGP_TABLE, rt);
130 return;
131}
132
133/* Utility mask array. */
134static u_char maskbit[] =
135{
136 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
137};
138
139/* Common prefix route genaration. */
140static void
141route_common (struct prefix *n, struct prefix *p, struct prefix *new)
142{
143 int i;
144 u_char diff;
145 u_char mask;
146
147 u_char *np = (u_char *)&n->u.prefix;
148 u_char *pp = (u_char *)&p->u.prefix;
149 u_char *newp = (u_char *)&new->u.prefix;
150
151 for (i = 0; i < p->prefixlen / 8; i++)
152 {
153 if (np[i] == pp[i])
154 newp[i] = np[i];
155 else
156 break;
157 }
158
159 new->prefixlen = i * 8;
160
161 if (new->prefixlen != p->prefixlen)
162 {
163 diff = np[i] ^ pp[i];
164 mask = 0x80;
165 while (new->prefixlen < p->prefixlen && !(mask & diff))
166 {
167 mask >>= 1;
168 new->prefixlen++;
169 }
170 newp[i] = np[i] & maskbit[new->prefixlen % 8];
171 }
172}
173
174/* Macro version of check_bit (). */
175#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
176
177/* Check bit of the prefix. */
178static int
179check_bit (u_char *prefix, u_char prefixlen)
180{
181 int offset;
182 int shift;
183 u_char *p = (u_char *)prefix;
184
185 assert (prefixlen <= 128);
186
187 offset = prefixlen / 8;
188 shift = 7 - (prefixlen % 8);
189
190 return (p[offset] >> shift & 1);
191}
192
193/* Macro version of set_link (). */
194#define SET_LINK(X,Y) (X)->link[CHECK_BIT(&(Y)->prefix,(X)->prefixlen)] = (Y);\
195 (Y)->parent = (X)
196
197static void
198set_link (struct bgp_node *node, struct bgp_node *new)
199{
200 int bit;
201
202 bit = check_bit (&new->p.u.prefix, node->p.prefixlen);
203
204 assert (bit == 0 || bit == 1);
205
206 node->link[bit] = new;
207 new->parent = node;
208}
209
210/* Lock node. */
211struct bgp_node *
212bgp_lock_node (struct bgp_node *node)
213{
214 node->lock++;
215 return node;
216}
217
218/* Unlock node. */
219void
220bgp_unlock_node (struct bgp_node *node)
221{
222 node->lock--;
223
224 if (node->lock == 0)
225 bgp_node_delete (node);
226}
227
228/* Find matched prefix. */
229struct bgp_node *
230bgp_node_match (struct bgp_table *table, struct prefix *p)
231{
232 struct bgp_node *node;
233 struct bgp_node *matched;
234
235 matched = NULL;
236 node = table->top;
237
238 /* Walk down tree. If there is matched route then store it to
239 matched. */
240 while (node && node->p.prefixlen <= p->prefixlen &&
241 prefix_match (&node->p, p))
242 {
243 if (node->info)
244 matched = node;
245 node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
246 }
247
248 /* If matched route found, return it. */
249 if (matched)
250 return bgp_lock_node (matched);
251
252 return NULL;
253}
254
255struct bgp_node *
256bgp_node_match_ipv4 (struct bgp_table *table, struct in_addr *addr)
257{
258 struct prefix_ipv4 p;
259
260 memset (&p, 0, sizeof (struct prefix_ipv4));
261 p.family = AF_INET;
262 p.prefixlen = IPV4_MAX_PREFIXLEN;
263 p.prefix = *addr;
264
265 return bgp_node_match (table, (struct prefix *) &p);
266}
267
268#ifdef HAVE_IPV6
269struct bgp_node *
270bgp_node_match_ipv6 (struct bgp_table *table, struct in6_addr *addr)
271{
272 struct prefix_ipv6 p;
273
274 memset (&p, 0, sizeof (struct prefix_ipv6));
275 p.family = AF_INET6;
276 p.prefixlen = IPV6_MAX_PREFIXLEN;
277 p.prefix = *addr;
278
279 return bgp_node_match (table, (struct prefix *) &p);
280}
281#endif /* HAVE_IPV6 */
282
283/* Lookup same prefix node. Return NULL when we can't find route. */
284struct bgp_node *
285bgp_node_lookup (struct bgp_table *table, struct prefix *p)
286{
287 struct bgp_node *node;
288
289 node = table->top;
290
291 while (node && node->p.prefixlen <= p->prefixlen &&
292 prefix_match (&node->p, p))
293 {
294 if (node->p.prefixlen == p->prefixlen && node->info)
295 return bgp_lock_node (node);
296
297 node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
298 }
299
300 return NULL;
301}
302
303/* Add node to routing table. */
304struct bgp_node *
305bgp_node_get (struct bgp_table *table, struct prefix *p)
306{
307 struct bgp_node *new;
308 struct bgp_node *node;
309 struct bgp_node *match;
310
311 match = NULL;
312 node = table->top;
313 while (node && node->p.prefixlen <= p->prefixlen &&
314 prefix_match (&node->p, p))
315 {
316 if (node->p.prefixlen == p->prefixlen)
317 {
318 bgp_lock_node (node);
319 return node;
320 }
321 match = node;
322 node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
323 }
324
325 if (node == NULL)
326 {
327 new = bgp_node_set (table, p);
328 if (match)
329 set_link (match, new);
330 else
331 table->top = new;
332 }
333 else
334 {
335 new = bgp_node_create ();
336 route_common (&node->p, p, &new->p);
337 new->p.family = p->family;
338 new->table = table;
339 set_link (new, node);
340
341 if (match)
342 set_link (match, new);
343 else
344 table->top = new;
345
346 if (new->p.prefixlen != p->prefixlen)
347 {
348 match = new;
349 new = bgp_node_set (table, p);
350 set_link (match, new);
351 }
352 }
353 bgp_lock_node (new);
354
355 return new;
356}
357
358/* Delete node from the routing table. */
359void
360bgp_node_delete (struct bgp_node *node)
361{
362 struct bgp_node *child;
363 struct bgp_node *parent;
364
365 assert (node->lock == 0);
366 assert (node->info == NULL);
367
368 if (node->l_left && node->l_right)
369 return;
370
371 if (node->l_left)
372 child = node->l_left;
373 else
374 child = node->l_right;
375
376 parent = node->parent;
377
378 if (child)
379 child->parent = parent;
380
381 if (parent)
382 {
383 if (parent->l_left == node)
384 parent->l_left = child;
385 else
386 parent->l_right = child;
387 }
388 else
389 node->table->top = child;
390
391 bgp_node_free (node);
392
393 /* If parent node is stub then delete it also. */
394 if (parent && parent->lock == 0)
395 bgp_node_delete (parent);
396}
397
398/* Get fist node and lock it. This function is useful when one want
399 to lookup all the node exist in the routing table. */
400struct bgp_node *
401bgp_table_top (struct bgp_table *table)
402{
403 /* If there is no node in the routing table return NULL. */
404 if (table->top == NULL)
405 return NULL;
406
407 /* Lock the top node and return it. */
408 bgp_lock_node (table->top);
409 return table->top;
410}
411
412/* Unlock current node and lock next node then return it. */
413struct bgp_node *
414bgp_route_next (struct bgp_node *node)
415{
416 struct bgp_node *next;
417 struct bgp_node *start;
418
419 /* Node may be deleted from bgp_unlock_node so we have to preserve
420 next node's pointer. */
421
422 if (node->l_left)
423 {
424 next = node->l_left;
425 bgp_lock_node (next);
426 bgp_unlock_node (node);
427 return next;
428 }
429 if (node->l_right)
430 {
431 next = node->l_right;
432 bgp_lock_node (next);
433 bgp_unlock_node (node);
434 return next;
435 }
436
437 start = node;
438 while (node->parent)
439 {
440 if (node->parent->l_left == node && node->parent->l_right)
441 {
442 next = node->parent->l_right;
443 bgp_lock_node (next);
444 bgp_unlock_node (start);
445 return next;
446 }
447 node = node->parent;
448 }
449 bgp_unlock_node (start);
450 return NULL;
451}
452
453/* Unlock current node and lock next node until limit. */
454struct bgp_node *
455bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)
456{
457 struct bgp_node *next;
458 struct bgp_node *start;
459
460 /* Node may be deleted from bgp_unlock_node so we have to preserve
461 next node's pointer. */
462
463 if (node->l_left)
464 {
465 next = node->l_left;
466 bgp_lock_node (next);
467 bgp_unlock_node (node);
468 return next;
469 }
470 if (node->l_right)
471 {
472 next = node->l_right;
473 bgp_lock_node (next);
474 bgp_unlock_node (node);
475 return next;
476 }
477
478 start = node;
479 while (node->parent && node != limit)
480 {
481 if (node->parent->l_left == node && node->parent->l_right)
482 {
483 next = node->parent->l_right;
484 bgp_lock_node (next);
485 bgp_unlock_node (start);
486 return next;
487 }
488 node = node->parent;
489 }
490 bgp_unlock_node (start);
491 return NULL;
492}