blob: 330bce77a14f2479ad546201bc3a4e6838bb4a8c [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 */
paula1038a12006-01-30 14:08:51 +0000935
936 /* Connected routes. Pick the last connected
937 * route of the set of lowest metric connected routes.
938 */
paula8d9c1f2006-01-25 06:31:04 +0000939 if (rib->type == ZEBRA_ROUTE_CONNECT)
940 {
paula1038a12006-01-30 14:08:51 +0000941 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +0000942 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +0000943 select = rib;
944 continue;
paula8d9c1f2006-01-25 06:31:04 +0000945 }
946 else if (select->type == ZEBRA_ROUTE_CONNECT)
947 continue;
948
949 /* higher distance loses */
950 if (rib->distance > select->distance)
951 continue;
952
953 /* lower wins */
954 if (rib->distance < select->distance)
955 {
paulaf887b52006-01-18 14:52:52 +0000956 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000957 continue;
958 }
959
960 /* metric tie-breaks equal distance */
961 if (rib->metric <= select->metric)
962 select = rib;
paul718e3742002-12-13 20:15:29 +0000963 }
paul4d38fdb2005-04-28 17:35:14 +0000964
paul718e3742002-12-13 20:15:29 +0000965 /* Deleted route check. */
966 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
967 fib = del;
paul4d38fdb2005-04-28 17:35:14 +0000968
969 /* We possibly should lock fib and select here However, all functions
970 * below are 'inline' and not asynchronous And if any were to be
971 * converted, they should manage references themselves really.. See
972 * previous comment above.
973 */
974
paul718e3742002-12-13 20:15:29 +0000975 /* Same route is selected. */
976 if (select && select == fib)
977 {
978 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000979 {
980 redistribute_delete (&rn->p, select);
981 if (! RIB_SYSTEM_ROUTE (select))
982 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000983
paul4d38fdb2005-04-28 17:35:14 +0000984 /* Set real nexthop. */
985 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +0000986
paul4d38fdb2005-04-28 17:35:14 +0000987 if (! RIB_SYSTEM_ROUTE (select))
988 rib_install_kernel (rn, select);
989 redistribute_add (&rn->p, select);
990 }
pauld753e9e2003-01-22 19:45:50 +0000991 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +0000992 {
993 /* Housekeeping code to deal with
994 race conditions in kernel with linux
995 netlink reporting interface up before IPv4 or IPv6 protocol
996 is ready to add routes.
997 This makes sure the routes are IN the kernel.
998 */
pauld753e9e2003-01-22 19:45:50 +0000999
paul4d38fdb2005-04-28 17:35:14 +00001000 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1001 {
1002 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1003 installed = 1;
1004 }
1005 if (! installed)
1006 rib_install_kernel (rn, select);
1007 }
1008 return WQ_SUCCESS;
paul718e3742002-12-13 20:15:29 +00001009 }
1010
1011 /* Uninstall old rib from forwarding table. */
1012 if (fib)
1013 {
1014 redistribute_delete (&rn->p, fib);
1015 if (! RIB_SYSTEM_ROUTE (fib))
1016 rib_uninstall_kernel (rn, fib);
1017 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1018
1019 /* Set real nexthop. */
1020 nexthop_active_update (rn, fib, 1);
1021 }
1022
1023 /* Install new rib into forwarding table. */
1024 if (select)
1025 {
1026 /* Set real nexthop. */
1027 nexthop_active_update (rn, select, 1);
1028
1029 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001030 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001031 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1032 redistribute_add (&rn->p, select);
1033 }
paul4d38fdb2005-04-28 17:35:14 +00001034
1035 return WQ_SUCCESS;
1036
1037}
1038
1039/* Add work queue item to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001040static void
paul4d38fdb2005-04-28 17:35:14 +00001041rib_queue_add_qnode (struct zebra_t *zebra, struct zebra_queue_node_t *qnode)
1042{
1043 route_lock_node (qnode->node);
1044
1045 if (IS_ZEBRA_DEBUG_EVENT)
1046 zlog_info ("rib_queue_add_qnode: work queue added");
1047
1048 assert (zebra && qnode && qnode->node);
1049
1050 if (qnode->del)
1051 rib_lock (qnode->del);
1052
1053 if (zebra->ribq == NULL)
1054 {
1055 zlog_err ("rib_queue_add_qnode: ribq work_queue does not exist!");
1056 route_unlock_node (qnode->node);
1057 return;
1058 }
1059
1060 work_queue_add (zebra->ribq, qnode);
1061
1062 return;
1063}
1064
1065/* Add route node and rib to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001066static void
paul4d38fdb2005-04-28 17:35:14 +00001067rib_queue_add (struct zebra_t *zebra, struct route_node *rn, struct rib *del)
1068{
1069 struct zebra_queue_node_t *qnode;
1070
1071 assert (zebra && rn);
1072
1073 qnode = (struct zebra_queue_node_t *)
1074 XCALLOC (MTYPE_RIB_QUEUE, sizeof (struct zebra_queue_node_t));
1075
1076 if (qnode == NULL)
1077 {
1078 zlog_err ("rib_queue_add: failed to allocate queue node memory, %s",
1079 strerror (errno));
1080 return;
1081 }
1082
1083 qnode->node = rn;
1084 qnode->del = del;
1085
1086 rib_queue_add_qnode (zebra, qnode);
1087
1088 return;
1089}
1090
1091/* free zebra_queue_node_t */
paula1ac18c2005-06-28 17:17:12 +00001092static void
paul0fb58d52005-11-14 14:31:49 +00001093rib_queue_qnode_del (struct work_queue *wq, void *data)
paul4d38fdb2005-04-28 17:35:14 +00001094{
paul0fb58d52005-11-14 14:31:49 +00001095 struct zebra_queue_node_t *qnode = data;
paul4d38fdb2005-04-28 17:35:14 +00001096 route_unlock_node (qnode->node);
1097
1098 if (qnode->del)
1099 rib_unlock (qnode->del);
1100
1101 XFREE (MTYPE_RIB_QUEUE, qnode);
1102}
1103
1104/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001105static void
paul4d38fdb2005-04-28 17:35:14 +00001106rib_queue_init (struct zebra_t *zebra)
1107{
1108 assert (zebra);
1109
1110 if (! (zebra->ribq = work_queue_new (zebra->master,
1111 "zebra_rib_work_queue")))
1112 {
1113 zlog_err ("rib_queue_init: could not initialise work queue!");
1114 return;
1115 }
1116
1117 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001118 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001119 zebra->ribq->spec.errorfunc = NULL;
paul0fb58d52005-11-14 14:31:49 +00001120 zebra->ribq->spec.del_item_data = &rib_queue_qnode_del;
paul4d38fdb2005-04-28 17:35:14 +00001121 /* XXX: TODO: These should be runtime configurable via vty */
1122 zebra->ribq->spec.max_retries = 3;
paul4d38fdb2005-04-28 17:35:14 +00001123
1124 return;
paul718e3742002-12-13 20:15:29 +00001125}
1126
1127/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001128static void
paul718e3742002-12-13 20:15:29 +00001129rib_addnode (struct route_node *rn, struct rib *rib)
1130{
1131 struct rib *head;
paul4d38fdb2005-04-28 17:35:14 +00001132
1133 assert (rib && rn);
1134
1135 rib_lock (rib);
1136 route_lock_node (rn);
1137
paul718e3742002-12-13 20:15:29 +00001138 head = rn->info;
1139 if (head)
1140 head->prev = rib;
1141 rib->next = head;
1142 rn->info = rib;
1143}
1144
paula1ac18c2005-06-28 17:17:12 +00001145static void
paul718e3742002-12-13 20:15:29 +00001146rib_delnode (struct route_node *rn, struct rib *rib)
1147{
paul4d38fdb2005-04-28 17:35:14 +00001148 assert (rn && rib);
1149
paul718e3742002-12-13 20:15:29 +00001150 if (rib->next)
1151 rib->next->prev = rib->prev;
1152 if (rib->prev)
1153 rib->prev->next = rib->next;
1154 else
1155 rn->info = rib->next;
paul4d38fdb2005-04-28 17:35:14 +00001156
1157 rib_unlock (rib);
1158 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001159}
1160
1161int
1162rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1163 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1164 u_int32_t metric, u_char distance)
1165{
1166 struct rib *rib;
1167 struct rib *same = NULL;
1168 struct route_table *table;
1169 struct route_node *rn;
1170 struct nexthop *nexthop;
1171
1172 /* Lookup table. */
1173 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1174 if (! table)
1175 return 0;
1176
1177 /* Make it sure prefixlen is applied to the prefix. */
1178 apply_mask_ipv4 (p);
1179
1180 /* Set default distance by route type. */
1181 if (distance == 0)
1182 {
1183 distance = route_info[type].distance;
1184
1185 /* iBGP distance is 200. */
1186 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1187 distance = 200;
1188 }
1189
1190 /* Lookup route node.*/
1191 rn = route_node_get (table, (struct prefix *) p);
1192
1193 /* If same type of route are installed, treat it as a implicit
1194 withdraw. */
1195 for (rib = rn->info; rib; rib = rib->next)
1196 {
hassoebf1ead2005-09-21 14:58:20 +00001197 if (rib->type != type)
1198 continue;
1199 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001200 {
1201 same = rib;
1202 break;
1203 }
hassoebf1ead2005-09-21 14:58:20 +00001204 /* Duplicate connected route comes in. */
1205 else if ((nexthop = rib->nexthop) &&
1206 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1207 nexthop->ifindex == ifindex)
1208 {
1209 rib->refcnt++;
1210 return 0 ;
1211 }
paul718e3742002-12-13 20:15:29 +00001212 }
1213
1214 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001215 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001216 rib->type = type;
1217 rib->distance = distance;
1218 rib->flags = flags;
1219 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001220 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001221 rib->nexthop_num = 0;
1222 rib->uptime = time (NULL);
1223
1224 /* Nexthop settings. */
1225 if (gate)
1226 {
1227 if (ifindex)
1228 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1229 else
1230 nexthop_ipv4_add (rib, gate);
1231 }
1232 else
1233 nexthop_ifindex_add (rib, ifindex);
1234
1235 /* If this route is kernel route, set FIB flag to the route. */
1236 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1237 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1238 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1239
1240 /* Link new rib to node.*/
1241 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001242
paul718e3742002-12-13 20:15:29 +00001243 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001244 rib_queue_add (&zebrad, rn, same);
1245
paul718e3742002-12-13 20:15:29 +00001246 /* Free implicit route.*/
1247 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001248 rib_delnode (rn, same);
1249
1250 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001251 return 0;
1252}
1253
1254int
1255rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1256{
1257 struct route_table *table;
1258 struct route_node *rn;
1259 struct rib *same;
1260 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001261
paul718e3742002-12-13 20:15:29 +00001262 /* Lookup table. */
1263 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1264 if (! table)
1265 return 0;
paul718e3742002-12-13 20:15:29 +00001266 /* Make it sure prefixlen is applied to the prefix. */
1267 apply_mask_ipv4 (p);
1268
1269 /* Set default distance by route type. */
1270 if (rib->distance == 0)
1271 {
1272 rib->distance = route_info[rib->type].distance;
1273
1274 /* iBGP distance is 200. */
1275 if (rib->type == ZEBRA_ROUTE_BGP
1276 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1277 rib->distance = 200;
1278 }
1279
1280 /* Lookup route node.*/
1281 rn = route_node_get (table, (struct prefix *) p);
1282
1283 /* If same type of route are installed, treat it as a implicit
1284 withdraw. */
1285 for (same = rn->info; same; same = same->next)
1286 {
1287 if (same->type == rib->type && same->table == rib->table
1288 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001289 break;
paul718e3742002-12-13 20:15:29 +00001290 }
paul4d38fdb2005-04-28 17:35:14 +00001291
paul718e3742002-12-13 20:15:29 +00001292 /* If this route is kernel route, set FIB flag to the route. */
1293 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1294 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1295 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1296
1297 /* Link new rib to node.*/
1298 rib_addnode (rn, rib);
1299
1300 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001301 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001302
1303 /* Free implicit route.*/
1304 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001305 rib_delnode (rn, same);
1306
1307 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001308 return 0;
1309}
1310
hassoebf1ead2005-09-21 14:58:20 +00001311/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001312int
1313rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1314 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1315{
1316 struct route_table *table;
1317 struct route_node *rn;
1318 struct rib *rib;
1319 struct rib *fib = NULL;
1320 struct rib *same = NULL;
1321 struct nexthop *nexthop;
1322 char buf1[BUFSIZ];
1323 char buf2[BUFSIZ];
1324
1325 /* Lookup table. */
1326 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1327 if (! table)
1328 return 0;
1329
1330 /* Apply mask. */
1331 apply_mask_ipv4 (p);
1332
paul5ec90d22003-06-19 01:41:37 +00001333 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001334 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001335 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1336 p->prefixlen,
1337 inet_ntoa (*gate),
1338 ifindex);
1339
paul718e3742002-12-13 20:15:29 +00001340 /* Lookup route node. */
1341 rn = route_node_lookup (table, (struct prefix *) p);
1342 if (! rn)
1343 {
1344 if (IS_ZEBRA_DEBUG_KERNEL)
1345 {
1346 if (gate)
ajsb6178002004-12-07 21:12:56 +00001347 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001348 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1349 p->prefixlen,
1350 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1351 ifindex);
1352 else
ajsb6178002004-12-07 21:12:56 +00001353 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001354 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1355 p->prefixlen,
1356 ifindex);
1357 }
1358 return ZEBRA_ERR_RTNOEXIST;
1359 }
1360
1361 /* Lookup same type route. */
1362 for (rib = rn->info; rib; rib = rib->next)
1363 {
1364 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1365 fib = rib;
1366
hassoebf1ead2005-09-21 14:58:20 +00001367 if (rib->type != type)
1368 continue;
1369 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1370 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001371 {
hassoebf1ead2005-09-21 14:58:20 +00001372 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001373 {
hassoebf1ead2005-09-21 14:58:20 +00001374 rib->refcnt--;
1375 route_unlock_node (rn);
1376 route_unlock_node (rn);
1377 return 0;
paul718e3742002-12-13 20:15:29 +00001378 }
hassoebf1ead2005-09-21 14:58:20 +00001379 same = rib;
1380 break;
paul718e3742002-12-13 20:15:29 +00001381 }
hassoebf1ead2005-09-21 14:58:20 +00001382 /* Make sure that the route found has the same gateway. */
1383 else if (gate == NULL ||
1384 ((nexthop = rib->nexthop) &&
1385 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1386 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001387 {
hassoebf1ead2005-09-21 14:58:20 +00001388 same = rib;
1389 break;
paul718e3742002-12-13 20:15:29 +00001390 }
1391 }
1392
1393 /* If same type of route can't be found and this message is from
1394 kernel. */
1395 if (! same)
1396 {
1397 if (fib && type == ZEBRA_ROUTE_KERNEL)
1398 {
1399 /* Unset flags. */
1400 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1401 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1402
1403 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1404 }
1405 else
1406 {
1407 if (IS_ZEBRA_DEBUG_KERNEL)
1408 {
1409 if (gate)
ajsb6178002004-12-07 21:12:56 +00001410 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001411 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1412 p->prefixlen,
1413 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1414 ifindex,
1415 type);
1416 else
ajsb6178002004-12-07 21:12:56 +00001417 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001418 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1419 p->prefixlen,
1420 ifindex,
1421 type);
1422 }
1423 route_unlock_node (rn);
1424 return ZEBRA_ERR_RTNOEXIST;
1425 }
1426 }
paul4d38fdb2005-04-28 17:35:14 +00001427
1428 /* Process changes. */
1429 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001430
1431 if (same)
1432 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001433
paul718e3742002-12-13 20:15:29 +00001434 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001435 return 0;
1436}
1437
1438/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001439static void
paul718e3742002-12-13 20:15:29 +00001440static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1441{
1442 struct rib *rib;
1443 struct route_node *rn;
1444 struct route_table *table;
1445
1446 /* Lookup table. */
1447 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1448 if (! table)
1449 return;
1450
1451 /* Lookup existing route */
1452 rn = route_node_get (table, p);
1453 for (rib = rn->info; rib; rib = rib->next)
1454 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1455 break;
1456
1457 if (rib)
1458 {
1459 /* Same distance static route is there. Update it with new
1460 nexthop. */
paul718e3742002-12-13 20:15:29 +00001461 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001462 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001463 {
1464 case STATIC_IPV4_GATEWAY:
1465 nexthop_ipv4_add (rib, &si->gate.ipv4);
1466 break;
1467 case STATIC_IPV4_IFNAME:
1468 nexthop_ifname_add (rib, si->gate.ifname);
1469 break;
1470 case STATIC_IPV4_BLACKHOLE:
1471 nexthop_blackhole_add (rib);
1472 break;
paul4d38fdb2005-04-28 17:35:14 +00001473 }
1474 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001475 }
1476 else
1477 {
1478 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001479 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1480
paul718e3742002-12-13 20:15:29 +00001481 rib->type = ZEBRA_ROUTE_STATIC;
1482 rib->distance = si->distance;
1483 rib->metric = 0;
1484 rib->nexthop_num = 0;
1485
1486 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001487 {
1488 case STATIC_IPV4_GATEWAY:
1489 nexthop_ipv4_add (rib, &si->gate.ipv4);
1490 break;
1491 case STATIC_IPV4_IFNAME:
1492 nexthop_ifname_add (rib, si->gate.ifname);
1493 break;
1494 case STATIC_IPV4_BLACKHOLE:
1495 nexthop_blackhole_add (rib);
1496 break;
1497 }
paul718e3742002-12-13 20:15:29 +00001498
hasso81dfcaa2003-05-25 19:21:25 +00001499 /* Save the flags of this static routes (reject, blackhole) */
1500 rib->flags = si->flags;
1501
paul718e3742002-12-13 20:15:29 +00001502 /* Link this rib to the tree. */
1503 rib_addnode (rn, rib);
1504
1505 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00001506 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001507 }
1508}
1509
paula1ac18c2005-06-28 17:17:12 +00001510static int
paul718e3742002-12-13 20:15:29 +00001511static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1512{
1513 if (nexthop->type == NEXTHOP_TYPE_IPV4
1514 && si->type == STATIC_IPV4_GATEWAY
1515 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1516 return 1;
1517 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1518 && si->type == STATIC_IPV4_IFNAME
1519 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1520 return 1;
paul595db7f2003-05-25 21:35:06 +00001521 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1522 && si->type == STATIC_IPV4_BLACKHOLE)
1523 return 1;
paule8e19462006-01-19 20:16:55 +00001524 return 0;
paul718e3742002-12-13 20:15:29 +00001525}
1526
1527/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001528static void
paul718e3742002-12-13 20:15:29 +00001529static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1530{
1531 struct route_node *rn;
1532 struct rib *rib;
1533 struct nexthop *nexthop;
1534 struct route_table *table;
1535
1536 /* Lookup table. */
1537 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1538 if (! table)
1539 return;
paul4d38fdb2005-04-28 17:35:14 +00001540
paul718e3742002-12-13 20:15:29 +00001541 /* Lookup existing route with type and distance. */
1542 rn = route_node_lookup (table, p);
1543 if (! rn)
1544 return;
1545
1546 for (rib = rn->info; rib; rib = rib->next)
1547 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1548 break;
1549
1550 if (! rib)
1551 {
1552 route_unlock_node (rn);
1553 return;
1554 }
1555
1556 /* Lookup nexthop. */
1557 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1558 if (static_ipv4_nexthop_same (nexthop, si))
1559 break;
1560
1561 /* Can't find nexthop. */
1562 if (! nexthop)
1563 {
1564 route_unlock_node (rn);
1565 return;
1566 }
1567
1568 /* Check nexthop. */
1569 if (rib->nexthop_num == 1)
1570 {
paul4d38fdb2005-04-28 17:35:14 +00001571 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00001572 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001573 }
1574 else
1575 {
paul6baeb982003-10-28 03:47:15 +00001576 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1577 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001578 nexthop_delete (rib, nexthop);
1579 nexthop_free (nexthop);
1580 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001581 }
paul718e3742002-12-13 20:15:29 +00001582 /* Unlock node. */
1583 route_unlock_node (rn);
1584}
1585
1586/* Add static route into static route configuration. */
1587int
hasso39db97e2004-10-12 20:50:58 +00001588static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001589 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001590{
1591 u_char type = 0;
1592 struct route_node *rn;
1593 struct static_ipv4 *si;
1594 struct static_ipv4 *pp;
1595 struct static_ipv4 *cp;
1596 struct static_ipv4 *update = NULL;
1597 struct route_table *stable;
1598
1599 /* Lookup table. */
1600 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1601 if (! stable)
1602 return -1;
1603
1604 /* Lookup static route prefix. */
1605 rn = route_node_get (stable, p);
1606
1607 /* Make flags. */
1608 if (gate)
1609 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001610 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001611 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001612 else
1613 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001614
1615 /* Do nothing if there is a same static route. */
1616 for (si = rn->info; si; si = si->next)
1617 {
1618 if (type == si->type
1619 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1620 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1621 {
1622 if (distance == si->distance)
1623 {
1624 route_unlock_node (rn);
1625 return 0;
1626 }
1627 else
1628 update = si;
1629 }
1630 }
1631
1632 /* Distance chaged. */
1633 if (update)
1634 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1635
1636 /* Make new static route structure. */
1637 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1638 memset (si, 0, sizeof (struct static_ipv4));
1639
1640 si->type = type;
1641 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001642 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001643
1644 if (gate)
1645 si->gate.ipv4 = *gate;
1646 if (ifname)
1647 si->gate.ifname = XSTRDUP (0, ifname);
1648
1649 /* Add new static route information to the tree with sort by
1650 distance value and gateway address. */
1651 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1652 {
1653 if (si->distance < cp->distance)
1654 break;
1655 if (si->distance > cp->distance)
1656 continue;
1657 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1658 {
1659 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1660 break;
1661 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1662 continue;
1663 }
1664 }
1665
1666 /* Make linked list. */
1667 if (pp)
1668 pp->next = si;
1669 else
1670 rn->info = si;
1671 if (cp)
1672 cp->prev = si;
1673 si->prev = pp;
1674 si->next = cp;
1675
1676 /* Install into rib. */
1677 static_install_ipv4 (p, si);
1678
1679 return 1;
1680}
1681
1682/* Delete static route from static route configuration. */
1683int
hasso39db97e2004-10-12 20:50:58 +00001684static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001685 u_char distance, u_int32_t vrf_id)
1686{
1687 u_char type = 0;
1688 struct route_node *rn;
1689 struct static_ipv4 *si;
1690 struct route_table *stable;
1691
1692 /* Lookup table. */
1693 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1694 if (! stable)
1695 return -1;
1696
1697 /* Lookup static route prefix. */
1698 rn = route_node_lookup (stable, p);
1699 if (! rn)
1700 return 0;
1701
1702 /* Make flags. */
1703 if (gate)
1704 type = STATIC_IPV4_GATEWAY;
1705 else if (ifname)
1706 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001707 else
1708 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001709
1710 /* Find same static route is the tree */
1711 for (si = rn->info; si; si = si->next)
1712 if (type == si->type
1713 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1714 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1715 break;
1716
1717 /* Can't find static route. */
1718 if (! si)
1719 {
1720 route_unlock_node (rn);
1721 return 0;
1722 }
1723
1724 /* Install into rib. */
1725 static_uninstall_ipv4 (p, si);
1726
1727 /* Unlink static route from linked list. */
1728 if (si->prev)
1729 si->prev->next = si->next;
1730 else
1731 rn->info = si->next;
1732 if (si->next)
1733 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001734 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001735
1736 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001737 if (ifname)
1738 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001739 XFREE (MTYPE_STATIC_IPV4, si);
1740
paul143a3852003-09-29 20:06:13 +00001741 route_unlock_node (rn);
1742
paul718e3742002-12-13 20:15:29 +00001743 return 1;
1744}
1745
1746
1747#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001748static int
paul718e3742002-12-13 20:15:29 +00001749rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1750 struct in6_addr *gate, unsigned int ifindex, int table)
1751{
hasso726f9b22003-05-25 21:04:54 +00001752 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1753#if defined (MUSICA) || defined (LINUX)
1754 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1755 if (p->prefixlen == 96)
1756 return 0;
1757#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001758 return 1;
hasso726f9b22003-05-25 21:04:54 +00001759 }
paul718e3742002-12-13 20:15:29 +00001760 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1761 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1762 {
1763 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1764 return 1;
1765 }
1766 return 0;
1767}
1768
1769int
1770rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001771 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1772 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001773{
1774 struct rib *rib;
1775 struct rib *same = NULL;
1776 struct route_table *table;
1777 struct route_node *rn;
1778 struct nexthop *nexthop;
1779
paul718e3742002-12-13 20:15:29 +00001780 /* Lookup table. */
1781 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1782 if (! table)
1783 return 0;
1784
1785 /* Make sure mask is applied. */
1786 apply_mask_ipv6 (p);
1787
1788 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001789 if (!distance)
1790 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001791
1792 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1793 distance = 200;
1794
1795 /* Filter bogus route. */
1796 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1797 return 0;
1798
1799 /* Lookup route node.*/
1800 rn = route_node_get (table, (struct prefix *) p);
1801
1802 /* If same type of route are installed, treat it as a implicit
1803 withdraw. */
1804 for (rib = rn->info; rib; rib = rib->next)
1805 {
hassoebf1ead2005-09-21 14:58:20 +00001806 if (rib->type != type)
1807 continue;
1808 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001809 {
1810 same = rib;
paul718e3742002-12-13 20:15:29 +00001811 break;
1812 }
hassoebf1ead2005-09-21 14:58:20 +00001813 else if ((nexthop = rib->nexthop) &&
1814 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1815 nexthop->ifindex == ifindex)
1816 {
1817 rib->refcnt++;
1818 return 0;
1819 }
paul718e3742002-12-13 20:15:29 +00001820 }
1821
1822 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001823 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1824
paul718e3742002-12-13 20:15:29 +00001825 rib->type = type;
1826 rib->distance = distance;
1827 rib->flags = flags;
1828 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001829 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001830 rib->nexthop_num = 0;
1831 rib->uptime = time (NULL);
1832
1833 /* Nexthop settings. */
1834 if (gate)
1835 {
1836 if (ifindex)
1837 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1838 else
1839 nexthop_ipv6_add (rib, gate);
1840 }
1841 else
1842 nexthop_ifindex_add (rib, ifindex);
1843
1844 /* If this route is kernel route, set FIB flag to the route. */
1845 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1846 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1847 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1848
1849 /* Link new rib to node.*/
1850 rib_addnode (rn, rib);
1851
1852 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001853 rib_queue_add (&zebrad, rn, same);
1854
paul718e3742002-12-13 20:15:29 +00001855 /* Free implicit route.*/
1856 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001857 rib_delnode (rn, same);
1858
1859 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001860 return 0;
1861}
1862
hassoebf1ead2005-09-21 14:58:20 +00001863/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001864int
1865rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1866 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1867{
1868 struct route_table *table;
1869 struct route_node *rn;
1870 struct rib *rib;
1871 struct rib *fib = NULL;
1872 struct rib *same = NULL;
1873 struct nexthop *nexthop;
1874 char buf1[BUFSIZ];
1875 char buf2[BUFSIZ];
1876
1877 /* Apply mask. */
1878 apply_mask_ipv6 (p);
1879
1880 /* Lookup table. */
1881 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1882 if (! table)
1883 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001884
paul718e3742002-12-13 20:15:29 +00001885 /* Lookup route node. */
1886 rn = route_node_lookup (table, (struct prefix *) p);
1887 if (! rn)
1888 {
1889 if (IS_ZEBRA_DEBUG_KERNEL)
1890 {
1891 if (gate)
ajsb6178002004-12-07 21:12:56 +00001892 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001893 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1894 p->prefixlen,
1895 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1896 ifindex);
1897 else
ajsb6178002004-12-07 21:12:56 +00001898 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001899 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1900 p->prefixlen,
1901 ifindex);
1902 }
1903 return ZEBRA_ERR_RTNOEXIST;
1904 }
1905
1906 /* Lookup same type route. */
1907 for (rib = rn->info; rib; rib = rib->next)
1908 {
1909 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1910 fib = rib;
1911
hassoebf1ead2005-09-21 14:58:20 +00001912 if (rib->type != type)
1913 continue;
1914 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1915 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001916 {
hassoebf1ead2005-09-21 14:58:20 +00001917 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001918 {
hassoebf1ead2005-09-21 14:58:20 +00001919 rib->refcnt--;
1920 route_unlock_node (rn);
1921 route_unlock_node (rn);
1922 return 0;
paul718e3742002-12-13 20:15:29 +00001923 }
hassoebf1ead2005-09-21 14:58:20 +00001924 same = rib;
1925 break;
paul718e3742002-12-13 20:15:29 +00001926 }
hassoebf1ead2005-09-21 14:58:20 +00001927 /* Make sure that the route found has the same gateway. */
1928 else if (gate == NULL ||
1929 ((nexthop = rib->nexthop) &&
1930 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
1931 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00001932 {
hassoebf1ead2005-09-21 14:58:20 +00001933 same = rib;
1934 break;
paul718e3742002-12-13 20:15:29 +00001935 }
1936 }
1937
1938 /* If same type of route can't be found and this message is from
1939 kernel. */
1940 if (! same)
1941 {
1942 if (fib && type == ZEBRA_ROUTE_KERNEL)
1943 {
1944 /* Unset flags. */
1945 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1946 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1947
1948 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1949 }
1950 else
1951 {
1952 if (IS_ZEBRA_DEBUG_KERNEL)
1953 {
1954 if (gate)
ajsb6178002004-12-07 21:12:56 +00001955 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001956 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1957 p->prefixlen,
1958 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1959 ifindex,
1960 type);
1961 else
ajsb6178002004-12-07 21:12:56 +00001962 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001963 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1964 p->prefixlen,
1965 ifindex,
1966 type);
1967 }
1968 route_unlock_node (rn);
1969 return ZEBRA_ERR_RTNOEXIST;
1970 }
1971 }
1972
paul4d38fdb2005-04-28 17:35:14 +00001973 /* Process changes. */
1974 rib_queue_add (&zebrad, rn, same);
1975
paul718e3742002-12-13 20:15:29 +00001976 if (same)
1977 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001978
paul718e3742002-12-13 20:15:29 +00001979 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001980 return 0;
1981}
1982
1983/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001984static void
paul718e3742002-12-13 20:15:29 +00001985static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1986{
1987 struct rib *rib;
1988 struct route_table *table;
1989 struct route_node *rn;
1990
1991 /* Lookup table. */
1992 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1993 if (! table)
1994 return;
1995
1996 /* Lookup existing route */
1997 rn = route_node_get (table, p);
1998 for (rib = rn->info; rib; rib = rib->next)
1999 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2000 break;
2001
2002 if (rib)
2003 {
2004 /* Same distance static route is there. Update it with new
2005 nexthop. */
paul718e3742002-12-13 20:15:29 +00002006 route_unlock_node (rn);
2007
2008 switch (si->type)
2009 {
2010 case STATIC_IPV6_GATEWAY:
2011 nexthop_ipv6_add (rib, &si->ipv6);
2012 break;
2013 case STATIC_IPV6_IFNAME:
2014 nexthop_ifname_add (rib, si->ifname);
2015 break;
2016 case STATIC_IPV6_GATEWAY_IFNAME:
2017 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2018 break;
2019 }
paul4d38fdb2005-04-28 17:35:14 +00002020 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002021 }
2022 else
2023 {
2024 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002025 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2026
paul718e3742002-12-13 20:15:29 +00002027 rib->type = ZEBRA_ROUTE_STATIC;
2028 rib->distance = si->distance;
2029 rib->metric = 0;
2030 rib->nexthop_num = 0;
2031
2032 switch (si->type)
2033 {
2034 case STATIC_IPV6_GATEWAY:
2035 nexthop_ipv6_add (rib, &si->ipv6);
2036 break;
2037 case STATIC_IPV6_IFNAME:
2038 nexthop_ifname_add (rib, si->ifname);
2039 break;
2040 case STATIC_IPV6_GATEWAY_IFNAME:
2041 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2042 break;
2043 }
2044
hasso81dfcaa2003-05-25 19:21:25 +00002045 /* Save the flags of this static routes (reject, blackhole) */
2046 rib->flags = si->flags;
2047
paul718e3742002-12-13 20:15:29 +00002048 /* Link this rib to the tree. */
2049 rib_addnode (rn, rib);
2050
2051 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00002052 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002053 }
2054}
2055
paula1ac18c2005-06-28 17:17:12 +00002056static int
paul718e3742002-12-13 20:15:29 +00002057static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2058{
2059 if (nexthop->type == NEXTHOP_TYPE_IPV6
2060 && si->type == STATIC_IPV6_GATEWAY
2061 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2062 return 1;
2063 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2064 && si->type == STATIC_IPV6_IFNAME
2065 && strcmp (nexthop->ifname, si->ifname) == 0)
2066 return 1;
2067 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2068 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2069 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2070 && strcmp (nexthop->ifname, si->ifname) == 0)
2071 return 1;
paule8e19462006-01-19 20:16:55 +00002072 return 0;
paul718e3742002-12-13 20:15:29 +00002073}
2074
paula1ac18c2005-06-28 17:17:12 +00002075static void
paul718e3742002-12-13 20:15:29 +00002076static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2077{
2078 struct route_table *table;
2079 struct route_node *rn;
2080 struct rib *rib;
2081 struct nexthop *nexthop;
2082
2083 /* Lookup table. */
2084 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2085 if (! table)
2086 return;
2087
2088 /* Lookup existing route with type and distance. */
2089 rn = route_node_lookup (table, (struct prefix *) p);
2090 if (! rn)
2091 return;
2092
2093 for (rib = rn->info; rib; rib = rib->next)
2094 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2095 break;
2096 if (! rib)
2097 {
2098 route_unlock_node (rn);
2099 return;
2100 }
2101
2102 /* Lookup nexthop. */
2103 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2104 if (static_ipv6_nexthop_same (nexthop, si))
2105 break;
2106
2107 /* Can't find nexthop. */
2108 if (! nexthop)
2109 {
2110 route_unlock_node (rn);
2111 return;
2112 }
2113
2114 /* Check nexthop. */
2115 if (rib->nexthop_num == 1)
2116 {
2117 rib_delnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002118 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00002119 }
2120 else
2121 {
paul6baeb982003-10-28 03:47:15 +00002122 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2123 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002124 nexthop_delete (rib, nexthop);
2125 nexthop_free (nexthop);
2126 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002127 }
paul718e3742002-12-13 20:15:29 +00002128 /* Unlock node. */
2129 route_unlock_node (rn);
2130}
2131
2132/* Add static route into static route configuration. */
2133int
2134static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002135 const char *ifname, u_char flags, u_char distance,
2136 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002137{
2138 struct route_node *rn;
2139 struct static_ipv6 *si;
2140 struct static_ipv6 *pp;
2141 struct static_ipv6 *cp;
2142 struct route_table *stable;
2143
2144 /* Lookup table. */
2145 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2146 if (! stable)
2147 return -1;
2148
2149 /* Lookup static route prefix. */
2150 rn = route_node_get (stable, p);
2151
2152 /* Do nothing if there is a same static route. */
2153 for (si = rn->info; si; si = si->next)
2154 {
2155 if (distance == si->distance
2156 && type == si->type
2157 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2158 && (! ifname || strcmp (ifname, si->ifname) == 0))
2159 {
2160 route_unlock_node (rn);
2161 return 0;
2162 }
2163 }
2164
2165 /* Make new static route structure. */
2166 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2167 memset (si, 0, sizeof (struct static_ipv6));
2168
2169 si->type = type;
2170 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002171 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002172
2173 switch (type)
2174 {
2175 case STATIC_IPV6_GATEWAY:
2176 si->ipv6 = *gate;
2177 break;
2178 case STATIC_IPV6_IFNAME:
2179 si->ifname = XSTRDUP (0, ifname);
2180 break;
2181 case STATIC_IPV6_GATEWAY_IFNAME:
2182 si->ipv6 = *gate;
2183 si->ifname = XSTRDUP (0, ifname);
2184 break;
2185 }
2186
2187 /* Add new static route information to the tree with sort by
2188 distance value and gateway address. */
2189 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2190 {
2191 if (si->distance < cp->distance)
2192 break;
2193 if (si->distance > cp->distance)
2194 continue;
2195 }
2196
2197 /* Make linked list. */
2198 if (pp)
2199 pp->next = si;
2200 else
2201 rn->info = si;
2202 if (cp)
2203 cp->prev = si;
2204 si->prev = pp;
2205 si->next = cp;
2206
2207 /* Install into rib. */
2208 static_install_ipv6 (p, si);
2209
2210 return 1;
2211}
2212
2213/* Delete static route from static route configuration. */
2214int
2215static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002216 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002217{
2218 struct route_node *rn;
2219 struct static_ipv6 *si;
2220 struct route_table *stable;
2221
2222 /* Lookup table. */
2223 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2224 if (! stable)
2225 return -1;
2226
2227 /* Lookup static route prefix. */
2228 rn = route_node_lookup (stable, p);
2229 if (! rn)
2230 return 0;
2231
2232 /* Find same static route is the tree */
2233 for (si = rn->info; si; si = si->next)
2234 if (distance == si->distance
2235 && type == si->type
2236 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2237 && (! ifname || strcmp (ifname, si->ifname) == 0))
2238 break;
2239
2240 /* Can't find static route. */
2241 if (! si)
2242 {
2243 route_unlock_node (rn);
2244 return 0;
2245 }
2246
2247 /* Install into rib. */
2248 static_uninstall_ipv6 (p, si);
2249
2250 /* Unlink static route from linked list. */
2251 if (si->prev)
2252 si->prev->next = si->next;
2253 else
2254 rn->info = si->next;
2255 if (si->next)
2256 si->next->prev = si->prev;
2257
2258 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002259 if (ifname)
2260 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002261 XFREE (MTYPE_STATIC_IPV6, si);
2262
2263 return 1;
2264}
2265#endif /* HAVE_IPV6 */
2266
2267/* RIB update function. */
2268void
paula1ac18c2005-06-28 17:17:12 +00002269rib_update (void)
paul718e3742002-12-13 20:15:29 +00002270{
2271 struct route_node *rn;
2272 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002273
paul718e3742002-12-13 20:15:29 +00002274 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2275 if (table)
2276 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002277 if (rn->info)
2278 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002279
2280 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2281 if (table)
2282 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002283 if (rn->info)
2284 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002285}
2286
2287/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002288static void
paul718e3742002-12-13 20:15:29 +00002289rib_if_up (struct interface *ifp)
2290{
2291 rib_update ();
2292}
2293
2294/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002295static void
paul718e3742002-12-13 20:15:29 +00002296rib_if_down (struct interface *ifp)
2297{
2298 rib_update ();
2299}
2300
2301/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002302static void
paul718e3742002-12-13 20:15:29 +00002303rib_weed_table (struct route_table *table)
2304{
2305 struct route_node *rn;
2306 struct rib *rib;
2307 struct rib *next;
2308
2309 if (table)
2310 for (rn = route_top (table); rn; rn = route_next (rn))
2311 for (rib = rn->info; rib; rib = next)
2312 {
2313 next = rib->next;
2314
paulb21b19c2003-06-15 01:28:29 +00002315 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002316 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002317 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002318 }
2319}
2320
2321/* Delete all routes from non main table. */
2322void
paula1ac18c2005-06-28 17:17:12 +00002323rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002324{
2325 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2326 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2327}
2328
2329/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002330static void
paul718e3742002-12-13 20:15:29 +00002331rib_sweep_table (struct route_table *table)
2332{
2333 struct route_node *rn;
2334 struct rib *rib;
2335 struct rib *next;
2336 int ret = 0;
2337
2338 if (table)
2339 for (rn = route_top (table); rn; rn = route_next (rn))
2340 for (rib = rn->info; rib; rib = next)
2341 {
2342 next = rib->next;
2343
2344 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2345 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2346 {
2347 ret = rib_uninstall_kernel (rn, rib);
2348 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002349 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002350 }
2351 }
2352}
2353
2354/* Sweep all RIB tables. */
2355void
paula1ac18c2005-06-28 17:17:12 +00002356rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002357{
2358 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2359 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2360}
2361
2362/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002363static void
paul718e3742002-12-13 20:15:29 +00002364rib_close_table (struct route_table *table)
2365{
2366 struct route_node *rn;
2367 struct rib *rib;
2368
2369 if (table)
2370 for (rn = route_top (table); rn; rn = route_next (rn))
2371 for (rib = rn->info; rib; rib = rib->next)
2372 if (! RIB_SYSTEM_ROUTE (rib)
2373 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2374 rib_uninstall_kernel (rn, rib);
2375}
2376
2377/* Close all RIB tables. */
2378void
paula1ac18c2005-06-28 17:17:12 +00002379rib_close (void)
paul718e3742002-12-13 20:15:29 +00002380{
2381 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2382 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2383}
2384
2385/* Routing information base initialize. */
2386void
paula1ac18c2005-06-28 17:17:12 +00002387rib_init (void)
paul718e3742002-12-13 20:15:29 +00002388{
paul4d38fdb2005-04-28 17:35:14 +00002389 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002390 /* VRF initialization. */
2391 vrf_init ();
2392}