blob: 02c73d1296dc7585752fee5408824634e3dd4114 [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};
69
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
paula1ac18c2005-06-28 17:17:12 +0000788static void
paul718e3742002-12-13 20:15:29 +0000789rib_install_kernel (struct route_node *rn, struct rib *rib)
790{
791 int ret = 0;
792 struct nexthop *nexthop;
793
794 switch (PREFIX_FAMILY (&rn->p))
795 {
796 case AF_INET:
797 ret = kernel_add_ipv4 (&rn->p, rib);
798 break;
799#ifdef HAVE_IPV6
800 case AF_INET6:
801 ret = kernel_add_ipv6 (&rn->p, rib);
802 break;
803#endif /* HAVE_IPV6 */
804 }
805
806 if (ret < 0)
807 {
808 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
809 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
810 }
811}
812
813/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000814static int
paul718e3742002-12-13 20:15:29 +0000815rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
816{
817 int ret = 0;
818 struct nexthop *nexthop;
819
820 switch (PREFIX_FAMILY (&rn->p))
821 {
822 case AF_INET:
823 ret = kernel_delete_ipv4 (&rn->p, rib);
824 break;
825#ifdef HAVE_IPV6
826 case AF_INET6:
827 ret = kernel_delete_ipv6 (&rn->p, rib);
828 break;
829#endif /* HAVE_IPV6 */
830 }
831
832 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
833 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
834
835 return ret;
836}
837
838/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000839static void
paul718e3742002-12-13 20:15:29 +0000840rib_uninstall (struct route_node *rn, struct rib *rib)
841{
842 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
843 {
844 redistribute_delete (&rn->p, rib);
845 if (! RIB_SYSTEM_ROUTE (rib))
846 rib_uninstall_kernel (rn, rib);
847 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
848 }
849}
850
Paul Jakma6d691122006-07-27 21:49:00 +0000851static void rib_unlink (struct route_node *, struct rib *);
852
paul718e3742002-12-13 20:15:29 +0000853/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000854static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000855rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000856{
857 struct rib *rib;
858 struct rib *next;
859 struct rib *fib = NULL;
860 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +0000861 struct rib *del = NULL;
862 struct route_node *rn = data;
pauld753e9e2003-01-22 19:45:50 +0000863 int installed = 0;
864 struct nexthop *nexthop = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000865
866 assert (rn);
867
paul718e3742002-12-13 20:15:29 +0000868 for (rib = rn->info; rib; rib = next)
869 {
870 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000871
paul718e3742002-12-13 20:15:29 +0000872 /* Currently installed rib. */
873 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +0000874 {
875 assert (fib == NULL);
876 fib = rib;
877 }
878
879 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
880 * which we need to do do further work with below.
881 */
882 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
883 {
884 if (rib != fib)
885 {
886 if (IS_ZEBRA_DEBUG_RIB)
887 zlog_debug ("%s: rn %p, removing rib %p", __func__, rn, rib);
888 rib_unlink (rn, rib);
889 }
890 else
891 del = rib;
892
893 continue;
894 }
paul4d38fdb2005-04-28 17:35:14 +0000895
paul718e3742002-12-13 20:15:29 +0000896 /* Skip unreachable nexthop. */
897 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000898 continue;
paul718e3742002-12-13 20:15:29 +0000899
900 /* Infinit distance. */
901 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000902 continue;
paul718e3742002-12-13 20:15:29 +0000903
paulaf887b52006-01-18 14:52:52 +0000904 /* Newly selected rib, the common case. */
905 if (!select)
906 {
907 select = rib;
908 continue;
909 }
910
911 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +0000912 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +0000913 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +0000914 * - lower metric beats higher for equal distance
915 * - last, hence oldest, route wins tie break.
916 */
paula1038a12006-01-30 14:08:51 +0000917
918 /* Connected routes. Pick the last connected
919 * route of the set of lowest metric connected routes.
920 */
paula8d9c1f2006-01-25 06:31:04 +0000921 if (rib->type == ZEBRA_ROUTE_CONNECT)
922 {
paula1038a12006-01-30 14:08:51 +0000923 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +0000924 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +0000925 select = rib;
926 continue;
paula8d9c1f2006-01-25 06:31:04 +0000927 }
928 else if (select->type == ZEBRA_ROUTE_CONNECT)
929 continue;
930
931 /* higher distance loses */
932 if (rib->distance > select->distance)
933 continue;
934
935 /* lower wins */
936 if (rib->distance < select->distance)
937 {
paulaf887b52006-01-18 14:52:52 +0000938 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000939 continue;
940 }
941
942 /* metric tie-breaks equal distance */
943 if (rib->metric <= select->metric)
944 select = rib;
paul718e3742002-12-13 20:15:29 +0000945 }
paul4d38fdb2005-04-28 17:35:14 +0000946
paul718e3742002-12-13 20:15:29 +0000947 /* Same route is selected. */
948 if (select && select == fib)
949 {
Paul Jakma6d691122006-07-27 21:49:00 +0000950 if (IS_ZEBRA_DEBUG_RIB)
951 zlog_debug ("%s: Updating existing route, select %p, fib %p",
952 __func__, select, fib);
paul718e3742002-12-13 20:15:29 +0000953 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000954 {
955 redistribute_delete (&rn->p, select);
956 if (! RIB_SYSTEM_ROUTE (select))
957 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000958
paul4d38fdb2005-04-28 17:35:14 +0000959 /* Set real nexthop. */
960 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +0000961
paul4d38fdb2005-04-28 17:35:14 +0000962 if (! RIB_SYSTEM_ROUTE (select))
963 rib_install_kernel (rn, select);
964 redistribute_add (&rn->p, select);
965 }
pauld753e9e2003-01-22 19:45:50 +0000966 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +0000967 {
968 /* Housekeeping code to deal with
969 race conditions in kernel with linux
970 netlink reporting interface up before IPv4 or IPv6 protocol
971 is ready to add routes.
972 This makes sure the routes are IN the kernel.
973 */
pauld753e9e2003-01-22 19:45:50 +0000974
paul4d38fdb2005-04-28 17:35:14 +0000975 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
976 {
977 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
978 installed = 1;
979 }
980 if (! installed)
981 rib_install_kernel (rn, select);
982 }
Paul Jakma6d691122006-07-27 21:49:00 +0000983 goto end;
paul718e3742002-12-13 20:15:29 +0000984 }
985
986 /* Uninstall old rib from forwarding table. */
987 if (fib)
988 {
Paul Jakma6d691122006-07-27 21:49:00 +0000989 if (IS_ZEBRA_DEBUG_RIB)
990 zlog_debug ("%s: Removing existing route, fib %p", __func__, fib);
paul718e3742002-12-13 20:15:29 +0000991 redistribute_delete (&rn->p, fib);
992 if (! RIB_SYSTEM_ROUTE (fib))
993 rib_uninstall_kernel (rn, fib);
994 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
995
996 /* Set real nexthop. */
997 nexthop_active_update (rn, fib, 1);
998 }
999
1000 /* Install new rib into forwarding table. */
1001 if (select)
1002 {
Paul Jakma6d691122006-07-27 21:49:00 +00001003 if (IS_ZEBRA_DEBUG_RIB)
1004 zlog_debug ("%s: Adding route, select %p", __func__, select);
paul718e3742002-12-13 20:15:29 +00001005 /* Set real nexthop. */
1006 nexthop_active_update (rn, select, 1);
1007
1008 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001009 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001010 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1011 redistribute_add (&rn->p, select);
1012 }
paul4d38fdb2005-04-28 17:35:14 +00001013
Paul Jakma6d691122006-07-27 21:49:00 +00001014 /* FIB route was removed, should be deleted */
1015 if (del)
1016 {
1017 if (IS_ZEBRA_DEBUG_RIB)
1018 zlog_debug ("%s: Deleting fib %p, rn %p", __func__, del, rn);
1019 rib_unlink (rn, del);
1020 }
paul4d38fdb2005-04-28 17:35:14 +00001021
Paul Jakma6d691122006-07-27 21:49:00 +00001022end:
1023 if (IS_ZEBRA_DEBUG_RIB_Q)
1024 zlog_debug ("%s: rn %p dequeued", __func__, rn);
1025 if (rn->info)
1026 UNSET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1027 route_unlock_node (rn); /* rib queue lock */
1028 return WQ_SUCCESS;
paul4d38fdb2005-04-28 17:35:14 +00001029}
1030
Paul Jakma6d691122006-07-27 21:49:00 +00001031/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001032static void
Paul Jakma6d691122006-07-27 21:49:00 +00001033rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001034{
Paul Jakma6d691122006-07-27 21:49:00 +00001035 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001036
Paul Jakma6d691122006-07-27 21:49:00 +00001037 /* Pointless to queue a route_node with no RIB entries to add or remove */
1038 if (!rn->info)
1039 {
1040 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1041 __func__, rn, rn->lock);
1042 zlog_backtrace(LOG_DEBUG);
1043 return;
1044 }
paul4d38fdb2005-04-28 17:35:14 +00001045
Paul Jakma6d691122006-07-27 21:49:00 +00001046 /* Route-table node already queued, so nothing to do */
1047 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED))
1048 {
1049 if (IS_ZEBRA_DEBUG_RIB_Q)
1050 zlog_debug ("%s: rn %p already queued", __func__, rn);
1051 return;
1052 }
paul4d38fdb2005-04-28 17:35:14 +00001053
Paul Jakma6d691122006-07-27 21:49:00 +00001054 route_lock_node (rn); /* rib queue lock */
1055
1056 if (IS_ZEBRA_DEBUG_RIB_Q)
1057 zlog_info ("%s: work queue added", __func__);
1058
1059 assert (zebra);
1060
paul4d38fdb2005-04-28 17:35:14 +00001061 if (zebra->ribq == NULL)
1062 {
Paul Jakma6d691122006-07-27 21:49:00 +00001063 zlog_err ("%s: work_queue does not exist!", __func__);
1064 route_unlock_node (rn);
paul4d38fdb2005-04-28 17:35:14 +00001065 return;
1066 }
1067
Paul Jakma6d691122006-07-27 21:49:00 +00001068 work_queue_add (zebra->ribq, rn);
1069
1070 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1071
1072 if (IS_ZEBRA_DEBUG_RIB_Q)
1073 zlog_debug ("%s: rn %p queued", __func__, rn);
paul4d38fdb2005-04-28 17:35:14 +00001074
1075 return;
1076}
1077
paul4d38fdb2005-04-28 17:35:14 +00001078/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001079static void
paul4d38fdb2005-04-28 17:35:14 +00001080rib_queue_init (struct zebra_t *zebra)
1081{
1082 assert (zebra);
1083
1084 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001085 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001086 {
Paul Jakma6d691122006-07-27 21:49:00 +00001087 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001088 return;
1089 }
1090
1091 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001092 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001093 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001094 /* XXX: TODO: These should be runtime configurable via vty */
1095 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001096 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001097
1098 return;
paul718e3742002-12-13 20:15:29 +00001099}
1100
Paul Jakma6d691122006-07-27 21:49:00 +00001101/* RIB updates are processed via a queue of pointers to route_nodes.
1102 *
1103 * The queue length is bounded by the maximal size of the routing table,
1104 * as a route_node will not be requeued, if already queued.
1105 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001106 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1107 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1108 * and then submit route_node to queue for best-path selection later.
1109 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001110 *
1111 * Deleted RIBs are reaped during best-path selection.
1112 *
1113 * rib_addnode
1114 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001115 * |-------->| | best RIB, if required
1116 * | |
1117 * static_install->|->rib_addqueue...... -> rib_process
1118 * | |
1119 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001120 * |-> set RIB_ENTRY_REMOVE |
1121 * rib_delnode (RIB freed)
1122 *
1123 *
1124 * Queueing state for a route_node is kept in the head RIB entry, this
1125 * state must be preserved as and when the head RIB entry of a
1126 * route_node is changed by rib_unlink / rib_link. A small complication,
1127 * but saves having to allocate a dedicated object for this.
1128 *
1129 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1130 *
1131 * - route_nodes: refcounted by:
1132 * - RIBs attached to route_node:
1133 * - managed by: rib_link/unlink
1134 * - route_node processing queue
1135 * - managed by: rib_addqueue, rib_process.
1136 *
1137 */
1138
paul718e3742002-12-13 20:15:29 +00001139/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001140static void
Paul Jakma6d691122006-07-27 21:49:00 +00001141rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001142{
1143 struct rib *head;
paul4d38fdb2005-04-28 17:35:14 +00001144
1145 assert (rib && rn);
1146
Paul Jakma6d691122006-07-27 21:49:00 +00001147 route_lock_node (rn); /* rn route table reference */
1148
1149 if (IS_ZEBRA_DEBUG_RIB)
1150 zlog_debug ("%s: rn %p, rib %p", __func__, rn, rib);
1151
paul718e3742002-12-13 20:15:29 +00001152 head = rn->info;
1153 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001154 {
1155 if (IS_ZEBRA_DEBUG_RIB)
1156 zlog_debug ("%s: new head, rn_status copied over", __func__);
1157 head->prev = rib;
1158 /* Transfer the rn status flags to the new head RIB */
1159 rib->rn_status = head->rn_status;
1160 }
paul718e3742002-12-13 20:15:29 +00001161 rib->next = head;
1162 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001163 rib_queue_add (&zebrad, rn);
1164}
1165
1166static void
1167rib_addnode (struct route_node *rn, struct rib *rib)
1168{
1169 /* RIB node has been un-removed before route-node is processed.
1170 * route_node must hence already be on the queue for processing..
1171 */
1172 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1173 {
1174 if (IS_ZEBRA_DEBUG_RIB)
1175 zlog_debug ("%s: rn %p, un-removed rib %p",
1176 __func__, rn, rib);
1177 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1178 return;
1179 }
1180 rib_link (rn, rib);
1181}
1182
1183static void
1184rib_unlink (struct route_node *rn, struct rib *rib)
1185{
1186 struct nexthop *nexthop, *next;
1187
1188 assert (rn && rib);
1189
1190 if (IS_ZEBRA_DEBUG_RIB)
1191 zlog_debug ("%s: rn %p, rib %p",
1192 __func__, rn, rib);
1193
1194 if (rib->next)
1195 rib->next->prev = rib->prev;
1196
1197 if (rib->prev)
1198 rib->prev->next = rib->next;
1199 else
1200 {
1201 rn->info = rib->next;
1202
1203 if (rn->info)
1204 {
1205 if (IS_ZEBRA_DEBUG_RIB)
1206 zlog_debug ("%s: rn %p, rib %p, new head copy",
1207 __func__, rn, rib);
1208 rib->next->rn_status = rib->rn_status;
1209 }
1210 }
1211
1212 /* free RIB and nexthops */
1213 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1214 {
1215 next = nexthop->next;
1216 nexthop_free (nexthop);
1217 }
1218 XFREE (MTYPE_RIB, rib);
1219
1220 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001221}
1222
paula1ac18c2005-06-28 17:17:12 +00001223static void
paul718e3742002-12-13 20:15:29 +00001224rib_delnode (struct route_node *rn, struct rib *rib)
1225{
Paul Jakma6d691122006-07-27 21:49:00 +00001226 if (IS_ZEBRA_DEBUG_RIB)
1227 zlog_debug ("%s: rn %p, rib %p, removing", __func__, rn, rib);
1228 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1229 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001230}
1231
1232int
1233rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1234 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1235 u_int32_t metric, u_char distance)
1236{
1237 struct rib *rib;
1238 struct rib *same = NULL;
1239 struct route_table *table;
1240 struct route_node *rn;
1241 struct nexthop *nexthop;
1242
1243 /* Lookup table. */
1244 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1245 if (! table)
1246 return 0;
1247
1248 /* Make it sure prefixlen is applied to the prefix. */
1249 apply_mask_ipv4 (p);
1250
1251 /* Set default distance by route type. */
1252 if (distance == 0)
1253 {
1254 distance = route_info[type].distance;
1255
1256 /* iBGP distance is 200. */
1257 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1258 distance = 200;
1259 }
1260
1261 /* Lookup route node.*/
1262 rn = route_node_get (table, (struct prefix *) p);
1263
1264 /* If same type of route are installed, treat it as a implicit
1265 withdraw. */
1266 for (rib = rn->info; rib; rib = rib->next)
1267 {
Paul Jakma6d691122006-07-27 21:49:00 +00001268 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1269 continue;
1270
hassoebf1ead2005-09-21 14:58:20 +00001271 if (rib->type != type)
1272 continue;
1273 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001274 {
1275 same = rib;
1276 break;
1277 }
hassoebf1ead2005-09-21 14:58:20 +00001278 /* Duplicate connected route comes in. */
1279 else if ((nexthop = rib->nexthop) &&
1280 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001281 nexthop->ifindex == ifindex &&
1282 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001283 {
1284 rib->refcnt++;
1285 return 0 ;
1286 }
paul718e3742002-12-13 20:15:29 +00001287 }
1288
1289 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001290 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001291 rib->type = type;
1292 rib->distance = distance;
1293 rib->flags = flags;
1294 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001295 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001296 rib->nexthop_num = 0;
1297 rib->uptime = time (NULL);
1298
1299 /* Nexthop settings. */
1300 if (gate)
1301 {
1302 if (ifindex)
1303 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1304 else
1305 nexthop_ipv4_add (rib, gate);
1306 }
1307 else
1308 nexthop_ifindex_add (rib, ifindex);
1309
1310 /* If this route is kernel route, set FIB flag to the route. */
1311 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1312 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1313 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1314
1315 /* Link new rib to node.*/
1316 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001317
paul718e3742002-12-13 20:15:29 +00001318 /* Free implicit route.*/
1319 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001320 rib_delnode (rn, same);
1321
1322 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001323 return 0;
1324}
1325
1326int
1327rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1328{
1329 struct route_table *table;
1330 struct route_node *rn;
1331 struct rib *same;
1332 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001333
paul718e3742002-12-13 20:15:29 +00001334 /* Lookup table. */
1335 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1336 if (! table)
1337 return 0;
paul718e3742002-12-13 20:15:29 +00001338 /* Make it sure prefixlen is applied to the prefix. */
1339 apply_mask_ipv4 (p);
1340
1341 /* Set default distance by route type. */
1342 if (rib->distance == 0)
1343 {
1344 rib->distance = route_info[rib->type].distance;
1345
1346 /* iBGP distance is 200. */
1347 if (rib->type == ZEBRA_ROUTE_BGP
1348 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1349 rib->distance = 200;
1350 }
1351
1352 /* Lookup route node.*/
1353 rn = route_node_get (table, (struct prefix *) p);
1354
1355 /* If same type of route are installed, treat it as a implicit
1356 withdraw. */
1357 for (same = rn->info; same; same = same->next)
1358 {
Paul Jakma6d691122006-07-27 21:49:00 +00001359 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1360 continue;
1361
paul718e3742002-12-13 20:15:29 +00001362 if (same->type == rib->type && same->table == rib->table
1363 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001364 break;
paul718e3742002-12-13 20:15:29 +00001365 }
paul4d38fdb2005-04-28 17:35:14 +00001366
paul718e3742002-12-13 20:15:29 +00001367 /* If this route is kernel route, set FIB flag to the route. */
1368 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1369 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1370 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1371
1372 /* Link new rib to node.*/
1373 rib_addnode (rn, rib);
1374
paul718e3742002-12-13 20:15:29 +00001375 /* Free implicit route.*/
1376 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001377 rib_delnode (rn, same);
1378
1379 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001380 return 0;
1381}
1382
hassoebf1ead2005-09-21 14:58:20 +00001383/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001384int
1385rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1386 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1387{
1388 struct route_table *table;
1389 struct route_node *rn;
1390 struct rib *rib;
1391 struct rib *fib = NULL;
1392 struct rib *same = NULL;
1393 struct nexthop *nexthop;
1394 char buf1[BUFSIZ];
1395 char buf2[BUFSIZ];
1396
1397 /* Lookup table. */
1398 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1399 if (! table)
1400 return 0;
1401
1402 /* Apply mask. */
1403 apply_mask_ipv4 (p);
1404
paul5ec90d22003-06-19 01:41:37 +00001405 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001406 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001407 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1408 p->prefixlen,
1409 inet_ntoa (*gate),
1410 ifindex);
1411
paul718e3742002-12-13 20:15:29 +00001412 /* Lookup route node. */
1413 rn = route_node_lookup (table, (struct prefix *) p);
1414 if (! rn)
1415 {
1416 if (IS_ZEBRA_DEBUG_KERNEL)
1417 {
1418 if (gate)
ajsb6178002004-12-07 21:12:56 +00001419 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001420 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1421 p->prefixlen,
1422 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1423 ifindex);
1424 else
ajsb6178002004-12-07 21:12:56 +00001425 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001426 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1427 p->prefixlen,
1428 ifindex);
1429 }
1430 return ZEBRA_ERR_RTNOEXIST;
1431 }
1432
1433 /* Lookup same type route. */
1434 for (rib = rn->info; rib; rib = rib->next)
1435 {
Paul Jakma6d691122006-07-27 21:49:00 +00001436 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1437 continue;
1438
paul718e3742002-12-13 20:15:29 +00001439 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1440 fib = rib;
1441
hassoebf1ead2005-09-21 14:58:20 +00001442 if (rib->type != type)
1443 continue;
1444 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1445 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001446 {
hassoebf1ead2005-09-21 14:58:20 +00001447 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001448 {
hassoebf1ead2005-09-21 14:58:20 +00001449 rib->refcnt--;
1450 route_unlock_node (rn);
1451 route_unlock_node (rn);
1452 return 0;
paul718e3742002-12-13 20:15:29 +00001453 }
hassoebf1ead2005-09-21 14:58:20 +00001454 same = rib;
1455 break;
paul718e3742002-12-13 20:15:29 +00001456 }
hassoebf1ead2005-09-21 14:58:20 +00001457 /* Make sure that the route found has the same gateway. */
1458 else if (gate == NULL ||
1459 ((nexthop = rib->nexthop) &&
1460 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1461 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001462 {
hassoebf1ead2005-09-21 14:58:20 +00001463 same = rib;
1464 break;
paul718e3742002-12-13 20:15:29 +00001465 }
1466 }
1467
1468 /* If same type of route can't be found and this message is from
1469 kernel. */
1470 if (! same)
1471 {
1472 if (fib && type == ZEBRA_ROUTE_KERNEL)
1473 {
1474 /* Unset flags. */
1475 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1476 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1477
1478 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1479 }
1480 else
1481 {
1482 if (IS_ZEBRA_DEBUG_KERNEL)
1483 {
1484 if (gate)
ajsb6178002004-12-07 21:12:56 +00001485 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001486 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1487 p->prefixlen,
1488 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1489 ifindex,
1490 type);
1491 else
ajsb6178002004-12-07 21:12:56 +00001492 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001493 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1494 p->prefixlen,
1495 ifindex,
1496 type);
1497 }
1498 route_unlock_node (rn);
1499 return ZEBRA_ERR_RTNOEXIST;
1500 }
1501 }
paul4d38fdb2005-04-28 17:35:14 +00001502
paul718e3742002-12-13 20:15:29 +00001503 if (same)
1504 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001505
paul718e3742002-12-13 20:15:29 +00001506 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001507 return 0;
1508}
1509
1510/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001511static void
paul718e3742002-12-13 20:15:29 +00001512static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1513{
1514 struct rib *rib;
1515 struct route_node *rn;
1516 struct route_table *table;
1517
1518 /* Lookup table. */
1519 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1520 if (! table)
1521 return;
1522
1523 /* Lookup existing route */
1524 rn = route_node_get (table, p);
1525 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001526 {
1527 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1528 continue;
1529
1530 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1531 break;
1532 }
paul718e3742002-12-13 20:15:29 +00001533
1534 if (rib)
1535 {
1536 /* Same distance static route is there. Update it with new
1537 nexthop. */
paul718e3742002-12-13 20:15:29 +00001538 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001539 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001540 {
1541 case STATIC_IPV4_GATEWAY:
1542 nexthop_ipv4_add (rib, &si->gate.ipv4);
1543 break;
1544 case STATIC_IPV4_IFNAME:
1545 nexthop_ifname_add (rib, si->gate.ifname);
1546 break;
1547 case STATIC_IPV4_BLACKHOLE:
1548 nexthop_blackhole_add (rib);
1549 break;
paul4d38fdb2005-04-28 17:35:14 +00001550 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00001551 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001552 }
1553 else
1554 {
1555 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001556 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1557
paul718e3742002-12-13 20:15:29 +00001558 rib->type = ZEBRA_ROUTE_STATIC;
1559 rib->distance = si->distance;
1560 rib->metric = 0;
1561 rib->nexthop_num = 0;
1562
1563 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001564 {
1565 case STATIC_IPV4_GATEWAY:
1566 nexthop_ipv4_add (rib, &si->gate.ipv4);
1567 break;
1568 case STATIC_IPV4_IFNAME:
1569 nexthop_ifname_add (rib, si->gate.ifname);
1570 break;
1571 case STATIC_IPV4_BLACKHOLE:
1572 nexthop_blackhole_add (rib);
1573 break;
1574 }
paul718e3742002-12-13 20:15:29 +00001575
hasso81dfcaa2003-05-25 19:21:25 +00001576 /* Save the flags of this static routes (reject, blackhole) */
1577 rib->flags = si->flags;
1578
paul718e3742002-12-13 20:15:29 +00001579 /* Link this rib to the tree. */
1580 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001581 }
1582}
1583
paula1ac18c2005-06-28 17:17:12 +00001584static int
paul718e3742002-12-13 20:15:29 +00001585static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1586{
1587 if (nexthop->type == NEXTHOP_TYPE_IPV4
1588 && si->type == STATIC_IPV4_GATEWAY
1589 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1590 return 1;
1591 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1592 && si->type == STATIC_IPV4_IFNAME
1593 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1594 return 1;
paul595db7f2003-05-25 21:35:06 +00001595 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1596 && si->type == STATIC_IPV4_BLACKHOLE)
1597 return 1;
paule8e19462006-01-19 20:16:55 +00001598 return 0;
paul718e3742002-12-13 20:15:29 +00001599}
1600
1601/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001602static void
paul718e3742002-12-13 20:15:29 +00001603static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1604{
1605 struct route_node *rn;
1606 struct rib *rib;
1607 struct nexthop *nexthop;
1608 struct route_table *table;
1609
1610 /* Lookup table. */
1611 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1612 if (! table)
1613 return;
paul4d38fdb2005-04-28 17:35:14 +00001614
paul718e3742002-12-13 20:15:29 +00001615 /* Lookup existing route with type and distance. */
1616 rn = route_node_lookup (table, p);
1617 if (! rn)
1618 return;
1619
1620 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001621 {
1622 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1623 continue;
1624
1625 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1626 break;
1627 }
paul718e3742002-12-13 20:15:29 +00001628
1629 if (! rib)
1630 {
1631 route_unlock_node (rn);
1632 return;
1633 }
1634
1635 /* Lookup nexthop. */
1636 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1637 if (static_ipv4_nexthop_same (nexthop, si))
1638 break;
1639
1640 /* Can't find nexthop. */
1641 if (! nexthop)
1642 {
1643 route_unlock_node (rn);
1644 return;
1645 }
1646
1647 /* Check nexthop. */
1648 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00001649 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001650 else
1651 {
paul6baeb982003-10-28 03:47:15 +00001652 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1653 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001654 nexthop_delete (rib, nexthop);
1655 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001656 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001657 }
paul718e3742002-12-13 20:15:29 +00001658 /* Unlock node. */
1659 route_unlock_node (rn);
1660}
1661
1662/* Add static route into static route configuration. */
1663int
hasso39db97e2004-10-12 20:50:58 +00001664static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001665 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001666{
1667 u_char type = 0;
1668 struct route_node *rn;
1669 struct static_ipv4 *si;
1670 struct static_ipv4 *pp;
1671 struct static_ipv4 *cp;
1672 struct static_ipv4 *update = NULL;
1673 struct route_table *stable;
1674
1675 /* Lookup table. */
1676 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1677 if (! stable)
1678 return -1;
1679
1680 /* Lookup static route prefix. */
1681 rn = route_node_get (stable, p);
1682
1683 /* Make flags. */
1684 if (gate)
1685 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001686 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001687 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001688 else
1689 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001690
1691 /* Do nothing if there is a same static route. */
1692 for (si = rn->info; si; si = si->next)
1693 {
1694 if (type == si->type
1695 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1696 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1697 {
1698 if (distance == si->distance)
1699 {
1700 route_unlock_node (rn);
1701 return 0;
1702 }
1703 else
1704 update = si;
1705 }
1706 }
1707
Paul Jakma3c0755d2006-12-08 00:53:14 +00001708 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00001709 if (update)
1710 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1711
1712 /* Make new static route structure. */
1713 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1714 memset (si, 0, sizeof (struct static_ipv4));
1715
1716 si->type = type;
1717 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001718 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001719
1720 if (gate)
1721 si->gate.ipv4 = *gate;
1722 if (ifname)
1723 si->gate.ifname = XSTRDUP (0, ifname);
1724
1725 /* Add new static route information to the tree with sort by
1726 distance value and gateway address. */
1727 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1728 {
1729 if (si->distance < cp->distance)
1730 break;
1731 if (si->distance > cp->distance)
1732 continue;
1733 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1734 {
1735 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1736 break;
1737 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1738 continue;
1739 }
1740 }
1741
1742 /* Make linked list. */
1743 if (pp)
1744 pp->next = si;
1745 else
1746 rn->info = si;
1747 if (cp)
1748 cp->prev = si;
1749 si->prev = pp;
1750 si->next = cp;
1751
1752 /* Install into rib. */
1753 static_install_ipv4 (p, si);
1754
1755 return 1;
1756}
1757
1758/* Delete static route from static route configuration. */
1759int
hasso39db97e2004-10-12 20:50:58 +00001760static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001761 u_char distance, u_int32_t vrf_id)
1762{
1763 u_char type = 0;
1764 struct route_node *rn;
1765 struct static_ipv4 *si;
1766 struct route_table *stable;
1767
1768 /* Lookup table. */
1769 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1770 if (! stable)
1771 return -1;
1772
1773 /* Lookup static route prefix. */
1774 rn = route_node_lookup (stable, p);
1775 if (! rn)
1776 return 0;
1777
1778 /* Make flags. */
1779 if (gate)
1780 type = STATIC_IPV4_GATEWAY;
1781 else if (ifname)
1782 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001783 else
1784 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001785
1786 /* Find same static route is the tree */
1787 for (si = rn->info; si; si = si->next)
1788 if (type == si->type
1789 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1790 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1791 break;
1792
1793 /* Can't find static route. */
1794 if (! si)
1795 {
1796 route_unlock_node (rn);
1797 return 0;
1798 }
1799
1800 /* Install into rib. */
1801 static_uninstall_ipv4 (p, si);
1802
1803 /* Unlink static route from linked list. */
1804 if (si->prev)
1805 si->prev->next = si->next;
1806 else
1807 rn->info = si->next;
1808 if (si->next)
1809 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001810 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001811
1812 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001813 if (ifname)
1814 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001815 XFREE (MTYPE_STATIC_IPV4, si);
1816
paul143a3852003-09-29 20:06:13 +00001817 route_unlock_node (rn);
1818
paul718e3742002-12-13 20:15:29 +00001819 return 1;
1820}
1821
1822
1823#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001824static int
paul718e3742002-12-13 20:15:29 +00001825rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1826 struct in6_addr *gate, unsigned int ifindex, int table)
1827{
hasso726f9b22003-05-25 21:04:54 +00001828 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1829#if defined (MUSICA) || defined (LINUX)
1830 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1831 if (p->prefixlen == 96)
1832 return 0;
1833#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001834 return 1;
hasso726f9b22003-05-25 21:04:54 +00001835 }
paul718e3742002-12-13 20:15:29 +00001836 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1837 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1838 {
1839 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1840 return 1;
1841 }
1842 return 0;
1843}
1844
1845int
1846rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001847 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1848 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001849{
1850 struct rib *rib;
1851 struct rib *same = NULL;
1852 struct route_table *table;
1853 struct route_node *rn;
1854 struct nexthop *nexthop;
1855
paul718e3742002-12-13 20:15:29 +00001856 /* Lookup table. */
1857 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1858 if (! table)
1859 return 0;
1860
1861 /* Make sure mask is applied. */
1862 apply_mask_ipv6 (p);
1863
1864 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001865 if (!distance)
1866 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001867
1868 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1869 distance = 200;
1870
1871 /* Filter bogus route. */
1872 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1873 return 0;
1874
1875 /* Lookup route node.*/
1876 rn = route_node_get (table, (struct prefix *) p);
1877
1878 /* If same type of route are installed, treat it as a implicit
1879 withdraw. */
1880 for (rib = rn->info; rib; rib = rib->next)
1881 {
Paul Jakma6d691122006-07-27 21:49:00 +00001882 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1883 continue;
1884
hassoebf1ead2005-09-21 14:58:20 +00001885 if (rib->type != type)
1886 continue;
1887 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001888 {
1889 same = rib;
paul718e3742002-12-13 20:15:29 +00001890 break;
1891 }
hassoebf1ead2005-09-21 14:58:20 +00001892 else if ((nexthop = rib->nexthop) &&
1893 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1894 nexthop->ifindex == ifindex)
1895 {
1896 rib->refcnt++;
1897 return 0;
1898 }
paul718e3742002-12-13 20:15:29 +00001899 }
1900
1901 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001902 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1903
paul718e3742002-12-13 20:15:29 +00001904 rib->type = type;
1905 rib->distance = distance;
1906 rib->flags = flags;
1907 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001908 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001909 rib->nexthop_num = 0;
1910 rib->uptime = time (NULL);
1911
1912 /* Nexthop settings. */
1913 if (gate)
1914 {
1915 if (ifindex)
1916 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1917 else
1918 nexthop_ipv6_add (rib, gate);
1919 }
1920 else
1921 nexthop_ifindex_add (rib, ifindex);
1922
1923 /* If this route is kernel route, set FIB flag to the route. */
1924 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1925 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1926 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1927
1928 /* Link new rib to node.*/
1929 rib_addnode (rn, rib);
1930
paul718e3742002-12-13 20:15:29 +00001931 /* Free implicit route.*/
1932 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001933 rib_delnode (rn, same);
1934
1935 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001936 return 0;
1937}
1938
hassoebf1ead2005-09-21 14:58:20 +00001939/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001940int
1941rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1942 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1943{
1944 struct route_table *table;
1945 struct route_node *rn;
1946 struct rib *rib;
1947 struct rib *fib = NULL;
1948 struct rib *same = NULL;
1949 struct nexthop *nexthop;
1950 char buf1[BUFSIZ];
1951 char buf2[BUFSIZ];
1952
1953 /* Apply mask. */
1954 apply_mask_ipv6 (p);
1955
1956 /* Lookup table. */
1957 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1958 if (! table)
1959 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001960
paul718e3742002-12-13 20:15:29 +00001961 /* Lookup route node. */
1962 rn = route_node_lookup (table, (struct prefix *) p);
1963 if (! rn)
1964 {
1965 if (IS_ZEBRA_DEBUG_KERNEL)
1966 {
1967 if (gate)
ajsb6178002004-12-07 21:12:56 +00001968 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001969 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1970 p->prefixlen,
1971 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1972 ifindex);
1973 else
ajsb6178002004-12-07 21:12:56 +00001974 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001975 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1976 p->prefixlen,
1977 ifindex);
1978 }
1979 return ZEBRA_ERR_RTNOEXIST;
1980 }
1981
1982 /* Lookup same type route. */
1983 for (rib = rn->info; rib; rib = rib->next)
1984 {
Paul Jakma6d691122006-07-27 21:49:00 +00001985 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
1986 continue;
1987
paul718e3742002-12-13 20:15:29 +00001988 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1989 fib = rib;
1990
hassoebf1ead2005-09-21 14:58:20 +00001991 if (rib->type != type)
1992 continue;
1993 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1994 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001995 {
hassoebf1ead2005-09-21 14:58:20 +00001996 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001997 {
hassoebf1ead2005-09-21 14:58:20 +00001998 rib->refcnt--;
1999 route_unlock_node (rn);
2000 route_unlock_node (rn);
2001 return 0;
paul718e3742002-12-13 20:15:29 +00002002 }
hassoebf1ead2005-09-21 14:58:20 +00002003 same = rib;
2004 break;
paul718e3742002-12-13 20:15:29 +00002005 }
hassoebf1ead2005-09-21 14:58:20 +00002006 /* Make sure that the route found has the same gateway. */
2007 else if (gate == NULL ||
2008 ((nexthop = rib->nexthop) &&
2009 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2010 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002011 {
hassoebf1ead2005-09-21 14:58:20 +00002012 same = rib;
2013 break;
paul718e3742002-12-13 20:15:29 +00002014 }
2015 }
2016
2017 /* If same type of route can't be found and this message is from
2018 kernel. */
2019 if (! same)
2020 {
2021 if (fib && type == ZEBRA_ROUTE_KERNEL)
2022 {
2023 /* Unset flags. */
2024 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2025 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2026
2027 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2028 }
2029 else
2030 {
2031 if (IS_ZEBRA_DEBUG_KERNEL)
2032 {
2033 if (gate)
ajsb6178002004-12-07 21:12:56 +00002034 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002035 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2036 p->prefixlen,
2037 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2038 ifindex,
2039 type);
2040 else
ajsb6178002004-12-07 21:12:56 +00002041 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002042 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2043 p->prefixlen,
2044 ifindex,
2045 type);
2046 }
2047 route_unlock_node (rn);
2048 return ZEBRA_ERR_RTNOEXIST;
2049 }
2050 }
2051
2052 if (same)
2053 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002054
paul718e3742002-12-13 20:15:29 +00002055 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002056 return 0;
2057}
2058
2059/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002060static void
paul718e3742002-12-13 20:15:29 +00002061static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2062{
2063 struct rib *rib;
2064 struct route_table *table;
2065 struct route_node *rn;
2066
2067 /* Lookup table. */
2068 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2069 if (! table)
2070 return;
2071
2072 /* Lookup existing route */
2073 rn = route_node_get (table, p);
2074 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002075 {
2076 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2077 continue;
2078
2079 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2080 break;
2081 }
paul718e3742002-12-13 20:15:29 +00002082
2083 if (rib)
2084 {
2085 /* Same distance static route is there. Update it with new
2086 nexthop. */
paul718e3742002-12-13 20:15:29 +00002087 route_unlock_node (rn);
2088
2089 switch (si->type)
2090 {
2091 case STATIC_IPV6_GATEWAY:
2092 nexthop_ipv6_add (rib, &si->ipv6);
2093 break;
2094 case STATIC_IPV6_IFNAME:
2095 nexthop_ifname_add (rib, si->ifname);
2096 break;
2097 case STATIC_IPV6_GATEWAY_IFNAME:
2098 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2099 break;
2100 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002101 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002102 }
2103 else
2104 {
2105 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002106 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2107
paul718e3742002-12-13 20:15:29 +00002108 rib->type = ZEBRA_ROUTE_STATIC;
2109 rib->distance = si->distance;
2110 rib->metric = 0;
2111 rib->nexthop_num = 0;
2112
2113 switch (si->type)
2114 {
2115 case STATIC_IPV6_GATEWAY:
2116 nexthop_ipv6_add (rib, &si->ipv6);
2117 break;
2118 case STATIC_IPV6_IFNAME:
2119 nexthop_ifname_add (rib, si->ifname);
2120 break;
2121 case STATIC_IPV6_GATEWAY_IFNAME:
2122 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2123 break;
2124 }
2125
hasso81dfcaa2003-05-25 19:21:25 +00002126 /* Save the flags of this static routes (reject, blackhole) */
2127 rib->flags = si->flags;
2128
paul718e3742002-12-13 20:15:29 +00002129 /* Link this rib to the tree. */
2130 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002131 }
2132}
2133
paula1ac18c2005-06-28 17:17:12 +00002134static int
paul718e3742002-12-13 20:15:29 +00002135static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2136{
2137 if (nexthop->type == NEXTHOP_TYPE_IPV6
2138 && si->type == STATIC_IPV6_GATEWAY
2139 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2140 return 1;
2141 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2142 && si->type == STATIC_IPV6_IFNAME
2143 && strcmp (nexthop->ifname, si->ifname) == 0)
2144 return 1;
2145 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2146 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2147 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2148 && strcmp (nexthop->ifname, si->ifname) == 0)
2149 return 1;
paule8e19462006-01-19 20:16:55 +00002150 return 0;
paul718e3742002-12-13 20:15:29 +00002151}
2152
paula1ac18c2005-06-28 17:17:12 +00002153static void
paul718e3742002-12-13 20:15:29 +00002154static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2155{
2156 struct route_table *table;
2157 struct route_node *rn;
2158 struct rib *rib;
2159 struct nexthop *nexthop;
2160
2161 /* Lookup table. */
2162 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2163 if (! table)
2164 return;
2165
2166 /* Lookup existing route with type and distance. */
2167 rn = route_node_lookup (table, (struct prefix *) p);
2168 if (! rn)
2169 return;
2170
2171 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002172 {
2173 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2174 continue;
2175
2176 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2177 break;
2178 }
2179
paul718e3742002-12-13 20:15:29 +00002180 if (! rib)
2181 {
2182 route_unlock_node (rn);
2183 return;
2184 }
2185
2186 /* Lookup nexthop. */
2187 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2188 if (static_ipv6_nexthop_same (nexthop, si))
2189 break;
2190
2191 /* Can't find nexthop. */
2192 if (! nexthop)
2193 {
2194 route_unlock_node (rn);
2195 return;
2196 }
2197
2198 /* Check nexthop. */
2199 if (rib->nexthop_num == 1)
2200 {
2201 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002202 }
2203 else
2204 {
paul6baeb982003-10-28 03:47:15 +00002205 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2206 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002207 nexthop_delete (rib, nexthop);
2208 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002209 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002210 }
paul718e3742002-12-13 20:15:29 +00002211 /* Unlock node. */
2212 route_unlock_node (rn);
2213}
2214
2215/* Add static route into static route configuration. */
2216int
2217static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002218 const char *ifname, u_char flags, u_char distance,
2219 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002220{
2221 struct route_node *rn;
2222 struct static_ipv6 *si;
2223 struct static_ipv6 *pp;
2224 struct static_ipv6 *cp;
2225 struct route_table *stable;
2226
2227 /* Lookup table. */
2228 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2229 if (! stable)
2230 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002231
2232 if (!gate &&
2233 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2234 return -1;
2235
2236 if (!ifname &&
2237 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2238 return -1;
paul718e3742002-12-13 20:15:29 +00002239
2240 /* Lookup static route prefix. */
2241 rn = route_node_get (stable, p);
2242
2243 /* Do nothing if there is a same static route. */
2244 for (si = rn->info; si; si = si->next)
2245 {
2246 if (distance == si->distance
2247 && type == si->type
2248 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2249 && (! ifname || strcmp (ifname, si->ifname) == 0))
2250 {
2251 route_unlock_node (rn);
2252 return 0;
2253 }
2254 }
2255
2256 /* Make new static route structure. */
2257 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2258 memset (si, 0, sizeof (struct static_ipv6));
2259
2260 si->type = type;
2261 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002262 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002263
2264 switch (type)
2265 {
2266 case STATIC_IPV6_GATEWAY:
2267 si->ipv6 = *gate;
2268 break;
2269 case STATIC_IPV6_IFNAME:
2270 si->ifname = XSTRDUP (0, ifname);
2271 break;
2272 case STATIC_IPV6_GATEWAY_IFNAME:
2273 si->ipv6 = *gate;
2274 si->ifname = XSTRDUP (0, ifname);
2275 break;
2276 }
2277
2278 /* Add new static route information to the tree with sort by
2279 distance value and gateway address. */
2280 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2281 {
2282 if (si->distance < cp->distance)
2283 break;
2284 if (si->distance > cp->distance)
2285 continue;
2286 }
2287
2288 /* Make linked list. */
2289 if (pp)
2290 pp->next = si;
2291 else
2292 rn->info = si;
2293 if (cp)
2294 cp->prev = si;
2295 si->prev = pp;
2296 si->next = cp;
2297
2298 /* Install into rib. */
2299 static_install_ipv6 (p, si);
2300
2301 return 1;
2302}
2303
2304/* Delete static route from static route configuration. */
2305int
2306static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002307 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002308{
2309 struct route_node *rn;
2310 struct static_ipv6 *si;
2311 struct route_table *stable;
2312
2313 /* Lookup table. */
2314 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2315 if (! stable)
2316 return -1;
2317
2318 /* Lookup static route prefix. */
2319 rn = route_node_lookup (stable, p);
2320 if (! rn)
2321 return 0;
2322
2323 /* Find same static route is the tree */
2324 for (si = rn->info; si; si = si->next)
2325 if (distance == si->distance
2326 && type == si->type
2327 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2328 && (! ifname || strcmp (ifname, si->ifname) == 0))
2329 break;
2330
2331 /* Can't find static route. */
2332 if (! si)
2333 {
2334 route_unlock_node (rn);
2335 return 0;
2336 }
2337
2338 /* Install into rib. */
2339 static_uninstall_ipv6 (p, si);
2340
2341 /* Unlink static route from linked list. */
2342 if (si->prev)
2343 si->prev->next = si->next;
2344 else
2345 rn->info = si->next;
2346 if (si->next)
2347 si->next->prev = si->prev;
2348
2349 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002350 if (ifname)
2351 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002352 XFREE (MTYPE_STATIC_IPV6, si);
2353
2354 return 1;
2355}
2356#endif /* HAVE_IPV6 */
2357
2358/* RIB update function. */
2359void
paula1ac18c2005-06-28 17:17:12 +00002360rib_update (void)
paul718e3742002-12-13 20:15:29 +00002361{
2362 struct route_node *rn;
2363 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002364
paul718e3742002-12-13 20:15:29 +00002365 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2366 if (table)
2367 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002368 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002369 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002370
2371 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2372 if (table)
2373 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002374 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002375 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002376}
2377
2378/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002379static void
paul718e3742002-12-13 20:15:29 +00002380rib_if_up (struct interface *ifp)
2381{
2382 rib_update ();
2383}
2384
2385/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002386static void
paul718e3742002-12-13 20:15:29 +00002387rib_if_down (struct interface *ifp)
2388{
2389 rib_update ();
2390}
2391
2392/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002393static void
paul718e3742002-12-13 20:15:29 +00002394rib_weed_table (struct route_table *table)
2395{
2396 struct route_node *rn;
2397 struct rib *rib;
2398 struct rib *next;
2399
2400 if (table)
2401 for (rn = route_top (table); rn; rn = route_next (rn))
2402 for (rib = rn->info; rib; rib = next)
2403 {
2404 next = rib->next;
2405
Paul Jakma6d691122006-07-27 21:49:00 +00002406 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2407 continue;
2408
paulb21b19c2003-06-15 01:28:29 +00002409 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002410 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002411 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002412 }
2413}
2414
2415/* Delete all routes from non main table. */
2416void
paula1ac18c2005-06-28 17:17:12 +00002417rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002418{
2419 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2420 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2421}
2422
2423/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002424static void
paul718e3742002-12-13 20:15:29 +00002425rib_sweep_table (struct route_table *table)
2426{
2427 struct route_node *rn;
2428 struct rib *rib;
2429 struct rib *next;
2430 int ret = 0;
2431
2432 if (table)
2433 for (rn = route_top (table); rn; rn = route_next (rn))
2434 for (rib = rn->info; rib; rib = next)
2435 {
2436 next = rib->next;
2437
Paul Jakma6d691122006-07-27 21:49:00 +00002438 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2439 continue;
2440
paul718e3742002-12-13 20:15:29 +00002441 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2442 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2443 {
2444 ret = rib_uninstall_kernel (rn, rib);
2445 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002446 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002447 }
2448 }
2449}
2450
2451/* Sweep all RIB tables. */
2452void
paula1ac18c2005-06-28 17:17:12 +00002453rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002454{
2455 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2456 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2457}
2458
2459/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002460static void
paul718e3742002-12-13 20:15:29 +00002461rib_close_table (struct route_table *table)
2462{
2463 struct route_node *rn;
2464 struct rib *rib;
2465
2466 if (table)
2467 for (rn = route_top (table); rn; rn = route_next (rn))
2468 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002469 {
2470 if (! RIB_SYSTEM_ROUTE (rib)
2471 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2472 rib_uninstall_kernel (rn, rib);
2473 }
paul718e3742002-12-13 20:15:29 +00002474}
2475
2476/* Close all RIB tables. */
2477void
paula1ac18c2005-06-28 17:17:12 +00002478rib_close (void)
paul718e3742002-12-13 20:15:29 +00002479{
2480 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2481 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2482}
2483
2484/* Routing information base initialize. */
2485void
paula1ac18c2005-06-28 17:17:12 +00002486rib_init (void)
paul718e3742002-12-13 20:15:29 +00002487{
paul4d38fdb2005-04-28 17:35:14 +00002488 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002489 /* VRF initialization. */
2490 vrf_init ();
2491}