blob: e5cce1e881a2b5e5ca5f3e76bde4f527dbc12575 [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
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000884/* Iterate over all nexthops of the given RIB entry and refresh their
885 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
886 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
887 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
888 * transparently passed to nexthop_active_check().
889 *
890 * Return value is the new number of active nexthops.
891 */
892
paula1ac18c2005-06-28 17:17:12 +0000893static int
paul718e3742002-12-13 20:15:29 +0000894nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
895{
896 struct nexthop *nexthop;
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000897 int prev_active, new_active;
paul718e3742002-12-13 20:15:29 +0000898
899 rib->nexthop_active_num = 0;
900 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
901
902 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000903 {
904 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
905 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
906 rib->nexthop_active_num++;
907 if (prev_active != new_active)
908 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
909 }
paul718e3742002-12-13 20:15:29 +0000910 return rib->nexthop_active_num;
911}
paul6baeb982003-10-28 03:47:15 +0000912
paul718e3742002-12-13 20:15:29 +0000913
paul718e3742002-12-13 20:15:29 +0000914
paula1ac18c2005-06-28 17:17:12 +0000915static void
paul718e3742002-12-13 20:15:29 +0000916rib_install_kernel (struct route_node *rn, struct rib *rib)
917{
918 int ret = 0;
919 struct nexthop *nexthop;
920
921 switch (PREFIX_FAMILY (&rn->p))
922 {
923 case AF_INET:
924 ret = kernel_add_ipv4 (&rn->p, rib);
925 break;
926#ifdef HAVE_IPV6
927 case AF_INET6:
928 ret = kernel_add_ipv6 (&rn->p, rib);
929 break;
930#endif /* HAVE_IPV6 */
931 }
932
Denis Ovsienkodc958242007-08-13 16:03:06 +0000933 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +0000934 if (ret < 0)
935 {
936 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
937 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
938 }
939}
940
941/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000942static int
paul718e3742002-12-13 20:15:29 +0000943rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
944{
945 int ret = 0;
946 struct nexthop *nexthop;
947
948 switch (PREFIX_FAMILY (&rn->p))
949 {
950 case AF_INET:
951 ret = kernel_delete_ipv4 (&rn->p, rib);
952 break;
953#ifdef HAVE_IPV6
954 case AF_INET6:
Denis Ovsienkodc958242007-08-13 16:03:06 +0000955 if (IS_ZEBRA_DEBUG_RIB)
956 zlog_debug ("%s: calling kernel_delete_ipv4 (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +0000957 ret = kernel_delete_ipv6 (&rn->p, rib);
958 break;
959#endif /* HAVE_IPV6 */
960 }
961
962 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
963 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
964
965 return ret;
966}
967
968/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000969static void
paul718e3742002-12-13 20:15:29 +0000970rib_uninstall (struct route_node *rn, struct rib *rib)
971{
972 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
973 {
974 redistribute_delete (&rn->p, rib);
975 if (! RIB_SYSTEM_ROUTE (rib))
976 rib_uninstall_kernel (rn, rib);
977 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
978 }
979}
980
Paul Jakma6d691122006-07-27 21:49:00 +0000981static void rib_unlink (struct route_node *, struct rib *);
982
paul718e3742002-12-13 20:15:29 +0000983/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000984static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000985rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000986{
987 struct rib *rib;
988 struct rib *next;
989 struct rib *fib = NULL;
990 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +0000991 struct rib *del = NULL;
992 struct route_node *rn = data;
pauld753e9e2003-01-22 19:45:50 +0000993 int installed = 0;
994 struct nexthop *nexthop = NULL;
Paul Jakma93bdada2007-08-06 19:25:11 +0000995 char buf[INET_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +0000996
997 assert (rn);
998
Paul Jakma93bdada2007-08-06 19:25:11 +0000999 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
1000 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1001
paul718e3742002-12-13 20:15:29 +00001002 for (rib = rn->info; rib; rib = next)
1003 {
Denis Ovsienkodc958242007-08-13 16:03:06 +00001004 /* The next pointer is saved, because current pointer
1005 * may be passed to rib_unlink() in the middle of iteration.
1006 */
paul718e3742002-12-13 20:15:29 +00001007 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +00001008
paul718e3742002-12-13 20:15:29 +00001009 /* Currently installed rib. */
1010 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001011 {
1012 assert (fib == NULL);
1013 fib = rib;
1014 }
1015
1016 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1017 * which we need to do do further work with below.
1018 */
1019 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1020 {
1021 if (rib != fib)
1022 {
1023 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001024 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
1025 buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001026 rib_unlink (rn, rib);
1027 }
1028 else
1029 del = rib;
1030
1031 continue;
1032 }
paul4d38fdb2005-04-28 17:35:14 +00001033
paul718e3742002-12-13 20:15:29 +00001034 /* Skip unreachable nexthop. */
1035 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001036 continue;
paul718e3742002-12-13 20:15:29 +00001037
1038 /* Infinit distance. */
1039 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001040 continue;
paul718e3742002-12-13 20:15:29 +00001041
paulaf887b52006-01-18 14:52:52 +00001042 /* Newly selected rib, the common case. */
1043 if (!select)
1044 {
1045 select = rib;
1046 continue;
1047 }
1048
1049 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001050 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001051 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001052 * - lower metric beats higher for equal distance
1053 * - last, hence oldest, route wins tie break.
1054 */
paula1038a12006-01-30 14:08:51 +00001055
1056 /* Connected routes. Pick the last connected
1057 * route of the set of lowest metric connected routes.
1058 */
paula8d9c1f2006-01-25 06:31:04 +00001059 if (rib->type == ZEBRA_ROUTE_CONNECT)
1060 {
paula1038a12006-01-30 14:08:51 +00001061 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001062 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001063 select = rib;
1064 continue;
paula8d9c1f2006-01-25 06:31:04 +00001065 }
1066 else if (select->type == ZEBRA_ROUTE_CONNECT)
1067 continue;
1068
1069 /* higher distance loses */
1070 if (rib->distance > select->distance)
1071 continue;
1072
1073 /* lower wins */
1074 if (rib->distance < select->distance)
1075 {
paulaf887b52006-01-18 14:52:52 +00001076 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001077 continue;
1078 }
1079
1080 /* metric tie-breaks equal distance */
1081 if (rib->metric <= select->metric)
1082 select = rib;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001083 } /* for (rib = rn->info; rib; rib = next) */
1084
1085 /* After the cycle is finished, the following pointers will be set:
1086 * select --- the winner RIB entry, if any was found, otherwise NULL
1087 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1088 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1089 * rib --- NULL
1090 */
1091
1092 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001093 if (select && select == fib)
1094 {
Paul Jakma6d691122006-07-27 21:49:00 +00001095 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001096 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
1097 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +00001098 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001099 {
1100 redistribute_delete (&rn->p, select);
1101 if (! RIB_SYSTEM_ROUTE (select))
1102 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001103
paul4d38fdb2005-04-28 17:35:14 +00001104 /* Set real nexthop. */
1105 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001106
paul4d38fdb2005-04-28 17:35:14 +00001107 if (! RIB_SYSTEM_ROUTE (select))
1108 rib_install_kernel (rn, select);
1109 redistribute_add (&rn->p, select);
1110 }
pauld753e9e2003-01-22 19:45:50 +00001111 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001112 {
1113 /* Housekeeping code to deal with
1114 race conditions in kernel with linux
1115 netlink reporting interface up before IPv4 or IPv6 protocol
1116 is ready to add routes.
1117 This makes sure the routes are IN the kernel.
1118 */
pauld753e9e2003-01-22 19:45:50 +00001119
paul4d38fdb2005-04-28 17:35:14 +00001120 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1121 {
1122 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1123 installed = 1;
1124 }
1125 if (! installed)
1126 rib_install_kernel (rn, select);
1127 }
Paul Jakma6d691122006-07-27 21:49:00 +00001128 goto end;
paul718e3742002-12-13 20:15:29 +00001129 }
1130
Denis Ovsienkodc958242007-08-13 16:03:06 +00001131 /* At this point we either haven't found the best RIB entry or it is
1132 * different from what we currently intend to flag with SELECTED. In both
1133 * cases, if a RIB block is present in FIB, it should be withdrawn.
1134 */
paul718e3742002-12-13 20:15:29 +00001135 if (fib)
1136 {
Paul Jakma6d691122006-07-27 21:49:00 +00001137 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001138 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1139 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001140 redistribute_delete (&rn->p, fib);
1141 if (! RIB_SYSTEM_ROUTE (fib))
1142 rib_uninstall_kernel (rn, fib);
1143 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1144
1145 /* Set real nexthop. */
1146 nexthop_active_update (rn, fib, 1);
1147 }
1148
Denis Ovsienkodc958242007-08-13 16:03:06 +00001149 /* Regardless of some RIB entry being SELECTED or not before, now we can
1150 * tell, that if a new winner exists, FIB is still not updated with this
1151 * data, but ready to be.
1152 */
paul718e3742002-12-13 20:15:29 +00001153 if (select)
1154 {
Paul Jakma6d691122006-07-27 21:49:00 +00001155 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001156 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1157 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001158 /* Set real nexthop. */
1159 nexthop_active_update (rn, select, 1);
1160
1161 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001162 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001163 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1164 redistribute_add (&rn->p, select);
1165 }
paul4d38fdb2005-04-28 17:35:14 +00001166
Paul Jakma6d691122006-07-27 21:49:00 +00001167 /* FIB route was removed, should be deleted */
1168 if (del)
1169 {
1170 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001171 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1172 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001173 rib_unlink (rn, del);
1174 }
paul4d38fdb2005-04-28 17:35:14 +00001175
Paul Jakma6d691122006-07-27 21:49:00 +00001176end:
1177 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001178 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001179 if (rn->info)
1180 UNSET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1181 route_unlock_node (rn); /* rib queue lock */
1182 return WQ_SUCCESS;
paul4d38fdb2005-04-28 17:35:14 +00001183}
1184
Paul Jakma6d691122006-07-27 21:49:00 +00001185/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001186static void
Paul Jakma6d691122006-07-27 21:49:00 +00001187rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001188{
Paul Jakma93bdada2007-08-06 19:25:11 +00001189 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001190 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001191
Paul Jakma93bdada2007-08-06 19:25:11 +00001192 if (IS_ZEBRA_DEBUG_RIB_Q)
1193 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1194
Paul Jakma6d691122006-07-27 21:49:00 +00001195 /* Pointless to queue a route_node with no RIB entries to add or remove */
1196 if (!rn->info)
1197 {
1198 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1199 __func__, rn, rn->lock);
1200 zlog_backtrace(LOG_DEBUG);
1201 return;
1202 }
paul4d38fdb2005-04-28 17:35:14 +00001203
Paul Jakma6d691122006-07-27 21:49:00 +00001204 /* Route-table node already queued, so nothing to do */
1205 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED))
1206 {
1207 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001208 zlog_debug ("%s: %s/%d: rn %p already queued", __func__, buf,
1209 rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001210 return;
1211 }
paul4d38fdb2005-04-28 17:35:14 +00001212
Paul Jakma6d691122006-07-27 21:49:00 +00001213 route_lock_node (rn); /* rib queue lock */
1214
1215 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001216 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001217
1218 assert (zebra);
1219
paul4d38fdb2005-04-28 17:35:14 +00001220 if (zebra->ribq == NULL)
1221 {
Paul Jakma6d691122006-07-27 21:49:00 +00001222 zlog_err ("%s: work_queue does not exist!", __func__);
1223 route_unlock_node (rn);
paul4d38fdb2005-04-28 17:35:14 +00001224 return;
1225 }
1226
Paul Jakma6d691122006-07-27 21:49:00 +00001227 work_queue_add (zebra->ribq, rn);
1228
1229 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1230
1231 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001232 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
paul4d38fdb2005-04-28 17:35:14 +00001233
1234 return;
1235}
1236
paul4d38fdb2005-04-28 17:35:14 +00001237/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001238static void
paul4d38fdb2005-04-28 17:35:14 +00001239rib_queue_init (struct zebra_t *zebra)
1240{
1241 assert (zebra);
1242
1243 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001244 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001245 {
Paul Jakma6d691122006-07-27 21:49:00 +00001246 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001247 return;
1248 }
1249
1250 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001251 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001252 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001253 /* XXX: TODO: These should be runtime configurable via vty */
1254 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001255 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001256
1257 return;
paul718e3742002-12-13 20:15:29 +00001258}
1259
Paul Jakma6d691122006-07-27 21:49:00 +00001260/* RIB updates are processed via a queue of pointers to route_nodes.
1261 *
1262 * The queue length is bounded by the maximal size of the routing table,
1263 * as a route_node will not be requeued, if already queued.
1264 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001265 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1266 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1267 * and then submit route_node to queue for best-path selection later.
1268 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001269 *
1270 * Deleted RIBs are reaped during best-path selection.
1271 *
1272 * rib_addnode
1273 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001274 * |-------->| | best RIB, if required
1275 * | |
1276 * static_install->|->rib_addqueue...... -> rib_process
1277 * | |
1278 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001279 * |-> set RIB_ENTRY_REMOVE |
1280 * rib_delnode (RIB freed)
1281 *
1282 *
1283 * Queueing state for a route_node is kept in the head RIB entry, this
1284 * state must be preserved as and when the head RIB entry of a
1285 * route_node is changed by rib_unlink / rib_link. A small complication,
1286 * but saves having to allocate a dedicated object for this.
1287 *
1288 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1289 *
1290 * - route_nodes: refcounted by:
1291 * - RIBs attached to route_node:
1292 * - managed by: rib_link/unlink
1293 * - route_node processing queue
1294 * - managed by: rib_addqueue, rib_process.
1295 *
1296 */
1297
paul718e3742002-12-13 20:15:29 +00001298/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001299static void
Paul Jakma6d691122006-07-27 21:49:00 +00001300rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001301{
1302 struct rib *head;
Paul Jakma93bdada2007-08-06 19:25:11 +00001303 char buf[INET_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001304
1305 assert (rib && rn);
1306
Paul Jakma6d691122006-07-27 21:49:00 +00001307 route_lock_node (rn); /* rn route table reference */
1308
1309 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001310 {
1311 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1312 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1313 buf, rn->p.prefixlen, rn, rib);
1314 }
Paul Jakma6d691122006-07-27 21:49:00 +00001315
paul718e3742002-12-13 20:15:29 +00001316 head = rn->info;
1317 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001318 {
1319 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001320 zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
1321 buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001322 head->prev = rib;
1323 /* Transfer the rn status flags to the new head RIB */
1324 rib->rn_status = head->rn_status;
1325 }
paul718e3742002-12-13 20:15:29 +00001326 rib->next = head;
1327 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001328 rib_queue_add (&zebrad, rn);
1329}
1330
1331static void
1332rib_addnode (struct route_node *rn, struct rib *rib)
1333{
1334 /* RIB node has been un-removed before route-node is processed.
1335 * route_node must hence already be on the queue for processing..
1336 */
1337 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1338 {
1339 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001340 {
1341 char buf[INET_ADDRSTRLEN];
1342 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1343 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1344 __func__, buf, rn->p.prefixlen, rn, rib);
1345 }
Paul Jakma6d691122006-07-27 21:49:00 +00001346 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1347 return;
1348 }
1349 rib_link (rn, rib);
1350}
1351
1352static void
1353rib_unlink (struct route_node *rn, struct rib *rib)
1354{
1355 struct nexthop *nexthop, *next;
Paul Jakma93bdada2007-08-06 19:25:11 +00001356 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001357
1358 assert (rn && rib);
1359
1360 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001361 {
1362 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1363 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1364 __func__, buf, rn->p.prefixlen, rn, rib);
1365 }
Paul Jakma6d691122006-07-27 21:49:00 +00001366
1367 if (rib->next)
1368 rib->next->prev = rib->prev;
1369
1370 if (rib->prev)
1371 rib->prev->next = rib->next;
1372 else
1373 {
1374 rn->info = rib->next;
1375
1376 if (rn->info)
1377 {
1378 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001379 zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
1380 __func__, buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001381 rib->next->rn_status = rib->rn_status;
1382 }
1383 }
1384
1385 /* free RIB and nexthops */
1386 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1387 {
1388 next = nexthop->next;
1389 nexthop_free (nexthop);
1390 }
1391 XFREE (MTYPE_RIB, rib);
1392
1393 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001394}
1395
paula1ac18c2005-06-28 17:17:12 +00001396static void
paul718e3742002-12-13 20:15:29 +00001397rib_delnode (struct route_node *rn, struct rib *rib)
1398{
Paul Jakma6d691122006-07-27 21:49:00 +00001399 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001400 {
1401 char buf[INET_ADDRSTRLEN];
1402 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1403 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1404 buf, rn->p.prefixlen, rn, rib);
1405 }
Paul Jakma6d691122006-07-27 21:49:00 +00001406 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1407 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001408}
1409
1410int
1411rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001412 struct in_addr *gate, struct in_addr *src,
1413 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001414 u_int32_t metric, u_char distance)
1415{
1416 struct rib *rib;
1417 struct rib *same = NULL;
1418 struct route_table *table;
1419 struct route_node *rn;
1420 struct nexthop *nexthop;
1421
1422 /* Lookup table. */
1423 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1424 if (! table)
1425 return 0;
1426
1427 /* Make it sure prefixlen is applied to the prefix. */
1428 apply_mask_ipv4 (p);
1429
1430 /* Set default distance by route type. */
1431 if (distance == 0)
1432 {
1433 distance = route_info[type].distance;
1434
1435 /* iBGP distance is 200. */
1436 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1437 distance = 200;
1438 }
1439
1440 /* Lookup route node.*/
1441 rn = route_node_get (table, (struct prefix *) p);
1442
1443 /* If same type of route are installed, treat it as a implicit
1444 withdraw. */
1445 for (rib = rn->info; rib; rib = rib->next)
1446 {
Paul Jakma6d691122006-07-27 21:49:00 +00001447 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1448 continue;
1449
hassoebf1ead2005-09-21 14:58:20 +00001450 if (rib->type != type)
1451 continue;
1452 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001453 {
1454 same = rib;
1455 break;
1456 }
hassoebf1ead2005-09-21 14:58:20 +00001457 /* Duplicate connected route comes in. */
1458 else if ((nexthop = rib->nexthop) &&
1459 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001460 nexthop->ifindex == ifindex &&
1461 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001462 {
1463 rib->refcnt++;
1464 return 0 ;
1465 }
paul718e3742002-12-13 20:15:29 +00001466 }
1467
1468 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001469 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001470 rib->type = type;
1471 rib->distance = distance;
1472 rib->flags = flags;
1473 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001474 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001475 rib->nexthop_num = 0;
1476 rib->uptime = time (NULL);
1477
1478 /* Nexthop settings. */
1479 if (gate)
1480 {
1481 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001482 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001483 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001484 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001485 }
1486 else
1487 nexthop_ifindex_add (rib, ifindex);
1488
1489 /* If this route is kernel route, set FIB flag to the route. */
1490 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1491 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1492 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1493
1494 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001495 if (IS_ZEBRA_DEBUG_RIB)
1496 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001497 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001498
paul718e3742002-12-13 20:15:29 +00001499 /* Free implicit route.*/
1500 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001501 {
1502 if (IS_ZEBRA_DEBUG_RIB)
1503 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001504 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001505 }
paul4d38fdb2005-04-28 17:35:14 +00001506
1507 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001508 return 0;
1509}
1510
Denis Ovsienkodc958242007-08-13 16:03:06 +00001511/* This function dumps the contents of a given RIB entry into
1512 * standard debug log. Calling function name and IP prefix in
1513 * question are passed as 1st and 2nd arguments.
1514 */
1515
1516void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1517{
1518 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1519 struct nexthop *nexthop;
1520
1521 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1522 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1523 zlog_debug
1524 (
1525 "%s: refcnt == %lu, uptime == %u, type == %u, table == %d",
1526 func,
1527 rib->refcnt,
1528 rib->uptime,
1529 rib->type,
1530 rib->table
1531 );
1532 zlog_debug
1533 (
1534 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1535 func,
1536 rib->metric,
1537 rib->distance,
1538 rib->flags,
1539 rib->status
1540 );
1541 zlog_debug
1542 (
1543 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1544 func,
1545 rib->nexthop_num,
1546 rib->nexthop_active_num,
1547 rib->nexthop_fib_num
1548 );
1549 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1550 {
1551 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1552 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1553 zlog_debug
1554 (
1555 "%s: NH %s (%s) with flags %s%s%s",
1556 func,
1557 straddr1,
1558 straddr2,
1559 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1560 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1561 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1562 );
1563 }
1564 zlog_debug ("%s: dump complete", func);
1565}
1566
1567/* This is an exported helper to rtm_read() to dump the strange
1568 * RIB entry found by rib_lookup_ipv4_route()
1569 */
1570
1571void rib_lookup_and_dump (struct prefix_ipv4 * p)
1572{
1573 struct route_table *table;
1574 struct route_node *rn;
1575 struct rib *rib;
1576 char prefix_buf[INET_ADDRSTRLEN];
1577
1578 /* Lookup table. */
1579 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1580 if (! table)
1581 {
1582 zlog_err ("%s: vrf_table() returned NULL", __func__);
1583 return;
1584 }
1585
1586 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1587 /* Scan the RIB table for exactly matching RIB entry. */
1588 rn = route_node_lookup (table, (struct prefix *) p);
1589
1590 /* No route for this prefix. */
1591 if (! rn)
1592 {
1593 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1594 return;
1595 }
1596
1597 /* Unlock node. */
1598 route_unlock_node (rn);
1599
1600 /* let's go */
1601 for (rib = rn->info; rib; rib = rib->next)
1602 {
1603 zlog_debug
1604 (
1605 "%s: rn %p, rib %p: %s, %s",
1606 __func__,
1607 rn,
1608 rib,
1609 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1610 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1611 );
1612 rib_dump (__func__, p, rib);
1613 }
1614}
1615
paul718e3742002-12-13 20:15:29 +00001616int
1617rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1618{
1619 struct route_table *table;
1620 struct route_node *rn;
1621 struct rib *same;
1622 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001623
paul718e3742002-12-13 20:15:29 +00001624 /* Lookup table. */
1625 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1626 if (! table)
1627 return 0;
paul718e3742002-12-13 20:15:29 +00001628 /* Make it sure prefixlen is applied to the prefix. */
1629 apply_mask_ipv4 (p);
1630
1631 /* Set default distance by route type. */
1632 if (rib->distance == 0)
1633 {
1634 rib->distance = route_info[rib->type].distance;
1635
1636 /* iBGP distance is 200. */
1637 if (rib->type == ZEBRA_ROUTE_BGP
1638 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1639 rib->distance = 200;
1640 }
1641
1642 /* Lookup route node.*/
1643 rn = route_node_get (table, (struct prefix *) p);
1644
1645 /* If same type of route are installed, treat it as a implicit
1646 withdraw. */
1647 for (same = rn->info; same; same = same->next)
1648 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001649 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001650 continue;
1651
paul718e3742002-12-13 20:15:29 +00001652 if (same->type == rib->type && same->table == rib->table
1653 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001654 break;
paul718e3742002-12-13 20:15:29 +00001655 }
paul4d38fdb2005-04-28 17:35:14 +00001656
paul718e3742002-12-13 20:15:29 +00001657 /* If this route is kernel route, set FIB flag to the route. */
1658 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1659 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1660 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1661
1662 /* Link new rib to node.*/
1663 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001664 if (IS_ZEBRA_DEBUG_RIB)
1665 {
1666 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1667 __func__, rn, rib);
1668 rib_dump (__func__, p, rib);
1669 }
paul718e3742002-12-13 20:15:29 +00001670
paul718e3742002-12-13 20:15:29 +00001671 /* Free implicit route.*/
1672 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001673 {
1674 if (IS_ZEBRA_DEBUG_RIB)
1675 {
1676 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1677 __func__, rn, same);
1678 rib_dump (__func__, p, same);
1679 }
paul4d38fdb2005-04-28 17:35:14 +00001680 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001681 }
paul4d38fdb2005-04-28 17:35:14 +00001682
1683 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001684 return 0;
1685}
1686
hassoebf1ead2005-09-21 14:58:20 +00001687/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001688int
1689rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1690 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1691{
1692 struct route_table *table;
1693 struct route_node *rn;
1694 struct rib *rib;
1695 struct rib *fib = NULL;
1696 struct rib *same = NULL;
1697 struct nexthop *nexthop;
1698 char buf1[BUFSIZ];
1699 char buf2[BUFSIZ];
1700
1701 /* Lookup table. */
1702 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1703 if (! table)
1704 return 0;
1705
1706 /* Apply mask. */
1707 apply_mask_ipv4 (p);
1708
paul5ec90d22003-06-19 01:41:37 +00001709 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001710 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001711 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1712 p->prefixlen,
1713 inet_ntoa (*gate),
1714 ifindex);
1715
paul718e3742002-12-13 20:15:29 +00001716 /* Lookup route node. */
1717 rn = route_node_lookup (table, (struct prefix *) p);
1718 if (! rn)
1719 {
1720 if (IS_ZEBRA_DEBUG_KERNEL)
1721 {
1722 if (gate)
ajsb6178002004-12-07 21:12:56 +00001723 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001724 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1725 p->prefixlen,
1726 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1727 ifindex);
1728 else
ajsb6178002004-12-07 21:12:56 +00001729 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001730 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1731 p->prefixlen,
1732 ifindex);
1733 }
1734 return ZEBRA_ERR_RTNOEXIST;
1735 }
1736
1737 /* Lookup same type route. */
1738 for (rib = rn->info; rib; rib = rib->next)
1739 {
Paul Jakma6d691122006-07-27 21:49:00 +00001740 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1741 continue;
1742
paul718e3742002-12-13 20:15:29 +00001743 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1744 fib = rib;
1745
hassoebf1ead2005-09-21 14:58:20 +00001746 if (rib->type != type)
1747 continue;
1748 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1749 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001750 {
hassoebf1ead2005-09-21 14:58:20 +00001751 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001752 {
hassoebf1ead2005-09-21 14:58:20 +00001753 rib->refcnt--;
1754 route_unlock_node (rn);
1755 route_unlock_node (rn);
1756 return 0;
paul718e3742002-12-13 20:15:29 +00001757 }
hassoebf1ead2005-09-21 14:58:20 +00001758 same = rib;
1759 break;
paul718e3742002-12-13 20:15:29 +00001760 }
hassoebf1ead2005-09-21 14:58:20 +00001761 /* Make sure that the route found has the same gateway. */
1762 else if (gate == NULL ||
1763 ((nexthop = rib->nexthop) &&
1764 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1765 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001766 {
hassoebf1ead2005-09-21 14:58:20 +00001767 same = rib;
1768 break;
paul718e3742002-12-13 20:15:29 +00001769 }
1770 }
1771
1772 /* If same type of route can't be found and this message is from
1773 kernel. */
1774 if (! same)
1775 {
1776 if (fib && type == ZEBRA_ROUTE_KERNEL)
1777 {
1778 /* Unset flags. */
1779 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1780 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1781
1782 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1783 }
1784 else
1785 {
1786 if (IS_ZEBRA_DEBUG_KERNEL)
1787 {
1788 if (gate)
ajsb6178002004-12-07 21:12:56 +00001789 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001790 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1791 p->prefixlen,
1792 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1793 ifindex,
1794 type);
1795 else
ajsb6178002004-12-07 21:12:56 +00001796 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001797 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1798 p->prefixlen,
1799 ifindex,
1800 type);
1801 }
1802 route_unlock_node (rn);
1803 return ZEBRA_ERR_RTNOEXIST;
1804 }
1805 }
paul4d38fdb2005-04-28 17:35:14 +00001806
paul718e3742002-12-13 20:15:29 +00001807 if (same)
1808 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001809
paul718e3742002-12-13 20:15:29 +00001810 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001811 return 0;
1812}
1813
1814/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001815static void
paul718e3742002-12-13 20:15:29 +00001816static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1817{
1818 struct rib *rib;
1819 struct route_node *rn;
1820 struct route_table *table;
1821
1822 /* Lookup table. */
1823 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1824 if (! table)
1825 return;
1826
1827 /* Lookup existing route */
1828 rn = route_node_get (table, p);
1829 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001830 {
1831 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1832 continue;
1833
1834 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1835 break;
1836 }
paul718e3742002-12-13 20:15:29 +00001837
1838 if (rib)
1839 {
1840 /* Same distance static route is there. Update it with new
1841 nexthop. */
paul718e3742002-12-13 20:15:29 +00001842 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001843 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001844 {
1845 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001846 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001847 break;
1848 case STATIC_IPV4_IFNAME:
1849 nexthop_ifname_add (rib, si->gate.ifname);
1850 break;
1851 case STATIC_IPV4_BLACKHOLE:
1852 nexthop_blackhole_add (rib);
1853 break;
paul4d38fdb2005-04-28 17:35:14 +00001854 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00001855 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001856 }
1857 else
1858 {
1859 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001860 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1861
paul718e3742002-12-13 20:15:29 +00001862 rib->type = ZEBRA_ROUTE_STATIC;
1863 rib->distance = si->distance;
1864 rib->metric = 0;
1865 rib->nexthop_num = 0;
1866
1867 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001868 {
1869 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001870 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001871 break;
1872 case STATIC_IPV4_IFNAME:
1873 nexthop_ifname_add (rib, si->gate.ifname);
1874 break;
1875 case STATIC_IPV4_BLACKHOLE:
1876 nexthop_blackhole_add (rib);
1877 break;
1878 }
paul718e3742002-12-13 20:15:29 +00001879
hasso81dfcaa2003-05-25 19:21:25 +00001880 /* Save the flags of this static routes (reject, blackhole) */
1881 rib->flags = si->flags;
1882
paul718e3742002-12-13 20:15:29 +00001883 /* Link this rib to the tree. */
1884 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001885 }
1886}
1887
paula1ac18c2005-06-28 17:17:12 +00001888static int
paul718e3742002-12-13 20:15:29 +00001889static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1890{
1891 if (nexthop->type == NEXTHOP_TYPE_IPV4
1892 && si->type == STATIC_IPV4_GATEWAY
1893 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1894 return 1;
1895 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1896 && si->type == STATIC_IPV4_IFNAME
1897 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1898 return 1;
paul595db7f2003-05-25 21:35:06 +00001899 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1900 && si->type == STATIC_IPV4_BLACKHOLE)
1901 return 1;
paule8e19462006-01-19 20:16:55 +00001902 return 0;
paul718e3742002-12-13 20:15:29 +00001903}
1904
1905/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001906static void
paul718e3742002-12-13 20:15:29 +00001907static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1908{
1909 struct route_node *rn;
1910 struct rib *rib;
1911 struct nexthop *nexthop;
1912 struct route_table *table;
1913
1914 /* Lookup table. */
1915 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1916 if (! table)
1917 return;
paul4d38fdb2005-04-28 17:35:14 +00001918
paul718e3742002-12-13 20:15:29 +00001919 /* Lookup existing route with type and distance. */
1920 rn = route_node_lookup (table, p);
1921 if (! rn)
1922 return;
1923
1924 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001925 {
1926 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1927 continue;
1928
1929 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1930 break;
1931 }
paul718e3742002-12-13 20:15:29 +00001932
1933 if (! rib)
1934 {
1935 route_unlock_node (rn);
1936 return;
1937 }
1938
1939 /* Lookup nexthop. */
1940 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1941 if (static_ipv4_nexthop_same (nexthop, si))
1942 break;
1943
1944 /* Can't find nexthop. */
1945 if (! nexthop)
1946 {
1947 route_unlock_node (rn);
1948 return;
1949 }
1950
1951 /* Check nexthop. */
1952 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00001953 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001954 else
1955 {
paul6baeb982003-10-28 03:47:15 +00001956 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1957 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001958 nexthop_delete (rib, nexthop);
1959 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001960 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001961 }
paul718e3742002-12-13 20:15:29 +00001962 /* Unlock node. */
1963 route_unlock_node (rn);
1964}
1965
1966/* Add static route into static route configuration. */
1967int
hasso39db97e2004-10-12 20:50:58 +00001968static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001969 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001970{
1971 u_char type = 0;
1972 struct route_node *rn;
1973 struct static_ipv4 *si;
1974 struct static_ipv4 *pp;
1975 struct static_ipv4 *cp;
1976 struct static_ipv4 *update = NULL;
1977 struct route_table *stable;
1978
1979 /* Lookup table. */
1980 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1981 if (! stable)
1982 return -1;
1983
1984 /* Lookup static route prefix. */
1985 rn = route_node_get (stable, p);
1986
1987 /* Make flags. */
1988 if (gate)
1989 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001990 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001991 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001992 else
1993 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001994
1995 /* Do nothing if there is a same static route. */
1996 for (si = rn->info; si; si = si->next)
1997 {
1998 if (type == si->type
1999 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2000 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2001 {
2002 if (distance == si->distance)
2003 {
2004 route_unlock_node (rn);
2005 return 0;
2006 }
2007 else
2008 update = si;
2009 }
2010 }
2011
Paul Jakma3c0755d2006-12-08 00:53:14 +00002012 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002013 if (update)
2014 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2015
2016 /* Make new static route structure. */
2017 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
2018 memset (si, 0, sizeof (struct static_ipv4));
2019
2020 si->type = type;
2021 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002022 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002023
2024 if (gate)
2025 si->gate.ipv4 = *gate;
2026 if (ifname)
2027 si->gate.ifname = XSTRDUP (0, ifname);
2028
2029 /* Add new static route information to the tree with sort by
2030 distance value and gateway address. */
2031 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2032 {
2033 if (si->distance < cp->distance)
2034 break;
2035 if (si->distance > cp->distance)
2036 continue;
2037 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2038 {
2039 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2040 break;
2041 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2042 continue;
2043 }
2044 }
2045
2046 /* Make linked list. */
2047 if (pp)
2048 pp->next = si;
2049 else
2050 rn->info = si;
2051 if (cp)
2052 cp->prev = si;
2053 si->prev = pp;
2054 si->next = cp;
2055
2056 /* Install into rib. */
2057 static_install_ipv4 (p, si);
2058
2059 return 1;
2060}
2061
2062/* Delete static route from static route configuration. */
2063int
hasso39db97e2004-10-12 20:50:58 +00002064static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002065 u_char distance, u_int32_t vrf_id)
2066{
2067 u_char type = 0;
2068 struct route_node *rn;
2069 struct static_ipv4 *si;
2070 struct route_table *stable;
2071
2072 /* Lookup table. */
2073 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2074 if (! stable)
2075 return -1;
2076
2077 /* Lookup static route prefix. */
2078 rn = route_node_lookup (stable, p);
2079 if (! rn)
2080 return 0;
2081
2082 /* Make flags. */
2083 if (gate)
2084 type = STATIC_IPV4_GATEWAY;
2085 else if (ifname)
2086 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002087 else
2088 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002089
2090 /* Find same static route is the tree */
2091 for (si = rn->info; si; si = si->next)
2092 if (type == si->type
2093 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2094 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2095 break;
2096
2097 /* Can't find static route. */
2098 if (! si)
2099 {
2100 route_unlock_node (rn);
2101 return 0;
2102 }
2103
2104 /* Install into rib. */
2105 static_uninstall_ipv4 (p, si);
2106
2107 /* Unlink static route from linked list. */
2108 if (si->prev)
2109 si->prev->next = si->next;
2110 else
2111 rn->info = si->next;
2112 if (si->next)
2113 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002114 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002115
2116 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002117 if (ifname)
2118 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002119 XFREE (MTYPE_STATIC_IPV4, si);
2120
paul143a3852003-09-29 20:06:13 +00002121 route_unlock_node (rn);
2122
paul718e3742002-12-13 20:15:29 +00002123 return 1;
2124}
2125
2126
2127#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002128static int
paul718e3742002-12-13 20:15:29 +00002129rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2130 struct in6_addr *gate, unsigned int ifindex, int table)
2131{
hasso726f9b22003-05-25 21:04:54 +00002132 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2133#if defined (MUSICA) || defined (LINUX)
2134 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2135 if (p->prefixlen == 96)
2136 return 0;
2137#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002138 return 1;
hasso726f9b22003-05-25 21:04:54 +00002139 }
paul718e3742002-12-13 20:15:29 +00002140 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2141 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2142 {
2143 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2144 return 1;
2145 }
2146 return 0;
2147}
2148
2149int
2150rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002151 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
2152 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00002153{
2154 struct rib *rib;
2155 struct rib *same = NULL;
2156 struct route_table *table;
2157 struct route_node *rn;
2158 struct nexthop *nexthop;
2159
paul718e3742002-12-13 20:15:29 +00002160 /* Lookup table. */
2161 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2162 if (! table)
2163 return 0;
2164
2165 /* Make sure mask is applied. */
2166 apply_mask_ipv6 (p);
2167
2168 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002169 if (!distance)
2170 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002171
2172 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2173 distance = 200;
2174
2175 /* Filter bogus route. */
2176 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2177 return 0;
2178
2179 /* Lookup route node.*/
2180 rn = route_node_get (table, (struct prefix *) p);
2181
2182 /* If same type of route are installed, treat it as a implicit
2183 withdraw. */
2184 for (rib = rn->info; rib; rib = rib->next)
2185 {
Paul Jakma6d691122006-07-27 21:49:00 +00002186 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2187 continue;
2188
hassoebf1ead2005-09-21 14:58:20 +00002189 if (rib->type != type)
2190 continue;
2191 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002192 {
2193 same = rib;
paul718e3742002-12-13 20:15:29 +00002194 break;
2195 }
hassoebf1ead2005-09-21 14:58:20 +00002196 else if ((nexthop = rib->nexthop) &&
2197 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2198 nexthop->ifindex == ifindex)
2199 {
2200 rib->refcnt++;
2201 return 0;
2202 }
paul718e3742002-12-13 20:15:29 +00002203 }
2204
2205 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002206 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2207
paul718e3742002-12-13 20:15:29 +00002208 rib->type = type;
2209 rib->distance = distance;
2210 rib->flags = flags;
2211 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002212 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002213 rib->nexthop_num = 0;
2214 rib->uptime = time (NULL);
2215
2216 /* Nexthop settings. */
2217 if (gate)
2218 {
2219 if (ifindex)
2220 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2221 else
2222 nexthop_ipv6_add (rib, gate);
2223 }
2224 else
2225 nexthop_ifindex_add (rib, ifindex);
2226
2227 /* If this route is kernel route, set FIB flag to the route. */
2228 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2229 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2230 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2231
2232 /* Link new rib to node.*/
2233 rib_addnode (rn, rib);
2234
paul718e3742002-12-13 20:15:29 +00002235 /* Free implicit route.*/
2236 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002237 rib_delnode (rn, same);
2238
2239 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002240 return 0;
2241}
2242
hassoebf1ead2005-09-21 14:58:20 +00002243/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002244int
2245rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2246 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
2247{
2248 struct route_table *table;
2249 struct route_node *rn;
2250 struct rib *rib;
2251 struct rib *fib = NULL;
2252 struct rib *same = NULL;
2253 struct nexthop *nexthop;
2254 char buf1[BUFSIZ];
2255 char buf2[BUFSIZ];
2256
2257 /* Apply mask. */
2258 apply_mask_ipv6 (p);
2259
2260 /* Lookup table. */
2261 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2262 if (! table)
2263 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002264
paul718e3742002-12-13 20:15:29 +00002265 /* Lookup route node. */
2266 rn = route_node_lookup (table, (struct prefix *) p);
2267 if (! rn)
2268 {
2269 if (IS_ZEBRA_DEBUG_KERNEL)
2270 {
2271 if (gate)
ajsb6178002004-12-07 21:12:56 +00002272 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002273 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2274 p->prefixlen,
2275 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2276 ifindex);
2277 else
ajsb6178002004-12-07 21:12:56 +00002278 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002279 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2280 p->prefixlen,
2281 ifindex);
2282 }
2283 return ZEBRA_ERR_RTNOEXIST;
2284 }
2285
2286 /* Lookup same type route. */
2287 for (rib = rn->info; rib; rib = rib->next)
2288 {
Paul Jakma6d691122006-07-27 21:49:00 +00002289 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2290 continue;
2291
paul718e3742002-12-13 20:15:29 +00002292 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2293 fib = rib;
2294
hassoebf1ead2005-09-21 14:58:20 +00002295 if (rib->type != type)
2296 continue;
2297 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2298 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002299 {
hassoebf1ead2005-09-21 14:58:20 +00002300 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002301 {
hassoebf1ead2005-09-21 14:58:20 +00002302 rib->refcnt--;
2303 route_unlock_node (rn);
2304 route_unlock_node (rn);
2305 return 0;
paul718e3742002-12-13 20:15:29 +00002306 }
hassoebf1ead2005-09-21 14:58:20 +00002307 same = rib;
2308 break;
paul718e3742002-12-13 20:15:29 +00002309 }
hassoebf1ead2005-09-21 14:58:20 +00002310 /* Make sure that the route found has the same gateway. */
2311 else if (gate == NULL ||
2312 ((nexthop = rib->nexthop) &&
2313 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2314 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002315 {
hassoebf1ead2005-09-21 14:58:20 +00002316 same = rib;
2317 break;
paul718e3742002-12-13 20:15:29 +00002318 }
2319 }
2320
2321 /* If same type of route can't be found and this message is from
2322 kernel. */
2323 if (! same)
2324 {
2325 if (fib && type == ZEBRA_ROUTE_KERNEL)
2326 {
2327 /* Unset flags. */
2328 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2329 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2330
2331 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2332 }
2333 else
2334 {
2335 if (IS_ZEBRA_DEBUG_KERNEL)
2336 {
2337 if (gate)
ajsb6178002004-12-07 21:12:56 +00002338 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002339 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2340 p->prefixlen,
2341 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2342 ifindex,
2343 type);
2344 else
ajsb6178002004-12-07 21:12:56 +00002345 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002346 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2347 p->prefixlen,
2348 ifindex,
2349 type);
2350 }
2351 route_unlock_node (rn);
2352 return ZEBRA_ERR_RTNOEXIST;
2353 }
2354 }
2355
2356 if (same)
2357 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002358
paul718e3742002-12-13 20:15:29 +00002359 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002360 return 0;
2361}
2362
2363/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002364static void
paul718e3742002-12-13 20:15:29 +00002365static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2366{
2367 struct rib *rib;
2368 struct route_table *table;
2369 struct route_node *rn;
2370
2371 /* Lookup table. */
2372 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2373 if (! table)
2374 return;
2375
2376 /* Lookup existing route */
2377 rn = route_node_get (table, p);
2378 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002379 {
2380 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2381 continue;
2382
2383 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2384 break;
2385 }
paul718e3742002-12-13 20:15:29 +00002386
2387 if (rib)
2388 {
2389 /* Same distance static route is there. Update it with new
2390 nexthop. */
paul718e3742002-12-13 20:15:29 +00002391 route_unlock_node (rn);
2392
2393 switch (si->type)
2394 {
2395 case STATIC_IPV6_GATEWAY:
2396 nexthop_ipv6_add (rib, &si->ipv6);
2397 break;
2398 case STATIC_IPV6_IFNAME:
2399 nexthop_ifname_add (rib, si->ifname);
2400 break;
2401 case STATIC_IPV6_GATEWAY_IFNAME:
2402 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2403 break;
2404 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002405 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002406 }
2407 else
2408 {
2409 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002410 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2411
paul718e3742002-12-13 20:15:29 +00002412 rib->type = ZEBRA_ROUTE_STATIC;
2413 rib->distance = si->distance;
2414 rib->metric = 0;
2415 rib->nexthop_num = 0;
2416
2417 switch (si->type)
2418 {
2419 case STATIC_IPV6_GATEWAY:
2420 nexthop_ipv6_add (rib, &si->ipv6);
2421 break;
2422 case STATIC_IPV6_IFNAME:
2423 nexthop_ifname_add (rib, si->ifname);
2424 break;
2425 case STATIC_IPV6_GATEWAY_IFNAME:
2426 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2427 break;
2428 }
2429
hasso81dfcaa2003-05-25 19:21:25 +00002430 /* Save the flags of this static routes (reject, blackhole) */
2431 rib->flags = si->flags;
2432
paul718e3742002-12-13 20:15:29 +00002433 /* Link this rib to the tree. */
2434 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002435 }
2436}
2437
paula1ac18c2005-06-28 17:17:12 +00002438static int
paul718e3742002-12-13 20:15:29 +00002439static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2440{
2441 if (nexthop->type == NEXTHOP_TYPE_IPV6
2442 && si->type == STATIC_IPV6_GATEWAY
2443 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2444 return 1;
2445 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2446 && si->type == STATIC_IPV6_IFNAME
2447 && strcmp (nexthop->ifname, si->ifname) == 0)
2448 return 1;
2449 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2450 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2451 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2452 && strcmp (nexthop->ifname, si->ifname) == 0)
2453 return 1;
paule8e19462006-01-19 20:16:55 +00002454 return 0;
paul718e3742002-12-13 20:15:29 +00002455}
2456
paula1ac18c2005-06-28 17:17:12 +00002457static void
paul718e3742002-12-13 20:15:29 +00002458static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2459{
2460 struct route_table *table;
2461 struct route_node *rn;
2462 struct rib *rib;
2463 struct nexthop *nexthop;
2464
2465 /* Lookup table. */
2466 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2467 if (! table)
2468 return;
2469
2470 /* Lookup existing route with type and distance. */
2471 rn = route_node_lookup (table, (struct prefix *) p);
2472 if (! rn)
2473 return;
2474
2475 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002476 {
2477 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2478 continue;
2479
2480 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2481 break;
2482 }
2483
paul718e3742002-12-13 20:15:29 +00002484 if (! rib)
2485 {
2486 route_unlock_node (rn);
2487 return;
2488 }
2489
2490 /* Lookup nexthop. */
2491 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2492 if (static_ipv6_nexthop_same (nexthop, si))
2493 break;
2494
2495 /* Can't find nexthop. */
2496 if (! nexthop)
2497 {
2498 route_unlock_node (rn);
2499 return;
2500 }
2501
2502 /* Check nexthop. */
2503 if (rib->nexthop_num == 1)
2504 {
2505 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002506 }
2507 else
2508 {
paul6baeb982003-10-28 03:47:15 +00002509 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2510 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002511 nexthop_delete (rib, nexthop);
2512 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002513 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002514 }
paul718e3742002-12-13 20:15:29 +00002515 /* Unlock node. */
2516 route_unlock_node (rn);
2517}
2518
2519/* Add static route into static route configuration. */
2520int
2521static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002522 const char *ifname, u_char flags, u_char distance,
2523 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002524{
2525 struct route_node *rn;
2526 struct static_ipv6 *si;
2527 struct static_ipv6 *pp;
2528 struct static_ipv6 *cp;
2529 struct route_table *stable;
2530
2531 /* Lookup table. */
2532 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2533 if (! stable)
2534 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002535
2536 if (!gate &&
2537 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2538 return -1;
2539
2540 if (!ifname &&
2541 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2542 return -1;
paul718e3742002-12-13 20:15:29 +00002543
2544 /* Lookup static route prefix. */
2545 rn = route_node_get (stable, p);
2546
2547 /* Do nothing if there is a same static route. */
2548 for (si = rn->info; si; si = si->next)
2549 {
2550 if (distance == si->distance
2551 && type == si->type
2552 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2553 && (! ifname || strcmp (ifname, si->ifname) == 0))
2554 {
2555 route_unlock_node (rn);
2556 return 0;
2557 }
2558 }
2559
2560 /* Make new static route structure. */
2561 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2562 memset (si, 0, sizeof (struct static_ipv6));
2563
2564 si->type = type;
2565 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002566 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002567
2568 switch (type)
2569 {
2570 case STATIC_IPV6_GATEWAY:
2571 si->ipv6 = *gate;
2572 break;
2573 case STATIC_IPV6_IFNAME:
2574 si->ifname = XSTRDUP (0, ifname);
2575 break;
2576 case STATIC_IPV6_GATEWAY_IFNAME:
2577 si->ipv6 = *gate;
2578 si->ifname = XSTRDUP (0, ifname);
2579 break;
2580 }
2581
2582 /* Add new static route information to the tree with sort by
2583 distance value and gateway address. */
2584 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2585 {
2586 if (si->distance < cp->distance)
2587 break;
2588 if (si->distance > cp->distance)
2589 continue;
2590 }
2591
2592 /* Make linked list. */
2593 if (pp)
2594 pp->next = si;
2595 else
2596 rn->info = si;
2597 if (cp)
2598 cp->prev = si;
2599 si->prev = pp;
2600 si->next = cp;
2601
2602 /* Install into rib. */
2603 static_install_ipv6 (p, si);
2604
2605 return 1;
2606}
2607
2608/* Delete static route from static route configuration. */
2609int
2610static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002611 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002612{
2613 struct route_node *rn;
2614 struct static_ipv6 *si;
2615 struct route_table *stable;
2616
2617 /* Lookup table. */
2618 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2619 if (! stable)
2620 return -1;
2621
2622 /* Lookup static route prefix. */
2623 rn = route_node_lookup (stable, p);
2624 if (! rn)
2625 return 0;
2626
2627 /* Find same static route is the tree */
2628 for (si = rn->info; si; si = si->next)
2629 if (distance == si->distance
2630 && type == si->type
2631 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2632 && (! ifname || strcmp (ifname, si->ifname) == 0))
2633 break;
2634
2635 /* Can't find static route. */
2636 if (! si)
2637 {
2638 route_unlock_node (rn);
2639 return 0;
2640 }
2641
2642 /* Install into rib. */
2643 static_uninstall_ipv6 (p, si);
2644
2645 /* Unlink static route from linked list. */
2646 if (si->prev)
2647 si->prev->next = si->next;
2648 else
2649 rn->info = si->next;
2650 if (si->next)
2651 si->next->prev = si->prev;
2652
2653 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002654 if (ifname)
2655 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002656 XFREE (MTYPE_STATIC_IPV6, si);
2657
2658 return 1;
2659}
2660#endif /* HAVE_IPV6 */
2661
2662/* RIB update function. */
2663void
paula1ac18c2005-06-28 17:17:12 +00002664rib_update (void)
paul718e3742002-12-13 20:15:29 +00002665{
2666 struct route_node *rn;
2667 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002668
paul718e3742002-12-13 20:15:29 +00002669 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2670 if (table)
2671 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002672 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002673 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002674
2675 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2676 if (table)
2677 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002678 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002679 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002680}
2681
2682/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002683static void
paul718e3742002-12-13 20:15:29 +00002684rib_if_up (struct interface *ifp)
2685{
2686 rib_update ();
2687}
2688
2689/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002690static void
paul718e3742002-12-13 20:15:29 +00002691rib_if_down (struct interface *ifp)
2692{
2693 rib_update ();
2694}
2695
2696/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002697static void
paul718e3742002-12-13 20:15:29 +00002698rib_weed_table (struct route_table *table)
2699{
2700 struct route_node *rn;
2701 struct rib *rib;
2702 struct rib *next;
2703
2704 if (table)
2705 for (rn = route_top (table); rn; rn = route_next (rn))
2706 for (rib = rn->info; rib; rib = next)
2707 {
2708 next = rib->next;
2709
Paul Jakma6d691122006-07-27 21:49:00 +00002710 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2711 continue;
2712
paulb21b19c2003-06-15 01:28:29 +00002713 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002714 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002715 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002716 }
2717}
2718
2719/* Delete all routes from non main table. */
2720void
paula1ac18c2005-06-28 17:17:12 +00002721rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002722{
2723 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2724 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2725}
2726
2727/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002728static void
paul718e3742002-12-13 20:15:29 +00002729rib_sweep_table (struct route_table *table)
2730{
2731 struct route_node *rn;
2732 struct rib *rib;
2733 struct rib *next;
2734 int ret = 0;
2735
2736 if (table)
2737 for (rn = route_top (table); rn; rn = route_next (rn))
2738 for (rib = rn->info; rib; rib = next)
2739 {
2740 next = rib->next;
2741
Paul Jakma6d691122006-07-27 21:49:00 +00002742 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2743 continue;
2744
paul718e3742002-12-13 20:15:29 +00002745 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2746 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2747 {
2748 ret = rib_uninstall_kernel (rn, rib);
2749 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002750 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002751 }
2752 }
2753}
2754
2755/* Sweep all RIB tables. */
2756void
paula1ac18c2005-06-28 17:17:12 +00002757rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002758{
2759 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2760 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2761}
2762
2763/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002764static void
paul718e3742002-12-13 20:15:29 +00002765rib_close_table (struct route_table *table)
2766{
2767 struct route_node *rn;
2768 struct rib *rib;
2769
2770 if (table)
2771 for (rn = route_top (table); rn; rn = route_next (rn))
2772 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002773 {
2774 if (! RIB_SYSTEM_ROUTE (rib)
2775 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2776 rib_uninstall_kernel (rn, rib);
2777 }
paul718e3742002-12-13 20:15:29 +00002778}
2779
2780/* Close all RIB tables. */
2781void
paula1ac18c2005-06-28 17:17:12 +00002782rib_close (void)
paul718e3742002-12-13 20:15:29 +00002783{
2784 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2785 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2786}
2787
2788/* Routing information base initialize. */
2789void
paula1ac18c2005-06-28 17:17:12 +00002790rib_init (void)
paul718e3742002-12-13 20:15:29 +00002791{
paul4d38fdb2005-04-28 17:35:14 +00002792 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002793 /* VRF initialization. */
2794 vrf_init ();
2795}