blob: acad065a02c53a2b0963beefb614c2c0526e54d5 [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 *
1106 * RIBs are submitted via rib_addnode and rib_delnode, which set
1107 * minimal state and then submit route_node to queue for best-path
1108 * selection later. Order of add/delete state changes are preserved for
1109 * any given RIB.
1110 *
1111 * Deleted RIBs are reaped during best-path selection.
1112 *
1113 * rib_addnode
1114 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
1115 * |-> rib_addqueue | best RIB, if required
1116 * | |
1117 * |-> .......................... -> rib_process
1118 * | |
1119 * |-> rib_addqueue |-> rib_unlink
1120 * |-> 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 }
paul718e3742002-12-13 20:15:29 +00001551 }
1552 else
1553 {
1554 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001555 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1556
paul718e3742002-12-13 20:15:29 +00001557 rib->type = ZEBRA_ROUTE_STATIC;
1558 rib->distance = si->distance;
1559 rib->metric = 0;
1560 rib->nexthop_num = 0;
1561
1562 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001563 {
1564 case STATIC_IPV4_GATEWAY:
1565 nexthop_ipv4_add (rib, &si->gate.ipv4);
1566 break;
1567 case STATIC_IPV4_IFNAME:
1568 nexthop_ifname_add (rib, si->gate.ifname);
1569 break;
1570 case STATIC_IPV4_BLACKHOLE:
1571 nexthop_blackhole_add (rib);
1572 break;
1573 }
paul718e3742002-12-13 20:15:29 +00001574
hasso81dfcaa2003-05-25 19:21:25 +00001575 /* Save the flags of this static routes (reject, blackhole) */
1576 rib->flags = si->flags;
1577
paul718e3742002-12-13 20:15:29 +00001578 /* Link this rib to the tree. */
1579 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001580 }
1581}
1582
paula1ac18c2005-06-28 17:17:12 +00001583static int
paul718e3742002-12-13 20:15:29 +00001584static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1585{
1586 if (nexthop->type == NEXTHOP_TYPE_IPV4
1587 && si->type == STATIC_IPV4_GATEWAY
1588 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1589 return 1;
1590 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1591 && si->type == STATIC_IPV4_IFNAME
1592 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1593 return 1;
paul595db7f2003-05-25 21:35:06 +00001594 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1595 && si->type == STATIC_IPV4_BLACKHOLE)
1596 return 1;
paule8e19462006-01-19 20:16:55 +00001597 return 0;
paul718e3742002-12-13 20:15:29 +00001598}
1599
1600/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001601static void
paul718e3742002-12-13 20:15:29 +00001602static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1603{
1604 struct route_node *rn;
1605 struct rib *rib;
1606 struct nexthop *nexthop;
1607 struct route_table *table;
1608
1609 /* Lookup table. */
1610 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1611 if (! table)
1612 return;
paul4d38fdb2005-04-28 17:35:14 +00001613
paul718e3742002-12-13 20:15:29 +00001614 /* Lookup existing route with type and distance. */
1615 rn = route_node_lookup (table, p);
1616 if (! rn)
1617 return;
1618
1619 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001620 {
1621 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1622 continue;
1623
1624 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1625 break;
1626 }
paul718e3742002-12-13 20:15:29 +00001627
1628 if (! rib)
1629 {
1630 route_unlock_node (rn);
1631 return;
1632 }
1633
1634 /* Lookup nexthop. */
1635 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1636 if (static_ipv4_nexthop_same (nexthop, si))
1637 break;
1638
1639 /* Can't find nexthop. */
1640 if (! nexthop)
1641 {
1642 route_unlock_node (rn);
1643 return;
1644 }
1645
1646 /* Check nexthop. */
1647 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00001648 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001649 else
1650 {
paul6baeb982003-10-28 03:47:15 +00001651 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1652 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001653 nexthop_delete (rib, nexthop);
1654 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001655 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001656 }
paul718e3742002-12-13 20:15:29 +00001657 /* Unlock node. */
1658 route_unlock_node (rn);
1659}
1660
1661/* Add static route into static route configuration. */
1662int
hasso39db97e2004-10-12 20:50:58 +00001663static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001664 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001665{
1666 u_char type = 0;
1667 struct route_node *rn;
1668 struct static_ipv4 *si;
1669 struct static_ipv4 *pp;
1670 struct static_ipv4 *cp;
1671 struct static_ipv4 *update = NULL;
1672 struct route_table *stable;
1673
1674 /* Lookup table. */
1675 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1676 if (! stable)
1677 return -1;
1678
1679 /* Lookup static route prefix. */
1680 rn = route_node_get (stable, p);
1681
1682 /* Make flags. */
1683 if (gate)
1684 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001685 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001686 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001687 else
1688 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001689
1690 /* Do nothing if there is a same static route. */
1691 for (si = rn->info; si; si = si->next)
1692 {
1693 if (type == si->type
1694 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1695 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1696 {
1697 if (distance == si->distance)
1698 {
1699 route_unlock_node (rn);
1700 return 0;
1701 }
1702 else
1703 update = si;
1704 }
1705 }
1706
1707 /* Distance chaged. */
1708 if (update)
1709 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1710
1711 /* Make new static route structure. */
1712 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1713 memset (si, 0, sizeof (struct static_ipv4));
1714
1715 si->type = type;
1716 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001717 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001718
1719 if (gate)
1720 si->gate.ipv4 = *gate;
1721 if (ifname)
1722 si->gate.ifname = XSTRDUP (0, ifname);
1723
1724 /* Add new static route information to the tree with sort by
1725 distance value and gateway address. */
1726 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1727 {
1728 if (si->distance < cp->distance)
1729 break;
1730 if (si->distance > cp->distance)
1731 continue;
1732 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1733 {
1734 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1735 break;
1736 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1737 continue;
1738 }
1739 }
1740
1741 /* Make linked list. */
1742 if (pp)
1743 pp->next = si;
1744 else
1745 rn->info = si;
1746 if (cp)
1747 cp->prev = si;
1748 si->prev = pp;
1749 si->next = cp;
1750
1751 /* Install into rib. */
1752 static_install_ipv4 (p, si);
1753
1754 return 1;
1755}
1756
1757/* Delete static route from static route configuration. */
1758int
hasso39db97e2004-10-12 20:50:58 +00001759static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001760 u_char distance, u_int32_t vrf_id)
1761{
1762 u_char type = 0;
1763 struct route_node *rn;
1764 struct static_ipv4 *si;
1765 struct route_table *stable;
1766
1767 /* Lookup table. */
1768 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1769 if (! stable)
1770 return -1;
1771
1772 /* Lookup static route prefix. */
1773 rn = route_node_lookup (stable, p);
1774 if (! rn)
1775 return 0;
1776
1777 /* Make flags. */
1778 if (gate)
1779 type = STATIC_IPV4_GATEWAY;
1780 else if (ifname)
1781 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001782 else
1783 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001784
1785 /* Find same static route is the tree */
1786 for (si = rn->info; si; si = si->next)
1787 if (type == si->type
1788 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1789 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1790 break;
1791
1792 /* Can't find static route. */
1793 if (! si)
1794 {
1795 route_unlock_node (rn);
1796 return 0;
1797 }
1798
1799 /* Install into rib. */
1800 static_uninstall_ipv4 (p, si);
1801
1802 /* Unlink static route from linked list. */
1803 if (si->prev)
1804 si->prev->next = si->next;
1805 else
1806 rn->info = si->next;
1807 if (si->next)
1808 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001809 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001810
1811 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001812 if (ifname)
1813 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001814 XFREE (MTYPE_STATIC_IPV4, si);
1815
paul143a3852003-09-29 20:06:13 +00001816 route_unlock_node (rn);
1817
paul718e3742002-12-13 20:15:29 +00001818 return 1;
1819}
1820
1821
1822#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001823static int
paul718e3742002-12-13 20:15:29 +00001824rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1825 struct in6_addr *gate, unsigned int ifindex, int table)
1826{
hasso726f9b22003-05-25 21:04:54 +00001827 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1828#if defined (MUSICA) || defined (LINUX)
1829 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1830 if (p->prefixlen == 96)
1831 return 0;
1832#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001833 return 1;
hasso726f9b22003-05-25 21:04:54 +00001834 }
paul718e3742002-12-13 20:15:29 +00001835 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1836 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1837 {
1838 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1839 return 1;
1840 }
1841 return 0;
1842}
1843
1844int
1845rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001846 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1847 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001848{
1849 struct rib *rib;
1850 struct rib *same = NULL;
1851 struct route_table *table;
1852 struct route_node *rn;
1853 struct nexthop *nexthop;
1854
paul718e3742002-12-13 20:15:29 +00001855 /* Lookup table. */
1856 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1857 if (! table)
1858 return 0;
1859
1860 /* Make sure mask is applied. */
1861 apply_mask_ipv6 (p);
1862
1863 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001864 if (!distance)
1865 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001866
1867 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1868 distance = 200;
1869
1870 /* Filter bogus route. */
1871 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1872 return 0;
1873
1874 /* Lookup route node.*/
1875 rn = route_node_get (table, (struct prefix *) p);
1876
1877 /* If same type of route are installed, treat it as a implicit
1878 withdraw. */
1879 for (rib = rn->info; rib; rib = rib->next)
1880 {
Paul Jakma6d691122006-07-27 21:49:00 +00001881 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1882 continue;
1883
hassoebf1ead2005-09-21 14:58:20 +00001884 if (rib->type != type)
1885 continue;
1886 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001887 {
1888 same = rib;
paul718e3742002-12-13 20:15:29 +00001889 break;
1890 }
hassoebf1ead2005-09-21 14:58:20 +00001891 else if ((nexthop = rib->nexthop) &&
1892 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1893 nexthop->ifindex == ifindex)
1894 {
1895 rib->refcnt++;
1896 return 0;
1897 }
paul718e3742002-12-13 20:15:29 +00001898 }
1899
1900 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001901 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1902
paul718e3742002-12-13 20:15:29 +00001903 rib->type = type;
1904 rib->distance = distance;
1905 rib->flags = flags;
1906 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001907 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001908 rib->nexthop_num = 0;
1909 rib->uptime = time (NULL);
1910
1911 /* Nexthop settings. */
1912 if (gate)
1913 {
1914 if (ifindex)
1915 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1916 else
1917 nexthop_ipv6_add (rib, gate);
1918 }
1919 else
1920 nexthop_ifindex_add (rib, ifindex);
1921
1922 /* If this route is kernel route, set FIB flag to the route. */
1923 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1924 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1925 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1926
1927 /* Link new rib to node.*/
1928 rib_addnode (rn, rib);
1929
paul718e3742002-12-13 20:15:29 +00001930 /* Free implicit route.*/
1931 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001932 rib_delnode (rn, same);
1933
1934 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001935 return 0;
1936}
1937
hassoebf1ead2005-09-21 14:58:20 +00001938/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001939int
1940rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1941 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1942{
1943 struct route_table *table;
1944 struct route_node *rn;
1945 struct rib *rib;
1946 struct rib *fib = NULL;
1947 struct rib *same = NULL;
1948 struct nexthop *nexthop;
1949 char buf1[BUFSIZ];
1950 char buf2[BUFSIZ];
1951
1952 /* Apply mask. */
1953 apply_mask_ipv6 (p);
1954
1955 /* Lookup table. */
1956 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1957 if (! table)
1958 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001959
paul718e3742002-12-13 20:15:29 +00001960 /* Lookup route node. */
1961 rn = route_node_lookup (table, (struct prefix *) p);
1962 if (! rn)
1963 {
1964 if (IS_ZEBRA_DEBUG_KERNEL)
1965 {
1966 if (gate)
ajsb6178002004-12-07 21:12:56 +00001967 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001968 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1969 p->prefixlen,
1970 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1971 ifindex);
1972 else
ajsb6178002004-12-07 21:12:56 +00001973 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001974 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1975 p->prefixlen,
1976 ifindex);
1977 }
1978 return ZEBRA_ERR_RTNOEXIST;
1979 }
1980
1981 /* Lookup same type route. */
1982 for (rib = rn->info; rib; rib = rib->next)
1983 {
Paul Jakma6d691122006-07-27 21:49:00 +00001984 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
1985 continue;
1986
paul718e3742002-12-13 20:15:29 +00001987 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1988 fib = rib;
1989
hassoebf1ead2005-09-21 14:58:20 +00001990 if (rib->type != type)
1991 continue;
1992 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1993 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001994 {
hassoebf1ead2005-09-21 14:58:20 +00001995 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001996 {
hassoebf1ead2005-09-21 14:58:20 +00001997 rib->refcnt--;
1998 route_unlock_node (rn);
1999 route_unlock_node (rn);
2000 return 0;
paul718e3742002-12-13 20:15:29 +00002001 }
hassoebf1ead2005-09-21 14:58:20 +00002002 same = rib;
2003 break;
paul718e3742002-12-13 20:15:29 +00002004 }
hassoebf1ead2005-09-21 14:58:20 +00002005 /* Make sure that the route found has the same gateway. */
2006 else if (gate == NULL ||
2007 ((nexthop = rib->nexthop) &&
2008 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2009 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002010 {
hassoebf1ead2005-09-21 14:58:20 +00002011 same = rib;
2012 break;
paul718e3742002-12-13 20:15:29 +00002013 }
2014 }
2015
2016 /* If same type of route can't be found and this message is from
2017 kernel. */
2018 if (! same)
2019 {
2020 if (fib && type == ZEBRA_ROUTE_KERNEL)
2021 {
2022 /* Unset flags. */
2023 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2024 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2025
2026 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2027 }
2028 else
2029 {
2030 if (IS_ZEBRA_DEBUG_KERNEL)
2031 {
2032 if (gate)
ajsb6178002004-12-07 21:12:56 +00002033 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002034 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2035 p->prefixlen,
2036 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2037 ifindex,
2038 type);
2039 else
ajsb6178002004-12-07 21:12:56 +00002040 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002041 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2042 p->prefixlen,
2043 ifindex,
2044 type);
2045 }
2046 route_unlock_node (rn);
2047 return ZEBRA_ERR_RTNOEXIST;
2048 }
2049 }
2050
2051 if (same)
2052 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002053
paul718e3742002-12-13 20:15:29 +00002054 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002055 return 0;
2056}
2057
2058/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002059static void
paul718e3742002-12-13 20:15:29 +00002060static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2061{
2062 struct rib *rib;
2063 struct route_table *table;
2064 struct route_node *rn;
2065
2066 /* Lookup table. */
2067 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2068 if (! table)
2069 return;
2070
2071 /* Lookup existing route */
2072 rn = route_node_get (table, p);
2073 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002074 {
2075 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2076 continue;
2077
2078 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2079 break;
2080 }
paul718e3742002-12-13 20:15:29 +00002081
2082 if (rib)
2083 {
2084 /* Same distance static route is there. Update it with new
2085 nexthop. */
paul718e3742002-12-13 20:15:29 +00002086 route_unlock_node (rn);
2087
2088 switch (si->type)
2089 {
2090 case STATIC_IPV6_GATEWAY:
2091 nexthop_ipv6_add (rib, &si->ipv6);
2092 break;
2093 case STATIC_IPV6_IFNAME:
2094 nexthop_ifname_add (rib, si->ifname);
2095 break;
2096 case STATIC_IPV6_GATEWAY_IFNAME:
2097 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2098 break;
2099 }
paul718e3742002-12-13 20:15:29 +00002100 }
2101 else
2102 {
2103 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002104 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2105
paul718e3742002-12-13 20:15:29 +00002106 rib->type = ZEBRA_ROUTE_STATIC;
2107 rib->distance = si->distance;
2108 rib->metric = 0;
2109 rib->nexthop_num = 0;
2110
2111 switch (si->type)
2112 {
2113 case STATIC_IPV6_GATEWAY:
2114 nexthop_ipv6_add (rib, &si->ipv6);
2115 break;
2116 case STATIC_IPV6_IFNAME:
2117 nexthop_ifname_add (rib, si->ifname);
2118 break;
2119 case STATIC_IPV6_GATEWAY_IFNAME:
2120 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2121 break;
2122 }
2123
hasso81dfcaa2003-05-25 19:21:25 +00002124 /* Save the flags of this static routes (reject, blackhole) */
2125 rib->flags = si->flags;
2126
paul718e3742002-12-13 20:15:29 +00002127 /* Link this rib to the tree. */
2128 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002129 }
2130}
2131
paula1ac18c2005-06-28 17:17:12 +00002132static int
paul718e3742002-12-13 20:15:29 +00002133static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2134{
2135 if (nexthop->type == NEXTHOP_TYPE_IPV6
2136 && si->type == STATIC_IPV6_GATEWAY
2137 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2138 return 1;
2139 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2140 && si->type == STATIC_IPV6_IFNAME
2141 && strcmp (nexthop->ifname, si->ifname) == 0)
2142 return 1;
2143 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2144 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2145 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2146 && strcmp (nexthop->ifname, si->ifname) == 0)
2147 return 1;
paule8e19462006-01-19 20:16:55 +00002148 return 0;
paul718e3742002-12-13 20:15:29 +00002149}
2150
paula1ac18c2005-06-28 17:17:12 +00002151static void
paul718e3742002-12-13 20:15:29 +00002152static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2153{
2154 struct route_table *table;
2155 struct route_node *rn;
2156 struct rib *rib;
2157 struct nexthop *nexthop;
2158
2159 /* Lookup table. */
2160 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2161 if (! table)
2162 return;
2163
2164 /* Lookup existing route with type and distance. */
2165 rn = route_node_lookup (table, (struct prefix *) p);
2166 if (! rn)
2167 return;
2168
2169 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002170 {
2171 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2172 continue;
2173
2174 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2175 break;
2176 }
2177
paul718e3742002-12-13 20:15:29 +00002178 if (! rib)
2179 {
2180 route_unlock_node (rn);
2181 return;
2182 }
2183
2184 /* Lookup nexthop. */
2185 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2186 if (static_ipv6_nexthop_same (nexthop, si))
2187 break;
2188
2189 /* Can't find nexthop. */
2190 if (! nexthop)
2191 {
2192 route_unlock_node (rn);
2193 return;
2194 }
2195
2196 /* Check nexthop. */
2197 if (rib->nexthop_num == 1)
2198 {
2199 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002200 }
2201 else
2202 {
paul6baeb982003-10-28 03:47:15 +00002203 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2204 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002205 nexthop_delete (rib, nexthop);
2206 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002207 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002208 }
paul718e3742002-12-13 20:15:29 +00002209 /* Unlock node. */
2210 route_unlock_node (rn);
2211}
2212
2213/* Add static route into static route configuration. */
2214int
2215static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002216 const char *ifname, u_char flags, u_char distance,
2217 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002218{
2219 struct route_node *rn;
2220 struct static_ipv6 *si;
2221 struct static_ipv6 *pp;
2222 struct static_ipv6 *cp;
2223 struct route_table *stable;
2224
2225 /* Lookup table. */
2226 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2227 if (! stable)
2228 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002229
2230 if (!gate &&
2231 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2232 return -1;
2233
2234 if (!ifname &&
2235 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2236 return -1;
paul718e3742002-12-13 20:15:29 +00002237
2238 /* Lookup static route prefix. */
2239 rn = route_node_get (stable, p);
2240
2241 /* Do nothing if there is a same static route. */
2242 for (si = rn->info; si; si = si->next)
2243 {
2244 if (distance == si->distance
2245 && type == si->type
2246 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2247 && (! ifname || strcmp (ifname, si->ifname) == 0))
2248 {
2249 route_unlock_node (rn);
2250 return 0;
2251 }
2252 }
2253
2254 /* Make new static route structure. */
2255 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2256 memset (si, 0, sizeof (struct static_ipv6));
2257
2258 si->type = type;
2259 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002260 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002261
2262 switch (type)
2263 {
2264 case STATIC_IPV6_GATEWAY:
2265 si->ipv6 = *gate;
2266 break;
2267 case STATIC_IPV6_IFNAME:
2268 si->ifname = XSTRDUP (0, ifname);
2269 break;
2270 case STATIC_IPV6_GATEWAY_IFNAME:
2271 si->ipv6 = *gate;
2272 si->ifname = XSTRDUP (0, ifname);
2273 break;
2274 }
2275
2276 /* Add new static route information to the tree with sort by
2277 distance value and gateway address. */
2278 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2279 {
2280 if (si->distance < cp->distance)
2281 break;
2282 if (si->distance > cp->distance)
2283 continue;
2284 }
2285
2286 /* Make linked list. */
2287 if (pp)
2288 pp->next = si;
2289 else
2290 rn->info = si;
2291 if (cp)
2292 cp->prev = si;
2293 si->prev = pp;
2294 si->next = cp;
2295
2296 /* Install into rib. */
2297 static_install_ipv6 (p, si);
2298
2299 return 1;
2300}
2301
2302/* Delete static route from static route configuration. */
2303int
2304static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002305 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002306{
2307 struct route_node *rn;
2308 struct static_ipv6 *si;
2309 struct route_table *stable;
2310
2311 /* Lookup table. */
2312 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2313 if (! stable)
2314 return -1;
2315
2316 /* Lookup static route prefix. */
2317 rn = route_node_lookup (stable, p);
2318 if (! rn)
2319 return 0;
2320
2321 /* Find same static route is the tree */
2322 for (si = rn->info; si; si = si->next)
2323 if (distance == si->distance
2324 && type == si->type
2325 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2326 && (! ifname || strcmp (ifname, si->ifname) == 0))
2327 break;
2328
2329 /* Can't find static route. */
2330 if (! si)
2331 {
2332 route_unlock_node (rn);
2333 return 0;
2334 }
2335
2336 /* Install into rib. */
2337 static_uninstall_ipv6 (p, si);
2338
2339 /* Unlink static route from linked list. */
2340 if (si->prev)
2341 si->prev->next = si->next;
2342 else
2343 rn->info = si->next;
2344 if (si->next)
2345 si->next->prev = si->prev;
2346
2347 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002348 if (ifname)
2349 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002350 XFREE (MTYPE_STATIC_IPV6, si);
2351
2352 return 1;
2353}
2354#endif /* HAVE_IPV6 */
2355
2356/* RIB update function. */
2357void
paula1ac18c2005-06-28 17:17:12 +00002358rib_update (void)
paul718e3742002-12-13 20:15:29 +00002359{
2360 struct route_node *rn;
2361 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002362
paul718e3742002-12-13 20:15:29 +00002363 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2364 if (table)
2365 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002366 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002367 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002368
2369 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2370 if (table)
2371 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002372 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002373 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002374}
2375
2376/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002377static void
paul718e3742002-12-13 20:15:29 +00002378rib_if_up (struct interface *ifp)
2379{
2380 rib_update ();
2381}
2382
2383/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002384static void
paul718e3742002-12-13 20:15:29 +00002385rib_if_down (struct interface *ifp)
2386{
2387 rib_update ();
2388}
2389
2390/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002391static void
paul718e3742002-12-13 20:15:29 +00002392rib_weed_table (struct route_table *table)
2393{
2394 struct route_node *rn;
2395 struct rib *rib;
2396 struct rib *next;
2397
2398 if (table)
2399 for (rn = route_top (table); rn; rn = route_next (rn))
2400 for (rib = rn->info; rib; rib = next)
2401 {
2402 next = rib->next;
2403
Paul Jakma6d691122006-07-27 21:49:00 +00002404 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2405 continue;
2406
paulb21b19c2003-06-15 01:28:29 +00002407 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002408 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002409 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002410 }
2411}
2412
2413/* Delete all routes from non main table. */
2414void
paula1ac18c2005-06-28 17:17:12 +00002415rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002416{
2417 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2418 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2419}
2420
2421/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002422static void
paul718e3742002-12-13 20:15:29 +00002423rib_sweep_table (struct route_table *table)
2424{
2425 struct route_node *rn;
2426 struct rib *rib;
2427 struct rib *next;
2428 int ret = 0;
2429
2430 if (table)
2431 for (rn = route_top (table); rn; rn = route_next (rn))
2432 for (rib = rn->info; rib; rib = next)
2433 {
2434 next = rib->next;
2435
Paul Jakma6d691122006-07-27 21:49:00 +00002436 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2437 continue;
2438
paul718e3742002-12-13 20:15:29 +00002439 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2440 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2441 {
2442 ret = rib_uninstall_kernel (rn, rib);
2443 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002444 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002445 }
2446 }
2447}
2448
2449/* Sweep all RIB tables. */
2450void
paula1ac18c2005-06-28 17:17:12 +00002451rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002452{
2453 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2454 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2455}
2456
2457/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002458static void
paul718e3742002-12-13 20:15:29 +00002459rib_close_table (struct route_table *table)
2460{
2461 struct route_node *rn;
2462 struct rib *rib;
2463
2464 if (table)
2465 for (rn = route_top (table); rn; rn = route_next (rn))
2466 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002467 {
2468 if (! RIB_SYSTEM_ROUTE (rib)
2469 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2470 rib_uninstall_kernel (rn, rib);
2471 }
paul718e3742002-12-13 20:15:29 +00002472}
2473
2474/* Close all RIB tables. */
2475void
paula1ac18c2005-06-28 17:17:12 +00002476rib_close (void)
paul718e3742002-12-13 20:15:29 +00002477{
2478 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2479 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2480}
2481
2482/* Routing information base initialize. */
2483void
paula1ac18c2005-06-28 17:17:12 +00002484rib_init (void)
paul718e3742002-12-13 20:15:29 +00002485{
paul4d38fdb2005-04-28 17:35:14 +00002486 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002487 /* VRF initialization. */
2488 vrf_init ();
2489}