blob: f377400f09c4e1137b11a2a7d5fd4f22af1f3b87 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "str.h"
28#include "command.h"
29#include "if.h"
30#include "log.h"
31#include "sockunion.h"
paul4d38fdb2005-04-28 17:35:14 +000032#include "linklist.h"
33#include "thread.h"
34#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000035
36#include "zebra/rib.h"
37#include "zebra/rt.h"
38#include "zebra/zserv.h"
39#include "zebra/redistribute.h"
40#include "zebra/debug.h"
41
42/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000043extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000044
45/* Each route type's string and default distance value. */
46struct
47{
48 int key;
49 int distance;
50} route_info[] =
51{
52 {ZEBRA_ROUTE_SYSTEM, 0},
53 {ZEBRA_ROUTE_KERNEL, 0},
54 {ZEBRA_ROUTE_CONNECT, 0},
55 {ZEBRA_ROUTE_STATIC, 1},
56 {ZEBRA_ROUTE_RIP, 120},
57 {ZEBRA_ROUTE_RIPNG, 120},
58 {ZEBRA_ROUTE_OSPF, 110},
59 {ZEBRA_ROUTE_OSPF6, 110},
jardin9e867fe2003-12-23 08:56:18 +000060 {ZEBRA_ROUTE_ISIS, 115},
paul718e3742002-12-13 20:15:29 +000061 {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
62};
paul4d38fdb2005-04-28 17:35:14 +000063
64struct zebra_queue_node_t
65{
66 struct route_node *node;
67 struct rib *del;
68};
paul718e3742002-12-13 20:15:29 +000069
70/* Vector for routing table. */
71vector vrf_vector;
72
73/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +000074static struct vrf *
hassofce954f2004-10-07 20:29:24 +000075vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +000076{
77 struct vrf *vrf;
78
79 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
80
81 /* Put name. */
82 if (name)
83 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
84
85 /* Allocate routing table and static table. */
86 vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
87 vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
88 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
89 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
90
91 return vrf;
92}
93
94/* Free VRF. */
paula1ac18c2005-06-28 17:17:12 +000095static void
paul718e3742002-12-13 20:15:29 +000096vrf_free (struct vrf *vrf)
97{
98 if (vrf->name)
99 XFREE (MTYPE_VRF_NAME, vrf->name);
100 XFREE (MTYPE_VRF, vrf);
101}
102
103/* Lookup VRF by identifier. */
104struct vrf *
105vrf_lookup (u_int32_t id)
106{
107 return vector_lookup (vrf_vector, id);
108}
109
110/* Lookup VRF by name. */
paula1ac18c2005-06-28 17:17:12 +0000111static struct vrf *
paul718e3742002-12-13 20:15:29 +0000112vrf_lookup_by_name (char *name)
113{
hassofce954f2004-10-07 20:29:24 +0000114 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000115 struct vrf *vrf;
116
paul55468c82005-03-14 20:19:01 +0000117 for (i = 0; i < vector_active (vrf_vector); i++)
paul718e3742002-12-13 20:15:29 +0000118 if ((vrf = vector_slot (vrf_vector, i)) != NULL)
119 if (vrf->name && name && strcmp (vrf->name, name) == 0)
120 return vrf;
121 return NULL;
122}
123
124/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000125static void
126vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000127{
128 struct vrf *default_table;
129
130 /* Allocate VRF vector. */
131 vrf_vector = vector_init (1);
132
133 /* Allocate default main table. */
134 default_table = vrf_alloc ("Default-IP-Routing-Table");
135
136 /* Default table index must be 0. */
137 vector_set_index (vrf_vector, 0, default_table);
138}
139
140/* Lookup route table. */
141struct route_table *
142vrf_table (afi_t afi, safi_t safi, u_int32_t id)
143{
144 struct vrf *vrf;
145
146 vrf = vrf_lookup (id);
147 if (! vrf)
148 return NULL;
149
150 return vrf->table[afi][safi];
151}
152
153/* Lookup static route table. */
154struct route_table *
155vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
156{
157 struct vrf *vrf;
158
159 vrf = vrf_lookup (id);
160 if (! vrf)
161 return NULL;
162
163 return vrf->stable[afi][safi];
164}
165
166/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000167static void
paul718e3742002-12-13 20:15:29 +0000168nexthop_add (struct rib *rib, struct nexthop *nexthop)
169{
170 struct nexthop *last;
171
172 for (last = rib->nexthop; last && last->next; last = last->next)
173 ;
174 if (last)
175 last->next = nexthop;
176 else
177 rib->nexthop = nexthop;
178 nexthop->prev = last;
179
180 rib->nexthop_num++;
181}
182
183/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000184static void
paul718e3742002-12-13 20:15:29 +0000185nexthop_delete (struct rib *rib, struct nexthop *nexthop)
186{
187 if (nexthop->next)
188 nexthop->next->prev = nexthop->prev;
189 if (nexthop->prev)
190 nexthop->prev->next = nexthop->next;
191 else
192 rib->nexthop = nexthop->next;
193 rib->nexthop_num--;
194}
195
196/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000197static void
paul718e3742002-12-13 20:15:29 +0000198nexthop_free (struct nexthop *nexthop)
199{
paula4b70762003-05-16 17:19:48 +0000200 if (nexthop->ifname)
201 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000202 XFREE (MTYPE_NEXTHOP, nexthop);
203}
204
205struct nexthop *
206nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
207{
208 struct nexthop *nexthop;
209
210 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
211 memset (nexthop, 0, sizeof (struct nexthop));
212 nexthop->type = NEXTHOP_TYPE_IFINDEX;
213 nexthop->ifindex = ifindex;
214
215 nexthop_add (rib, nexthop);
216
217 return nexthop;
218}
219
220struct nexthop *
221nexthop_ifname_add (struct rib *rib, char *ifname)
222{
223 struct nexthop *nexthop;
224
225 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
226 memset (nexthop, 0, sizeof (struct nexthop));
227 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000228 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000229
230 nexthop_add (rib, nexthop);
231
232 return nexthop;
233}
234
235struct nexthop *
236nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
237{
238 struct nexthop *nexthop;
239
240 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
241 memset (nexthop, 0, sizeof (struct nexthop));
242 nexthop->type = NEXTHOP_TYPE_IPV4;
243 nexthop->gate.ipv4 = *ipv4;
244
245 nexthop_add (rib, nexthop);
246
247 return nexthop;
248}
249
paula1ac18c2005-06-28 17:17:12 +0000250static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000251nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
252 unsigned int ifindex)
253{
254 struct nexthop *nexthop;
255
256 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
257 memset (nexthop, 0, sizeof (struct nexthop));
258 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
259 nexthop->gate.ipv4 = *ipv4;
260 nexthop->ifindex = ifindex;
261
262 nexthop_add (rib, nexthop);
263
264 return nexthop;
265}
266
267#ifdef HAVE_IPV6
268struct nexthop *
269nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
270{
271 struct nexthop *nexthop;
272
273 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
274 memset (nexthop, 0, sizeof (struct nexthop));
275 nexthop->type = NEXTHOP_TYPE_IPV6;
276 nexthop->gate.ipv6 = *ipv6;
277
278 nexthop_add (rib, nexthop);
279
280 return nexthop;
281}
282
paula1ac18c2005-06-28 17:17:12 +0000283static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000284nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
285 char *ifname)
286{
287 struct nexthop *nexthop;
288
289 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
290 memset (nexthop, 0, sizeof (struct nexthop));
291 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
292 nexthop->gate.ipv6 = *ipv6;
293 nexthop->ifname = XSTRDUP (0, ifname);
294
295 nexthop_add (rib, nexthop);
296
297 return nexthop;
298}
299
paula1ac18c2005-06-28 17:17:12 +0000300static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000301nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
302 unsigned int ifindex)
303{
304 struct nexthop *nexthop;
305
306 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
307 memset (nexthop, 0, sizeof (struct nexthop));
308 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
309 nexthop->gate.ipv6 = *ipv6;
310 nexthop->ifindex = ifindex;
311
312 nexthop_add (rib, nexthop);
313
314 return nexthop;
315}
316#endif /* HAVE_IPV6 */
317
paul595db7f2003-05-25 21:35:06 +0000318struct nexthop *
319nexthop_blackhole_add (struct rib *rib)
320{
321 struct nexthop *nexthop;
322
323 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
324 memset (nexthop, 0, sizeof (struct nexthop));
325 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
326 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
327
328 nexthop_add (rib, nexthop);
329
330 return nexthop;
331}
332
paul718e3742002-12-13 20:15:29 +0000333/* If force flag is not set, do not modify falgs at all for uninstall
334 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000335static int
paul718e3742002-12-13 20:15:29 +0000336nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
337 struct route_node *top)
338{
339 struct prefix_ipv4 p;
340 struct route_table *table;
341 struct route_node *rn;
342 struct rib *match;
343 struct nexthop *newhop;
344
345 if (nexthop->type == NEXTHOP_TYPE_IPV4)
346 nexthop->ifindex = 0;
347
348 if (set)
349 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
350
351 /* Make lookup prefix. */
352 memset (&p, 0, sizeof (struct prefix_ipv4));
353 p.family = AF_INET;
354 p.prefixlen = IPV4_MAX_PREFIXLEN;
355 p.prefix = nexthop->gate.ipv4;
356
357 /* Lookup table. */
358 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
359 if (! table)
360 return 0;
361
362 rn = route_node_match (table, (struct prefix *) &p);
363 while (rn)
364 {
365 route_unlock_node (rn);
366
367 /* If lookup self prefix return immidiately. */
368 if (rn == top)
369 return 0;
370
371 /* Pick up selected route. */
372 for (match = rn->info; match; match = match->next)
373 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
374 break;
375
376 /* If there is no selected route or matched route is EGP, go up
377 tree. */
378 if (! match
379 || match->type == ZEBRA_ROUTE_BGP)
380 {
381 do {
382 rn = rn->parent;
383 } while (rn && rn->info == NULL);
384 if (rn)
385 route_lock_node (rn);
386 }
387 else
388 {
389 if (match->type == ZEBRA_ROUTE_CONNECT)
390 {
391 /* Directly point connected route. */
392 newhop = match->nexthop;
393 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
394 nexthop->ifindex = newhop->ifindex;
395
396 return 1;
397 }
398 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
399 {
400 for (newhop = match->nexthop; newhop; newhop = newhop->next)
401 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
402 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
403 {
404 if (set)
405 {
406 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
407 nexthop->rtype = newhop->type;
408 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
409 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
410 nexthop->rgate.ipv4 = newhop->gate.ipv4;
411 if (newhop->type == NEXTHOP_TYPE_IFINDEX
412 || newhop->type == NEXTHOP_TYPE_IFNAME
413 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
414 nexthop->rifindex = newhop->ifindex;
415 }
416 return 1;
417 }
418 return 0;
419 }
420 else
421 {
422 return 0;
423 }
424 }
425 }
426 return 0;
427}
428
429#ifdef HAVE_IPV6
430/* If force flag is not set, do not modify falgs at all for uninstall
431 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000432static int
paul718e3742002-12-13 20:15:29 +0000433nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
434 struct route_node *top)
435{
436 struct prefix_ipv6 p;
437 struct route_table *table;
438 struct route_node *rn;
439 struct rib *match;
440 struct nexthop *newhop;
441
442 if (nexthop->type == NEXTHOP_TYPE_IPV6)
443 nexthop->ifindex = 0;
444
445 if (set)
446 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
447
448 /* Make lookup prefix. */
449 memset (&p, 0, sizeof (struct prefix_ipv6));
450 p.family = AF_INET6;
451 p.prefixlen = IPV6_MAX_PREFIXLEN;
452 p.prefix = nexthop->gate.ipv6;
453
454 /* Lookup table. */
455 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
456 if (! table)
457 return 0;
458
459 rn = route_node_match (table, (struct prefix *) &p);
460 while (rn)
461 {
462 route_unlock_node (rn);
463
464 /* If lookup self prefix return immidiately. */
465 if (rn == top)
466 return 0;
467
468 /* Pick up selected route. */
469 for (match = rn->info; match; match = match->next)
470 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
471 break;
472
473 /* If there is no selected route or matched route is EGP, go up
474 tree. */
475 if (! match
476 || match->type == ZEBRA_ROUTE_BGP)
477 {
478 do {
479 rn = rn->parent;
480 } while (rn && rn->info == NULL);
481 if (rn)
482 route_lock_node (rn);
483 }
484 else
485 {
486 if (match->type == ZEBRA_ROUTE_CONNECT)
487 {
488 /* Directly point connected route. */
489 newhop = match->nexthop;
490
491 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
492 nexthop->ifindex = newhop->ifindex;
493
494 return 1;
495 }
496 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
497 {
498 for (newhop = match->nexthop; newhop; newhop = newhop->next)
499 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
500 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
501 {
502 if (set)
503 {
504 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
505 nexthop->rtype = newhop->type;
506 if (newhop->type == NEXTHOP_TYPE_IPV6
507 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
508 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
509 nexthop->rgate.ipv6 = newhop->gate.ipv6;
510 if (newhop->type == NEXTHOP_TYPE_IFINDEX
511 || newhop->type == NEXTHOP_TYPE_IFNAME
512 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
513 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
514 nexthop->rifindex = newhop->ifindex;
515 }
516 return 1;
517 }
518 return 0;
519 }
520 else
521 {
522 return 0;
523 }
524 }
525 }
526 return 0;
527}
528#endif /* HAVE_IPV6 */
529
530struct rib *
531rib_match_ipv4 (struct in_addr addr)
532{
533 struct prefix_ipv4 p;
534 struct route_table *table;
535 struct route_node *rn;
536 struct rib *match;
537 struct nexthop *newhop;
538
539 /* Lookup table. */
540 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
541 if (! table)
542 return 0;
543
544 memset (&p, 0, sizeof (struct prefix_ipv4));
545 p.family = AF_INET;
546 p.prefixlen = IPV4_MAX_PREFIXLEN;
547 p.prefix = addr;
548
549 rn = route_node_match (table, (struct prefix *) &p);
550
551 while (rn)
552 {
553 route_unlock_node (rn);
554
555 /* Pick up selected route. */
556 for (match = rn->info; match; match = match->next)
557 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
558 break;
559
560 /* If there is no selected route or matched route is EGP, go up
561 tree. */
562 if (! match
563 || match->type == ZEBRA_ROUTE_BGP)
564 {
565 do {
566 rn = rn->parent;
567 } while (rn && rn->info == NULL);
568 if (rn)
569 route_lock_node (rn);
570 }
571 else
572 {
573 if (match->type == ZEBRA_ROUTE_CONNECT)
574 /* Directly point connected route. */
575 return match;
576 else
577 {
578 for (newhop = match->nexthop; newhop; newhop = newhop->next)
579 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
580 return match;
581 return NULL;
582 }
583 }
584 }
585 return NULL;
586}
587
588struct rib *
589rib_lookup_ipv4 (struct prefix_ipv4 *p)
590{
591 struct route_table *table;
592 struct route_node *rn;
593 struct rib *match;
594 struct nexthop *nexthop;
595
596 /* Lookup table. */
597 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
598 if (! table)
599 return 0;
600
601 rn = route_node_lookup (table, (struct prefix *) p);
602
603 /* No route for this prefix. */
604 if (! rn)
605 return NULL;
606
607 /* Unlock node. */
608 route_unlock_node (rn);
609
610 /* Pick up selected route. */
611 for (match = rn->info; match; match = match->next)
612 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
613 break;
614
615 if (! match || match->type == ZEBRA_ROUTE_BGP)
616 return NULL;
617
618 if (match->type == ZEBRA_ROUTE_CONNECT)
619 return match;
620
621 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
622 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
623 return match;
624
625 return NULL;
626}
627
628#ifdef HAVE_IPV6
629struct rib *
630rib_match_ipv6 (struct in6_addr *addr)
631{
632 struct prefix_ipv6 p;
633 struct route_table *table;
634 struct route_node *rn;
635 struct rib *match;
636 struct nexthop *newhop;
637
638 /* Lookup table. */
639 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
640 if (! table)
641 return 0;
642
643 memset (&p, 0, sizeof (struct prefix_ipv6));
644 p.family = AF_INET6;
645 p.prefixlen = IPV6_MAX_PREFIXLEN;
646 IPV6_ADDR_COPY (&p.prefix, addr);
647
648 rn = route_node_match (table, (struct prefix *) &p);
649
650 while (rn)
651 {
652 route_unlock_node (rn);
653
654 /* Pick up selected route. */
655 for (match = rn->info; match; match = match->next)
656 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
657 break;
658
659 /* If there is no selected route or matched route is EGP, go up
660 tree. */
661 if (! match
662 || match->type == ZEBRA_ROUTE_BGP)
663 {
664 do {
665 rn = rn->parent;
666 } while (rn && rn->info == NULL);
667 if (rn)
668 route_lock_node (rn);
669 }
670 else
671 {
672 if (match->type == ZEBRA_ROUTE_CONNECT)
673 /* Directly point connected route. */
674 return match;
675 else
676 {
677 for (newhop = match->nexthop; newhop; newhop = newhop->next)
678 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
679 return match;
680 return NULL;
681 }
682 }
683 }
684 return NULL;
685}
686#endif /* HAVE_IPV6 */
687
paula1ac18c2005-06-28 17:17:12 +0000688static int
paul718e3742002-12-13 20:15:29 +0000689nexthop_active_check (struct route_node *rn, struct rib *rib,
690 struct nexthop *nexthop, int set)
691{
692 struct interface *ifp;
693
694 switch (nexthop->type)
695 {
696 case NEXTHOP_TYPE_IFINDEX:
697 ifp = if_lookup_by_index (nexthop->ifindex);
698 if (ifp && if_is_up (ifp))
699 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
700 else
701 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
702 break;
703 case NEXTHOP_TYPE_IFNAME:
704 case NEXTHOP_TYPE_IPV6_IFNAME:
705 ifp = if_lookup_by_name (nexthop->ifname);
706 if (ifp && if_is_up (ifp))
707 {
708 if (set)
709 nexthop->ifindex = ifp->ifindex;
710 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
711 }
712 else
713 {
714 if (set)
715 nexthop->ifindex = 0;
716 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
717 }
718 break;
719 case NEXTHOP_TYPE_IPV4:
720 case NEXTHOP_TYPE_IPV4_IFINDEX:
721 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
722 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
723 else
724 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
725 break;
726#ifdef HAVE_IPV6
727 case NEXTHOP_TYPE_IPV6:
728 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
729 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
730 else
731 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
732 break;
733 case NEXTHOP_TYPE_IPV6_IFINDEX:
734 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
735 {
736 ifp = if_lookup_by_index (nexthop->ifindex);
737 if (ifp && if_is_up (ifp))
738 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
739 else
740 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
741 }
742 else
743 {
744 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
745 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
746 else
747 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
748 }
749 break;
750#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000751 case NEXTHOP_TYPE_BLACKHOLE:
752 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
753 break;
paul718e3742002-12-13 20:15:29 +0000754 default:
755 break;
756 }
757 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
758}
759
paula1ac18c2005-06-28 17:17:12 +0000760static int
paul718e3742002-12-13 20:15:29 +0000761nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
762{
763 struct nexthop *nexthop;
764 int active;
765
766 rib->nexthop_active_num = 0;
767 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
768
769 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
770 {
771 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul6baeb982003-10-28 03:47:15 +0000772
773 nexthop_active_check (rn, rib, nexthop, set);
774 if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM)
775 && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
776 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
777
778 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
779 rib->nexthop_active_num++;
paul718e3742002-12-13 20:15:29 +0000780 }
781 return rib->nexthop_active_num;
782}
paul6baeb982003-10-28 03:47:15 +0000783
paul718e3742002-12-13 20:15:29 +0000784
785#define RIB_SYSTEM_ROUTE(R) \
786 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
787
paul4d38fdb2005-04-28 17:35:14 +0000788static struct rib *
789rib_lock (struct rib *rib)
790{
791 assert (rib->lock >= 0);
792
793 rib->lock++;
794 return rib;
795}
796
797static struct rib *
798rib_unlock (struct rib *rib)
paul718e3742002-12-13 20:15:29 +0000799{
800 struct nexthop *nexthop;
801 struct nexthop *next;
paul4d38fdb2005-04-28 17:35:14 +0000802
803 assert (rib->lock > 0);
804 rib->lock--;
paul718e3742002-12-13 20:15:29 +0000805
paul4d38fdb2005-04-28 17:35:14 +0000806 if (rib->lock == 0)
paul718e3742002-12-13 20:15:29 +0000807 {
paul4d38fdb2005-04-28 17:35:14 +0000808 for (nexthop = rib->nexthop; nexthop; nexthop = next)
809 {
810 next = nexthop->next;
811 nexthop_free (nexthop);
812 }
813 XFREE (MTYPE_RIB, rib);
814 return NULL;
paul718e3742002-12-13 20:15:29 +0000815 }
paul4d38fdb2005-04-28 17:35:14 +0000816 return rib;
paul718e3742002-12-13 20:15:29 +0000817}
818
paula1ac18c2005-06-28 17:17:12 +0000819static void
paul718e3742002-12-13 20:15:29 +0000820rib_install_kernel (struct route_node *rn, struct rib *rib)
821{
822 int ret = 0;
823 struct nexthop *nexthop;
824
825 switch (PREFIX_FAMILY (&rn->p))
826 {
827 case AF_INET:
828 ret = kernel_add_ipv4 (&rn->p, rib);
829 break;
830#ifdef HAVE_IPV6
831 case AF_INET6:
832 ret = kernel_add_ipv6 (&rn->p, rib);
833 break;
834#endif /* HAVE_IPV6 */
835 }
836
837 if (ret < 0)
838 {
839 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
840 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
841 }
842}
843
844/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000845static int
paul718e3742002-12-13 20:15:29 +0000846rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
847{
848 int ret = 0;
849 struct nexthop *nexthop;
850
851 switch (PREFIX_FAMILY (&rn->p))
852 {
853 case AF_INET:
854 ret = kernel_delete_ipv4 (&rn->p, rib);
855 break;
856#ifdef HAVE_IPV6
857 case AF_INET6:
858 ret = kernel_delete_ipv6 (&rn->p, rib);
859 break;
860#endif /* HAVE_IPV6 */
861 }
862
863 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
864 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
865
866 return ret;
867}
868
869/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000870static void
paul718e3742002-12-13 20:15:29 +0000871rib_uninstall (struct route_node *rn, struct rib *rib)
872{
873 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
874 {
875 redistribute_delete (&rn->p, rib);
876 if (! RIB_SYSTEM_ROUTE (rib))
877 rib_uninstall_kernel (rn, rib);
878 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
879 }
880}
881
882/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000883static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000884rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000885{
paul0fb58d52005-11-14 14:31:49 +0000886 struct zebra_queue_node_t *qnode = data;
paul718e3742002-12-13 20:15:29 +0000887 struct rib *rib;
888 struct rib *next;
889 struct rib *fib = NULL;
890 struct rib *select = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000891 struct rib *del = qnode->del;
892 struct route_node *rn = qnode->node;
pauld753e9e2003-01-22 19:45:50 +0000893 int installed = 0;
894 struct nexthop *nexthop = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000895
896 assert (rn);
897
898 /* possibly should lock and unlock rib on each iteration. however, for
899 * now, we assume called functions are synchronous and dont delete RIBs
900 * (as the work-queue deconstructor for this function is supposed to be
901 * the canonical 'delete' path for RIBs). Further if called functions
902 * below were to made asynchronous they should themselves acquire any
903 * locks/refcounts as needed and not depend on this caller to do it for
904 * them
905 */
paul718e3742002-12-13 20:15:29 +0000906 for (rib = rn->info; rib; rib = next)
907 {
908 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000909
paul718e3742002-12-13 20:15:29 +0000910 /* Currently installed rib. */
911 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
paul7021c422003-07-15 12:52:22 +0000912 fib = rib;
paul4d38fdb2005-04-28 17:35:14 +0000913
paul718e3742002-12-13 20:15:29 +0000914 /* Skip unreachable nexthop. */
915 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000916 continue;
paul718e3742002-12-13 20:15:29 +0000917
918 /* Infinit distance. */
919 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000920 continue;
paul718e3742002-12-13 20:15:29 +0000921
paulaf887b52006-01-18 14:52:52 +0000922 /* Newly selected rib, the common case. */
923 if (!select)
924 {
925 select = rib;
926 continue;
927 }
928
929 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +0000930 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +0000931 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +0000932 * - lower metric beats higher for equal distance
933 * - last, hence oldest, route wins tie break.
934 */
paula8d9c1f2006-01-25 06:31:04 +0000935 if (rib->type == ZEBRA_ROUTE_CONNECT)
936 {
937 if (select->type != ZEBRA_ROUTE_CONNECT
938 || rib->metric <= select->metric)
939 {
940 select = rib;
941 continue;
942 }
943 }
944 else if (select->type == ZEBRA_ROUTE_CONNECT)
945 continue;
946
947 /* higher distance loses */
948 if (rib->distance > select->distance)
949 continue;
950
951 /* lower wins */
952 if (rib->distance < select->distance)
953 {
paulaf887b52006-01-18 14:52:52 +0000954 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000955 continue;
956 }
957
958 /* metric tie-breaks equal distance */
959 if (rib->metric <= select->metric)
960 select = rib;
paul718e3742002-12-13 20:15:29 +0000961 }
paul4d38fdb2005-04-28 17:35:14 +0000962
paul718e3742002-12-13 20:15:29 +0000963 /* Deleted route check. */
964 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
965 fib = del;
paul4d38fdb2005-04-28 17:35:14 +0000966
967 /* We possibly should lock fib and select here However, all functions
968 * below are 'inline' and not asynchronous And if any were to be
969 * converted, they should manage references themselves really.. See
970 * previous comment above.
971 */
972
paul718e3742002-12-13 20:15:29 +0000973 /* Same route is selected. */
974 if (select && select == fib)
975 {
976 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000977 {
978 redistribute_delete (&rn->p, select);
979 if (! RIB_SYSTEM_ROUTE (select))
980 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000981
paul4d38fdb2005-04-28 17:35:14 +0000982 /* Set real nexthop. */
983 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +0000984
paul4d38fdb2005-04-28 17:35:14 +0000985 if (! RIB_SYSTEM_ROUTE (select))
986 rib_install_kernel (rn, select);
987 redistribute_add (&rn->p, select);
988 }
pauld753e9e2003-01-22 19:45:50 +0000989 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +0000990 {
991 /* Housekeeping code to deal with
992 race conditions in kernel with linux
993 netlink reporting interface up before IPv4 or IPv6 protocol
994 is ready to add routes.
995 This makes sure the routes are IN the kernel.
996 */
pauld753e9e2003-01-22 19:45:50 +0000997
paul4d38fdb2005-04-28 17:35:14 +0000998 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
999 {
1000 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1001 installed = 1;
1002 }
1003 if (! installed)
1004 rib_install_kernel (rn, select);
1005 }
1006 return WQ_SUCCESS;
paul718e3742002-12-13 20:15:29 +00001007 }
1008
1009 /* Uninstall old rib from forwarding table. */
1010 if (fib)
1011 {
1012 redistribute_delete (&rn->p, fib);
1013 if (! RIB_SYSTEM_ROUTE (fib))
1014 rib_uninstall_kernel (rn, fib);
1015 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1016
1017 /* Set real nexthop. */
1018 nexthop_active_update (rn, fib, 1);
1019 }
1020
1021 /* Install new rib into forwarding table. */
1022 if (select)
1023 {
1024 /* Set real nexthop. */
1025 nexthop_active_update (rn, select, 1);
1026
1027 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001028 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001029 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1030 redistribute_add (&rn->p, select);
1031 }
paul4d38fdb2005-04-28 17:35:14 +00001032
1033 return WQ_SUCCESS;
1034
1035}
1036
1037/* Add work queue item to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001038static void
paul4d38fdb2005-04-28 17:35:14 +00001039rib_queue_add_qnode (struct zebra_t *zebra, struct zebra_queue_node_t *qnode)
1040{
1041 route_lock_node (qnode->node);
1042
1043 if (IS_ZEBRA_DEBUG_EVENT)
1044 zlog_info ("rib_queue_add_qnode: work queue added");
1045
1046 assert (zebra && qnode && qnode->node);
1047
1048 if (qnode->del)
1049 rib_lock (qnode->del);
1050
1051 if (zebra->ribq == NULL)
1052 {
1053 zlog_err ("rib_queue_add_qnode: ribq work_queue does not exist!");
1054 route_unlock_node (qnode->node);
1055 return;
1056 }
1057
1058 work_queue_add (zebra->ribq, qnode);
1059
1060 return;
1061}
1062
1063/* Add route node and rib to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001064static void
paul4d38fdb2005-04-28 17:35:14 +00001065rib_queue_add (struct zebra_t *zebra, struct route_node *rn, struct rib *del)
1066{
1067 struct zebra_queue_node_t *qnode;
1068
1069 assert (zebra && rn);
1070
1071 qnode = (struct zebra_queue_node_t *)
1072 XCALLOC (MTYPE_RIB_QUEUE, sizeof (struct zebra_queue_node_t));
1073
1074 if (qnode == NULL)
1075 {
1076 zlog_err ("rib_queue_add: failed to allocate queue node memory, %s",
1077 strerror (errno));
1078 return;
1079 }
1080
1081 qnode->node = rn;
1082 qnode->del = del;
1083
1084 rib_queue_add_qnode (zebra, qnode);
1085
1086 return;
1087}
1088
1089/* free zebra_queue_node_t */
paula1ac18c2005-06-28 17:17:12 +00001090static void
paul0fb58d52005-11-14 14:31:49 +00001091rib_queue_qnode_del (struct work_queue *wq, void *data)
paul4d38fdb2005-04-28 17:35:14 +00001092{
paul0fb58d52005-11-14 14:31:49 +00001093 struct zebra_queue_node_t *qnode = data;
paul4d38fdb2005-04-28 17:35:14 +00001094 route_unlock_node (qnode->node);
1095
1096 if (qnode->del)
1097 rib_unlock (qnode->del);
1098
1099 XFREE (MTYPE_RIB_QUEUE, qnode);
1100}
1101
1102/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001103static void
paul4d38fdb2005-04-28 17:35:14 +00001104rib_queue_init (struct zebra_t *zebra)
1105{
1106 assert (zebra);
1107
1108 if (! (zebra->ribq = work_queue_new (zebra->master,
1109 "zebra_rib_work_queue")))
1110 {
1111 zlog_err ("rib_queue_init: could not initialise work queue!");
1112 return;
1113 }
1114
1115 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001116 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001117 zebra->ribq->spec.errorfunc = NULL;
paul0fb58d52005-11-14 14:31:49 +00001118 zebra->ribq->spec.del_item_data = &rib_queue_qnode_del;
paul4d38fdb2005-04-28 17:35:14 +00001119 /* XXX: TODO: These should be runtime configurable via vty */
1120 zebra->ribq->spec.max_retries = 3;
paul4d38fdb2005-04-28 17:35:14 +00001121
1122 return;
paul718e3742002-12-13 20:15:29 +00001123}
1124
1125/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001126static void
paul718e3742002-12-13 20:15:29 +00001127rib_addnode (struct route_node *rn, struct rib *rib)
1128{
1129 struct rib *head;
paul4d38fdb2005-04-28 17:35:14 +00001130
1131 assert (rib && rn);
1132
1133 rib_lock (rib);
1134 route_lock_node (rn);
1135
paul718e3742002-12-13 20:15:29 +00001136 head = rn->info;
1137 if (head)
1138 head->prev = rib;
1139 rib->next = head;
1140 rn->info = rib;
1141}
1142
paula1ac18c2005-06-28 17:17:12 +00001143static void
paul718e3742002-12-13 20:15:29 +00001144rib_delnode (struct route_node *rn, struct rib *rib)
1145{
paul4d38fdb2005-04-28 17:35:14 +00001146 assert (rn && rib);
1147
paul718e3742002-12-13 20:15:29 +00001148 if (rib->next)
1149 rib->next->prev = rib->prev;
1150 if (rib->prev)
1151 rib->prev->next = rib->next;
1152 else
1153 rn->info = rib->next;
paul4d38fdb2005-04-28 17:35:14 +00001154
1155 rib_unlock (rib);
1156 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001157}
1158
1159int
1160rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1161 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1162 u_int32_t metric, u_char distance)
1163{
1164 struct rib *rib;
1165 struct rib *same = NULL;
1166 struct route_table *table;
1167 struct route_node *rn;
1168 struct nexthop *nexthop;
1169
1170 /* Lookup table. */
1171 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1172 if (! table)
1173 return 0;
1174
1175 /* Make it sure prefixlen is applied to the prefix. */
1176 apply_mask_ipv4 (p);
1177
1178 /* Set default distance by route type. */
1179 if (distance == 0)
1180 {
1181 distance = route_info[type].distance;
1182
1183 /* iBGP distance is 200. */
1184 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1185 distance = 200;
1186 }
1187
1188 /* Lookup route node.*/
1189 rn = route_node_get (table, (struct prefix *) p);
1190
1191 /* If same type of route are installed, treat it as a implicit
1192 withdraw. */
1193 for (rib = rn->info; rib; rib = rib->next)
1194 {
hassoebf1ead2005-09-21 14:58:20 +00001195 if (rib->type != type)
1196 continue;
1197 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001198 {
1199 same = rib;
1200 break;
1201 }
hassoebf1ead2005-09-21 14:58:20 +00001202 /* Duplicate connected route comes in. */
1203 else if ((nexthop = rib->nexthop) &&
1204 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1205 nexthop->ifindex == ifindex)
1206 {
1207 rib->refcnt++;
1208 return 0 ;
1209 }
paul718e3742002-12-13 20:15:29 +00001210 }
1211
1212 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001213 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001214 rib->type = type;
1215 rib->distance = distance;
1216 rib->flags = flags;
1217 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001218 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001219 rib->nexthop_num = 0;
1220 rib->uptime = time (NULL);
1221
1222 /* Nexthop settings. */
1223 if (gate)
1224 {
1225 if (ifindex)
1226 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1227 else
1228 nexthop_ipv4_add (rib, gate);
1229 }
1230 else
1231 nexthop_ifindex_add (rib, ifindex);
1232
1233 /* If this route is kernel route, set FIB flag to the route. */
1234 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1235 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1236 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1237
1238 /* Link new rib to node.*/
1239 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001240
paul718e3742002-12-13 20:15:29 +00001241 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001242 rib_queue_add (&zebrad, rn, same);
1243
paul718e3742002-12-13 20:15:29 +00001244 /* Free implicit route.*/
1245 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001246 rib_delnode (rn, same);
1247
1248 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001249 return 0;
1250}
1251
1252int
1253rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1254{
1255 struct route_table *table;
1256 struct route_node *rn;
1257 struct rib *same;
1258 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001259
paul718e3742002-12-13 20:15:29 +00001260 /* Lookup table. */
1261 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1262 if (! table)
1263 return 0;
paul718e3742002-12-13 20:15:29 +00001264 /* Make it sure prefixlen is applied to the prefix. */
1265 apply_mask_ipv4 (p);
1266
1267 /* Set default distance by route type. */
1268 if (rib->distance == 0)
1269 {
1270 rib->distance = route_info[rib->type].distance;
1271
1272 /* iBGP distance is 200. */
1273 if (rib->type == ZEBRA_ROUTE_BGP
1274 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1275 rib->distance = 200;
1276 }
1277
1278 /* Lookup route node.*/
1279 rn = route_node_get (table, (struct prefix *) p);
1280
1281 /* If same type of route are installed, treat it as a implicit
1282 withdraw. */
1283 for (same = rn->info; same; same = same->next)
1284 {
1285 if (same->type == rib->type && same->table == rib->table
1286 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001287 break;
paul718e3742002-12-13 20:15:29 +00001288 }
paul4d38fdb2005-04-28 17:35:14 +00001289
paul718e3742002-12-13 20:15:29 +00001290 /* If this route is kernel route, set FIB flag to the route. */
1291 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1292 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1293 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1294
1295 /* Link new rib to node.*/
1296 rib_addnode (rn, rib);
1297
1298 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001299 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001300
1301 /* Free implicit route.*/
1302 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001303 rib_delnode (rn, same);
1304
1305 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001306 return 0;
1307}
1308
hassoebf1ead2005-09-21 14:58:20 +00001309/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001310int
1311rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1312 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1313{
1314 struct route_table *table;
1315 struct route_node *rn;
1316 struct rib *rib;
1317 struct rib *fib = NULL;
1318 struct rib *same = NULL;
1319 struct nexthop *nexthop;
1320 char buf1[BUFSIZ];
1321 char buf2[BUFSIZ];
1322
1323 /* Lookup table. */
1324 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1325 if (! table)
1326 return 0;
1327
1328 /* Apply mask. */
1329 apply_mask_ipv4 (p);
1330
paul5ec90d22003-06-19 01:41:37 +00001331 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001332 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001333 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1334 p->prefixlen,
1335 inet_ntoa (*gate),
1336 ifindex);
1337
paul718e3742002-12-13 20:15:29 +00001338 /* Lookup route node. */
1339 rn = route_node_lookup (table, (struct prefix *) p);
1340 if (! rn)
1341 {
1342 if (IS_ZEBRA_DEBUG_KERNEL)
1343 {
1344 if (gate)
ajsb6178002004-12-07 21:12:56 +00001345 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001346 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1347 p->prefixlen,
1348 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1349 ifindex);
1350 else
ajsb6178002004-12-07 21:12:56 +00001351 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001352 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1353 p->prefixlen,
1354 ifindex);
1355 }
1356 return ZEBRA_ERR_RTNOEXIST;
1357 }
1358
1359 /* Lookup same type route. */
1360 for (rib = rn->info; rib; rib = rib->next)
1361 {
1362 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1363 fib = rib;
1364
hassoebf1ead2005-09-21 14:58:20 +00001365 if (rib->type != type)
1366 continue;
1367 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1368 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001369 {
hassoebf1ead2005-09-21 14:58:20 +00001370 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001371 {
hassoebf1ead2005-09-21 14:58:20 +00001372 rib->refcnt--;
1373 route_unlock_node (rn);
1374 route_unlock_node (rn);
1375 return 0;
paul718e3742002-12-13 20:15:29 +00001376 }
hassoebf1ead2005-09-21 14:58:20 +00001377 same = rib;
1378 break;
paul718e3742002-12-13 20:15:29 +00001379 }
hassoebf1ead2005-09-21 14:58:20 +00001380 /* Make sure that the route found has the same gateway. */
1381 else if (gate == NULL ||
1382 ((nexthop = rib->nexthop) &&
1383 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1384 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001385 {
hassoebf1ead2005-09-21 14:58:20 +00001386 same = rib;
1387 break;
paul718e3742002-12-13 20:15:29 +00001388 }
1389 }
1390
1391 /* If same type of route can't be found and this message is from
1392 kernel. */
1393 if (! same)
1394 {
1395 if (fib && type == ZEBRA_ROUTE_KERNEL)
1396 {
1397 /* Unset flags. */
1398 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1399 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1400
1401 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1402 }
1403 else
1404 {
1405 if (IS_ZEBRA_DEBUG_KERNEL)
1406 {
1407 if (gate)
ajsb6178002004-12-07 21:12:56 +00001408 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001409 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1410 p->prefixlen,
1411 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1412 ifindex,
1413 type);
1414 else
ajsb6178002004-12-07 21:12:56 +00001415 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001416 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1417 p->prefixlen,
1418 ifindex,
1419 type);
1420 }
1421 route_unlock_node (rn);
1422 return ZEBRA_ERR_RTNOEXIST;
1423 }
1424 }
paul4d38fdb2005-04-28 17:35:14 +00001425
1426 /* Process changes. */
1427 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001428
1429 if (same)
1430 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001431
paul718e3742002-12-13 20:15:29 +00001432 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001433 return 0;
1434}
1435
1436/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001437static void
paul718e3742002-12-13 20:15:29 +00001438static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1439{
1440 struct rib *rib;
1441 struct route_node *rn;
1442 struct route_table *table;
1443
1444 /* Lookup table. */
1445 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1446 if (! table)
1447 return;
1448
1449 /* Lookup existing route */
1450 rn = route_node_get (table, p);
1451 for (rib = rn->info; rib; rib = rib->next)
1452 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1453 break;
1454
1455 if (rib)
1456 {
1457 /* Same distance static route is there. Update it with new
1458 nexthop. */
paul718e3742002-12-13 20:15:29 +00001459 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001460 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001461 {
1462 case STATIC_IPV4_GATEWAY:
1463 nexthop_ipv4_add (rib, &si->gate.ipv4);
1464 break;
1465 case STATIC_IPV4_IFNAME:
1466 nexthop_ifname_add (rib, si->gate.ifname);
1467 break;
1468 case STATIC_IPV4_BLACKHOLE:
1469 nexthop_blackhole_add (rib);
1470 break;
paul4d38fdb2005-04-28 17:35:14 +00001471 }
1472 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001473 }
1474 else
1475 {
1476 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001477 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1478
paul718e3742002-12-13 20:15:29 +00001479 rib->type = ZEBRA_ROUTE_STATIC;
1480 rib->distance = si->distance;
1481 rib->metric = 0;
1482 rib->nexthop_num = 0;
1483
1484 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001485 {
1486 case STATIC_IPV4_GATEWAY:
1487 nexthop_ipv4_add (rib, &si->gate.ipv4);
1488 break;
1489 case STATIC_IPV4_IFNAME:
1490 nexthop_ifname_add (rib, si->gate.ifname);
1491 break;
1492 case STATIC_IPV4_BLACKHOLE:
1493 nexthop_blackhole_add (rib);
1494 break;
1495 }
paul718e3742002-12-13 20:15:29 +00001496
hasso81dfcaa2003-05-25 19:21:25 +00001497 /* Save the flags of this static routes (reject, blackhole) */
1498 rib->flags = si->flags;
1499
paul718e3742002-12-13 20:15:29 +00001500 /* Link this rib to the tree. */
1501 rib_addnode (rn, rib);
1502
1503 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00001504 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001505 }
1506}
1507
paula1ac18c2005-06-28 17:17:12 +00001508static int
paul718e3742002-12-13 20:15:29 +00001509static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1510{
1511 if (nexthop->type == NEXTHOP_TYPE_IPV4
1512 && si->type == STATIC_IPV4_GATEWAY
1513 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1514 return 1;
1515 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1516 && si->type == STATIC_IPV4_IFNAME
1517 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1518 return 1;
paul595db7f2003-05-25 21:35:06 +00001519 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1520 && si->type == STATIC_IPV4_BLACKHOLE)
1521 return 1;
paule8e19462006-01-19 20:16:55 +00001522 return 0;
paul718e3742002-12-13 20:15:29 +00001523}
1524
1525/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001526static void
paul718e3742002-12-13 20:15:29 +00001527static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1528{
1529 struct route_node *rn;
1530 struct rib *rib;
1531 struct nexthop *nexthop;
1532 struct route_table *table;
1533
1534 /* Lookup table. */
1535 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1536 if (! table)
1537 return;
paul4d38fdb2005-04-28 17:35:14 +00001538
paul718e3742002-12-13 20:15:29 +00001539 /* Lookup existing route with type and distance. */
1540 rn = route_node_lookup (table, p);
1541 if (! rn)
1542 return;
1543
1544 for (rib = rn->info; rib; rib = rib->next)
1545 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1546 break;
1547
1548 if (! rib)
1549 {
1550 route_unlock_node (rn);
1551 return;
1552 }
1553
1554 /* Lookup nexthop. */
1555 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1556 if (static_ipv4_nexthop_same (nexthop, si))
1557 break;
1558
1559 /* Can't find nexthop. */
1560 if (! nexthop)
1561 {
1562 route_unlock_node (rn);
1563 return;
1564 }
1565
1566 /* Check nexthop. */
1567 if (rib->nexthop_num == 1)
1568 {
paul4d38fdb2005-04-28 17:35:14 +00001569 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00001570 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001571 }
1572 else
1573 {
paul6baeb982003-10-28 03:47:15 +00001574 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1575 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001576 nexthop_delete (rib, nexthop);
1577 nexthop_free (nexthop);
1578 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001579 }
paul718e3742002-12-13 20:15:29 +00001580 /* Unlock node. */
1581 route_unlock_node (rn);
1582}
1583
1584/* Add static route into static route configuration. */
1585int
hasso39db97e2004-10-12 20:50:58 +00001586static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001587 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001588{
1589 u_char type = 0;
1590 struct route_node *rn;
1591 struct static_ipv4 *si;
1592 struct static_ipv4 *pp;
1593 struct static_ipv4 *cp;
1594 struct static_ipv4 *update = NULL;
1595 struct route_table *stable;
1596
1597 /* Lookup table. */
1598 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1599 if (! stable)
1600 return -1;
1601
1602 /* Lookup static route prefix. */
1603 rn = route_node_get (stable, p);
1604
1605 /* Make flags. */
1606 if (gate)
1607 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001608 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001609 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001610 else
1611 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001612
1613 /* Do nothing if there is a same static route. */
1614 for (si = rn->info; si; si = si->next)
1615 {
1616 if (type == si->type
1617 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1618 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1619 {
1620 if (distance == si->distance)
1621 {
1622 route_unlock_node (rn);
1623 return 0;
1624 }
1625 else
1626 update = si;
1627 }
1628 }
1629
1630 /* Distance chaged. */
1631 if (update)
1632 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1633
1634 /* Make new static route structure. */
1635 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1636 memset (si, 0, sizeof (struct static_ipv4));
1637
1638 si->type = type;
1639 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001640 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001641
1642 if (gate)
1643 si->gate.ipv4 = *gate;
1644 if (ifname)
1645 si->gate.ifname = XSTRDUP (0, ifname);
1646
1647 /* Add new static route information to the tree with sort by
1648 distance value and gateway address. */
1649 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1650 {
1651 if (si->distance < cp->distance)
1652 break;
1653 if (si->distance > cp->distance)
1654 continue;
1655 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1656 {
1657 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1658 break;
1659 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1660 continue;
1661 }
1662 }
1663
1664 /* Make linked list. */
1665 if (pp)
1666 pp->next = si;
1667 else
1668 rn->info = si;
1669 if (cp)
1670 cp->prev = si;
1671 si->prev = pp;
1672 si->next = cp;
1673
1674 /* Install into rib. */
1675 static_install_ipv4 (p, si);
1676
1677 return 1;
1678}
1679
1680/* Delete static route from static route configuration. */
1681int
hasso39db97e2004-10-12 20:50:58 +00001682static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001683 u_char distance, u_int32_t vrf_id)
1684{
1685 u_char type = 0;
1686 struct route_node *rn;
1687 struct static_ipv4 *si;
1688 struct route_table *stable;
1689
1690 /* Lookup table. */
1691 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1692 if (! stable)
1693 return -1;
1694
1695 /* Lookup static route prefix. */
1696 rn = route_node_lookup (stable, p);
1697 if (! rn)
1698 return 0;
1699
1700 /* Make flags. */
1701 if (gate)
1702 type = STATIC_IPV4_GATEWAY;
1703 else if (ifname)
1704 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001705 else
1706 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001707
1708 /* Find same static route is the tree */
1709 for (si = rn->info; si; si = si->next)
1710 if (type == si->type
1711 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1712 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1713 break;
1714
1715 /* Can't find static route. */
1716 if (! si)
1717 {
1718 route_unlock_node (rn);
1719 return 0;
1720 }
1721
1722 /* Install into rib. */
1723 static_uninstall_ipv4 (p, si);
1724
1725 /* Unlink static route from linked list. */
1726 if (si->prev)
1727 si->prev->next = si->next;
1728 else
1729 rn->info = si->next;
1730 if (si->next)
1731 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001732 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001733
1734 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001735 if (ifname)
1736 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001737 XFREE (MTYPE_STATIC_IPV4, si);
1738
paul143a3852003-09-29 20:06:13 +00001739 route_unlock_node (rn);
1740
paul718e3742002-12-13 20:15:29 +00001741 return 1;
1742}
1743
1744
1745#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001746static int
paul718e3742002-12-13 20:15:29 +00001747rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1748 struct in6_addr *gate, unsigned int ifindex, int table)
1749{
hasso726f9b22003-05-25 21:04:54 +00001750 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1751#if defined (MUSICA) || defined (LINUX)
1752 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1753 if (p->prefixlen == 96)
1754 return 0;
1755#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001756 return 1;
hasso726f9b22003-05-25 21:04:54 +00001757 }
paul718e3742002-12-13 20:15:29 +00001758 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1759 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1760 {
1761 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1762 return 1;
1763 }
1764 return 0;
1765}
1766
1767int
1768rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001769 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1770 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001771{
1772 struct rib *rib;
1773 struct rib *same = NULL;
1774 struct route_table *table;
1775 struct route_node *rn;
1776 struct nexthop *nexthop;
1777
paul718e3742002-12-13 20:15:29 +00001778 /* Lookup table. */
1779 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1780 if (! table)
1781 return 0;
1782
1783 /* Make sure mask is applied. */
1784 apply_mask_ipv6 (p);
1785
1786 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001787 if (!distance)
1788 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001789
1790 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1791 distance = 200;
1792
1793 /* Filter bogus route. */
1794 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1795 return 0;
1796
1797 /* Lookup route node.*/
1798 rn = route_node_get (table, (struct prefix *) p);
1799
1800 /* If same type of route are installed, treat it as a implicit
1801 withdraw. */
1802 for (rib = rn->info; rib; rib = rib->next)
1803 {
hassoebf1ead2005-09-21 14:58:20 +00001804 if (rib->type != type)
1805 continue;
1806 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001807 {
1808 same = rib;
paul718e3742002-12-13 20:15:29 +00001809 break;
1810 }
hassoebf1ead2005-09-21 14:58:20 +00001811 else if ((nexthop = rib->nexthop) &&
1812 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1813 nexthop->ifindex == ifindex)
1814 {
1815 rib->refcnt++;
1816 return 0;
1817 }
paul718e3742002-12-13 20:15:29 +00001818 }
1819
1820 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001821 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1822
paul718e3742002-12-13 20:15:29 +00001823 rib->type = type;
1824 rib->distance = distance;
1825 rib->flags = flags;
1826 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001827 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001828 rib->nexthop_num = 0;
1829 rib->uptime = time (NULL);
1830
1831 /* Nexthop settings. */
1832 if (gate)
1833 {
1834 if (ifindex)
1835 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1836 else
1837 nexthop_ipv6_add (rib, gate);
1838 }
1839 else
1840 nexthop_ifindex_add (rib, ifindex);
1841
1842 /* If this route is kernel route, set FIB flag to the route. */
1843 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1844 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1845 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1846
1847 /* Link new rib to node.*/
1848 rib_addnode (rn, rib);
1849
1850 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001851 rib_queue_add (&zebrad, rn, same);
1852
paul718e3742002-12-13 20:15:29 +00001853 /* Free implicit route.*/
1854 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001855 rib_delnode (rn, same);
1856
1857 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001858 return 0;
1859}
1860
hassoebf1ead2005-09-21 14:58:20 +00001861/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001862int
1863rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1864 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1865{
1866 struct route_table *table;
1867 struct route_node *rn;
1868 struct rib *rib;
1869 struct rib *fib = NULL;
1870 struct rib *same = NULL;
1871 struct nexthop *nexthop;
1872 char buf1[BUFSIZ];
1873 char buf2[BUFSIZ];
1874
1875 /* Apply mask. */
1876 apply_mask_ipv6 (p);
1877
1878 /* Lookup table. */
1879 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1880 if (! table)
1881 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001882
paul718e3742002-12-13 20:15:29 +00001883 /* Lookup route node. */
1884 rn = route_node_lookup (table, (struct prefix *) p);
1885 if (! rn)
1886 {
1887 if (IS_ZEBRA_DEBUG_KERNEL)
1888 {
1889 if (gate)
ajsb6178002004-12-07 21:12:56 +00001890 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001891 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1892 p->prefixlen,
1893 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1894 ifindex);
1895 else
ajsb6178002004-12-07 21:12:56 +00001896 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001897 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1898 p->prefixlen,
1899 ifindex);
1900 }
1901 return ZEBRA_ERR_RTNOEXIST;
1902 }
1903
1904 /* Lookup same type route. */
1905 for (rib = rn->info; rib; rib = rib->next)
1906 {
1907 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1908 fib = rib;
1909
hassoebf1ead2005-09-21 14:58:20 +00001910 if (rib->type != type)
1911 continue;
1912 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1913 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001914 {
hassoebf1ead2005-09-21 14:58:20 +00001915 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001916 {
hassoebf1ead2005-09-21 14:58:20 +00001917 rib->refcnt--;
1918 route_unlock_node (rn);
1919 route_unlock_node (rn);
1920 return 0;
paul718e3742002-12-13 20:15:29 +00001921 }
hassoebf1ead2005-09-21 14:58:20 +00001922 same = rib;
1923 break;
paul718e3742002-12-13 20:15:29 +00001924 }
hassoebf1ead2005-09-21 14:58:20 +00001925 /* Make sure that the route found has the same gateway. */
1926 else if (gate == NULL ||
1927 ((nexthop = rib->nexthop) &&
1928 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
1929 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00001930 {
hassoebf1ead2005-09-21 14:58:20 +00001931 same = rib;
1932 break;
paul718e3742002-12-13 20:15:29 +00001933 }
1934 }
1935
1936 /* If same type of route can't be found and this message is from
1937 kernel. */
1938 if (! same)
1939 {
1940 if (fib && type == ZEBRA_ROUTE_KERNEL)
1941 {
1942 /* Unset flags. */
1943 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1944 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1945
1946 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1947 }
1948 else
1949 {
1950 if (IS_ZEBRA_DEBUG_KERNEL)
1951 {
1952 if (gate)
ajsb6178002004-12-07 21:12:56 +00001953 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001954 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1955 p->prefixlen,
1956 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1957 ifindex,
1958 type);
1959 else
ajsb6178002004-12-07 21:12:56 +00001960 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001961 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1962 p->prefixlen,
1963 ifindex,
1964 type);
1965 }
1966 route_unlock_node (rn);
1967 return ZEBRA_ERR_RTNOEXIST;
1968 }
1969 }
1970
paul4d38fdb2005-04-28 17:35:14 +00001971 /* Process changes. */
1972 rib_queue_add (&zebrad, rn, same);
1973
paul718e3742002-12-13 20:15:29 +00001974 if (same)
1975 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001976
paul718e3742002-12-13 20:15:29 +00001977 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001978 return 0;
1979}
1980
1981/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001982static void
paul718e3742002-12-13 20:15:29 +00001983static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1984{
1985 struct rib *rib;
1986 struct route_table *table;
1987 struct route_node *rn;
1988
1989 /* Lookup table. */
1990 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1991 if (! table)
1992 return;
1993
1994 /* Lookup existing route */
1995 rn = route_node_get (table, p);
1996 for (rib = rn->info; rib; rib = rib->next)
1997 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1998 break;
1999
2000 if (rib)
2001 {
2002 /* Same distance static route is there. Update it with new
2003 nexthop. */
paul718e3742002-12-13 20:15:29 +00002004 route_unlock_node (rn);
2005
2006 switch (si->type)
2007 {
2008 case STATIC_IPV6_GATEWAY:
2009 nexthop_ipv6_add (rib, &si->ipv6);
2010 break;
2011 case STATIC_IPV6_IFNAME:
2012 nexthop_ifname_add (rib, si->ifname);
2013 break;
2014 case STATIC_IPV6_GATEWAY_IFNAME:
2015 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2016 break;
2017 }
paul4d38fdb2005-04-28 17:35:14 +00002018 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002019 }
2020 else
2021 {
2022 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002023 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2024
paul718e3742002-12-13 20:15:29 +00002025 rib->type = ZEBRA_ROUTE_STATIC;
2026 rib->distance = si->distance;
2027 rib->metric = 0;
2028 rib->nexthop_num = 0;
2029
2030 switch (si->type)
2031 {
2032 case STATIC_IPV6_GATEWAY:
2033 nexthop_ipv6_add (rib, &si->ipv6);
2034 break;
2035 case STATIC_IPV6_IFNAME:
2036 nexthop_ifname_add (rib, si->ifname);
2037 break;
2038 case STATIC_IPV6_GATEWAY_IFNAME:
2039 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2040 break;
2041 }
2042
hasso81dfcaa2003-05-25 19:21:25 +00002043 /* Save the flags of this static routes (reject, blackhole) */
2044 rib->flags = si->flags;
2045
paul718e3742002-12-13 20:15:29 +00002046 /* Link this rib to the tree. */
2047 rib_addnode (rn, rib);
2048
2049 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00002050 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002051 }
2052}
2053
paula1ac18c2005-06-28 17:17:12 +00002054static int
paul718e3742002-12-13 20:15:29 +00002055static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2056{
2057 if (nexthop->type == NEXTHOP_TYPE_IPV6
2058 && si->type == STATIC_IPV6_GATEWAY
2059 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2060 return 1;
2061 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2062 && si->type == STATIC_IPV6_IFNAME
2063 && strcmp (nexthop->ifname, si->ifname) == 0)
2064 return 1;
2065 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2066 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2067 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2068 && strcmp (nexthop->ifname, si->ifname) == 0)
2069 return 1;
paule8e19462006-01-19 20:16:55 +00002070 return 0;
paul718e3742002-12-13 20:15:29 +00002071}
2072
paula1ac18c2005-06-28 17:17:12 +00002073static void
paul718e3742002-12-13 20:15:29 +00002074static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2075{
2076 struct route_table *table;
2077 struct route_node *rn;
2078 struct rib *rib;
2079 struct nexthop *nexthop;
2080
2081 /* Lookup table. */
2082 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2083 if (! table)
2084 return;
2085
2086 /* Lookup existing route with type and distance. */
2087 rn = route_node_lookup (table, (struct prefix *) p);
2088 if (! rn)
2089 return;
2090
2091 for (rib = rn->info; rib; rib = rib->next)
2092 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2093 break;
2094 if (! rib)
2095 {
2096 route_unlock_node (rn);
2097 return;
2098 }
2099
2100 /* Lookup nexthop. */
2101 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2102 if (static_ipv6_nexthop_same (nexthop, si))
2103 break;
2104
2105 /* Can't find nexthop. */
2106 if (! nexthop)
2107 {
2108 route_unlock_node (rn);
2109 return;
2110 }
2111
2112 /* Check nexthop. */
2113 if (rib->nexthop_num == 1)
2114 {
2115 rib_delnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002116 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00002117 }
2118 else
2119 {
paul6baeb982003-10-28 03:47:15 +00002120 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2121 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002122 nexthop_delete (rib, nexthop);
2123 nexthop_free (nexthop);
2124 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002125 }
paul718e3742002-12-13 20:15:29 +00002126 /* Unlock node. */
2127 route_unlock_node (rn);
2128}
2129
2130/* Add static route into static route configuration. */
2131int
2132static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002133 const char *ifname, u_char flags, u_char distance,
2134 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002135{
2136 struct route_node *rn;
2137 struct static_ipv6 *si;
2138 struct static_ipv6 *pp;
2139 struct static_ipv6 *cp;
2140 struct route_table *stable;
2141
2142 /* Lookup table. */
2143 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2144 if (! stable)
2145 return -1;
2146
2147 /* Lookup static route prefix. */
2148 rn = route_node_get (stable, p);
2149
2150 /* Do nothing if there is a same static route. */
2151 for (si = rn->info; si; si = si->next)
2152 {
2153 if (distance == si->distance
2154 && type == si->type
2155 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2156 && (! ifname || strcmp (ifname, si->ifname) == 0))
2157 {
2158 route_unlock_node (rn);
2159 return 0;
2160 }
2161 }
2162
2163 /* Make new static route structure. */
2164 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2165 memset (si, 0, sizeof (struct static_ipv6));
2166
2167 si->type = type;
2168 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002169 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002170
2171 switch (type)
2172 {
2173 case STATIC_IPV6_GATEWAY:
2174 si->ipv6 = *gate;
2175 break;
2176 case STATIC_IPV6_IFNAME:
2177 si->ifname = XSTRDUP (0, ifname);
2178 break;
2179 case STATIC_IPV6_GATEWAY_IFNAME:
2180 si->ipv6 = *gate;
2181 si->ifname = XSTRDUP (0, ifname);
2182 break;
2183 }
2184
2185 /* Add new static route information to the tree with sort by
2186 distance value and gateway address. */
2187 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2188 {
2189 if (si->distance < cp->distance)
2190 break;
2191 if (si->distance > cp->distance)
2192 continue;
2193 }
2194
2195 /* Make linked list. */
2196 if (pp)
2197 pp->next = si;
2198 else
2199 rn->info = si;
2200 if (cp)
2201 cp->prev = si;
2202 si->prev = pp;
2203 si->next = cp;
2204
2205 /* Install into rib. */
2206 static_install_ipv6 (p, si);
2207
2208 return 1;
2209}
2210
2211/* Delete static route from static route configuration. */
2212int
2213static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002214 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002215{
2216 struct route_node *rn;
2217 struct static_ipv6 *si;
2218 struct route_table *stable;
2219
2220 /* Lookup table. */
2221 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2222 if (! stable)
2223 return -1;
2224
2225 /* Lookup static route prefix. */
2226 rn = route_node_lookup (stable, p);
2227 if (! rn)
2228 return 0;
2229
2230 /* Find same static route is the tree */
2231 for (si = rn->info; si; si = si->next)
2232 if (distance == si->distance
2233 && type == si->type
2234 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2235 && (! ifname || strcmp (ifname, si->ifname) == 0))
2236 break;
2237
2238 /* Can't find static route. */
2239 if (! si)
2240 {
2241 route_unlock_node (rn);
2242 return 0;
2243 }
2244
2245 /* Install into rib. */
2246 static_uninstall_ipv6 (p, si);
2247
2248 /* Unlink static route from linked list. */
2249 if (si->prev)
2250 si->prev->next = si->next;
2251 else
2252 rn->info = si->next;
2253 if (si->next)
2254 si->next->prev = si->prev;
2255
2256 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002257 if (ifname)
2258 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002259 XFREE (MTYPE_STATIC_IPV6, si);
2260
2261 return 1;
2262}
2263#endif /* HAVE_IPV6 */
2264
2265/* RIB update function. */
2266void
paula1ac18c2005-06-28 17:17:12 +00002267rib_update (void)
paul718e3742002-12-13 20:15:29 +00002268{
2269 struct route_node *rn;
2270 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002271
paul718e3742002-12-13 20:15:29 +00002272 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2273 if (table)
2274 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002275 if (rn->info)
2276 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002277
2278 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2279 if (table)
2280 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002281 if (rn->info)
2282 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002283}
2284
2285/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002286static void
paul718e3742002-12-13 20:15:29 +00002287rib_if_up (struct interface *ifp)
2288{
2289 rib_update ();
2290}
2291
2292/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002293static void
paul718e3742002-12-13 20:15:29 +00002294rib_if_down (struct interface *ifp)
2295{
2296 rib_update ();
2297}
2298
2299/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002300static void
paul718e3742002-12-13 20:15:29 +00002301rib_weed_table (struct route_table *table)
2302{
2303 struct route_node *rn;
2304 struct rib *rib;
2305 struct rib *next;
2306
2307 if (table)
2308 for (rn = route_top (table); rn; rn = route_next (rn))
2309 for (rib = rn->info; rib; rib = next)
2310 {
2311 next = rib->next;
2312
paulb21b19c2003-06-15 01:28:29 +00002313 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002314 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002315 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002316 }
2317}
2318
2319/* Delete all routes from non main table. */
2320void
paula1ac18c2005-06-28 17:17:12 +00002321rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002322{
2323 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2324 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2325}
2326
2327/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002328static void
paul718e3742002-12-13 20:15:29 +00002329rib_sweep_table (struct route_table *table)
2330{
2331 struct route_node *rn;
2332 struct rib *rib;
2333 struct rib *next;
2334 int ret = 0;
2335
2336 if (table)
2337 for (rn = route_top (table); rn; rn = route_next (rn))
2338 for (rib = rn->info; rib; rib = next)
2339 {
2340 next = rib->next;
2341
2342 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2343 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2344 {
2345 ret = rib_uninstall_kernel (rn, rib);
2346 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002347 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002348 }
2349 }
2350}
2351
2352/* Sweep all RIB tables. */
2353void
paula1ac18c2005-06-28 17:17:12 +00002354rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002355{
2356 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2357 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2358}
2359
2360/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002361static void
paul718e3742002-12-13 20:15:29 +00002362rib_close_table (struct route_table *table)
2363{
2364 struct route_node *rn;
2365 struct rib *rib;
2366
2367 if (table)
2368 for (rn = route_top (table); rn; rn = route_next (rn))
2369 for (rib = rn->info; rib; rib = rib->next)
2370 if (! RIB_SYSTEM_ROUTE (rib)
2371 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2372 rib_uninstall_kernel (rn, rib);
2373}
2374
2375/* Close all RIB tables. */
2376void
paula1ac18c2005-06-28 17:17:12 +00002377rib_close (void)
paul718e3742002-12-13 20:15:29 +00002378{
2379 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2380 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2381}
2382
2383/* Routing information base initialize. */
2384void
paula1ac18c2005-06-28 17:17:12 +00002385rib_init (void)
paul718e3742002-12-13 20:15:29 +00002386{
paul4d38fdb2005-04-28 17:35:14 +00002387 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002388 /* VRF initialization. */
2389 vrf_init ();
2390}