blob: f61cbe319f16b36c5f30bcd69acad48dec6ff878 [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"
Paul Jakma7514fb72007-05-02 16:05:35 +000035#include "prefix.h"
36#include "routemap.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "zebra/rib.h"
39#include "zebra/rt.h"
40#include "zebra/zserv.h"
41#include "zebra/redistribute.h"
42#include "zebra/debug.h"
43
44/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000045extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000046
Paul Jakma457eb9a2006-07-27 19:59:58 +000047/* Hold time for RIB process, should be very minimal.
48 * it is useful to able to set it otherwise for testing, hence exported
49 * as global here for test-rig code.
50 */
51int rib_process_hold_time = 10;
52
paul718e3742002-12-13 20:15:29 +000053/* Each route type's string and default distance value. */
54struct
55{
56 int key;
57 int distance;
58} route_info[] =
59{
60 {ZEBRA_ROUTE_SYSTEM, 0},
61 {ZEBRA_ROUTE_KERNEL, 0},
62 {ZEBRA_ROUTE_CONNECT, 0},
63 {ZEBRA_ROUTE_STATIC, 1},
64 {ZEBRA_ROUTE_RIP, 120},
65 {ZEBRA_ROUTE_RIPNG, 120},
66 {ZEBRA_ROUTE_OSPF, 110},
67 {ZEBRA_ROUTE_OSPF6, 110},
jardin9e867fe2003-12-23 08:56:18 +000068 {ZEBRA_ROUTE_ISIS, 115},
paul718e3742002-12-13 20:15:29 +000069 {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
70};
71
72/* Vector for routing table. */
73vector vrf_vector;
74
75/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +000076static struct vrf *
hassofce954f2004-10-07 20:29:24 +000077vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +000078{
79 struct vrf *vrf;
80
81 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
82
83 /* Put name. */
84 if (name)
85 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
86
87 /* Allocate routing table and static table. */
88 vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
89 vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
90 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
91 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
92
93 return vrf;
94}
95
96/* Free VRF. */
paula1ac18c2005-06-28 17:17:12 +000097static void
paul718e3742002-12-13 20:15:29 +000098vrf_free (struct vrf *vrf)
99{
100 if (vrf->name)
101 XFREE (MTYPE_VRF_NAME, vrf->name);
102 XFREE (MTYPE_VRF, vrf);
103}
104
105/* Lookup VRF by identifier. */
106struct vrf *
107vrf_lookup (u_int32_t id)
108{
109 return vector_lookup (vrf_vector, id);
110}
111
112/* Lookup VRF by name. */
paula1ac18c2005-06-28 17:17:12 +0000113static struct vrf *
paul718e3742002-12-13 20:15:29 +0000114vrf_lookup_by_name (char *name)
115{
hassofce954f2004-10-07 20:29:24 +0000116 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000117 struct vrf *vrf;
118
paul55468c82005-03-14 20:19:01 +0000119 for (i = 0; i < vector_active (vrf_vector); i++)
paul718e3742002-12-13 20:15:29 +0000120 if ((vrf = vector_slot (vrf_vector, i)) != NULL)
121 if (vrf->name && name && strcmp (vrf->name, name) == 0)
122 return vrf;
123 return NULL;
124}
125
126/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000127static void
128vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000129{
130 struct vrf *default_table;
131
132 /* Allocate VRF vector. */
133 vrf_vector = vector_init (1);
134
135 /* Allocate default main table. */
136 default_table = vrf_alloc ("Default-IP-Routing-Table");
137
138 /* Default table index must be 0. */
139 vector_set_index (vrf_vector, 0, default_table);
140}
141
142/* Lookup route table. */
143struct route_table *
144vrf_table (afi_t afi, safi_t safi, u_int32_t id)
145{
146 struct vrf *vrf;
147
148 vrf = vrf_lookup (id);
149 if (! vrf)
150 return NULL;
151
152 return vrf->table[afi][safi];
153}
154
155/* Lookup static route table. */
156struct route_table *
157vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
158{
159 struct vrf *vrf;
160
161 vrf = vrf_lookup (id);
162 if (! vrf)
163 return NULL;
164
165 return vrf->stable[afi][safi];
166}
167
168/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000169static void
paul718e3742002-12-13 20:15:29 +0000170nexthop_add (struct rib *rib, struct nexthop *nexthop)
171{
172 struct nexthop *last;
173
174 for (last = rib->nexthop; last && last->next; last = last->next)
175 ;
176 if (last)
177 last->next = nexthop;
178 else
179 rib->nexthop = nexthop;
180 nexthop->prev = last;
181
182 rib->nexthop_num++;
183}
184
185/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000186static void
paul718e3742002-12-13 20:15:29 +0000187nexthop_delete (struct rib *rib, struct nexthop *nexthop)
188{
189 if (nexthop->next)
190 nexthop->next->prev = nexthop->prev;
191 if (nexthop->prev)
192 nexthop->prev->next = nexthop->next;
193 else
194 rib->nexthop = nexthop->next;
195 rib->nexthop_num--;
196}
197
198/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000199static void
paul718e3742002-12-13 20:15:29 +0000200nexthop_free (struct nexthop *nexthop)
201{
paula4b70762003-05-16 17:19:48 +0000202 if (nexthop->ifname)
203 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000204 XFREE (MTYPE_NEXTHOP, nexthop);
205}
206
207struct nexthop *
208nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
209{
210 struct nexthop *nexthop;
211
212 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
213 memset (nexthop, 0, sizeof (struct nexthop));
214 nexthop->type = NEXTHOP_TYPE_IFINDEX;
215 nexthop->ifindex = ifindex;
216
217 nexthop_add (rib, nexthop);
218
219 return nexthop;
220}
221
222struct nexthop *
223nexthop_ifname_add (struct rib *rib, char *ifname)
224{
225 struct nexthop *nexthop;
226
227 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
228 memset (nexthop, 0, sizeof (struct nexthop));
229 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000230 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000231
232 nexthop_add (rib, nexthop);
233
234 return nexthop;
235}
236
237struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000238nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000239{
240 struct nexthop *nexthop;
241
242 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
243 memset (nexthop, 0, sizeof (struct nexthop));
244 nexthop->type = NEXTHOP_TYPE_IPV4;
245 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000246 if (src)
247 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000248
249 nexthop_add (rib, nexthop);
250
251 return nexthop;
252}
253
paula1ac18c2005-06-28 17:17:12 +0000254static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000255nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000256 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000257{
258 struct nexthop *nexthop;
259
260 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
261 memset (nexthop, 0, sizeof (struct nexthop));
262 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
263 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000264 if (src)
265 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000266 nexthop->ifindex = ifindex;
267
268 nexthop_add (rib, nexthop);
269
270 return nexthop;
271}
272
273#ifdef HAVE_IPV6
274struct nexthop *
275nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
276{
277 struct nexthop *nexthop;
278
279 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
280 memset (nexthop, 0, sizeof (struct nexthop));
281 nexthop->type = NEXTHOP_TYPE_IPV6;
282 nexthop->gate.ipv6 = *ipv6;
283
284 nexthop_add (rib, nexthop);
285
286 return nexthop;
287}
288
paula1ac18c2005-06-28 17:17:12 +0000289static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000290nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
291 char *ifname)
292{
293 struct nexthop *nexthop;
294
295 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
296 memset (nexthop, 0, sizeof (struct nexthop));
297 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
298 nexthop->gate.ipv6 = *ipv6;
299 nexthop->ifname = XSTRDUP (0, ifname);
300
301 nexthop_add (rib, nexthop);
302
303 return nexthop;
304}
305
paula1ac18c2005-06-28 17:17:12 +0000306static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000307nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
308 unsigned int ifindex)
309{
310 struct nexthop *nexthop;
311
312 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
313 memset (nexthop, 0, sizeof (struct nexthop));
314 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
315 nexthop->gate.ipv6 = *ipv6;
316 nexthop->ifindex = ifindex;
317
318 nexthop_add (rib, nexthop);
319
320 return nexthop;
321}
322#endif /* HAVE_IPV6 */
323
paul595db7f2003-05-25 21:35:06 +0000324struct nexthop *
325nexthop_blackhole_add (struct rib *rib)
326{
327 struct nexthop *nexthop;
328
329 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
330 memset (nexthop, 0, sizeof (struct nexthop));
331 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
332 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
333
334 nexthop_add (rib, nexthop);
335
336 return nexthop;
337}
338
paul718e3742002-12-13 20:15:29 +0000339/* If force flag is not set, do not modify falgs at all for uninstall
340 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000341static int
paul718e3742002-12-13 20:15:29 +0000342nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
343 struct route_node *top)
344{
345 struct prefix_ipv4 p;
346 struct route_table *table;
347 struct route_node *rn;
348 struct rib *match;
349 struct nexthop *newhop;
350
351 if (nexthop->type == NEXTHOP_TYPE_IPV4)
352 nexthop->ifindex = 0;
353
354 if (set)
355 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
356
357 /* Make lookup prefix. */
358 memset (&p, 0, sizeof (struct prefix_ipv4));
359 p.family = AF_INET;
360 p.prefixlen = IPV4_MAX_PREFIXLEN;
361 p.prefix = nexthop->gate.ipv4;
362
363 /* Lookup table. */
364 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
365 if (! table)
366 return 0;
367
368 rn = route_node_match (table, (struct prefix *) &p);
369 while (rn)
370 {
371 route_unlock_node (rn);
372
373 /* If lookup self prefix return immidiately. */
374 if (rn == top)
375 return 0;
376
377 /* Pick up selected route. */
378 for (match = rn->info; match; match = match->next)
379 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
380 break;
381
382 /* If there is no selected route or matched route is EGP, go up
383 tree. */
384 if (! match
385 || match->type == ZEBRA_ROUTE_BGP)
386 {
387 do {
388 rn = rn->parent;
389 } while (rn && rn->info == NULL);
390 if (rn)
391 route_lock_node (rn);
392 }
393 else
394 {
395 if (match->type == ZEBRA_ROUTE_CONNECT)
396 {
397 /* Directly point connected route. */
398 newhop = match->nexthop;
399 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
400 nexthop->ifindex = newhop->ifindex;
401
402 return 1;
403 }
404 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
405 {
406 for (newhop = match->nexthop; newhop; newhop = newhop->next)
407 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
408 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
409 {
410 if (set)
411 {
412 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
413 nexthop->rtype = newhop->type;
414 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
415 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
416 nexthop->rgate.ipv4 = newhop->gate.ipv4;
417 if (newhop->type == NEXTHOP_TYPE_IFINDEX
418 || newhop->type == NEXTHOP_TYPE_IFNAME
419 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
420 nexthop->rifindex = newhop->ifindex;
421 }
422 return 1;
423 }
424 return 0;
425 }
426 else
427 {
428 return 0;
429 }
430 }
431 }
432 return 0;
433}
434
435#ifdef HAVE_IPV6
436/* If force flag is not set, do not modify falgs at all for uninstall
437 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000438static int
paul718e3742002-12-13 20:15:29 +0000439nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
440 struct route_node *top)
441{
442 struct prefix_ipv6 p;
443 struct route_table *table;
444 struct route_node *rn;
445 struct rib *match;
446 struct nexthop *newhop;
447
448 if (nexthop->type == NEXTHOP_TYPE_IPV6)
449 nexthop->ifindex = 0;
450
451 if (set)
452 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
453
454 /* Make lookup prefix. */
455 memset (&p, 0, sizeof (struct prefix_ipv6));
456 p.family = AF_INET6;
457 p.prefixlen = IPV6_MAX_PREFIXLEN;
458 p.prefix = nexthop->gate.ipv6;
459
460 /* Lookup table. */
461 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
462 if (! table)
463 return 0;
464
465 rn = route_node_match (table, (struct prefix *) &p);
466 while (rn)
467 {
468 route_unlock_node (rn);
469
470 /* If lookup self prefix return immidiately. */
471 if (rn == top)
472 return 0;
473
474 /* Pick up selected route. */
475 for (match = rn->info; match; match = match->next)
476 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
477 break;
478
479 /* If there is no selected route or matched route is EGP, go up
480 tree. */
481 if (! match
482 || match->type == ZEBRA_ROUTE_BGP)
483 {
484 do {
485 rn = rn->parent;
486 } while (rn && rn->info == NULL);
487 if (rn)
488 route_lock_node (rn);
489 }
490 else
491 {
492 if (match->type == ZEBRA_ROUTE_CONNECT)
493 {
494 /* Directly point connected route. */
495 newhop = match->nexthop;
496
497 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
498 nexthop->ifindex = newhop->ifindex;
499
500 return 1;
501 }
502 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
503 {
504 for (newhop = match->nexthop; newhop; newhop = newhop->next)
505 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
506 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
507 {
508 if (set)
509 {
510 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
511 nexthop->rtype = newhop->type;
512 if (newhop->type == NEXTHOP_TYPE_IPV6
513 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
514 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
515 nexthop->rgate.ipv6 = newhop->gate.ipv6;
516 if (newhop->type == NEXTHOP_TYPE_IFINDEX
517 || newhop->type == NEXTHOP_TYPE_IFNAME
518 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
519 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
520 nexthop->rifindex = newhop->ifindex;
521 }
522 return 1;
523 }
524 return 0;
525 }
526 else
527 {
528 return 0;
529 }
530 }
531 }
532 return 0;
533}
534#endif /* HAVE_IPV6 */
535
536struct rib *
537rib_match_ipv4 (struct in_addr addr)
538{
539 struct prefix_ipv4 p;
540 struct route_table *table;
541 struct route_node *rn;
542 struct rib *match;
543 struct nexthop *newhop;
544
545 /* Lookup table. */
546 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
547 if (! table)
548 return 0;
549
550 memset (&p, 0, sizeof (struct prefix_ipv4));
551 p.family = AF_INET;
552 p.prefixlen = IPV4_MAX_PREFIXLEN;
553 p.prefix = addr;
554
555 rn = route_node_match (table, (struct prefix *) &p);
556
557 while (rn)
558 {
559 route_unlock_node (rn);
560
561 /* Pick up selected route. */
562 for (match = rn->info; match; match = match->next)
563 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
564 break;
565
566 /* If there is no selected route or matched route is EGP, go up
567 tree. */
568 if (! match
569 || match->type == ZEBRA_ROUTE_BGP)
570 {
571 do {
572 rn = rn->parent;
573 } while (rn && rn->info == NULL);
574 if (rn)
575 route_lock_node (rn);
576 }
577 else
578 {
579 if (match->type == ZEBRA_ROUTE_CONNECT)
580 /* Directly point connected route. */
581 return match;
582 else
583 {
584 for (newhop = match->nexthop; newhop; newhop = newhop->next)
585 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
586 return match;
587 return NULL;
588 }
589 }
590 }
591 return NULL;
592}
593
594struct rib *
595rib_lookup_ipv4 (struct prefix_ipv4 *p)
596{
597 struct route_table *table;
598 struct route_node *rn;
599 struct rib *match;
600 struct nexthop *nexthop;
601
602 /* Lookup table. */
603 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
604 if (! table)
605 return 0;
606
607 rn = route_node_lookup (table, (struct prefix *) p);
608
609 /* No route for this prefix. */
610 if (! rn)
611 return NULL;
612
613 /* Unlock node. */
614 route_unlock_node (rn);
615
616 /* Pick up selected route. */
617 for (match = rn->info; match; match = match->next)
618 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
619 break;
620
621 if (! match || match->type == ZEBRA_ROUTE_BGP)
622 return NULL;
623
624 if (match->type == ZEBRA_ROUTE_CONNECT)
625 return match;
626
627 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
628 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
629 return match;
630
631 return NULL;
632}
633
Denis Ovsienkodc958242007-08-13 16:03:06 +0000634/*
635 * This clone function, unlike its original rib_lookup_ipv4(), checks
636 * if specified IPv4 route record (prefix/mask -> gate) exists in
637 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
638 *
639 * Return values:
640 * -1: error
641 * 0: exact match found
642 * 1: a match was found with a different gate
643 * 2: connected route found
644 * 3: no matches found
645 */
646int
647rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
648{
649 struct route_table *table;
650 struct route_node *rn;
651 struct rib *match;
652 struct nexthop *nexthop;
653
654 /* Lookup table. */
655 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
656 if (! table)
657 return ZEBRA_RIB_LOOKUP_ERROR;
658
659 /* Scan the RIB table for exactly matching RIB entry. */
660 rn = route_node_lookup (table, (struct prefix *) p);
661
662 /* No route for this prefix. */
663 if (! rn)
664 return ZEBRA_RIB_NOTFOUND;
665
666 /* Unlock node. */
667 route_unlock_node (rn);
668
669 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
670 for (match = rn->info; match; match = match->next)
671 {
672 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
673 continue;
674 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
675 break;
676 }
677
678 /* None such found :( */
679 if (!match)
680 return ZEBRA_RIB_NOTFOUND;
681
682 if (match->type == ZEBRA_ROUTE_CONNECT)
683 return ZEBRA_RIB_FOUND_CONNECTED;
684
685 /* Ok, we have a cood candidate, let's check it's nexthop list... */
686 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
687 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
688 {
689 /* We are happy with either direct or recursive hexthop */
690 if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr ||
691 nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr)
692 return ZEBRA_RIB_FOUND_EXACT;
693 else
694 {
695 if (IS_ZEBRA_DEBUG_RIB)
696 {
697 char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
698 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
699 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
700 inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN);
701 zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
702 }
703 return ZEBRA_RIB_FOUND_NOGATE;
704 }
705 }
706
707 return ZEBRA_RIB_NOTFOUND;
708}
709
paul718e3742002-12-13 20:15:29 +0000710#ifdef HAVE_IPV6
711struct rib *
712rib_match_ipv6 (struct in6_addr *addr)
713{
714 struct prefix_ipv6 p;
715 struct route_table *table;
716 struct route_node *rn;
717 struct rib *match;
718 struct nexthop *newhop;
719
720 /* Lookup table. */
721 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
722 if (! table)
723 return 0;
724
725 memset (&p, 0, sizeof (struct prefix_ipv6));
726 p.family = AF_INET6;
727 p.prefixlen = IPV6_MAX_PREFIXLEN;
728 IPV6_ADDR_COPY (&p.prefix, addr);
729
730 rn = route_node_match (table, (struct prefix *) &p);
731
732 while (rn)
733 {
734 route_unlock_node (rn);
735
736 /* Pick up selected route. */
737 for (match = rn->info; match; match = match->next)
738 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
739 break;
740
741 /* If there is no selected route or matched route is EGP, go up
742 tree. */
743 if (! match
744 || match->type == ZEBRA_ROUTE_BGP)
745 {
746 do {
747 rn = rn->parent;
748 } while (rn && rn->info == NULL);
749 if (rn)
750 route_lock_node (rn);
751 }
752 else
753 {
754 if (match->type == ZEBRA_ROUTE_CONNECT)
755 /* Directly point connected route. */
756 return match;
757 else
758 {
759 for (newhop = match->nexthop; newhop; newhop = newhop->next)
760 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
761 return match;
762 return NULL;
763 }
764 }
765 }
766 return NULL;
767}
768#endif /* HAVE_IPV6 */
769
Paul Jakma7514fb72007-05-02 16:05:35 +0000770#define RIB_SYSTEM_ROUTE(R) \
771 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
772
Denis Ovsienkodc958242007-08-13 16:03:06 +0000773/* This function verifies reachability of one given nexthop, which can be
774 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
775 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
776 * nexthop->ifindex will be updated appropriately as well.
777 * An existing route map can turn (otherwise active) nexthop into inactive, but
778 * not vice versa.
779 *
780 * The return value is the final value of 'ACTIVE' flag.
781 */
782
paula1ac18c2005-06-28 17:17:12 +0000783static int
paul718e3742002-12-13 20:15:29 +0000784nexthop_active_check (struct route_node *rn, struct rib *rib,
785 struct nexthop *nexthop, int set)
786{
787 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000788 route_map_result_t ret = RMAP_MATCH;
789 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
790 struct route_map *rmap;
791 int family;
paul718e3742002-12-13 20:15:29 +0000792
Paul Jakma7514fb72007-05-02 16:05:35 +0000793 family = 0;
paul718e3742002-12-13 20:15:29 +0000794 switch (nexthop->type)
795 {
796 case NEXTHOP_TYPE_IFINDEX:
797 ifp = if_lookup_by_index (nexthop->ifindex);
798 if (ifp && if_is_up (ifp))
799 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
800 else
801 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
802 break;
paul718e3742002-12-13 20:15:29 +0000803 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000804 family = AFI_IP6;
805 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000806 ifp = if_lookup_by_name (nexthop->ifname);
807 if (ifp && if_is_up (ifp))
808 {
809 if (set)
810 nexthop->ifindex = ifp->ifindex;
811 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
812 }
813 else
814 {
815 if (set)
816 nexthop->ifindex = 0;
817 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
818 }
819 break;
820 case NEXTHOP_TYPE_IPV4:
821 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000822 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000823 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
824 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
825 else
826 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
827 break;
828#ifdef HAVE_IPV6
829 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000830 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000831 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
832 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
833 else
834 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
835 break;
836 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000837 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000838 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
839 {
840 ifp = if_lookup_by_index (nexthop->ifindex);
841 if (ifp && if_is_up (ifp))
842 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
843 else
844 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
845 }
846 else
847 {
848 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
849 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
850 else
851 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
852 }
853 break;
854#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000855 case NEXTHOP_TYPE_BLACKHOLE:
856 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
857 break;
paul718e3742002-12-13 20:15:29 +0000858 default:
859 break;
860 }
Paul Jakma7514fb72007-05-02 16:05:35 +0000861 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
862 return 0;
863
864 if (RIB_SYSTEM_ROUTE(rib) ||
865 (family == AFI_IP && rn->p.family != AF_INET) ||
866 (family == AFI_IP6 && rn->p.family != AF_INET6))
867 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
868
869 rmap = 0;
870 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
871 proto_rm[family][rib->type])
872 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
873 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
874 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
875 if (rmap) {
876 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
877 }
878
879 if (ret == RMAP_DENYMATCH)
880 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000881 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
882}
883
paula1ac18c2005-06-28 17:17:12 +0000884static int
paul718e3742002-12-13 20:15:29 +0000885nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
886{
887 struct nexthop *nexthop;
888 int active;
889
890 rib->nexthop_active_num = 0;
891 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
892
893 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
894 {
895 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul6baeb982003-10-28 03:47:15 +0000896
897 nexthop_active_check (rn, rib, nexthop, set);
898 if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM)
899 && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
900 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
901
902 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
903 rib->nexthop_active_num++;
paul718e3742002-12-13 20:15:29 +0000904 }
905 return rib->nexthop_active_num;
906}
paul6baeb982003-10-28 03:47:15 +0000907
paul718e3742002-12-13 20:15:29 +0000908
paul718e3742002-12-13 20:15:29 +0000909
paula1ac18c2005-06-28 17:17:12 +0000910static void
paul718e3742002-12-13 20:15:29 +0000911rib_install_kernel (struct route_node *rn, struct rib *rib)
912{
913 int ret = 0;
914 struct nexthop *nexthop;
915
916 switch (PREFIX_FAMILY (&rn->p))
917 {
918 case AF_INET:
919 ret = kernel_add_ipv4 (&rn->p, rib);
920 break;
921#ifdef HAVE_IPV6
922 case AF_INET6:
923 ret = kernel_add_ipv6 (&rn->p, rib);
924 break;
925#endif /* HAVE_IPV6 */
926 }
927
Denis Ovsienkodc958242007-08-13 16:03:06 +0000928 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +0000929 if (ret < 0)
930 {
931 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
932 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
933 }
934}
935
936/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000937static int
paul718e3742002-12-13 20:15:29 +0000938rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
939{
940 int ret = 0;
941 struct nexthop *nexthop;
942
943 switch (PREFIX_FAMILY (&rn->p))
944 {
945 case AF_INET:
946 ret = kernel_delete_ipv4 (&rn->p, rib);
947 break;
948#ifdef HAVE_IPV6
949 case AF_INET6:
Denis Ovsienkodc958242007-08-13 16:03:06 +0000950 if (IS_ZEBRA_DEBUG_RIB)
951 zlog_debug ("%s: calling kernel_delete_ipv4 (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +0000952 ret = kernel_delete_ipv6 (&rn->p, rib);
953 break;
954#endif /* HAVE_IPV6 */
955 }
956
957 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
958 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
959
960 return ret;
961}
962
963/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000964static void
paul718e3742002-12-13 20:15:29 +0000965rib_uninstall (struct route_node *rn, struct rib *rib)
966{
967 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
968 {
969 redistribute_delete (&rn->p, rib);
970 if (! RIB_SYSTEM_ROUTE (rib))
971 rib_uninstall_kernel (rn, rib);
972 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
973 }
974}
975
Paul Jakma6d691122006-07-27 21:49:00 +0000976static void rib_unlink (struct route_node *, struct rib *);
977
paul718e3742002-12-13 20:15:29 +0000978/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000979static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000980rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000981{
982 struct rib *rib;
983 struct rib *next;
984 struct rib *fib = NULL;
985 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +0000986 struct rib *del = NULL;
987 struct route_node *rn = data;
pauld753e9e2003-01-22 19:45:50 +0000988 int installed = 0;
989 struct nexthop *nexthop = NULL;
Paul Jakma93bdada2007-08-06 19:25:11 +0000990 char buf[INET_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +0000991
992 assert (rn);
993
Paul Jakma93bdada2007-08-06 19:25:11 +0000994 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
995 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
996
paul718e3742002-12-13 20:15:29 +0000997 for (rib = rn->info; rib; rib = next)
998 {
Denis Ovsienkodc958242007-08-13 16:03:06 +0000999 /* The next pointer is saved, because current pointer
1000 * may be passed to rib_unlink() in the middle of iteration.
1001 */
paul718e3742002-12-13 20:15:29 +00001002 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +00001003
paul718e3742002-12-13 20:15:29 +00001004 /* Currently installed rib. */
1005 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001006 {
1007 assert (fib == NULL);
1008 fib = rib;
1009 }
1010
1011 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1012 * which we need to do do further work with below.
1013 */
1014 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1015 {
1016 if (rib != fib)
1017 {
1018 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001019 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
1020 buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001021 rib_unlink (rn, rib);
1022 }
1023 else
1024 del = rib;
1025
1026 continue;
1027 }
paul4d38fdb2005-04-28 17:35:14 +00001028
paul718e3742002-12-13 20:15:29 +00001029 /* Skip unreachable nexthop. */
1030 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001031 continue;
paul718e3742002-12-13 20:15:29 +00001032
1033 /* Infinit distance. */
1034 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001035 continue;
paul718e3742002-12-13 20:15:29 +00001036
paulaf887b52006-01-18 14:52:52 +00001037 /* Newly selected rib, the common case. */
1038 if (!select)
1039 {
1040 select = rib;
1041 continue;
1042 }
1043
1044 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001045 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001046 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001047 * - lower metric beats higher for equal distance
1048 * - last, hence oldest, route wins tie break.
1049 */
paula1038a12006-01-30 14:08:51 +00001050
1051 /* Connected routes. Pick the last connected
1052 * route of the set of lowest metric connected routes.
1053 */
paula8d9c1f2006-01-25 06:31:04 +00001054 if (rib->type == ZEBRA_ROUTE_CONNECT)
1055 {
paula1038a12006-01-30 14:08:51 +00001056 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001057 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001058 select = rib;
1059 continue;
paula8d9c1f2006-01-25 06:31:04 +00001060 }
1061 else if (select->type == ZEBRA_ROUTE_CONNECT)
1062 continue;
1063
1064 /* higher distance loses */
1065 if (rib->distance > select->distance)
1066 continue;
1067
1068 /* lower wins */
1069 if (rib->distance < select->distance)
1070 {
paulaf887b52006-01-18 14:52:52 +00001071 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001072 continue;
1073 }
1074
1075 /* metric tie-breaks equal distance */
1076 if (rib->metric <= select->metric)
1077 select = rib;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001078 } /* for (rib = rn->info; rib; rib = next) */
1079
1080 /* After the cycle is finished, the following pointers will be set:
1081 * select --- the winner RIB entry, if any was found, otherwise NULL
1082 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1083 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1084 * rib --- NULL
1085 */
1086
1087 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001088 if (select && select == fib)
1089 {
Paul Jakma6d691122006-07-27 21:49:00 +00001090 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001091 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
1092 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +00001093 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001094 {
1095 redistribute_delete (&rn->p, select);
1096 if (! RIB_SYSTEM_ROUTE (select))
1097 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001098
paul4d38fdb2005-04-28 17:35:14 +00001099 /* Set real nexthop. */
1100 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001101
paul4d38fdb2005-04-28 17:35:14 +00001102 if (! RIB_SYSTEM_ROUTE (select))
1103 rib_install_kernel (rn, select);
1104 redistribute_add (&rn->p, select);
1105 }
pauld753e9e2003-01-22 19:45:50 +00001106 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001107 {
1108 /* Housekeeping code to deal with
1109 race conditions in kernel with linux
1110 netlink reporting interface up before IPv4 or IPv6 protocol
1111 is ready to add routes.
1112 This makes sure the routes are IN the kernel.
1113 */
pauld753e9e2003-01-22 19:45:50 +00001114
paul4d38fdb2005-04-28 17:35:14 +00001115 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1116 {
1117 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1118 installed = 1;
1119 }
1120 if (! installed)
1121 rib_install_kernel (rn, select);
1122 }
Paul Jakma6d691122006-07-27 21:49:00 +00001123 goto end;
paul718e3742002-12-13 20:15:29 +00001124 }
1125
Denis Ovsienkodc958242007-08-13 16:03:06 +00001126 /* At this point we either haven't found the best RIB entry or it is
1127 * different from what we currently intend to flag with SELECTED. In both
1128 * cases, if a RIB block is present in FIB, it should be withdrawn.
1129 */
paul718e3742002-12-13 20:15:29 +00001130 if (fib)
1131 {
Paul Jakma6d691122006-07-27 21:49:00 +00001132 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001133 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1134 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001135 redistribute_delete (&rn->p, fib);
1136 if (! RIB_SYSTEM_ROUTE (fib))
1137 rib_uninstall_kernel (rn, fib);
1138 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1139
1140 /* Set real nexthop. */
1141 nexthop_active_update (rn, fib, 1);
1142 }
1143
Denis Ovsienkodc958242007-08-13 16:03:06 +00001144 /* Regardless of some RIB entry being SELECTED or not before, now we can
1145 * tell, that if a new winner exists, FIB is still not updated with this
1146 * data, but ready to be.
1147 */
paul718e3742002-12-13 20:15:29 +00001148 if (select)
1149 {
Paul Jakma6d691122006-07-27 21:49:00 +00001150 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001151 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1152 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001153 /* Set real nexthop. */
1154 nexthop_active_update (rn, select, 1);
1155
1156 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001157 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001158 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1159 redistribute_add (&rn->p, select);
1160 }
paul4d38fdb2005-04-28 17:35:14 +00001161
Paul Jakma6d691122006-07-27 21:49:00 +00001162 /* FIB route was removed, should be deleted */
1163 if (del)
1164 {
1165 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001166 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1167 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001168 rib_unlink (rn, del);
1169 }
paul4d38fdb2005-04-28 17:35:14 +00001170
Paul Jakma6d691122006-07-27 21:49:00 +00001171end:
1172 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001173 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001174 if (rn->info)
1175 UNSET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1176 route_unlock_node (rn); /* rib queue lock */
1177 return WQ_SUCCESS;
paul4d38fdb2005-04-28 17:35:14 +00001178}
1179
Paul Jakma6d691122006-07-27 21:49:00 +00001180/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001181static void
Paul Jakma6d691122006-07-27 21:49:00 +00001182rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001183{
Paul Jakma93bdada2007-08-06 19:25:11 +00001184 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001185 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001186
Paul Jakma93bdada2007-08-06 19:25:11 +00001187 if (IS_ZEBRA_DEBUG_RIB_Q)
1188 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1189
Paul Jakma6d691122006-07-27 21:49:00 +00001190 /* Pointless to queue a route_node with no RIB entries to add or remove */
1191 if (!rn->info)
1192 {
1193 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1194 __func__, rn, rn->lock);
1195 zlog_backtrace(LOG_DEBUG);
1196 return;
1197 }
paul4d38fdb2005-04-28 17:35:14 +00001198
Paul Jakma6d691122006-07-27 21:49:00 +00001199 /* Route-table node already queued, so nothing to do */
1200 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED))
1201 {
1202 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001203 zlog_debug ("%s: %s/%d: rn %p already queued", __func__, buf,
1204 rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001205 return;
1206 }
paul4d38fdb2005-04-28 17:35:14 +00001207
Paul Jakma6d691122006-07-27 21:49:00 +00001208 route_lock_node (rn); /* rib queue lock */
1209
1210 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001211 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001212
1213 assert (zebra);
1214
paul4d38fdb2005-04-28 17:35:14 +00001215 if (zebra->ribq == NULL)
1216 {
Paul Jakma6d691122006-07-27 21:49:00 +00001217 zlog_err ("%s: work_queue does not exist!", __func__);
1218 route_unlock_node (rn);
paul4d38fdb2005-04-28 17:35:14 +00001219 return;
1220 }
1221
Paul Jakma6d691122006-07-27 21:49:00 +00001222 work_queue_add (zebra->ribq, rn);
1223
1224 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1225
1226 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001227 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
paul4d38fdb2005-04-28 17:35:14 +00001228
1229 return;
1230}
1231
paul4d38fdb2005-04-28 17:35:14 +00001232/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001233static void
paul4d38fdb2005-04-28 17:35:14 +00001234rib_queue_init (struct zebra_t *zebra)
1235{
1236 assert (zebra);
1237
1238 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001239 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001240 {
Paul Jakma6d691122006-07-27 21:49:00 +00001241 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001242 return;
1243 }
1244
1245 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001246 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001247 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001248 /* XXX: TODO: These should be runtime configurable via vty */
1249 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001250 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001251
1252 return;
paul718e3742002-12-13 20:15:29 +00001253}
1254
Paul Jakma6d691122006-07-27 21:49:00 +00001255/* RIB updates are processed via a queue of pointers to route_nodes.
1256 *
1257 * The queue length is bounded by the maximal size of the routing table,
1258 * as a route_node will not be requeued, if already queued.
1259 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001260 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1261 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1262 * and then submit route_node to queue for best-path selection later.
1263 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001264 *
1265 * Deleted RIBs are reaped during best-path selection.
1266 *
1267 * rib_addnode
1268 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001269 * |-------->| | best RIB, if required
1270 * | |
1271 * static_install->|->rib_addqueue...... -> rib_process
1272 * | |
1273 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001274 * |-> set RIB_ENTRY_REMOVE |
1275 * rib_delnode (RIB freed)
1276 *
1277 *
1278 * Queueing state for a route_node is kept in the head RIB entry, this
1279 * state must be preserved as and when the head RIB entry of a
1280 * route_node is changed by rib_unlink / rib_link. A small complication,
1281 * but saves having to allocate a dedicated object for this.
1282 *
1283 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1284 *
1285 * - route_nodes: refcounted by:
1286 * - RIBs attached to route_node:
1287 * - managed by: rib_link/unlink
1288 * - route_node processing queue
1289 * - managed by: rib_addqueue, rib_process.
1290 *
1291 */
1292
paul718e3742002-12-13 20:15:29 +00001293/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001294static void
Paul Jakma6d691122006-07-27 21:49:00 +00001295rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001296{
1297 struct rib *head;
Paul Jakma93bdada2007-08-06 19:25:11 +00001298 char buf[INET_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001299
1300 assert (rib && rn);
1301
Paul Jakma6d691122006-07-27 21:49:00 +00001302 route_lock_node (rn); /* rn route table reference */
1303
1304 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001305 {
1306 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1307 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1308 buf, rn->p.prefixlen, rn, rib);
1309 }
Paul Jakma6d691122006-07-27 21:49:00 +00001310
paul718e3742002-12-13 20:15:29 +00001311 head = rn->info;
1312 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001313 {
1314 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001315 zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
1316 buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001317 head->prev = rib;
1318 /* Transfer the rn status flags to the new head RIB */
1319 rib->rn_status = head->rn_status;
1320 }
paul718e3742002-12-13 20:15:29 +00001321 rib->next = head;
1322 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001323 rib_queue_add (&zebrad, rn);
1324}
1325
1326static void
1327rib_addnode (struct route_node *rn, struct rib *rib)
1328{
1329 /* RIB node has been un-removed before route-node is processed.
1330 * route_node must hence already be on the queue for processing..
1331 */
1332 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1333 {
1334 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001335 {
1336 char buf[INET_ADDRSTRLEN];
1337 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1338 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1339 __func__, buf, rn->p.prefixlen, rn, rib);
1340 }
Paul Jakma6d691122006-07-27 21:49:00 +00001341 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1342 return;
1343 }
1344 rib_link (rn, rib);
1345}
1346
1347static void
1348rib_unlink (struct route_node *rn, struct rib *rib)
1349{
1350 struct nexthop *nexthop, *next;
Paul Jakma93bdada2007-08-06 19:25:11 +00001351 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001352
1353 assert (rn && rib);
1354
1355 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001356 {
1357 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1358 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1359 __func__, buf, rn->p.prefixlen, rn, rib);
1360 }
Paul Jakma6d691122006-07-27 21:49:00 +00001361
1362 if (rib->next)
1363 rib->next->prev = rib->prev;
1364
1365 if (rib->prev)
1366 rib->prev->next = rib->next;
1367 else
1368 {
1369 rn->info = rib->next;
1370
1371 if (rn->info)
1372 {
1373 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001374 zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
1375 __func__, buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001376 rib->next->rn_status = rib->rn_status;
1377 }
1378 }
1379
1380 /* free RIB and nexthops */
1381 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1382 {
1383 next = nexthop->next;
1384 nexthop_free (nexthop);
1385 }
1386 XFREE (MTYPE_RIB, rib);
1387
1388 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001389}
1390
paula1ac18c2005-06-28 17:17:12 +00001391static void
paul718e3742002-12-13 20:15:29 +00001392rib_delnode (struct route_node *rn, struct rib *rib)
1393{
Paul Jakma6d691122006-07-27 21:49:00 +00001394 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001395 {
1396 char buf[INET_ADDRSTRLEN];
1397 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1398 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1399 buf, rn->p.prefixlen, rn, rib);
1400 }
Paul Jakma6d691122006-07-27 21:49:00 +00001401 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1402 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001403}
1404
1405int
1406rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001407 struct in_addr *gate, struct in_addr *src,
1408 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001409 u_int32_t metric, u_char distance)
1410{
1411 struct rib *rib;
1412 struct rib *same = NULL;
1413 struct route_table *table;
1414 struct route_node *rn;
1415 struct nexthop *nexthop;
1416
1417 /* Lookup table. */
1418 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1419 if (! table)
1420 return 0;
1421
1422 /* Make it sure prefixlen is applied to the prefix. */
1423 apply_mask_ipv4 (p);
1424
1425 /* Set default distance by route type. */
1426 if (distance == 0)
1427 {
1428 distance = route_info[type].distance;
1429
1430 /* iBGP distance is 200. */
1431 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1432 distance = 200;
1433 }
1434
1435 /* Lookup route node.*/
1436 rn = route_node_get (table, (struct prefix *) p);
1437
1438 /* If same type of route are installed, treat it as a implicit
1439 withdraw. */
1440 for (rib = rn->info; rib; rib = rib->next)
1441 {
Paul Jakma6d691122006-07-27 21:49:00 +00001442 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1443 continue;
1444
hassoebf1ead2005-09-21 14:58:20 +00001445 if (rib->type != type)
1446 continue;
1447 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001448 {
1449 same = rib;
1450 break;
1451 }
hassoebf1ead2005-09-21 14:58:20 +00001452 /* Duplicate connected route comes in. */
1453 else if ((nexthop = rib->nexthop) &&
1454 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001455 nexthop->ifindex == ifindex &&
1456 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001457 {
1458 rib->refcnt++;
1459 return 0 ;
1460 }
paul718e3742002-12-13 20:15:29 +00001461 }
1462
1463 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001464 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001465 rib->type = type;
1466 rib->distance = distance;
1467 rib->flags = flags;
1468 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001469 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001470 rib->nexthop_num = 0;
1471 rib->uptime = time (NULL);
1472
1473 /* Nexthop settings. */
1474 if (gate)
1475 {
1476 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001477 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001478 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001479 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001480 }
1481 else
1482 nexthop_ifindex_add (rib, ifindex);
1483
1484 /* If this route is kernel route, set FIB flag to the route. */
1485 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1486 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1487 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1488
1489 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001490 if (IS_ZEBRA_DEBUG_RIB)
1491 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001492 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001493
paul718e3742002-12-13 20:15:29 +00001494 /* Free implicit route.*/
1495 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001496 {
1497 if (IS_ZEBRA_DEBUG_RIB)
1498 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001499 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001500 }
paul4d38fdb2005-04-28 17:35:14 +00001501
1502 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001503 return 0;
1504}
1505
Denis Ovsienkodc958242007-08-13 16:03:06 +00001506/* This function dumps the contents of a given RIB entry into
1507 * standard debug log. Calling function name and IP prefix in
1508 * question are passed as 1st and 2nd arguments.
1509 */
1510
1511void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1512{
1513 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1514 struct nexthop *nexthop;
1515
1516 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1517 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1518 zlog_debug
1519 (
1520 "%s: refcnt == %lu, uptime == %u, type == %u, table == %d",
1521 func,
1522 rib->refcnt,
1523 rib->uptime,
1524 rib->type,
1525 rib->table
1526 );
1527 zlog_debug
1528 (
1529 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1530 func,
1531 rib->metric,
1532 rib->distance,
1533 rib->flags,
1534 rib->status
1535 );
1536 zlog_debug
1537 (
1538 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1539 func,
1540 rib->nexthop_num,
1541 rib->nexthop_active_num,
1542 rib->nexthop_fib_num
1543 );
1544 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1545 {
1546 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1547 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1548 zlog_debug
1549 (
1550 "%s: NH %s (%s) with flags %s%s%s",
1551 func,
1552 straddr1,
1553 straddr2,
1554 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1555 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1556 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1557 );
1558 }
1559 zlog_debug ("%s: dump complete", func);
1560}
1561
1562/* This is an exported helper to rtm_read() to dump the strange
1563 * RIB entry found by rib_lookup_ipv4_route()
1564 */
1565
1566void rib_lookup_and_dump (struct prefix_ipv4 * p)
1567{
1568 struct route_table *table;
1569 struct route_node *rn;
1570 struct rib *rib;
1571 char prefix_buf[INET_ADDRSTRLEN];
1572
1573 /* Lookup table. */
1574 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1575 if (! table)
1576 {
1577 zlog_err ("%s: vrf_table() returned NULL", __func__);
1578 return;
1579 }
1580
1581 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1582 /* Scan the RIB table for exactly matching RIB entry. */
1583 rn = route_node_lookup (table, (struct prefix *) p);
1584
1585 /* No route for this prefix. */
1586 if (! rn)
1587 {
1588 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1589 return;
1590 }
1591
1592 /* Unlock node. */
1593 route_unlock_node (rn);
1594
1595 /* let's go */
1596 for (rib = rn->info; rib; rib = rib->next)
1597 {
1598 zlog_debug
1599 (
1600 "%s: rn %p, rib %p: %s, %s",
1601 __func__,
1602 rn,
1603 rib,
1604 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1605 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1606 );
1607 rib_dump (__func__, p, rib);
1608 }
1609}
1610
paul718e3742002-12-13 20:15:29 +00001611int
1612rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1613{
1614 struct route_table *table;
1615 struct route_node *rn;
1616 struct rib *same;
1617 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001618
paul718e3742002-12-13 20:15:29 +00001619 /* Lookup table. */
1620 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1621 if (! table)
1622 return 0;
paul718e3742002-12-13 20:15:29 +00001623 /* Make it sure prefixlen is applied to the prefix. */
1624 apply_mask_ipv4 (p);
1625
1626 /* Set default distance by route type. */
1627 if (rib->distance == 0)
1628 {
1629 rib->distance = route_info[rib->type].distance;
1630
1631 /* iBGP distance is 200. */
1632 if (rib->type == ZEBRA_ROUTE_BGP
1633 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1634 rib->distance = 200;
1635 }
1636
1637 /* Lookup route node.*/
1638 rn = route_node_get (table, (struct prefix *) p);
1639
1640 /* If same type of route are installed, treat it as a implicit
1641 withdraw. */
1642 for (same = rn->info; same; same = same->next)
1643 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001644 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001645 continue;
1646
paul718e3742002-12-13 20:15:29 +00001647 if (same->type == rib->type && same->table == rib->table
1648 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001649 break;
paul718e3742002-12-13 20:15:29 +00001650 }
paul4d38fdb2005-04-28 17:35:14 +00001651
paul718e3742002-12-13 20:15:29 +00001652 /* If this route is kernel route, set FIB flag to the route. */
1653 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1654 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1655 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1656
1657 /* Link new rib to node.*/
1658 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001659 if (IS_ZEBRA_DEBUG_RIB)
1660 {
1661 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1662 __func__, rn, rib);
1663 rib_dump (__func__, p, rib);
1664 }
paul718e3742002-12-13 20:15:29 +00001665
paul718e3742002-12-13 20:15:29 +00001666 /* Free implicit route.*/
1667 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001668 {
1669 if (IS_ZEBRA_DEBUG_RIB)
1670 {
1671 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1672 __func__, rn, same);
1673 rib_dump (__func__, p, same);
1674 }
paul4d38fdb2005-04-28 17:35:14 +00001675 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001676 }
paul4d38fdb2005-04-28 17:35:14 +00001677
1678 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001679 return 0;
1680}
1681
hassoebf1ead2005-09-21 14:58:20 +00001682/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001683int
1684rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1685 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1686{
1687 struct route_table *table;
1688 struct route_node *rn;
1689 struct rib *rib;
1690 struct rib *fib = NULL;
1691 struct rib *same = NULL;
1692 struct nexthop *nexthop;
1693 char buf1[BUFSIZ];
1694 char buf2[BUFSIZ];
1695
1696 /* Lookup table. */
1697 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1698 if (! table)
1699 return 0;
1700
1701 /* Apply mask. */
1702 apply_mask_ipv4 (p);
1703
paul5ec90d22003-06-19 01:41:37 +00001704 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001705 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001706 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1707 p->prefixlen,
1708 inet_ntoa (*gate),
1709 ifindex);
1710
paul718e3742002-12-13 20:15:29 +00001711 /* Lookup route node. */
1712 rn = route_node_lookup (table, (struct prefix *) p);
1713 if (! rn)
1714 {
1715 if (IS_ZEBRA_DEBUG_KERNEL)
1716 {
1717 if (gate)
ajsb6178002004-12-07 21:12:56 +00001718 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001719 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1720 p->prefixlen,
1721 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1722 ifindex);
1723 else
ajsb6178002004-12-07 21:12:56 +00001724 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001725 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1726 p->prefixlen,
1727 ifindex);
1728 }
1729 return ZEBRA_ERR_RTNOEXIST;
1730 }
1731
1732 /* Lookup same type route. */
1733 for (rib = rn->info; rib; rib = rib->next)
1734 {
Paul Jakma6d691122006-07-27 21:49:00 +00001735 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1736 continue;
1737
paul718e3742002-12-13 20:15:29 +00001738 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1739 fib = rib;
1740
hassoebf1ead2005-09-21 14:58:20 +00001741 if (rib->type != type)
1742 continue;
1743 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1744 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001745 {
hassoebf1ead2005-09-21 14:58:20 +00001746 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001747 {
hassoebf1ead2005-09-21 14:58:20 +00001748 rib->refcnt--;
1749 route_unlock_node (rn);
1750 route_unlock_node (rn);
1751 return 0;
paul718e3742002-12-13 20:15:29 +00001752 }
hassoebf1ead2005-09-21 14:58:20 +00001753 same = rib;
1754 break;
paul718e3742002-12-13 20:15:29 +00001755 }
hassoebf1ead2005-09-21 14:58:20 +00001756 /* Make sure that the route found has the same gateway. */
1757 else if (gate == NULL ||
1758 ((nexthop = rib->nexthop) &&
1759 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1760 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001761 {
hassoebf1ead2005-09-21 14:58:20 +00001762 same = rib;
1763 break;
paul718e3742002-12-13 20:15:29 +00001764 }
1765 }
1766
1767 /* If same type of route can't be found and this message is from
1768 kernel. */
1769 if (! same)
1770 {
1771 if (fib && type == ZEBRA_ROUTE_KERNEL)
1772 {
1773 /* Unset flags. */
1774 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1775 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1776
1777 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1778 }
1779 else
1780 {
1781 if (IS_ZEBRA_DEBUG_KERNEL)
1782 {
1783 if (gate)
ajsb6178002004-12-07 21:12:56 +00001784 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001785 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1786 p->prefixlen,
1787 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1788 ifindex,
1789 type);
1790 else
ajsb6178002004-12-07 21:12:56 +00001791 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001792 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1793 p->prefixlen,
1794 ifindex,
1795 type);
1796 }
1797 route_unlock_node (rn);
1798 return ZEBRA_ERR_RTNOEXIST;
1799 }
1800 }
paul4d38fdb2005-04-28 17:35:14 +00001801
paul718e3742002-12-13 20:15:29 +00001802 if (same)
1803 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001804
paul718e3742002-12-13 20:15:29 +00001805 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001806 return 0;
1807}
1808
1809/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001810static void
paul718e3742002-12-13 20:15:29 +00001811static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1812{
1813 struct rib *rib;
1814 struct route_node *rn;
1815 struct route_table *table;
1816
1817 /* Lookup table. */
1818 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1819 if (! table)
1820 return;
1821
1822 /* Lookup existing route */
1823 rn = route_node_get (table, p);
1824 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001825 {
1826 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1827 continue;
1828
1829 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1830 break;
1831 }
paul718e3742002-12-13 20:15:29 +00001832
1833 if (rib)
1834 {
1835 /* Same distance static route is there. Update it with new
1836 nexthop. */
paul718e3742002-12-13 20:15:29 +00001837 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001838 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001839 {
1840 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001841 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001842 break;
1843 case STATIC_IPV4_IFNAME:
1844 nexthop_ifname_add (rib, si->gate.ifname);
1845 break;
1846 case STATIC_IPV4_BLACKHOLE:
1847 nexthop_blackhole_add (rib);
1848 break;
paul4d38fdb2005-04-28 17:35:14 +00001849 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00001850 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001851 }
1852 else
1853 {
1854 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001855 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1856
paul718e3742002-12-13 20:15:29 +00001857 rib->type = ZEBRA_ROUTE_STATIC;
1858 rib->distance = si->distance;
1859 rib->metric = 0;
1860 rib->nexthop_num = 0;
1861
1862 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001863 {
1864 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001865 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001866 break;
1867 case STATIC_IPV4_IFNAME:
1868 nexthop_ifname_add (rib, si->gate.ifname);
1869 break;
1870 case STATIC_IPV4_BLACKHOLE:
1871 nexthop_blackhole_add (rib);
1872 break;
1873 }
paul718e3742002-12-13 20:15:29 +00001874
hasso81dfcaa2003-05-25 19:21:25 +00001875 /* Save the flags of this static routes (reject, blackhole) */
1876 rib->flags = si->flags;
1877
paul718e3742002-12-13 20:15:29 +00001878 /* Link this rib to the tree. */
1879 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001880 }
1881}
1882
paula1ac18c2005-06-28 17:17:12 +00001883static int
paul718e3742002-12-13 20:15:29 +00001884static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1885{
1886 if (nexthop->type == NEXTHOP_TYPE_IPV4
1887 && si->type == STATIC_IPV4_GATEWAY
1888 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1889 return 1;
1890 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1891 && si->type == STATIC_IPV4_IFNAME
1892 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1893 return 1;
paul595db7f2003-05-25 21:35:06 +00001894 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1895 && si->type == STATIC_IPV4_BLACKHOLE)
1896 return 1;
paule8e19462006-01-19 20:16:55 +00001897 return 0;
paul718e3742002-12-13 20:15:29 +00001898}
1899
1900/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001901static void
paul718e3742002-12-13 20:15:29 +00001902static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1903{
1904 struct route_node *rn;
1905 struct rib *rib;
1906 struct nexthop *nexthop;
1907 struct route_table *table;
1908
1909 /* Lookup table. */
1910 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1911 if (! table)
1912 return;
paul4d38fdb2005-04-28 17:35:14 +00001913
paul718e3742002-12-13 20:15:29 +00001914 /* Lookup existing route with type and distance. */
1915 rn = route_node_lookup (table, p);
1916 if (! rn)
1917 return;
1918
1919 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001920 {
1921 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1922 continue;
1923
1924 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1925 break;
1926 }
paul718e3742002-12-13 20:15:29 +00001927
1928 if (! rib)
1929 {
1930 route_unlock_node (rn);
1931 return;
1932 }
1933
1934 /* Lookup nexthop. */
1935 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1936 if (static_ipv4_nexthop_same (nexthop, si))
1937 break;
1938
1939 /* Can't find nexthop. */
1940 if (! nexthop)
1941 {
1942 route_unlock_node (rn);
1943 return;
1944 }
1945
1946 /* Check nexthop. */
1947 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00001948 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001949 else
1950 {
paul6baeb982003-10-28 03:47:15 +00001951 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1952 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001953 nexthop_delete (rib, nexthop);
1954 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001955 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001956 }
paul718e3742002-12-13 20:15:29 +00001957 /* Unlock node. */
1958 route_unlock_node (rn);
1959}
1960
1961/* Add static route into static route configuration. */
1962int
hasso39db97e2004-10-12 20:50:58 +00001963static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001964 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001965{
1966 u_char type = 0;
1967 struct route_node *rn;
1968 struct static_ipv4 *si;
1969 struct static_ipv4 *pp;
1970 struct static_ipv4 *cp;
1971 struct static_ipv4 *update = NULL;
1972 struct route_table *stable;
1973
1974 /* Lookup table. */
1975 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1976 if (! stable)
1977 return -1;
1978
1979 /* Lookup static route prefix. */
1980 rn = route_node_get (stable, p);
1981
1982 /* Make flags. */
1983 if (gate)
1984 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001985 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001986 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001987 else
1988 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001989
1990 /* Do nothing if there is a same static route. */
1991 for (si = rn->info; si; si = si->next)
1992 {
1993 if (type == si->type
1994 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1995 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1996 {
1997 if (distance == si->distance)
1998 {
1999 route_unlock_node (rn);
2000 return 0;
2001 }
2002 else
2003 update = si;
2004 }
2005 }
2006
Paul Jakma3c0755d2006-12-08 00:53:14 +00002007 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002008 if (update)
2009 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2010
2011 /* Make new static route structure. */
2012 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
2013 memset (si, 0, sizeof (struct static_ipv4));
2014
2015 si->type = type;
2016 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002017 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002018
2019 if (gate)
2020 si->gate.ipv4 = *gate;
2021 if (ifname)
2022 si->gate.ifname = XSTRDUP (0, ifname);
2023
2024 /* Add new static route information to the tree with sort by
2025 distance value and gateway address. */
2026 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2027 {
2028 if (si->distance < cp->distance)
2029 break;
2030 if (si->distance > cp->distance)
2031 continue;
2032 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2033 {
2034 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2035 break;
2036 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2037 continue;
2038 }
2039 }
2040
2041 /* Make linked list. */
2042 if (pp)
2043 pp->next = si;
2044 else
2045 rn->info = si;
2046 if (cp)
2047 cp->prev = si;
2048 si->prev = pp;
2049 si->next = cp;
2050
2051 /* Install into rib. */
2052 static_install_ipv4 (p, si);
2053
2054 return 1;
2055}
2056
2057/* Delete static route from static route configuration. */
2058int
hasso39db97e2004-10-12 20:50:58 +00002059static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002060 u_char distance, u_int32_t vrf_id)
2061{
2062 u_char type = 0;
2063 struct route_node *rn;
2064 struct static_ipv4 *si;
2065 struct route_table *stable;
2066
2067 /* Lookup table. */
2068 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2069 if (! stable)
2070 return -1;
2071
2072 /* Lookup static route prefix. */
2073 rn = route_node_lookup (stable, p);
2074 if (! rn)
2075 return 0;
2076
2077 /* Make flags. */
2078 if (gate)
2079 type = STATIC_IPV4_GATEWAY;
2080 else if (ifname)
2081 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002082 else
2083 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002084
2085 /* Find same static route is the tree */
2086 for (si = rn->info; si; si = si->next)
2087 if (type == si->type
2088 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2089 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2090 break;
2091
2092 /* Can't find static route. */
2093 if (! si)
2094 {
2095 route_unlock_node (rn);
2096 return 0;
2097 }
2098
2099 /* Install into rib. */
2100 static_uninstall_ipv4 (p, si);
2101
2102 /* Unlink static route from linked list. */
2103 if (si->prev)
2104 si->prev->next = si->next;
2105 else
2106 rn->info = si->next;
2107 if (si->next)
2108 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002109 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002110
2111 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002112 if (ifname)
2113 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002114 XFREE (MTYPE_STATIC_IPV4, si);
2115
paul143a3852003-09-29 20:06:13 +00002116 route_unlock_node (rn);
2117
paul718e3742002-12-13 20:15:29 +00002118 return 1;
2119}
2120
2121
2122#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002123static int
paul718e3742002-12-13 20:15:29 +00002124rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2125 struct in6_addr *gate, unsigned int ifindex, int table)
2126{
hasso726f9b22003-05-25 21:04:54 +00002127 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2128#if defined (MUSICA) || defined (LINUX)
2129 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2130 if (p->prefixlen == 96)
2131 return 0;
2132#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002133 return 1;
hasso726f9b22003-05-25 21:04:54 +00002134 }
paul718e3742002-12-13 20:15:29 +00002135 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2136 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2137 {
2138 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2139 return 1;
2140 }
2141 return 0;
2142}
2143
2144int
2145rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002146 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
2147 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00002148{
2149 struct rib *rib;
2150 struct rib *same = NULL;
2151 struct route_table *table;
2152 struct route_node *rn;
2153 struct nexthop *nexthop;
2154
paul718e3742002-12-13 20:15:29 +00002155 /* Lookup table. */
2156 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2157 if (! table)
2158 return 0;
2159
2160 /* Make sure mask is applied. */
2161 apply_mask_ipv6 (p);
2162
2163 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002164 if (!distance)
2165 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002166
2167 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2168 distance = 200;
2169
2170 /* Filter bogus route. */
2171 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2172 return 0;
2173
2174 /* Lookup route node.*/
2175 rn = route_node_get (table, (struct prefix *) p);
2176
2177 /* If same type of route are installed, treat it as a implicit
2178 withdraw. */
2179 for (rib = rn->info; rib; rib = rib->next)
2180 {
Paul Jakma6d691122006-07-27 21:49:00 +00002181 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2182 continue;
2183
hassoebf1ead2005-09-21 14:58:20 +00002184 if (rib->type != type)
2185 continue;
2186 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002187 {
2188 same = rib;
paul718e3742002-12-13 20:15:29 +00002189 break;
2190 }
hassoebf1ead2005-09-21 14:58:20 +00002191 else if ((nexthop = rib->nexthop) &&
2192 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2193 nexthop->ifindex == ifindex)
2194 {
2195 rib->refcnt++;
2196 return 0;
2197 }
paul718e3742002-12-13 20:15:29 +00002198 }
2199
2200 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002201 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2202
paul718e3742002-12-13 20:15:29 +00002203 rib->type = type;
2204 rib->distance = distance;
2205 rib->flags = flags;
2206 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002207 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002208 rib->nexthop_num = 0;
2209 rib->uptime = time (NULL);
2210
2211 /* Nexthop settings. */
2212 if (gate)
2213 {
2214 if (ifindex)
2215 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2216 else
2217 nexthop_ipv6_add (rib, gate);
2218 }
2219 else
2220 nexthop_ifindex_add (rib, ifindex);
2221
2222 /* If this route is kernel route, set FIB flag to the route. */
2223 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2224 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2225 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2226
2227 /* Link new rib to node.*/
2228 rib_addnode (rn, rib);
2229
paul718e3742002-12-13 20:15:29 +00002230 /* Free implicit route.*/
2231 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002232 rib_delnode (rn, same);
2233
2234 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002235 return 0;
2236}
2237
hassoebf1ead2005-09-21 14:58:20 +00002238/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002239int
2240rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2241 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
2242{
2243 struct route_table *table;
2244 struct route_node *rn;
2245 struct rib *rib;
2246 struct rib *fib = NULL;
2247 struct rib *same = NULL;
2248 struct nexthop *nexthop;
2249 char buf1[BUFSIZ];
2250 char buf2[BUFSIZ];
2251
2252 /* Apply mask. */
2253 apply_mask_ipv6 (p);
2254
2255 /* Lookup table. */
2256 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2257 if (! table)
2258 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002259
paul718e3742002-12-13 20:15:29 +00002260 /* Lookup route node. */
2261 rn = route_node_lookup (table, (struct prefix *) p);
2262 if (! rn)
2263 {
2264 if (IS_ZEBRA_DEBUG_KERNEL)
2265 {
2266 if (gate)
ajsb6178002004-12-07 21:12:56 +00002267 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002268 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2269 p->prefixlen,
2270 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2271 ifindex);
2272 else
ajsb6178002004-12-07 21:12:56 +00002273 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002274 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2275 p->prefixlen,
2276 ifindex);
2277 }
2278 return ZEBRA_ERR_RTNOEXIST;
2279 }
2280
2281 /* Lookup same type route. */
2282 for (rib = rn->info; rib; rib = rib->next)
2283 {
Paul Jakma6d691122006-07-27 21:49:00 +00002284 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2285 continue;
2286
paul718e3742002-12-13 20:15:29 +00002287 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2288 fib = rib;
2289
hassoebf1ead2005-09-21 14:58:20 +00002290 if (rib->type != type)
2291 continue;
2292 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2293 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002294 {
hassoebf1ead2005-09-21 14:58:20 +00002295 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002296 {
hassoebf1ead2005-09-21 14:58:20 +00002297 rib->refcnt--;
2298 route_unlock_node (rn);
2299 route_unlock_node (rn);
2300 return 0;
paul718e3742002-12-13 20:15:29 +00002301 }
hassoebf1ead2005-09-21 14:58:20 +00002302 same = rib;
2303 break;
paul718e3742002-12-13 20:15:29 +00002304 }
hassoebf1ead2005-09-21 14:58:20 +00002305 /* Make sure that the route found has the same gateway. */
2306 else if (gate == NULL ||
2307 ((nexthop = rib->nexthop) &&
2308 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2309 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002310 {
hassoebf1ead2005-09-21 14:58:20 +00002311 same = rib;
2312 break;
paul718e3742002-12-13 20:15:29 +00002313 }
2314 }
2315
2316 /* If same type of route can't be found and this message is from
2317 kernel. */
2318 if (! same)
2319 {
2320 if (fib && type == ZEBRA_ROUTE_KERNEL)
2321 {
2322 /* Unset flags. */
2323 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2324 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2325
2326 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2327 }
2328 else
2329 {
2330 if (IS_ZEBRA_DEBUG_KERNEL)
2331 {
2332 if (gate)
ajsb6178002004-12-07 21:12:56 +00002333 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002334 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2335 p->prefixlen,
2336 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2337 ifindex,
2338 type);
2339 else
ajsb6178002004-12-07 21:12:56 +00002340 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002341 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2342 p->prefixlen,
2343 ifindex,
2344 type);
2345 }
2346 route_unlock_node (rn);
2347 return ZEBRA_ERR_RTNOEXIST;
2348 }
2349 }
2350
2351 if (same)
2352 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002353
paul718e3742002-12-13 20:15:29 +00002354 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002355 return 0;
2356}
2357
2358/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002359static void
paul718e3742002-12-13 20:15:29 +00002360static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2361{
2362 struct rib *rib;
2363 struct route_table *table;
2364 struct route_node *rn;
2365
2366 /* Lookup table. */
2367 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2368 if (! table)
2369 return;
2370
2371 /* Lookup existing route */
2372 rn = route_node_get (table, p);
2373 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002374 {
2375 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2376 continue;
2377
2378 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2379 break;
2380 }
paul718e3742002-12-13 20:15:29 +00002381
2382 if (rib)
2383 {
2384 /* Same distance static route is there. Update it with new
2385 nexthop. */
paul718e3742002-12-13 20:15:29 +00002386 route_unlock_node (rn);
2387
2388 switch (si->type)
2389 {
2390 case STATIC_IPV6_GATEWAY:
2391 nexthop_ipv6_add (rib, &si->ipv6);
2392 break;
2393 case STATIC_IPV6_IFNAME:
2394 nexthop_ifname_add (rib, si->ifname);
2395 break;
2396 case STATIC_IPV6_GATEWAY_IFNAME:
2397 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2398 break;
2399 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002400 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002401 }
2402 else
2403 {
2404 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002405 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2406
paul718e3742002-12-13 20:15:29 +00002407 rib->type = ZEBRA_ROUTE_STATIC;
2408 rib->distance = si->distance;
2409 rib->metric = 0;
2410 rib->nexthop_num = 0;
2411
2412 switch (si->type)
2413 {
2414 case STATIC_IPV6_GATEWAY:
2415 nexthop_ipv6_add (rib, &si->ipv6);
2416 break;
2417 case STATIC_IPV6_IFNAME:
2418 nexthop_ifname_add (rib, si->ifname);
2419 break;
2420 case STATIC_IPV6_GATEWAY_IFNAME:
2421 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2422 break;
2423 }
2424
hasso81dfcaa2003-05-25 19:21:25 +00002425 /* Save the flags of this static routes (reject, blackhole) */
2426 rib->flags = si->flags;
2427
paul718e3742002-12-13 20:15:29 +00002428 /* Link this rib to the tree. */
2429 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002430 }
2431}
2432
paula1ac18c2005-06-28 17:17:12 +00002433static int
paul718e3742002-12-13 20:15:29 +00002434static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2435{
2436 if (nexthop->type == NEXTHOP_TYPE_IPV6
2437 && si->type == STATIC_IPV6_GATEWAY
2438 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2439 return 1;
2440 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2441 && si->type == STATIC_IPV6_IFNAME
2442 && strcmp (nexthop->ifname, si->ifname) == 0)
2443 return 1;
2444 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2445 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2446 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2447 && strcmp (nexthop->ifname, si->ifname) == 0)
2448 return 1;
paule8e19462006-01-19 20:16:55 +00002449 return 0;
paul718e3742002-12-13 20:15:29 +00002450}
2451
paula1ac18c2005-06-28 17:17:12 +00002452static void
paul718e3742002-12-13 20:15:29 +00002453static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2454{
2455 struct route_table *table;
2456 struct route_node *rn;
2457 struct rib *rib;
2458 struct nexthop *nexthop;
2459
2460 /* Lookup table. */
2461 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2462 if (! table)
2463 return;
2464
2465 /* Lookup existing route with type and distance. */
2466 rn = route_node_lookup (table, (struct prefix *) p);
2467 if (! rn)
2468 return;
2469
2470 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002471 {
2472 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2473 continue;
2474
2475 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2476 break;
2477 }
2478
paul718e3742002-12-13 20:15:29 +00002479 if (! rib)
2480 {
2481 route_unlock_node (rn);
2482 return;
2483 }
2484
2485 /* Lookup nexthop. */
2486 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2487 if (static_ipv6_nexthop_same (nexthop, si))
2488 break;
2489
2490 /* Can't find nexthop. */
2491 if (! nexthop)
2492 {
2493 route_unlock_node (rn);
2494 return;
2495 }
2496
2497 /* Check nexthop. */
2498 if (rib->nexthop_num == 1)
2499 {
2500 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002501 }
2502 else
2503 {
paul6baeb982003-10-28 03:47:15 +00002504 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2505 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002506 nexthop_delete (rib, nexthop);
2507 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002508 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002509 }
paul718e3742002-12-13 20:15:29 +00002510 /* Unlock node. */
2511 route_unlock_node (rn);
2512}
2513
2514/* Add static route into static route configuration. */
2515int
2516static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002517 const char *ifname, u_char flags, u_char distance,
2518 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002519{
2520 struct route_node *rn;
2521 struct static_ipv6 *si;
2522 struct static_ipv6 *pp;
2523 struct static_ipv6 *cp;
2524 struct route_table *stable;
2525
2526 /* Lookup table. */
2527 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2528 if (! stable)
2529 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002530
2531 if (!gate &&
2532 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2533 return -1;
2534
2535 if (!ifname &&
2536 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2537 return -1;
paul718e3742002-12-13 20:15:29 +00002538
2539 /* Lookup static route prefix. */
2540 rn = route_node_get (stable, p);
2541
2542 /* Do nothing if there is a same static route. */
2543 for (si = rn->info; si; si = si->next)
2544 {
2545 if (distance == si->distance
2546 && type == si->type
2547 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2548 && (! ifname || strcmp (ifname, si->ifname) == 0))
2549 {
2550 route_unlock_node (rn);
2551 return 0;
2552 }
2553 }
2554
2555 /* Make new static route structure. */
2556 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2557 memset (si, 0, sizeof (struct static_ipv6));
2558
2559 si->type = type;
2560 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002561 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002562
2563 switch (type)
2564 {
2565 case STATIC_IPV6_GATEWAY:
2566 si->ipv6 = *gate;
2567 break;
2568 case STATIC_IPV6_IFNAME:
2569 si->ifname = XSTRDUP (0, ifname);
2570 break;
2571 case STATIC_IPV6_GATEWAY_IFNAME:
2572 si->ipv6 = *gate;
2573 si->ifname = XSTRDUP (0, ifname);
2574 break;
2575 }
2576
2577 /* Add new static route information to the tree with sort by
2578 distance value and gateway address. */
2579 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2580 {
2581 if (si->distance < cp->distance)
2582 break;
2583 if (si->distance > cp->distance)
2584 continue;
2585 }
2586
2587 /* Make linked list. */
2588 if (pp)
2589 pp->next = si;
2590 else
2591 rn->info = si;
2592 if (cp)
2593 cp->prev = si;
2594 si->prev = pp;
2595 si->next = cp;
2596
2597 /* Install into rib. */
2598 static_install_ipv6 (p, si);
2599
2600 return 1;
2601}
2602
2603/* Delete static route from static route configuration. */
2604int
2605static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002606 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002607{
2608 struct route_node *rn;
2609 struct static_ipv6 *si;
2610 struct route_table *stable;
2611
2612 /* Lookup table. */
2613 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2614 if (! stable)
2615 return -1;
2616
2617 /* Lookup static route prefix. */
2618 rn = route_node_lookup (stable, p);
2619 if (! rn)
2620 return 0;
2621
2622 /* Find same static route is the tree */
2623 for (si = rn->info; si; si = si->next)
2624 if (distance == si->distance
2625 && type == si->type
2626 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2627 && (! ifname || strcmp (ifname, si->ifname) == 0))
2628 break;
2629
2630 /* Can't find static route. */
2631 if (! si)
2632 {
2633 route_unlock_node (rn);
2634 return 0;
2635 }
2636
2637 /* Install into rib. */
2638 static_uninstall_ipv6 (p, si);
2639
2640 /* Unlink static route from linked list. */
2641 if (si->prev)
2642 si->prev->next = si->next;
2643 else
2644 rn->info = si->next;
2645 if (si->next)
2646 si->next->prev = si->prev;
2647
2648 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002649 if (ifname)
2650 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002651 XFREE (MTYPE_STATIC_IPV6, si);
2652
2653 return 1;
2654}
2655#endif /* HAVE_IPV6 */
2656
2657/* RIB update function. */
2658void
paula1ac18c2005-06-28 17:17:12 +00002659rib_update (void)
paul718e3742002-12-13 20:15:29 +00002660{
2661 struct route_node *rn;
2662 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002663
paul718e3742002-12-13 20:15:29 +00002664 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2665 if (table)
2666 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002667 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002668 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002669
2670 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2671 if (table)
2672 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002673 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002674 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002675}
2676
2677/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002678static void
paul718e3742002-12-13 20:15:29 +00002679rib_if_up (struct interface *ifp)
2680{
2681 rib_update ();
2682}
2683
2684/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002685static void
paul718e3742002-12-13 20:15:29 +00002686rib_if_down (struct interface *ifp)
2687{
2688 rib_update ();
2689}
2690
2691/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002692static void
paul718e3742002-12-13 20:15:29 +00002693rib_weed_table (struct route_table *table)
2694{
2695 struct route_node *rn;
2696 struct rib *rib;
2697 struct rib *next;
2698
2699 if (table)
2700 for (rn = route_top (table); rn; rn = route_next (rn))
2701 for (rib = rn->info; rib; rib = next)
2702 {
2703 next = rib->next;
2704
Paul Jakma6d691122006-07-27 21:49:00 +00002705 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2706 continue;
2707
paulb21b19c2003-06-15 01:28:29 +00002708 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002709 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002710 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002711 }
2712}
2713
2714/* Delete all routes from non main table. */
2715void
paula1ac18c2005-06-28 17:17:12 +00002716rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002717{
2718 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2719 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2720}
2721
2722/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002723static void
paul718e3742002-12-13 20:15:29 +00002724rib_sweep_table (struct route_table *table)
2725{
2726 struct route_node *rn;
2727 struct rib *rib;
2728 struct rib *next;
2729 int ret = 0;
2730
2731 if (table)
2732 for (rn = route_top (table); rn; rn = route_next (rn))
2733 for (rib = rn->info; rib; rib = next)
2734 {
2735 next = rib->next;
2736
Paul Jakma6d691122006-07-27 21:49:00 +00002737 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2738 continue;
2739
paul718e3742002-12-13 20:15:29 +00002740 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2741 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2742 {
2743 ret = rib_uninstall_kernel (rn, rib);
2744 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002745 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002746 }
2747 }
2748}
2749
2750/* Sweep all RIB tables. */
2751void
paula1ac18c2005-06-28 17:17:12 +00002752rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002753{
2754 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2755 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2756}
2757
2758/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002759static void
paul718e3742002-12-13 20:15:29 +00002760rib_close_table (struct route_table *table)
2761{
2762 struct route_node *rn;
2763 struct rib *rib;
2764
2765 if (table)
2766 for (rn = route_top (table); rn; rn = route_next (rn))
2767 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002768 {
2769 if (! RIB_SYSTEM_ROUTE (rib)
2770 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2771 rib_uninstall_kernel (rn, rib);
2772 }
paul718e3742002-12-13 20:15:29 +00002773}
2774
2775/* Close all RIB tables. */
2776void
paula1ac18c2005-06-28 17:17:12 +00002777rib_close (void)
paul718e3742002-12-13 20:15:29 +00002778{
2779 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2780 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2781}
2782
2783/* Routing information base initialize. */
2784void
paula1ac18c2005-06-28 17:17:12 +00002785rib_init (void)
paul718e3742002-12-13 20:15:29 +00002786{
paul4d38fdb2005-04-28 17:35:14 +00002787 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002788 /* VRF initialization. */
2789 vrf_init ();
2790}