blob: 7373c6d8460949d5bfbe04f85494c54f1e58588b [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
Paul Jakma457eb9a2006-07-27 19:59:58 +000045/* Hold time for RIB process, should be very minimal.
46 * it is useful to able to set it otherwise for testing, hence exported
47 * as global here for test-rig code.
48 */
49int rib_process_hold_time = 10;
50
paul718e3742002-12-13 20:15:29 +000051/* Each route type's string and default distance value. */
52struct
53{
54 int key;
55 int distance;
56} route_info[] =
57{
58 {ZEBRA_ROUTE_SYSTEM, 0},
59 {ZEBRA_ROUTE_KERNEL, 0},
60 {ZEBRA_ROUTE_CONNECT, 0},
61 {ZEBRA_ROUTE_STATIC, 1},
62 {ZEBRA_ROUTE_RIP, 120},
63 {ZEBRA_ROUTE_RIPNG, 120},
64 {ZEBRA_ROUTE_OSPF, 110},
65 {ZEBRA_ROUTE_OSPF6, 110},
jardin9e867fe2003-12-23 08:56:18 +000066 {ZEBRA_ROUTE_ISIS, 115},
paul718e3742002-12-13 20:15:29 +000067 {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
68};
paul4d38fdb2005-04-28 17:35:14 +000069
70struct zebra_queue_node_t
71{
72 struct route_node *node;
73 struct rib *del;
74};
paul718e3742002-12-13 20:15:29 +000075
76/* Vector for routing table. */
77vector vrf_vector;
78
79/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +000080static struct vrf *
hassofce954f2004-10-07 20:29:24 +000081vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +000082{
83 struct vrf *vrf;
84
85 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
86
87 /* Put name. */
88 if (name)
89 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
90
91 /* Allocate routing table and static table. */
92 vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
93 vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
94 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
95 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
96
97 return vrf;
98}
99
100/* Free VRF. */
paula1ac18c2005-06-28 17:17:12 +0000101static void
paul718e3742002-12-13 20:15:29 +0000102vrf_free (struct vrf *vrf)
103{
104 if (vrf->name)
105 XFREE (MTYPE_VRF_NAME, vrf->name);
106 XFREE (MTYPE_VRF, vrf);
107}
108
109/* Lookup VRF by identifier. */
110struct vrf *
111vrf_lookup (u_int32_t id)
112{
113 return vector_lookup (vrf_vector, id);
114}
115
116/* Lookup VRF by name. */
paula1ac18c2005-06-28 17:17:12 +0000117static struct vrf *
paul718e3742002-12-13 20:15:29 +0000118vrf_lookup_by_name (char *name)
119{
hassofce954f2004-10-07 20:29:24 +0000120 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000121 struct vrf *vrf;
122
paul55468c82005-03-14 20:19:01 +0000123 for (i = 0; i < vector_active (vrf_vector); i++)
paul718e3742002-12-13 20:15:29 +0000124 if ((vrf = vector_slot (vrf_vector, i)) != NULL)
125 if (vrf->name && name && strcmp (vrf->name, name) == 0)
126 return vrf;
127 return NULL;
128}
129
130/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000131static void
132vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000133{
134 struct vrf *default_table;
135
136 /* Allocate VRF vector. */
137 vrf_vector = vector_init (1);
138
139 /* Allocate default main table. */
140 default_table = vrf_alloc ("Default-IP-Routing-Table");
141
142 /* Default table index must be 0. */
143 vector_set_index (vrf_vector, 0, default_table);
144}
145
146/* Lookup route table. */
147struct route_table *
148vrf_table (afi_t afi, safi_t safi, u_int32_t id)
149{
150 struct vrf *vrf;
151
152 vrf = vrf_lookup (id);
153 if (! vrf)
154 return NULL;
155
156 return vrf->table[afi][safi];
157}
158
159/* Lookup static route table. */
160struct route_table *
161vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
162{
163 struct vrf *vrf;
164
165 vrf = vrf_lookup (id);
166 if (! vrf)
167 return NULL;
168
169 return vrf->stable[afi][safi];
170}
171
172/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000173static void
paul718e3742002-12-13 20:15:29 +0000174nexthop_add (struct rib *rib, struct nexthop *nexthop)
175{
176 struct nexthop *last;
177
178 for (last = rib->nexthop; last && last->next; last = last->next)
179 ;
180 if (last)
181 last->next = nexthop;
182 else
183 rib->nexthop = nexthop;
184 nexthop->prev = last;
185
186 rib->nexthop_num++;
187}
188
189/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000190static void
paul718e3742002-12-13 20:15:29 +0000191nexthop_delete (struct rib *rib, struct nexthop *nexthop)
192{
193 if (nexthop->next)
194 nexthop->next->prev = nexthop->prev;
195 if (nexthop->prev)
196 nexthop->prev->next = nexthop->next;
197 else
198 rib->nexthop = nexthop->next;
199 rib->nexthop_num--;
200}
201
202/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000203static void
paul718e3742002-12-13 20:15:29 +0000204nexthop_free (struct nexthop *nexthop)
205{
paula4b70762003-05-16 17:19:48 +0000206 if (nexthop->ifname)
207 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000208 XFREE (MTYPE_NEXTHOP, nexthop);
209}
210
211struct nexthop *
212nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
213{
214 struct nexthop *nexthop;
215
216 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
217 memset (nexthop, 0, sizeof (struct nexthop));
218 nexthop->type = NEXTHOP_TYPE_IFINDEX;
219 nexthop->ifindex = ifindex;
220
221 nexthop_add (rib, nexthop);
222
223 return nexthop;
224}
225
226struct nexthop *
227nexthop_ifname_add (struct rib *rib, char *ifname)
228{
229 struct nexthop *nexthop;
230
231 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
232 memset (nexthop, 0, sizeof (struct nexthop));
233 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000234 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000235
236 nexthop_add (rib, nexthop);
237
238 return nexthop;
239}
240
241struct nexthop *
242nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
243{
244 struct nexthop *nexthop;
245
246 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
247 memset (nexthop, 0, sizeof (struct nexthop));
248 nexthop->type = NEXTHOP_TYPE_IPV4;
249 nexthop->gate.ipv4 = *ipv4;
250
251 nexthop_add (rib, nexthop);
252
253 return nexthop;
254}
255
paula1ac18c2005-06-28 17:17:12 +0000256static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000257nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
258 unsigned int ifindex)
259{
260 struct nexthop *nexthop;
261
262 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
263 memset (nexthop, 0, sizeof (struct nexthop));
264 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
265 nexthop->gate.ipv4 = *ipv4;
266 nexthop->ifindex = ifindex;
267
268 nexthop_add (rib, nexthop);
269
270 return nexthop;
271}
272
273#ifdef HAVE_IPV6
274struct nexthop *
275nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
276{
277 struct nexthop *nexthop;
278
279 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
280 memset (nexthop, 0, sizeof (struct nexthop));
281 nexthop->type = NEXTHOP_TYPE_IPV6;
282 nexthop->gate.ipv6 = *ipv6;
283
284 nexthop_add (rib, nexthop);
285
286 return nexthop;
287}
288
paula1ac18c2005-06-28 17:17:12 +0000289static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000290nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
291 char *ifname)
292{
293 struct nexthop *nexthop;
294
295 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
296 memset (nexthop, 0, sizeof (struct nexthop));
297 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
298 nexthop->gate.ipv6 = *ipv6;
299 nexthop->ifname = XSTRDUP (0, ifname);
300
301 nexthop_add (rib, nexthop);
302
303 return nexthop;
304}
305
paula1ac18c2005-06-28 17:17:12 +0000306static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000307nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
308 unsigned int ifindex)
309{
310 struct nexthop *nexthop;
311
312 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
313 memset (nexthop, 0, sizeof (struct nexthop));
314 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
315 nexthop->gate.ipv6 = *ipv6;
316 nexthop->ifindex = ifindex;
317
318 nexthop_add (rib, nexthop);
319
320 return nexthop;
321}
322#endif /* HAVE_IPV6 */
323
paul595db7f2003-05-25 21:35:06 +0000324struct nexthop *
325nexthop_blackhole_add (struct rib *rib)
326{
327 struct nexthop *nexthop;
328
329 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
330 memset (nexthop, 0, sizeof (struct nexthop));
331 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
332 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
333
334 nexthop_add (rib, nexthop);
335
336 return nexthop;
337}
338
paul718e3742002-12-13 20:15:29 +0000339/* If force flag is not set, do not modify falgs at all for uninstall
340 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000341static int
paul718e3742002-12-13 20:15:29 +0000342nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
343 struct route_node *top)
344{
345 struct prefix_ipv4 p;
346 struct route_table *table;
347 struct route_node *rn;
348 struct rib *match;
349 struct nexthop *newhop;
350
351 if (nexthop->type == NEXTHOP_TYPE_IPV4)
352 nexthop->ifindex = 0;
353
354 if (set)
355 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
356
357 /* Make lookup prefix. */
358 memset (&p, 0, sizeof (struct prefix_ipv4));
359 p.family = AF_INET;
360 p.prefixlen = IPV4_MAX_PREFIXLEN;
361 p.prefix = nexthop->gate.ipv4;
362
363 /* Lookup table. */
364 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
365 if (! table)
366 return 0;
367
368 rn = route_node_match (table, (struct prefix *) &p);
369 while (rn)
370 {
371 route_unlock_node (rn);
372
373 /* If lookup self prefix return immidiately. */
374 if (rn == top)
375 return 0;
376
377 /* Pick up selected route. */
378 for (match = rn->info; match; match = match->next)
379 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
380 break;
381
382 /* If there is no selected route or matched route is EGP, go up
383 tree. */
384 if (! match
385 || match->type == ZEBRA_ROUTE_BGP)
386 {
387 do {
388 rn = rn->parent;
389 } while (rn && rn->info == NULL);
390 if (rn)
391 route_lock_node (rn);
392 }
393 else
394 {
395 if (match->type == ZEBRA_ROUTE_CONNECT)
396 {
397 /* Directly point connected route. */
398 newhop = match->nexthop;
399 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
400 nexthop->ifindex = newhop->ifindex;
401
402 return 1;
403 }
404 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
405 {
406 for (newhop = match->nexthop; newhop; newhop = newhop->next)
407 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
408 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
409 {
410 if (set)
411 {
412 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
413 nexthop->rtype = newhop->type;
414 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
415 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
416 nexthop->rgate.ipv4 = newhop->gate.ipv4;
417 if (newhop->type == NEXTHOP_TYPE_IFINDEX
418 || newhop->type == NEXTHOP_TYPE_IFNAME
419 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
420 nexthop->rifindex = newhop->ifindex;
421 }
422 return 1;
423 }
424 return 0;
425 }
426 else
427 {
428 return 0;
429 }
430 }
431 }
432 return 0;
433}
434
435#ifdef HAVE_IPV6
436/* If force flag is not set, do not modify falgs at all for uninstall
437 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000438static int
paul718e3742002-12-13 20:15:29 +0000439nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
440 struct route_node *top)
441{
442 struct prefix_ipv6 p;
443 struct route_table *table;
444 struct route_node *rn;
445 struct rib *match;
446 struct nexthop *newhop;
447
448 if (nexthop->type == NEXTHOP_TYPE_IPV6)
449 nexthop->ifindex = 0;
450
451 if (set)
452 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
453
454 /* Make lookup prefix. */
455 memset (&p, 0, sizeof (struct prefix_ipv6));
456 p.family = AF_INET6;
457 p.prefixlen = IPV6_MAX_PREFIXLEN;
458 p.prefix = nexthop->gate.ipv6;
459
460 /* Lookup table. */
461 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
462 if (! table)
463 return 0;
464
465 rn = route_node_match (table, (struct prefix *) &p);
466 while (rn)
467 {
468 route_unlock_node (rn);
469
470 /* If lookup self prefix return immidiately. */
471 if (rn == top)
472 return 0;
473
474 /* Pick up selected route. */
475 for (match = rn->info; match; match = match->next)
476 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
477 break;
478
479 /* If there is no selected route or matched route is EGP, go up
480 tree. */
481 if (! match
482 || match->type == ZEBRA_ROUTE_BGP)
483 {
484 do {
485 rn = rn->parent;
486 } while (rn && rn->info == NULL);
487 if (rn)
488 route_lock_node (rn);
489 }
490 else
491 {
492 if (match->type == ZEBRA_ROUTE_CONNECT)
493 {
494 /* Directly point connected route. */
495 newhop = match->nexthop;
496
497 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
498 nexthop->ifindex = newhop->ifindex;
499
500 return 1;
501 }
502 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
503 {
504 for (newhop = match->nexthop; newhop; newhop = newhop->next)
505 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
506 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
507 {
508 if (set)
509 {
510 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
511 nexthop->rtype = newhop->type;
512 if (newhop->type == NEXTHOP_TYPE_IPV6
513 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
514 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
515 nexthop->rgate.ipv6 = newhop->gate.ipv6;
516 if (newhop->type == NEXTHOP_TYPE_IFINDEX
517 || newhop->type == NEXTHOP_TYPE_IFNAME
518 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
519 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
520 nexthop->rifindex = newhop->ifindex;
521 }
522 return 1;
523 }
524 return 0;
525 }
526 else
527 {
528 return 0;
529 }
530 }
531 }
532 return 0;
533}
534#endif /* HAVE_IPV6 */
535
536struct rib *
537rib_match_ipv4 (struct in_addr addr)
538{
539 struct prefix_ipv4 p;
540 struct route_table *table;
541 struct route_node *rn;
542 struct rib *match;
543 struct nexthop *newhop;
544
545 /* Lookup table. */
546 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
547 if (! table)
548 return 0;
549
550 memset (&p, 0, sizeof (struct prefix_ipv4));
551 p.family = AF_INET;
552 p.prefixlen = IPV4_MAX_PREFIXLEN;
553 p.prefix = addr;
554
555 rn = route_node_match (table, (struct prefix *) &p);
556
557 while (rn)
558 {
559 route_unlock_node (rn);
560
561 /* Pick up selected route. */
562 for (match = rn->info; match; match = match->next)
563 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
564 break;
565
566 /* If there is no selected route or matched route is EGP, go up
567 tree. */
568 if (! match
569 || match->type == ZEBRA_ROUTE_BGP)
570 {
571 do {
572 rn = rn->parent;
573 } while (rn && rn->info == NULL);
574 if (rn)
575 route_lock_node (rn);
576 }
577 else
578 {
579 if (match->type == ZEBRA_ROUTE_CONNECT)
580 /* Directly point connected route. */
581 return match;
582 else
583 {
584 for (newhop = match->nexthop; newhop; newhop = newhop->next)
585 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
586 return match;
587 return NULL;
588 }
589 }
590 }
591 return NULL;
592}
593
594struct rib *
595rib_lookup_ipv4 (struct prefix_ipv4 *p)
596{
597 struct route_table *table;
598 struct route_node *rn;
599 struct rib *match;
600 struct nexthop *nexthop;
601
602 /* Lookup table. */
603 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
604 if (! table)
605 return 0;
606
607 rn = route_node_lookup (table, (struct prefix *) p);
608
609 /* No route for this prefix. */
610 if (! rn)
611 return NULL;
612
613 /* Unlock node. */
614 route_unlock_node (rn);
615
616 /* Pick up selected route. */
617 for (match = rn->info; match; match = match->next)
618 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
619 break;
620
621 if (! match || match->type == ZEBRA_ROUTE_BGP)
622 return NULL;
623
624 if (match->type == ZEBRA_ROUTE_CONNECT)
625 return match;
626
627 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
628 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
629 return match;
630
631 return NULL;
632}
633
634#ifdef HAVE_IPV6
635struct rib *
636rib_match_ipv6 (struct in6_addr *addr)
637{
638 struct prefix_ipv6 p;
639 struct route_table *table;
640 struct route_node *rn;
641 struct rib *match;
642 struct nexthop *newhop;
643
644 /* Lookup table. */
645 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
646 if (! table)
647 return 0;
648
649 memset (&p, 0, sizeof (struct prefix_ipv6));
650 p.family = AF_INET6;
651 p.prefixlen = IPV6_MAX_PREFIXLEN;
652 IPV6_ADDR_COPY (&p.prefix, addr);
653
654 rn = route_node_match (table, (struct prefix *) &p);
655
656 while (rn)
657 {
658 route_unlock_node (rn);
659
660 /* Pick up selected route. */
661 for (match = rn->info; match; match = match->next)
662 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
663 break;
664
665 /* If there is no selected route or matched route is EGP, go up
666 tree. */
667 if (! match
668 || match->type == ZEBRA_ROUTE_BGP)
669 {
670 do {
671 rn = rn->parent;
672 } while (rn && rn->info == NULL);
673 if (rn)
674 route_lock_node (rn);
675 }
676 else
677 {
678 if (match->type == ZEBRA_ROUTE_CONNECT)
679 /* Directly point connected route. */
680 return match;
681 else
682 {
683 for (newhop = match->nexthop; newhop; newhop = newhop->next)
684 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
685 return match;
686 return NULL;
687 }
688 }
689 }
690 return NULL;
691}
692#endif /* HAVE_IPV6 */
693
paula1ac18c2005-06-28 17:17:12 +0000694static int
paul718e3742002-12-13 20:15:29 +0000695nexthop_active_check (struct route_node *rn, struct rib *rib,
696 struct nexthop *nexthop, int set)
697{
698 struct interface *ifp;
699
700 switch (nexthop->type)
701 {
702 case NEXTHOP_TYPE_IFINDEX:
703 ifp = if_lookup_by_index (nexthop->ifindex);
704 if (ifp && if_is_up (ifp))
705 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
706 else
707 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
708 break;
709 case NEXTHOP_TYPE_IFNAME:
710 case NEXTHOP_TYPE_IPV6_IFNAME:
711 ifp = if_lookup_by_name (nexthop->ifname);
712 if (ifp && if_is_up (ifp))
713 {
714 if (set)
715 nexthop->ifindex = ifp->ifindex;
716 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
717 }
718 else
719 {
720 if (set)
721 nexthop->ifindex = 0;
722 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
723 }
724 break;
725 case NEXTHOP_TYPE_IPV4:
726 case NEXTHOP_TYPE_IPV4_IFINDEX:
727 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
728 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
729 else
730 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
731 break;
732#ifdef HAVE_IPV6
733 case NEXTHOP_TYPE_IPV6:
734 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
735 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
736 else
737 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
738 break;
739 case NEXTHOP_TYPE_IPV6_IFINDEX:
740 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
741 {
742 ifp = if_lookup_by_index (nexthop->ifindex);
743 if (ifp && if_is_up (ifp))
744 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
745 else
746 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
747 }
748 else
749 {
750 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
751 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
752 else
753 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
754 }
755 break;
756#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000757 case NEXTHOP_TYPE_BLACKHOLE:
758 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
759 break;
paul718e3742002-12-13 20:15:29 +0000760 default:
761 break;
762 }
763 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
764}
765
paula1ac18c2005-06-28 17:17:12 +0000766static int
paul718e3742002-12-13 20:15:29 +0000767nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
768{
769 struct nexthop *nexthop;
770 int active;
771
772 rib->nexthop_active_num = 0;
773 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
774
775 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
776 {
777 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul6baeb982003-10-28 03:47:15 +0000778
779 nexthop_active_check (rn, rib, nexthop, set);
780 if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM)
781 && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
782 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
783
784 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
785 rib->nexthop_active_num++;
paul718e3742002-12-13 20:15:29 +0000786 }
787 return rib->nexthop_active_num;
788}
paul6baeb982003-10-28 03:47:15 +0000789
paul718e3742002-12-13 20:15:29 +0000790
791#define RIB_SYSTEM_ROUTE(R) \
792 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
793
paul4d38fdb2005-04-28 17:35:14 +0000794static struct rib *
795rib_lock (struct rib *rib)
796{
797 assert (rib->lock >= 0);
798
799 rib->lock++;
800 return rib;
801}
802
803static struct rib *
804rib_unlock (struct rib *rib)
paul718e3742002-12-13 20:15:29 +0000805{
806 struct nexthop *nexthop;
807 struct nexthop *next;
paul4d38fdb2005-04-28 17:35:14 +0000808
809 assert (rib->lock > 0);
810 rib->lock--;
paul718e3742002-12-13 20:15:29 +0000811
paul4d38fdb2005-04-28 17:35:14 +0000812 if (rib->lock == 0)
paul718e3742002-12-13 20:15:29 +0000813 {
paul4d38fdb2005-04-28 17:35:14 +0000814 for (nexthop = rib->nexthop; nexthop; nexthop = next)
815 {
816 next = nexthop->next;
817 nexthop_free (nexthop);
818 }
819 XFREE (MTYPE_RIB, rib);
820 return NULL;
paul718e3742002-12-13 20:15:29 +0000821 }
paul4d38fdb2005-04-28 17:35:14 +0000822 return rib;
paul718e3742002-12-13 20:15:29 +0000823}
824
paula1ac18c2005-06-28 17:17:12 +0000825static void
paul718e3742002-12-13 20:15:29 +0000826rib_install_kernel (struct route_node *rn, struct rib *rib)
827{
828 int ret = 0;
829 struct nexthop *nexthop;
830
831 switch (PREFIX_FAMILY (&rn->p))
832 {
833 case AF_INET:
834 ret = kernel_add_ipv4 (&rn->p, rib);
835 break;
836#ifdef HAVE_IPV6
837 case AF_INET6:
838 ret = kernel_add_ipv6 (&rn->p, rib);
839 break;
840#endif /* HAVE_IPV6 */
841 }
842
843 if (ret < 0)
844 {
845 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
846 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
847 }
848}
849
850/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000851static int
paul718e3742002-12-13 20:15:29 +0000852rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
853{
854 int ret = 0;
855 struct nexthop *nexthop;
856
857 switch (PREFIX_FAMILY (&rn->p))
858 {
859 case AF_INET:
860 ret = kernel_delete_ipv4 (&rn->p, rib);
861 break;
862#ifdef HAVE_IPV6
863 case AF_INET6:
864 ret = kernel_delete_ipv6 (&rn->p, rib);
865 break;
866#endif /* HAVE_IPV6 */
867 }
868
869 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
870 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
871
872 return ret;
873}
874
875/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000876static void
paul718e3742002-12-13 20:15:29 +0000877rib_uninstall (struct route_node *rn, struct rib *rib)
878{
879 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
880 {
881 redistribute_delete (&rn->p, rib);
882 if (! RIB_SYSTEM_ROUTE (rib))
883 rib_uninstall_kernel (rn, rib);
884 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
885 }
886}
887
888/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000889static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000890rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000891{
paul0fb58d52005-11-14 14:31:49 +0000892 struct zebra_queue_node_t *qnode = data;
paul718e3742002-12-13 20:15:29 +0000893 struct rib *rib;
894 struct rib *next;
895 struct rib *fib = NULL;
896 struct rib *select = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000897 struct rib *del = qnode->del;
898 struct route_node *rn = qnode->node;
pauld753e9e2003-01-22 19:45:50 +0000899 int installed = 0;
900 struct nexthop *nexthop = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000901
902 assert (rn);
903
904 /* possibly should lock and unlock rib on each iteration. however, for
905 * now, we assume called functions are synchronous and dont delete RIBs
906 * (as the work-queue deconstructor for this function is supposed to be
907 * the canonical 'delete' path for RIBs). Further if called functions
908 * below were to made asynchronous they should themselves acquire any
909 * locks/refcounts as needed and not depend on this caller to do it for
910 * them
911 */
paul718e3742002-12-13 20:15:29 +0000912 for (rib = rn->info; rib; rib = next)
913 {
914 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000915
paul718e3742002-12-13 20:15:29 +0000916 /* Currently installed rib. */
917 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
paul7021c422003-07-15 12:52:22 +0000918 fib = rib;
paul4d38fdb2005-04-28 17:35:14 +0000919
paul718e3742002-12-13 20:15:29 +0000920 /* Skip unreachable nexthop. */
921 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000922 continue;
paul718e3742002-12-13 20:15:29 +0000923
924 /* Infinit distance. */
925 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000926 continue;
paul718e3742002-12-13 20:15:29 +0000927
paulaf887b52006-01-18 14:52:52 +0000928 /* Newly selected rib, the common case. */
929 if (!select)
930 {
931 select = rib;
932 continue;
933 }
934
935 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +0000936 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +0000937 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +0000938 * - lower metric beats higher for equal distance
939 * - last, hence oldest, route wins tie break.
940 */
paula1038a12006-01-30 14:08:51 +0000941
942 /* Connected routes. Pick the last connected
943 * route of the set of lowest metric connected routes.
944 */
paula8d9c1f2006-01-25 06:31:04 +0000945 if (rib->type == ZEBRA_ROUTE_CONNECT)
946 {
paula1038a12006-01-30 14:08:51 +0000947 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +0000948 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +0000949 select = rib;
950 continue;
paula8d9c1f2006-01-25 06:31:04 +0000951 }
952 else if (select->type == ZEBRA_ROUTE_CONNECT)
953 continue;
954
955 /* higher distance loses */
956 if (rib->distance > select->distance)
957 continue;
958
959 /* lower wins */
960 if (rib->distance < select->distance)
961 {
paulaf887b52006-01-18 14:52:52 +0000962 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000963 continue;
964 }
965
966 /* metric tie-breaks equal distance */
967 if (rib->metric <= select->metric)
968 select = rib;
paul718e3742002-12-13 20:15:29 +0000969 }
paul4d38fdb2005-04-28 17:35:14 +0000970
paul718e3742002-12-13 20:15:29 +0000971 /* Deleted route check. */
972 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
973 fib = del;
paul4d38fdb2005-04-28 17:35:14 +0000974
975 /* We possibly should lock fib and select here However, all functions
976 * below are 'inline' and not asynchronous And if any were to be
977 * converted, they should manage references themselves really.. See
978 * previous comment above.
979 */
980
paul718e3742002-12-13 20:15:29 +0000981 /* Same route is selected. */
982 if (select && select == fib)
983 {
984 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000985 {
986 redistribute_delete (&rn->p, select);
987 if (! RIB_SYSTEM_ROUTE (select))
988 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000989
paul4d38fdb2005-04-28 17:35:14 +0000990 /* Set real nexthop. */
991 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +0000992
paul4d38fdb2005-04-28 17:35:14 +0000993 if (! RIB_SYSTEM_ROUTE (select))
994 rib_install_kernel (rn, select);
995 redistribute_add (&rn->p, select);
996 }
pauld753e9e2003-01-22 19:45:50 +0000997 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +0000998 {
999 /* Housekeeping code to deal with
1000 race conditions in kernel with linux
1001 netlink reporting interface up before IPv4 or IPv6 protocol
1002 is ready to add routes.
1003 This makes sure the routes are IN the kernel.
1004 */
pauld753e9e2003-01-22 19:45:50 +00001005
paul4d38fdb2005-04-28 17:35:14 +00001006 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1007 {
1008 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1009 installed = 1;
1010 }
1011 if (! installed)
1012 rib_install_kernel (rn, select);
1013 }
1014 return WQ_SUCCESS;
paul718e3742002-12-13 20:15:29 +00001015 }
1016
1017 /* Uninstall old rib from forwarding table. */
1018 if (fib)
1019 {
1020 redistribute_delete (&rn->p, fib);
1021 if (! RIB_SYSTEM_ROUTE (fib))
1022 rib_uninstall_kernel (rn, fib);
1023 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1024
1025 /* Set real nexthop. */
1026 nexthop_active_update (rn, fib, 1);
1027 }
1028
1029 /* Install new rib into forwarding table. */
1030 if (select)
1031 {
1032 /* Set real nexthop. */
1033 nexthop_active_update (rn, select, 1);
1034
1035 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001036 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001037 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1038 redistribute_add (&rn->p, select);
1039 }
paul4d38fdb2005-04-28 17:35:14 +00001040
1041 return WQ_SUCCESS;
1042
1043}
1044
1045/* Add work queue item to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001046static void
paul4d38fdb2005-04-28 17:35:14 +00001047rib_queue_add_qnode (struct zebra_t *zebra, struct zebra_queue_node_t *qnode)
1048{
1049 route_lock_node (qnode->node);
1050
1051 if (IS_ZEBRA_DEBUG_EVENT)
1052 zlog_info ("rib_queue_add_qnode: work queue added");
1053
1054 assert (zebra && qnode && qnode->node);
1055
1056 if (qnode->del)
1057 rib_lock (qnode->del);
1058
1059 if (zebra->ribq == NULL)
1060 {
1061 zlog_err ("rib_queue_add_qnode: ribq work_queue does not exist!");
1062 route_unlock_node (qnode->node);
1063 return;
1064 }
1065
1066 work_queue_add (zebra->ribq, qnode);
1067
1068 return;
1069}
1070
1071/* Add route node and rib to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001072static void
paul4d38fdb2005-04-28 17:35:14 +00001073rib_queue_add (struct zebra_t *zebra, struct route_node *rn, struct rib *del)
1074{
1075 struct zebra_queue_node_t *qnode;
1076
1077 assert (zebra && rn);
1078
1079 qnode = (struct zebra_queue_node_t *)
1080 XCALLOC (MTYPE_RIB_QUEUE, sizeof (struct zebra_queue_node_t));
1081
1082 if (qnode == NULL)
1083 {
1084 zlog_err ("rib_queue_add: failed to allocate queue node memory, %s",
1085 strerror (errno));
1086 return;
1087 }
1088
1089 qnode->node = rn;
1090 qnode->del = del;
1091
1092 rib_queue_add_qnode (zebra, qnode);
1093
1094 return;
1095}
1096
1097/* free zebra_queue_node_t */
paula1ac18c2005-06-28 17:17:12 +00001098static void
paul0fb58d52005-11-14 14:31:49 +00001099rib_queue_qnode_del (struct work_queue *wq, void *data)
paul4d38fdb2005-04-28 17:35:14 +00001100{
paul0fb58d52005-11-14 14:31:49 +00001101 struct zebra_queue_node_t *qnode = data;
paul4d38fdb2005-04-28 17:35:14 +00001102 route_unlock_node (qnode->node);
1103
1104 if (qnode->del)
1105 rib_unlock (qnode->del);
1106
1107 XFREE (MTYPE_RIB_QUEUE, qnode);
1108}
1109
1110/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001111static void
paul4d38fdb2005-04-28 17:35:14 +00001112rib_queue_init (struct zebra_t *zebra)
1113{
1114 assert (zebra);
1115
1116 if (! (zebra->ribq = work_queue_new (zebra->master,
1117 "zebra_rib_work_queue")))
1118 {
1119 zlog_err ("rib_queue_init: could not initialise work queue!");
1120 return;
1121 }
1122
1123 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001124 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001125 zebra->ribq->spec.errorfunc = NULL;
paul0fb58d52005-11-14 14:31:49 +00001126 zebra->ribq->spec.del_item_data = &rib_queue_qnode_del;
paul4d38fdb2005-04-28 17:35:14 +00001127 /* XXX: TODO: These should be runtime configurable via vty */
1128 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001129 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001130
1131 return;
paul718e3742002-12-13 20:15:29 +00001132}
1133
1134/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001135static void
paul718e3742002-12-13 20:15:29 +00001136rib_addnode (struct route_node *rn, struct rib *rib)
1137{
1138 struct rib *head;
paul4d38fdb2005-04-28 17:35:14 +00001139
1140 assert (rib && rn);
1141
1142 rib_lock (rib);
1143 route_lock_node (rn);
1144
paul718e3742002-12-13 20:15:29 +00001145 head = rn->info;
1146 if (head)
1147 head->prev = rib;
1148 rib->next = head;
1149 rn->info = rib;
1150}
1151
paula1ac18c2005-06-28 17:17:12 +00001152static void
paul718e3742002-12-13 20:15:29 +00001153rib_delnode (struct route_node *rn, struct rib *rib)
1154{
paul4d38fdb2005-04-28 17:35:14 +00001155 assert (rn && rib);
1156
paul718e3742002-12-13 20:15:29 +00001157 if (rib->next)
1158 rib->next->prev = rib->prev;
1159 if (rib->prev)
1160 rib->prev->next = rib->next;
1161 else
1162 rn->info = rib->next;
paul4d38fdb2005-04-28 17:35:14 +00001163
1164 rib_unlock (rib);
1165 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001166}
1167
1168int
1169rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1170 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1171 u_int32_t metric, u_char distance)
1172{
1173 struct rib *rib;
1174 struct rib *same = NULL;
1175 struct route_table *table;
1176 struct route_node *rn;
1177 struct nexthop *nexthop;
1178
1179 /* Lookup table. */
1180 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1181 if (! table)
1182 return 0;
1183
1184 /* Make it sure prefixlen is applied to the prefix. */
1185 apply_mask_ipv4 (p);
1186
1187 /* Set default distance by route type. */
1188 if (distance == 0)
1189 {
1190 distance = route_info[type].distance;
1191
1192 /* iBGP distance is 200. */
1193 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1194 distance = 200;
1195 }
1196
1197 /* Lookup route node.*/
1198 rn = route_node_get (table, (struct prefix *) p);
1199
1200 /* If same type of route are installed, treat it as a implicit
1201 withdraw. */
1202 for (rib = rn->info; rib; rib = rib->next)
1203 {
hassoebf1ead2005-09-21 14:58:20 +00001204 if (rib->type != type)
1205 continue;
1206 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001207 {
1208 same = rib;
1209 break;
1210 }
hassoebf1ead2005-09-21 14:58:20 +00001211 /* Duplicate connected route comes in. */
1212 else if ((nexthop = rib->nexthop) &&
1213 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1214 nexthop->ifindex == ifindex)
1215 {
1216 rib->refcnt++;
1217 return 0 ;
1218 }
paul718e3742002-12-13 20:15:29 +00001219 }
1220
1221 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001222 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001223 rib->type = type;
1224 rib->distance = distance;
1225 rib->flags = flags;
1226 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001227 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001228 rib->nexthop_num = 0;
1229 rib->uptime = time (NULL);
1230
1231 /* Nexthop settings. */
1232 if (gate)
1233 {
1234 if (ifindex)
1235 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1236 else
1237 nexthop_ipv4_add (rib, gate);
1238 }
1239 else
1240 nexthop_ifindex_add (rib, ifindex);
1241
1242 /* If this route is kernel route, set FIB flag to the route. */
1243 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1244 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1245 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1246
1247 /* Link new rib to node.*/
1248 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001249
paul718e3742002-12-13 20:15:29 +00001250 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001251 rib_queue_add (&zebrad, rn, same);
1252
paul718e3742002-12-13 20:15:29 +00001253 /* Free implicit route.*/
1254 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001255 rib_delnode (rn, same);
1256
1257 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001258 return 0;
1259}
1260
1261int
1262rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1263{
1264 struct route_table *table;
1265 struct route_node *rn;
1266 struct rib *same;
1267 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001268
paul718e3742002-12-13 20:15:29 +00001269 /* Lookup table. */
1270 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1271 if (! table)
1272 return 0;
paul718e3742002-12-13 20:15:29 +00001273 /* Make it sure prefixlen is applied to the prefix. */
1274 apply_mask_ipv4 (p);
1275
1276 /* Set default distance by route type. */
1277 if (rib->distance == 0)
1278 {
1279 rib->distance = route_info[rib->type].distance;
1280
1281 /* iBGP distance is 200. */
1282 if (rib->type == ZEBRA_ROUTE_BGP
1283 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1284 rib->distance = 200;
1285 }
1286
1287 /* Lookup route node.*/
1288 rn = route_node_get (table, (struct prefix *) p);
1289
1290 /* If same type of route are installed, treat it as a implicit
1291 withdraw. */
1292 for (same = rn->info; same; same = same->next)
1293 {
1294 if (same->type == rib->type && same->table == rib->table
1295 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001296 break;
paul718e3742002-12-13 20:15:29 +00001297 }
paul4d38fdb2005-04-28 17:35:14 +00001298
paul718e3742002-12-13 20:15:29 +00001299 /* If this route is kernel route, set FIB flag to the route. */
1300 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1301 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1302 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1303
1304 /* Link new rib to node.*/
1305 rib_addnode (rn, rib);
1306
1307 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001308 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001309
1310 /* Free implicit route.*/
1311 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001312 rib_delnode (rn, same);
1313
1314 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001315 return 0;
1316}
1317
hassoebf1ead2005-09-21 14:58:20 +00001318/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001319int
1320rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1321 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1322{
1323 struct route_table *table;
1324 struct route_node *rn;
1325 struct rib *rib;
1326 struct rib *fib = NULL;
1327 struct rib *same = NULL;
1328 struct nexthop *nexthop;
1329 char buf1[BUFSIZ];
1330 char buf2[BUFSIZ];
1331
1332 /* Lookup table. */
1333 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1334 if (! table)
1335 return 0;
1336
1337 /* Apply mask. */
1338 apply_mask_ipv4 (p);
1339
paul5ec90d22003-06-19 01:41:37 +00001340 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001341 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001342 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1343 p->prefixlen,
1344 inet_ntoa (*gate),
1345 ifindex);
1346
paul718e3742002-12-13 20:15:29 +00001347 /* Lookup route node. */
1348 rn = route_node_lookup (table, (struct prefix *) p);
1349 if (! rn)
1350 {
1351 if (IS_ZEBRA_DEBUG_KERNEL)
1352 {
1353 if (gate)
ajsb6178002004-12-07 21:12:56 +00001354 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001355 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1356 p->prefixlen,
1357 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1358 ifindex);
1359 else
ajsb6178002004-12-07 21:12:56 +00001360 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001361 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1362 p->prefixlen,
1363 ifindex);
1364 }
1365 return ZEBRA_ERR_RTNOEXIST;
1366 }
1367
1368 /* Lookup same type route. */
1369 for (rib = rn->info; rib; rib = rib->next)
1370 {
1371 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1372 fib = rib;
1373
hassoebf1ead2005-09-21 14:58:20 +00001374 if (rib->type != type)
1375 continue;
1376 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1377 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001378 {
hassoebf1ead2005-09-21 14:58:20 +00001379 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001380 {
hassoebf1ead2005-09-21 14:58:20 +00001381 rib->refcnt--;
1382 route_unlock_node (rn);
1383 route_unlock_node (rn);
1384 return 0;
paul718e3742002-12-13 20:15:29 +00001385 }
hassoebf1ead2005-09-21 14:58:20 +00001386 same = rib;
1387 break;
paul718e3742002-12-13 20:15:29 +00001388 }
hassoebf1ead2005-09-21 14:58:20 +00001389 /* Make sure that the route found has the same gateway. */
1390 else if (gate == NULL ||
1391 ((nexthop = rib->nexthop) &&
1392 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1393 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001394 {
hassoebf1ead2005-09-21 14:58:20 +00001395 same = rib;
1396 break;
paul718e3742002-12-13 20:15:29 +00001397 }
1398 }
1399
1400 /* If same type of route can't be found and this message is from
1401 kernel. */
1402 if (! same)
1403 {
1404 if (fib && type == ZEBRA_ROUTE_KERNEL)
1405 {
1406 /* Unset flags. */
1407 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1408 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1409
1410 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1411 }
1412 else
1413 {
1414 if (IS_ZEBRA_DEBUG_KERNEL)
1415 {
1416 if (gate)
ajsb6178002004-12-07 21:12:56 +00001417 zlog_debug ("route %s/%d via %s 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 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1421 ifindex,
1422 type);
1423 else
ajsb6178002004-12-07 21:12:56 +00001424 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001425 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1426 p->prefixlen,
1427 ifindex,
1428 type);
1429 }
1430 route_unlock_node (rn);
1431 return ZEBRA_ERR_RTNOEXIST;
1432 }
1433 }
paul4d38fdb2005-04-28 17:35:14 +00001434
1435 /* Process changes. */
1436 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001437
1438 if (same)
1439 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001440
paul718e3742002-12-13 20:15:29 +00001441 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001442 return 0;
1443}
1444
1445/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001446static void
paul718e3742002-12-13 20:15:29 +00001447static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1448{
1449 struct rib *rib;
1450 struct route_node *rn;
1451 struct route_table *table;
1452
1453 /* Lookup table. */
1454 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1455 if (! table)
1456 return;
1457
1458 /* Lookup existing route */
1459 rn = route_node_get (table, p);
1460 for (rib = rn->info; rib; rib = rib->next)
1461 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1462 break;
1463
1464 if (rib)
1465 {
1466 /* Same distance static route is there. Update it with new
1467 nexthop. */
paul718e3742002-12-13 20:15:29 +00001468 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001469 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001470 {
1471 case STATIC_IPV4_GATEWAY:
1472 nexthop_ipv4_add (rib, &si->gate.ipv4);
1473 break;
1474 case STATIC_IPV4_IFNAME:
1475 nexthop_ifname_add (rib, si->gate.ifname);
1476 break;
1477 case STATIC_IPV4_BLACKHOLE:
1478 nexthop_blackhole_add (rib);
1479 break;
paul4d38fdb2005-04-28 17:35:14 +00001480 }
1481 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001482 }
1483 else
1484 {
1485 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001486 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1487
paul718e3742002-12-13 20:15:29 +00001488 rib->type = ZEBRA_ROUTE_STATIC;
1489 rib->distance = si->distance;
1490 rib->metric = 0;
1491 rib->nexthop_num = 0;
Paul Jakma171eee32006-07-27 16:11:02 +00001492 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00001493
1494 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001495 {
1496 case STATIC_IPV4_GATEWAY:
1497 nexthop_ipv4_add (rib, &si->gate.ipv4);
1498 break;
1499 case STATIC_IPV4_IFNAME:
1500 nexthop_ifname_add (rib, si->gate.ifname);
1501 break;
1502 case STATIC_IPV4_BLACKHOLE:
1503 nexthop_blackhole_add (rib);
1504 break;
1505 }
paul718e3742002-12-13 20:15:29 +00001506
hasso81dfcaa2003-05-25 19:21:25 +00001507 /* Save the flags of this static routes (reject, blackhole) */
1508 rib->flags = si->flags;
1509
paul718e3742002-12-13 20:15:29 +00001510 /* Link this rib to the tree. */
1511 rib_addnode (rn, rib);
1512
1513 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00001514 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001515 }
1516}
1517
paula1ac18c2005-06-28 17:17:12 +00001518static int
paul718e3742002-12-13 20:15:29 +00001519static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1520{
1521 if (nexthop->type == NEXTHOP_TYPE_IPV4
1522 && si->type == STATIC_IPV4_GATEWAY
1523 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1524 return 1;
1525 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1526 && si->type == STATIC_IPV4_IFNAME
1527 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1528 return 1;
paul595db7f2003-05-25 21:35:06 +00001529 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1530 && si->type == STATIC_IPV4_BLACKHOLE)
1531 return 1;
paule8e19462006-01-19 20:16:55 +00001532 return 0;
paul718e3742002-12-13 20:15:29 +00001533}
1534
1535/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001536static void
paul718e3742002-12-13 20:15:29 +00001537static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1538{
1539 struct route_node *rn;
1540 struct rib *rib;
1541 struct nexthop *nexthop;
1542 struct route_table *table;
1543
1544 /* Lookup table. */
1545 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1546 if (! table)
1547 return;
paul4d38fdb2005-04-28 17:35:14 +00001548
paul718e3742002-12-13 20:15:29 +00001549 /* Lookup existing route with type and distance. */
1550 rn = route_node_lookup (table, p);
1551 if (! rn)
1552 return;
1553
1554 for (rib = rn->info; rib; rib = rib->next)
1555 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1556 break;
1557
1558 if (! rib)
1559 {
1560 route_unlock_node (rn);
1561 return;
1562 }
1563
1564 /* Lookup nexthop. */
1565 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1566 if (static_ipv4_nexthop_same (nexthop, si))
1567 break;
1568
1569 /* Can't find nexthop. */
1570 if (! nexthop)
1571 {
1572 route_unlock_node (rn);
1573 return;
1574 }
1575
1576 /* Check nexthop. */
1577 if (rib->nexthop_num == 1)
1578 {
paul4d38fdb2005-04-28 17:35:14 +00001579 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00001580 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001581 }
1582 else
1583 {
paul6baeb982003-10-28 03:47:15 +00001584 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1585 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001586 nexthop_delete (rib, nexthop);
1587 nexthop_free (nexthop);
1588 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001589 }
paul718e3742002-12-13 20:15:29 +00001590 /* Unlock node. */
1591 route_unlock_node (rn);
1592}
1593
1594/* Add static route into static route configuration. */
1595int
hasso39db97e2004-10-12 20:50:58 +00001596static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001597 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001598{
1599 u_char type = 0;
1600 struct route_node *rn;
1601 struct static_ipv4 *si;
1602 struct static_ipv4 *pp;
1603 struct static_ipv4 *cp;
1604 struct static_ipv4 *update = NULL;
1605 struct route_table *stable;
1606
1607 /* Lookup table. */
1608 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1609 if (! stable)
1610 return -1;
1611
1612 /* Lookup static route prefix. */
1613 rn = route_node_get (stable, p);
1614
1615 /* Make flags. */
1616 if (gate)
1617 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001618 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001619 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001620 else
1621 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001622
1623 /* Do nothing if there is a same static route. */
1624 for (si = rn->info; si; si = si->next)
1625 {
1626 if (type == si->type
1627 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1628 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1629 {
1630 if (distance == si->distance)
1631 {
1632 route_unlock_node (rn);
1633 return 0;
1634 }
1635 else
1636 update = si;
1637 }
1638 }
1639
1640 /* Distance chaged. */
1641 if (update)
1642 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1643
1644 /* Make new static route structure. */
1645 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1646 memset (si, 0, sizeof (struct static_ipv4));
1647
1648 si->type = type;
1649 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001650 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001651
1652 if (gate)
1653 si->gate.ipv4 = *gate;
1654 if (ifname)
1655 si->gate.ifname = XSTRDUP (0, ifname);
1656
1657 /* Add new static route information to the tree with sort by
1658 distance value and gateway address. */
1659 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1660 {
1661 if (si->distance < cp->distance)
1662 break;
1663 if (si->distance > cp->distance)
1664 continue;
1665 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1666 {
1667 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1668 break;
1669 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1670 continue;
1671 }
1672 }
1673
1674 /* Make linked list. */
1675 if (pp)
1676 pp->next = si;
1677 else
1678 rn->info = si;
1679 if (cp)
1680 cp->prev = si;
1681 si->prev = pp;
1682 si->next = cp;
1683
1684 /* Install into rib. */
1685 static_install_ipv4 (p, si);
1686
1687 return 1;
1688}
1689
1690/* Delete static route from static route configuration. */
1691int
hasso39db97e2004-10-12 20:50:58 +00001692static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001693 u_char distance, u_int32_t vrf_id)
1694{
1695 u_char type = 0;
1696 struct route_node *rn;
1697 struct static_ipv4 *si;
1698 struct route_table *stable;
1699
1700 /* Lookup table. */
1701 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1702 if (! stable)
1703 return -1;
1704
1705 /* Lookup static route prefix. */
1706 rn = route_node_lookup (stable, p);
1707 if (! rn)
1708 return 0;
1709
1710 /* Make flags. */
1711 if (gate)
1712 type = STATIC_IPV4_GATEWAY;
1713 else if (ifname)
1714 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001715 else
1716 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001717
1718 /* Find same static route is the tree */
1719 for (si = rn->info; si; si = si->next)
1720 if (type == si->type
1721 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1722 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1723 break;
1724
1725 /* Can't find static route. */
1726 if (! si)
1727 {
1728 route_unlock_node (rn);
1729 return 0;
1730 }
1731
1732 /* Install into rib. */
1733 static_uninstall_ipv4 (p, si);
1734
1735 /* Unlink static route from linked list. */
1736 if (si->prev)
1737 si->prev->next = si->next;
1738 else
1739 rn->info = si->next;
1740 if (si->next)
1741 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001742 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001743
1744 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001745 if (ifname)
1746 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001747 XFREE (MTYPE_STATIC_IPV4, si);
1748
paul143a3852003-09-29 20:06:13 +00001749 route_unlock_node (rn);
1750
paul718e3742002-12-13 20:15:29 +00001751 return 1;
1752}
1753
1754
1755#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001756static int
paul718e3742002-12-13 20:15:29 +00001757rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1758 struct in6_addr *gate, unsigned int ifindex, int table)
1759{
hasso726f9b22003-05-25 21:04:54 +00001760 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1761#if defined (MUSICA) || defined (LINUX)
1762 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1763 if (p->prefixlen == 96)
1764 return 0;
1765#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001766 return 1;
hasso726f9b22003-05-25 21:04:54 +00001767 }
paul718e3742002-12-13 20:15:29 +00001768 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1769 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1770 {
1771 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1772 return 1;
1773 }
1774 return 0;
1775}
1776
1777int
1778rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001779 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1780 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001781{
1782 struct rib *rib;
1783 struct rib *same = NULL;
1784 struct route_table *table;
1785 struct route_node *rn;
1786 struct nexthop *nexthop;
1787
paul718e3742002-12-13 20:15:29 +00001788 /* Lookup table. */
1789 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1790 if (! table)
1791 return 0;
1792
1793 /* Make sure mask is applied. */
1794 apply_mask_ipv6 (p);
1795
1796 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001797 if (!distance)
1798 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001799
1800 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1801 distance = 200;
1802
1803 /* Filter bogus route. */
1804 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1805 return 0;
1806
1807 /* Lookup route node.*/
1808 rn = route_node_get (table, (struct prefix *) p);
1809
1810 /* If same type of route are installed, treat it as a implicit
1811 withdraw. */
1812 for (rib = rn->info; rib; rib = rib->next)
1813 {
hassoebf1ead2005-09-21 14:58:20 +00001814 if (rib->type != type)
1815 continue;
1816 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001817 {
1818 same = rib;
paul718e3742002-12-13 20:15:29 +00001819 break;
1820 }
hassoebf1ead2005-09-21 14:58:20 +00001821 else if ((nexthop = rib->nexthop) &&
1822 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1823 nexthop->ifindex == ifindex)
1824 {
1825 rib->refcnt++;
1826 return 0;
1827 }
paul718e3742002-12-13 20:15:29 +00001828 }
1829
1830 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001831 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1832
paul718e3742002-12-13 20:15:29 +00001833 rib->type = type;
1834 rib->distance = distance;
1835 rib->flags = flags;
1836 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001837 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001838 rib->nexthop_num = 0;
1839 rib->uptime = time (NULL);
1840
1841 /* Nexthop settings. */
1842 if (gate)
1843 {
1844 if (ifindex)
1845 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1846 else
1847 nexthop_ipv6_add (rib, gate);
1848 }
1849 else
1850 nexthop_ifindex_add (rib, ifindex);
1851
1852 /* If this route is kernel route, set FIB flag to the route. */
1853 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1854 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1855 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1856
1857 /* Link new rib to node.*/
1858 rib_addnode (rn, rib);
1859
1860 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001861 rib_queue_add (&zebrad, rn, same);
1862
paul718e3742002-12-13 20:15:29 +00001863 /* Free implicit route.*/
1864 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001865 rib_delnode (rn, same);
1866
1867 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001868 return 0;
1869}
1870
hassoebf1ead2005-09-21 14:58:20 +00001871/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001872int
1873rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1874 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1875{
1876 struct route_table *table;
1877 struct route_node *rn;
1878 struct rib *rib;
1879 struct rib *fib = NULL;
1880 struct rib *same = NULL;
1881 struct nexthop *nexthop;
1882 char buf1[BUFSIZ];
1883 char buf2[BUFSIZ];
1884
1885 /* Apply mask. */
1886 apply_mask_ipv6 (p);
1887
1888 /* Lookup table. */
1889 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1890 if (! table)
1891 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001892
paul718e3742002-12-13 20:15:29 +00001893 /* Lookup route node. */
1894 rn = route_node_lookup (table, (struct prefix *) p);
1895 if (! rn)
1896 {
1897 if (IS_ZEBRA_DEBUG_KERNEL)
1898 {
1899 if (gate)
ajsb6178002004-12-07 21:12:56 +00001900 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001901 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1902 p->prefixlen,
1903 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1904 ifindex);
1905 else
ajsb6178002004-12-07 21:12:56 +00001906 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001907 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1908 p->prefixlen,
1909 ifindex);
1910 }
1911 return ZEBRA_ERR_RTNOEXIST;
1912 }
1913
1914 /* Lookup same type route. */
1915 for (rib = rn->info; rib; rib = rib->next)
1916 {
1917 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1918 fib = rib;
1919
hassoebf1ead2005-09-21 14:58:20 +00001920 if (rib->type != type)
1921 continue;
1922 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1923 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001924 {
hassoebf1ead2005-09-21 14:58:20 +00001925 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001926 {
hassoebf1ead2005-09-21 14:58:20 +00001927 rib->refcnt--;
1928 route_unlock_node (rn);
1929 route_unlock_node (rn);
1930 return 0;
paul718e3742002-12-13 20:15:29 +00001931 }
hassoebf1ead2005-09-21 14:58:20 +00001932 same = rib;
1933 break;
paul718e3742002-12-13 20:15:29 +00001934 }
hassoebf1ead2005-09-21 14:58:20 +00001935 /* Make sure that the route found has the same gateway. */
1936 else if (gate == NULL ||
1937 ((nexthop = rib->nexthop) &&
1938 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
1939 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00001940 {
hassoebf1ead2005-09-21 14:58:20 +00001941 same = rib;
1942 break;
paul718e3742002-12-13 20:15:29 +00001943 }
1944 }
1945
1946 /* If same type of route can't be found and this message is from
1947 kernel. */
1948 if (! same)
1949 {
1950 if (fib && type == ZEBRA_ROUTE_KERNEL)
1951 {
1952 /* Unset flags. */
1953 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1954 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1955
1956 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1957 }
1958 else
1959 {
1960 if (IS_ZEBRA_DEBUG_KERNEL)
1961 {
1962 if (gate)
ajsb6178002004-12-07 21:12:56 +00001963 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001964 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1965 p->prefixlen,
1966 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1967 ifindex,
1968 type);
1969 else
ajsb6178002004-12-07 21:12:56 +00001970 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001971 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1972 p->prefixlen,
1973 ifindex,
1974 type);
1975 }
1976 route_unlock_node (rn);
1977 return ZEBRA_ERR_RTNOEXIST;
1978 }
1979 }
1980
paul4d38fdb2005-04-28 17:35:14 +00001981 /* Process changes. */
1982 rib_queue_add (&zebrad, rn, same);
1983
paul718e3742002-12-13 20:15:29 +00001984 if (same)
1985 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001986
paul718e3742002-12-13 20:15:29 +00001987 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001988 return 0;
1989}
1990
1991/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001992static void
paul718e3742002-12-13 20:15:29 +00001993static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1994{
1995 struct rib *rib;
1996 struct route_table *table;
1997 struct route_node *rn;
1998
1999 /* Lookup table. */
2000 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2001 if (! table)
2002 return;
2003
2004 /* Lookup existing route */
2005 rn = route_node_get (table, p);
2006 for (rib = rn->info; rib; rib = rib->next)
2007 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2008 break;
2009
2010 if (rib)
2011 {
2012 /* Same distance static route is there. Update it with new
2013 nexthop. */
paul718e3742002-12-13 20:15:29 +00002014 route_unlock_node (rn);
2015
2016 switch (si->type)
2017 {
2018 case STATIC_IPV6_GATEWAY:
2019 nexthop_ipv6_add (rib, &si->ipv6);
2020 break;
2021 case STATIC_IPV6_IFNAME:
2022 nexthop_ifname_add (rib, si->ifname);
2023 break;
2024 case STATIC_IPV6_GATEWAY_IFNAME:
2025 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2026 break;
2027 }
paul4d38fdb2005-04-28 17:35:14 +00002028 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002029 }
2030 else
2031 {
2032 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002033 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2034
paul718e3742002-12-13 20:15:29 +00002035 rib->type = ZEBRA_ROUTE_STATIC;
2036 rib->distance = si->distance;
2037 rib->metric = 0;
2038 rib->nexthop_num = 0;
2039
2040 switch (si->type)
2041 {
2042 case STATIC_IPV6_GATEWAY:
2043 nexthop_ipv6_add (rib, &si->ipv6);
2044 break;
2045 case STATIC_IPV6_IFNAME:
2046 nexthop_ifname_add (rib, si->ifname);
2047 break;
2048 case STATIC_IPV6_GATEWAY_IFNAME:
2049 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2050 break;
2051 }
2052
hasso81dfcaa2003-05-25 19:21:25 +00002053 /* Save the flags of this static routes (reject, blackhole) */
2054 rib->flags = si->flags;
2055
paul718e3742002-12-13 20:15:29 +00002056 /* Link this rib to the tree. */
2057 rib_addnode (rn, rib);
2058
2059 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00002060 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002061 }
2062}
2063
paula1ac18c2005-06-28 17:17:12 +00002064static int
paul718e3742002-12-13 20:15:29 +00002065static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2066{
2067 if (nexthop->type == NEXTHOP_TYPE_IPV6
2068 && si->type == STATIC_IPV6_GATEWAY
2069 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2070 return 1;
2071 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2072 && si->type == STATIC_IPV6_IFNAME
2073 && strcmp (nexthop->ifname, si->ifname) == 0)
2074 return 1;
2075 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2076 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2077 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2078 && strcmp (nexthop->ifname, si->ifname) == 0)
2079 return 1;
paule8e19462006-01-19 20:16:55 +00002080 return 0;
paul718e3742002-12-13 20:15:29 +00002081}
2082
paula1ac18c2005-06-28 17:17:12 +00002083static void
paul718e3742002-12-13 20:15:29 +00002084static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2085{
2086 struct route_table *table;
2087 struct route_node *rn;
2088 struct rib *rib;
2089 struct nexthop *nexthop;
2090
2091 /* Lookup table. */
2092 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2093 if (! table)
2094 return;
2095
2096 /* Lookup existing route with type and distance. */
2097 rn = route_node_lookup (table, (struct prefix *) p);
2098 if (! rn)
2099 return;
2100
2101 for (rib = rn->info; rib; rib = rib->next)
2102 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2103 break;
2104 if (! rib)
2105 {
2106 route_unlock_node (rn);
2107 return;
2108 }
2109
2110 /* Lookup nexthop. */
2111 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2112 if (static_ipv6_nexthop_same (nexthop, si))
2113 break;
2114
2115 /* Can't find nexthop. */
2116 if (! nexthop)
2117 {
2118 route_unlock_node (rn);
2119 return;
2120 }
2121
2122 /* Check nexthop. */
2123 if (rib->nexthop_num == 1)
2124 {
2125 rib_delnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002126 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00002127 }
2128 else
2129 {
paul6baeb982003-10-28 03:47:15 +00002130 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2131 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002132 nexthop_delete (rib, nexthop);
2133 nexthop_free (nexthop);
2134 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002135 }
paul718e3742002-12-13 20:15:29 +00002136 /* Unlock node. */
2137 route_unlock_node (rn);
2138}
2139
2140/* Add static route into static route configuration. */
2141int
2142static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002143 const char *ifname, u_char flags, u_char distance,
2144 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002145{
2146 struct route_node *rn;
2147 struct static_ipv6 *si;
2148 struct static_ipv6 *pp;
2149 struct static_ipv6 *cp;
2150 struct route_table *stable;
2151
2152 /* Lookup table. */
2153 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2154 if (! stable)
2155 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002156
2157 if (!gate &&
2158 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2159 return -1;
2160
2161 if (!ifname &&
2162 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2163 return -1;
paul718e3742002-12-13 20:15:29 +00002164
2165 /* Lookup static route prefix. */
2166 rn = route_node_get (stable, p);
2167
2168 /* Do nothing if there is a same static route. */
2169 for (si = rn->info; si; si = si->next)
2170 {
2171 if (distance == si->distance
2172 && type == si->type
2173 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2174 && (! ifname || strcmp (ifname, si->ifname) == 0))
2175 {
2176 route_unlock_node (rn);
2177 return 0;
2178 }
2179 }
2180
2181 /* Make new static route structure. */
2182 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2183 memset (si, 0, sizeof (struct static_ipv6));
2184
2185 si->type = type;
2186 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002187 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002188
2189 switch (type)
2190 {
2191 case STATIC_IPV6_GATEWAY:
2192 si->ipv6 = *gate;
2193 break;
2194 case STATIC_IPV6_IFNAME:
2195 si->ifname = XSTRDUP (0, ifname);
2196 break;
2197 case STATIC_IPV6_GATEWAY_IFNAME:
2198 si->ipv6 = *gate;
2199 si->ifname = XSTRDUP (0, ifname);
2200 break;
2201 }
2202
2203 /* Add new static route information to the tree with sort by
2204 distance value and gateway address. */
2205 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2206 {
2207 if (si->distance < cp->distance)
2208 break;
2209 if (si->distance > cp->distance)
2210 continue;
2211 }
2212
2213 /* Make linked list. */
2214 if (pp)
2215 pp->next = si;
2216 else
2217 rn->info = si;
2218 if (cp)
2219 cp->prev = si;
2220 si->prev = pp;
2221 si->next = cp;
2222
2223 /* Install into rib. */
2224 static_install_ipv6 (p, si);
2225
2226 return 1;
2227}
2228
2229/* Delete static route from static route configuration. */
2230int
2231static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002232 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002233{
2234 struct route_node *rn;
2235 struct static_ipv6 *si;
2236 struct route_table *stable;
2237
2238 /* Lookup table. */
2239 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2240 if (! stable)
2241 return -1;
2242
2243 /* Lookup static route prefix. */
2244 rn = route_node_lookup (stable, p);
2245 if (! rn)
2246 return 0;
2247
2248 /* Find same static route is the tree */
2249 for (si = rn->info; si; si = si->next)
2250 if (distance == si->distance
2251 && type == si->type
2252 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2253 && (! ifname || strcmp (ifname, si->ifname) == 0))
2254 break;
2255
2256 /* Can't find static route. */
2257 if (! si)
2258 {
2259 route_unlock_node (rn);
2260 return 0;
2261 }
2262
2263 /* Install into rib. */
2264 static_uninstall_ipv6 (p, si);
2265
2266 /* Unlink static route from linked list. */
2267 if (si->prev)
2268 si->prev->next = si->next;
2269 else
2270 rn->info = si->next;
2271 if (si->next)
2272 si->next->prev = si->prev;
2273
2274 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002275 if (ifname)
2276 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002277 XFREE (MTYPE_STATIC_IPV6, si);
2278
2279 return 1;
2280}
2281#endif /* HAVE_IPV6 */
2282
2283/* RIB update function. */
2284void
paula1ac18c2005-06-28 17:17:12 +00002285rib_update (void)
paul718e3742002-12-13 20:15:29 +00002286{
2287 struct route_node *rn;
2288 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002289
paul718e3742002-12-13 20:15:29 +00002290 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2291 if (table)
2292 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002293 if (rn->info)
2294 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002295
2296 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2297 if (table)
2298 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002299 if (rn->info)
2300 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002301}
2302
2303/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002304static void
paul718e3742002-12-13 20:15:29 +00002305rib_if_up (struct interface *ifp)
2306{
2307 rib_update ();
2308}
2309
2310/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002311static void
paul718e3742002-12-13 20:15:29 +00002312rib_if_down (struct interface *ifp)
2313{
2314 rib_update ();
2315}
2316
2317/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002318static void
paul718e3742002-12-13 20:15:29 +00002319rib_weed_table (struct route_table *table)
2320{
2321 struct route_node *rn;
2322 struct rib *rib;
2323 struct rib *next;
2324
2325 if (table)
2326 for (rn = route_top (table); rn; rn = route_next (rn))
2327 for (rib = rn->info; rib; rib = next)
2328 {
2329 next = rib->next;
2330
paulb21b19c2003-06-15 01:28:29 +00002331 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002332 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002333 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002334 }
2335}
2336
2337/* Delete all routes from non main table. */
2338void
paula1ac18c2005-06-28 17:17:12 +00002339rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002340{
2341 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2342 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2343}
2344
2345/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002346static void
paul718e3742002-12-13 20:15:29 +00002347rib_sweep_table (struct route_table *table)
2348{
2349 struct route_node *rn;
2350 struct rib *rib;
2351 struct rib *next;
2352 int ret = 0;
2353
2354 if (table)
2355 for (rn = route_top (table); rn; rn = route_next (rn))
2356 for (rib = rn->info; rib; rib = next)
2357 {
2358 next = rib->next;
2359
2360 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2361 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2362 {
2363 ret = rib_uninstall_kernel (rn, rib);
2364 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002365 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002366 }
2367 }
2368}
2369
2370/* Sweep all RIB tables. */
2371void
paula1ac18c2005-06-28 17:17:12 +00002372rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002373{
2374 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2375 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2376}
2377
2378/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002379static void
paul718e3742002-12-13 20:15:29 +00002380rib_close_table (struct route_table *table)
2381{
2382 struct route_node *rn;
2383 struct rib *rib;
2384
2385 if (table)
2386 for (rn = route_top (table); rn; rn = route_next (rn))
2387 for (rib = rn->info; rib; rib = rib->next)
2388 if (! RIB_SYSTEM_ROUTE (rib)
2389 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2390 rib_uninstall_kernel (rn, rib);
2391}
2392
2393/* Close all RIB tables. */
2394void
paula1ac18c2005-06-28 17:17:12 +00002395rib_close (void)
paul718e3742002-12-13 20:15:29 +00002396{
2397 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2398 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2399}
2400
2401/* Routing information base initialize. */
2402void
paula1ac18c2005-06-28 17:17:12 +00002403rib_init (void)
paul718e3742002-12-13 20:15:29 +00002404{
paul4d38fdb2005-04-28 17:35:14 +00002405 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002406 /* VRF initialization. */
2407 vrf_init ();
2408}