blob: c6af32904942ec3459899239e8afaa6a17cd585b [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);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000798 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000799 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);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000807 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000808 {
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);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000841 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000842 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;
Denis Ovsienkof304cb42007-10-03 12:27:16 +0000995 char buf[INET6_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)
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001000 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001001
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)
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001121 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001122 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001123 installed = 1;
1124 break;
paul4d38fdb2005-04-28 17:35:14 +00001125 }
1126 if (! installed)
1127 rib_install_kernel (rn, select);
1128 }
Paul Jakma6d691122006-07-27 21:49:00 +00001129 goto end;
paul718e3742002-12-13 20:15:29 +00001130 }
1131
Denis Ovsienkodc958242007-08-13 16:03:06 +00001132 /* At this point we either haven't found the best RIB entry or it is
1133 * different from what we currently intend to flag with SELECTED. In both
1134 * cases, if a RIB block is present in FIB, it should be withdrawn.
1135 */
paul718e3742002-12-13 20:15:29 +00001136 if (fib)
1137 {
Paul Jakma6d691122006-07-27 21:49:00 +00001138 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001139 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1140 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001141 redistribute_delete (&rn->p, fib);
1142 if (! RIB_SYSTEM_ROUTE (fib))
1143 rib_uninstall_kernel (rn, fib);
1144 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1145
1146 /* Set real nexthop. */
1147 nexthop_active_update (rn, fib, 1);
1148 }
1149
Denis Ovsienkodc958242007-08-13 16:03:06 +00001150 /* Regardless of some RIB entry being SELECTED or not before, now we can
1151 * tell, that if a new winner exists, FIB is still not updated with this
1152 * data, but ready to be.
1153 */
paul718e3742002-12-13 20:15:29 +00001154 if (select)
1155 {
Paul Jakma6d691122006-07-27 21:49:00 +00001156 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001157 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1158 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001159 /* Set real nexthop. */
1160 nexthop_active_update (rn, select, 1);
1161
1162 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001163 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001164 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1165 redistribute_add (&rn->p, select);
1166 }
paul4d38fdb2005-04-28 17:35:14 +00001167
Paul Jakma6d691122006-07-27 21:49:00 +00001168 /* FIB route was removed, should be deleted */
1169 if (del)
1170 {
1171 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001172 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1173 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001174 rib_unlink (rn, del);
1175 }
paul4d38fdb2005-04-28 17:35:14 +00001176
Paul Jakma6d691122006-07-27 21:49:00 +00001177end:
1178 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001179 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001180 if (rn->info)
1181 UNSET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1182 route_unlock_node (rn); /* rib queue lock */
1183 return WQ_SUCCESS;
paul4d38fdb2005-04-28 17:35:14 +00001184}
1185
Paul Jakma6d691122006-07-27 21:49:00 +00001186/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001187static void
Paul Jakma6d691122006-07-27 21:49:00 +00001188rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001189{
Paul Jakma93bdada2007-08-06 19:25:11 +00001190 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001191 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001192
Paul Jakma93bdada2007-08-06 19:25:11 +00001193 if (IS_ZEBRA_DEBUG_RIB_Q)
1194 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1195
Paul Jakma6d691122006-07-27 21:49:00 +00001196 /* Pointless to queue a route_node with no RIB entries to add or remove */
1197 if (!rn->info)
1198 {
1199 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1200 __func__, rn, rn->lock);
1201 zlog_backtrace(LOG_DEBUG);
1202 return;
1203 }
paul4d38fdb2005-04-28 17:35:14 +00001204
Paul Jakma6d691122006-07-27 21:49:00 +00001205 /* Route-table node already queued, so nothing to do */
1206 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED))
1207 {
1208 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001209 zlog_debug ("%s: %s/%d: rn %p already queued", __func__, buf,
1210 rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001211 return;
1212 }
paul4d38fdb2005-04-28 17:35:14 +00001213
Paul Jakma6d691122006-07-27 21:49:00 +00001214 route_lock_node (rn); /* rib queue lock */
1215
1216 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001217 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001218
1219 assert (zebra);
1220
paul4d38fdb2005-04-28 17:35:14 +00001221 if (zebra->ribq == NULL)
1222 {
Paul Jakma6d691122006-07-27 21:49:00 +00001223 zlog_err ("%s: work_queue does not exist!", __func__);
1224 route_unlock_node (rn);
paul4d38fdb2005-04-28 17:35:14 +00001225 return;
1226 }
1227
Paul Jakma6d691122006-07-27 21:49:00 +00001228 work_queue_add (zebra->ribq, rn);
1229
1230 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1231
1232 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001233 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
paul4d38fdb2005-04-28 17:35:14 +00001234
1235 return;
1236}
1237
paul4d38fdb2005-04-28 17:35:14 +00001238/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001239static void
paul4d38fdb2005-04-28 17:35:14 +00001240rib_queue_init (struct zebra_t *zebra)
1241{
1242 assert (zebra);
1243
1244 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001245 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001246 {
Paul Jakma6d691122006-07-27 21:49:00 +00001247 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001248 return;
1249 }
1250
1251 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001252 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001253 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001254 /* XXX: TODO: These should be runtime configurable via vty */
1255 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001256 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001257
1258 return;
paul718e3742002-12-13 20:15:29 +00001259}
1260
Paul Jakma6d691122006-07-27 21:49:00 +00001261/* RIB updates are processed via a queue of pointers to route_nodes.
1262 *
1263 * The queue length is bounded by the maximal size of the routing table,
1264 * as a route_node will not be requeued, if already queued.
1265 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001266 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1267 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1268 * and then submit route_node to queue for best-path selection later.
1269 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001270 *
1271 * Deleted RIBs are reaped during best-path selection.
1272 *
1273 * rib_addnode
1274 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001275 * |-------->| | best RIB, if required
1276 * | |
1277 * static_install->|->rib_addqueue...... -> rib_process
1278 * | |
1279 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001280 * |-> set RIB_ENTRY_REMOVE |
1281 * rib_delnode (RIB freed)
1282 *
1283 *
1284 * Queueing state for a route_node is kept in the head RIB entry, this
1285 * state must be preserved as and when the head RIB entry of a
1286 * route_node is changed by rib_unlink / rib_link. A small complication,
1287 * but saves having to allocate a dedicated object for this.
1288 *
1289 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1290 *
1291 * - route_nodes: refcounted by:
1292 * - RIBs attached to route_node:
1293 * - managed by: rib_link/unlink
1294 * - route_node processing queue
1295 * - managed by: rib_addqueue, rib_process.
1296 *
1297 */
1298
paul718e3742002-12-13 20:15:29 +00001299/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001300static void
Paul Jakma6d691122006-07-27 21:49:00 +00001301rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001302{
1303 struct rib *head;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001304 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001305
1306 assert (rib && rn);
1307
Paul Jakma6d691122006-07-27 21:49:00 +00001308 route_lock_node (rn); /* rn route table reference */
1309
1310 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001311 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001312 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001313 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1314 buf, rn->p.prefixlen, rn, rib);
1315 }
Paul Jakma6d691122006-07-27 21:49:00 +00001316
paul718e3742002-12-13 20:15:29 +00001317 head = rn->info;
1318 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001319 {
1320 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001321 zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
1322 buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001323 head->prev = rib;
1324 /* Transfer the rn status flags to the new head RIB */
1325 rib->rn_status = head->rn_status;
1326 }
paul718e3742002-12-13 20:15:29 +00001327 rib->next = head;
1328 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001329 rib_queue_add (&zebrad, rn);
1330}
1331
1332static void
1333rib_addnode (struct route_node *rn, struct rib *rib)
1334{
1335 /* RIB node has been un-removed before route-node is processed.
1336 * route_node must hence already be on the queue for processing..
1337 */
1338 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1339 {
1340 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001341 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001342 char buf[INET6_ADDRSTRLEN];
1343 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001344 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1345 __func__, buf, rn->p.prefixlen, rn, rib);
1346 }
Paul Jakma6d691122006-07-27 21:49:00 +00001347 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1348 return;
1349 }
1350 rib_link (rn, rib);
1351}
1352
1353static void
1354rib_unlink (struct route_node *rn, struct rib *rib)
1355{
1356 struct nexthop *nexthop, *next;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001357 char buf[INET6_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001358
1359 assert (rn && rib);
1360
1361 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001362 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001363 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001364 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1365 __func__, buf, rn->p.prefixlen, rn, rib);
1366 }
Paul Jakma6d691122006-07-27 21:49:00 +00001367
1368 if (rib->next)
1369 rib->next->prev = rib->prev;
1370
1371 if (rib->prev)
1372 rib->prev->next = rib->next;
1373 else
1374 {
1375 rn->info = rib->next;
1376
1377 if (rn->info)
1378 {
1379 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001380 zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
1381 __func__, buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001382 rib->next->rn_status = rib->rn_status;
1383 }
1384 }
1385
1386 /* free RIB and nexthops */
1387 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1388 {
1389 next = nexthop->next;
1390 nexthop_free (nexthop);
1391 }
1392 XFREE (MTYPE_RIB, rib);
1393
1394 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001395}
1396
paula1ac18c2005-06-28 17:17:12 +00001397static void
paul718e3742002-12-13 20:15:29 +00001398rib_delnode (struct route_node *rn, struct rib *rib)
1399{
Paul Jakma6d691122006-07-27 21:49:00 +00001400 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001401 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001402 char buf[INET6_ADDRSTRLEN];
1403 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001404 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1405 buf, rn->p.prefixlen, rn, rib);
1406 }
Paul Jakma6d691122006-07-27 21:49:00 +00001407 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1408 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001409}
1410
1411int
1412rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001413 struct in_addr *gate, struct in_addr *src,
1414 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001415 u_int32_t metric, u_char distance)
1416{
1417 struct rib *rib;
1418 struct rib *same = NULL;
1419 struct route_table *table;
1420 struct route_node *rn;
1421 struct nexthop *nexthop;
1422
1423 /* Lookup table. */
1424 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1425 if (! table)
1426 return 0;
1427
1428 /* Make it sure prefixlen is applied to the prefix. */
1429 apply_mask_ipv4 (p);
1430
1431 /* Set default distance by route type. */
1432 if (distance == 0)
1433 {
1434 distance = route_info[type].distance;
1435
1436 /* iBGP distance is 200. */
1437 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1438 distance = 200;
1439 }
1440
1441 /* Lookup route node.*/
1442 rn = route_node_get (table, (struct prefix *) p);
1443
1444 /* If same type of route are installed, treat it as a implicit
1445 withdraw. */
1446 for (rib = rn->info; rib; rib = rib->next)
1447 {
Paul Jakma6d691122006-07-27 21:49:00 +00001448 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1449 continue;
1450
hassoebf1ead2005-09-21 14:58:20 +00001451 if (rib->type != type)
1452 continue;
1453 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001454 {
1455 same = rib;
1456 break;
1457 }
hassoebf1ead2005-09-21 14:58:20 +00001458 /* Duplicate connected route comes in. */
1459 else if ((nexthop = rib->nexthop) &&
1460 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001461 nexthop->ifindex == ifindex &&
1462 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001463 {
1464 rib->refcnt++;
1465 return 0 ;
1466 }
paul718e3742002-12-13 20:15:29 +00001467 }
1468
1469 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001470 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001471 rib->type = type;
1472 rib->distance = distance;
1473 rib->flags = flags;
1474 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001475 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001476 rib->nexthop_num = 0;
1477 rib->uptime = time (NULL);
1478
1479 /* Nexthop settings. */
1480 if (gate)
1481 {
1482 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001483 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001484 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001485 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001486 }
1487 else
1488 nexthop_ifindex_add (rib, ifindex);
1489
1490 /* If this route is kernel route, set FIB flag to the route. */
1491 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1492 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1493 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1494
1495 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001496 if (IS_ZEBRA_DEBUG_RIB)
1497 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001498 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001499
paul718e3742002-12-13 20:15:29 +00001500 /* Free implicit route.*/
1501 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001502 {
1503 if (IS_ZEBRA_DEBUG_RIB)
1504 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001505 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001506 }
paul4d38fdb2005-04-28 17:35:14 +00001507
1508 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001509 return 0;
1510}
1511
Denis Ovsienkodc958242007-08-13 16:03:06 +00001512/* This function dumps the contents of a given RIB entry into
1513 * standard debug log. Calling function name and IP prefix in
1514 * question are passed as 1st and 2nd arguments.
1515 */
1516
1517void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1518{
1519 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1520 struct nexthop *nexthop;
1521
1522 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1523 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1524 zlog_debug
1525 (
1526 "%s: refcnt == %lu, uptime == %u, type == %u, table == %d",
1527 func,
1528 rib->refcnt,
1529 rib->uptime,
1530 rib->type,
1531 rib->table
1532 );
1533 zlog_debug
1534 (
1535 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1536 func,
1537 rib->metric,
1538 rib->distance,
1539 rib->flags,
1540 rib->status
1541 );
1542 zlog_debug
1543 (
1544 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1545 func,
1546 rib->nexthop_num,
1547 rib->nexthop_active_num,
1548 rib->nexthop_fib_num
1549 );
1550 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1551 {
1552 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1553 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1554 zlog_debug
1555 (
1556 "%s: NH %s (%s) with flags %s%s%s",
1557 func,
1558 straddr1,
1559 straddr2,
1560 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1561 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1562 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1563 );
1564 }
1565 zlog_debug ("%s: dump complete", func);
1566}
1567
1568/* This is an exported helper to rtm_read() to dump the strange
1569 * RIB entry found by rib_lookup_ipv4_route()
1570 */
1571
1572void rib_lookup_and_dump (struct prefix_ipv4 * p)
1573{
1574 struct route_table *table;
1575 struct route_node *rn;
1576 struct rib *rib;
1577 char prefix_buf[INET_ADDRSTRLEN];
1578
1579 /* Lookup table. */
1580 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1581 if (! table)
1582 {
1583 zlog_err ("%s: vrf_table() returned NULL", __func__);
1584 return;
1585 }
1586
1587 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1588 /* Scan the RIB table for exactly matching RIB entry. */
1589 rn = route_node_lookup (table, (struct prefix *) p);
1590
1591 /* No route for this prefix. */
1592 if (! rn)
1593 {
1594 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1595 return;
1596 }
1597
1598 /* Unlock node. */
1599 route_unlock_node (rn);
1600
1601 /* let's go */
1602 for (rib = rn->info; rib; rib = rib->next)
1603 {
1604 zlog_debug
1605 (
1606 "%s: rn %p, rib %p: %s, %s",
1607 __func__,
1608 rn,
1609 rib,
1610 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1611 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1612 );
1613 rib_dump (__func__, p, rib);
1614 }
1615}
1616
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001617/* Check if requested address assignment will fail due to another
1618 * route being installed by zebra in FIB already. Take necessary
1619 * actions, if needed: remove such a route from FIB and deSELECT
1620 * corresponding RIB entry. Then put affected RN into RIBQ head.
1621 */
1622void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1623{
1624 struct route_table *table;
1625 struct route_node *rn;
1626 struct rib *rib;
1627 unsigned changed = 0;
1628
1629 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
1630 {
1631 zlog_err ("%s: vrf_table() returned NULL", __func__);
1632 return;
1633 }
1634
1635 /* No matches would be the simplest case. */
1636 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1637 return;
1638
1639 /* Unlock node. */
1640 route_unlock_node (rn);
1641
1642 /* Check all RIB entries. In case any changes have to be done, requeue
1643 * the RN into RIBQ head. If the routing message about the new connected
1644 * route (generated by the IP address we are going to assign very soon)
1645 * comes before the RIBQ is processed, the new RIB entry will join
1646 * RIBQ record already on head. This is necessary for proper revalidation
1647 * of the rest of the RIB.
1648 */
1649 for (rib = rn->info; rib; rib = rib->next)
1650 {
1651 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1652 ! RIB_SYSTEM_ROUTE (rib))
1653 {
1654 changed = 1;
1655 if (IS_ZEBRA_DEBUG_RIB)
1656 {
1657 char buf[INET_ADDRSTRLEN];
1658 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
1659 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
1660 rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
1661 }
1662 rib_uninstall (rn, rib);
1663 }
1664 }
1665 if (changed)
1666 {
1667 work_queue_aim_head (zebrad.ribq, 1);
1668 rib_queue_add (&zebrad, rn);
1669 work_queue_aim_head (zebrad.ribq, 0);
1670 }
1671}
1672
paul718e3742002-12-13 20:15:29 +00001673int
1674rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1675{
1676 struct route_table *table;
1677 struct route_node *rn;
1678 struct rib *same;
1679 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001680
paul718e3742002-12-13 20:15:29 +00001681 /* Lookup table. */
1682 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1683 if (! table)
1684 return 0;
paul718e3742002-12-13 20:15:29 +00001685 /* Make it sure prefixlen is applied to the prefix. */
1686 apply_mask_ipv4 (p);
1687
1688 /* Set default distance by route type. */
1689 if (rib->distance == 0)
1690 {
1691 rib->distance = route_info[rib->type].distance;
1692
1693 /* iBGP distance is 200. */
1694 if (rib->type == ZEBRA_ROUTE_BGP
1695 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1696 rib->distance = 200;
1697 }
1698
1699 /* Lookup route node.*/
1700 rn = route_node_get (table, (struct prefix *) p);
1701
1702 /* If same type of route are installed, treat it as a implicit
1703 withdraw. */
1704 for (same = rn->info; same; same = same->next)
1705 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001706 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001707 continue;
1708
paul718e3742002-12-13 20:15:29 +00001709 if (same->type == rib->type && same->table == rib->table
1710 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001711 break;
paul718e3742002-12-13 20:15:29 +00001712 }
paul4d38fdb2005-04-28 17:35:14 +00001713
paul718e3742002-12-13 20:15:29 +00001714 /* If this route is kernel route, set FIB flag to the route. */
1715 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1716 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1717 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1718
1719 /* Link new rib to node.*/
1720 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001721 if (IS_ZEBRA_DEBUG_RIB)
1722 {
1723 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1724 __func__, rn, rib);
1725 rib_dump (__func__, p, rib);
1726 }
paul718e3742002-12-13 20:15:29 +00001727
paul718e3742002-12-13 20:15:29 +00001728 /* Free implicit route.*/
1729 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001730 {
1731 if (IS_ZEBRA_DEBUG_RIB)
1732 {
1733 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1734 __func__, rn, same);
1735 rib_dump (__func__, p, same);
1736 }
paul4d38fdb2005-04-28 17:35:14 +00001737 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001738 }
paul4d38fdb2005-04-28 17:35:14 +00001739
1740 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001741 return 0;
1742}
1743
hassoebf1ead2005-09-21 14:58:20 +00001744/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001745int
1746rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1747 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1748{
1749 struct route_table *table;
1750 struct route_node *rn;
1751 struct rib *rib;
1752 struct rib *fib = NULL;
1753 struct rib *same = NULL;
1754 struct nexthop *nexthop;
1755 char buf1[BUFSIZ];
1756 char buf2[BUFSIZ];
1757
1758 /* Lookup table. */
1759 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1760 if (! table)
1761 return 0;
1762
1763 /* Apply mask. */
1764 apply_mask_ipv4 (p);
1765
paul5ec90d22003-06-19 01:41:37 +00001766 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001767 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001768 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1769 p->prefixlen,
1770 inet_ntoa (*gate),
1771 ifindex);
1772
paul718e3742002-12-13 20:15:29 +00001773 /* Lookup route node. */
1774 rn = route_node_lookup (table, (struct prefix *) p);
1775 if (! rn)
1776 {
1777 if (IS_ZEBRA_DEBUG_KERNEL)
1778 {
1779 if (gate)
ajsb6178002004-12-07 21:12:56 +00001780 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001781 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1782 p->prefixlen,
1783 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1784 ifindex);
1785 else
ajsb6178002004-12-07 21:12:56 +00001786 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001787 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1788 p->prefixlen,
1789 ifindex);
1790 }
1791 return ZEBRA_ERR_RTNOEXIST;
1792 }
1793
1794 /* Lookup same type route. */
1795 for (rib = rn->info; rib; rib = rib->next)
1796 {
Paul Jakma6d691122006-07-27 21:49:00 +00001797 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1798 continue;
1799
paul718e3742002-12-13 20:15:29 +00001800 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1801 fib = rib;
1802
hassoebf1ead2005-09-21 14:58:20 +00001803 if (rib->type != type)
1804 continue;
1805 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1806 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001807 {
hassoebf1ead2005-09-21 14:58:20 +00001808 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001809 {
hassoebf1ead2005-09-21 14:58:20 +00001810 rib->refcnt--;
1811 route_unlock_node (rn);
1812 route_unlock_node (rn);
1813 return 0;
paul718e3742002-12-13 20:15:29 +00001814 }
hassoebf1ead2005-09-21 14:58:20 +00001815 same = rib;
1816 break;
paul718e3742002-12-13 20:15:29 +00001817 }
hassoebf1ead2005-09-21 14:58:20 +00001818 /* Make sure that the route found has the same gateway. */
1819 else if (gate == NULL ||
1820 ((nexthop = rib->nexthop) &&
1821 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1822 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001823 {
hassoebf1ead2005-09-21 14:58:20 +00001824 same = rib;
1825 break;
paul718e3742002-12-13 20:15:29 +00001826 }
1827 }
1828
1829 /* If same type of route can't be found and this message is from
1830 kernel. */
1831 if (! same)
1832 {
1833 if (fib && type == ZEBRA_ROUTE_KERNEL)
1834 {
1835 /* Unset flags. */
1836 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1837 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1838
1839 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1840 }
1841 else
1842 {
1843 if (IS_ZEBRA_DEBUG_KERNEL)
1844 {
1845 if (gate)
ajsb6178002004-12-07 21:12:56 +00001846 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001847 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1848 p->prefixlen,
1849 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1850 ifindex,
1851 type);
1852 else
ajsb6178002004-12-07 21:12:56 +00001853 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001854 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1855 p->prefixlen,
1856 ifindex,
1857 type);
1858 }
1859 route_unlock_node (rn);
1860 return ZEBRA_ERR_RTNOEXIST;
1861 }
1862 }
paul4d38fdb2005-04-28 17:35:14 +00001863
paul718e3742002-12-13 20:15:29 +00001864 if (same)
1865 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001866
paul718e3742002-12-13 20:15:29 +00001867 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001868 return 0;
1869}
1870
1871/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001872static void
paul718e3742002-12-13 20:15:29 +00001873static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1874{
1875 struct rib *rib;
1876 struct route_node *rn;
1877 struct route_table *table;
1878
1879 /* Lookup table. */
1880 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1881 if (! table)
1882 return;
1883
1884 /* Lookup existing route */
1885 rn = route_node_get (table, p);
1886 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001887 {
1888 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1889 continue;
1890
1891 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1892 break;
1893 }
paul718e3742002-12-13 20:15:29 +00001894
1895 if (rib)
1896 {
1897 /* Same distance static route is there. Update it with new
1898 nexthop. */
paul718e3742002-12-13 20:15:29 +00001899 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001900 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001901 {
1902 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001903 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001904 break;
1905 case STATIC_IPV4_IFNAME:
1906 nexthop_ifname_add (rib, si->gate.ifname);
1907 break;
1908 case STATIC_IPV4_BLACKHOLE:
1909 nexthop_blackhole_add (rib);
1910 break;
paul4d38fdb2005-04-28 17:35:14 +00001911 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00001912 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001913 }
1914 else
1915 {
1916 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001917 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1918
paul718e3742002-12-13 20:15:29 +00001919 rib->type = ZEBRA_ROUTE_STATIC;
1920 rib->distance = si->distance;
1921 rib->metric = 0;
1922 rib->nexthop_num = 0;
1923
1924 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001925 {
1926 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001927 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001928 break;
1929 case STATIC_IPV4_IFNAME:
1930 nexthop_ifname_add (rib, si->gate.ifname);
1931 break;
1932 case STATIC_IPV4_BLACKHOLE:
1933 nexthop_blackhole_add (rib);
1934 break;
1935 }
paul718e3742002-12-13 20:15:29 +00001936
hasso81dfcaa2003-05-25 19:21:25 +00001937 /* Save the flags of this static routes (reject, blackhole) */
1938 rib->flags = si->flags;
1939
paul718e3742002-12-13 20:15:29 +00001940 /* Link this rib to the tree. */
1941 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001942 }
1943}
1944
paula1ac18c2005-06-28 17:17:12 +00001945static int
paul718e3742002-12-13 20:15:29 +00001946static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1947{
1948 if (nexthop->type == NEXTHOP_TYPE_IPV4
1949 && si->type == STATIC_IPV4_GATEWAY
1950 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1951 return 1;
1952 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1953 && si->type == STATIC_IPV4_IFNAME
1954 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1955 return 1;
paul595db7f2003-05-25 21:35:06 +00001956 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1957 && si->type == STATIC_IPV4_BLACKHOLE)
1958 return 1;
paule8e19462006-01-19 20:16:55 +00001959 return 0;
paul718e3742002-12-13 20:15:29 +00001960}
1961
1962/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001963static void
paul718e3742002-12-13 20:15:29 +00001964static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1965{
1966 struct route_node *rn;
1967 struct rib *rib;
1968 struct nexthop *nexthop;
1969 struct route_table *table;
1970
1971 /* Lookup table. */
1972 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1973 if (! table)
1974 return;
paul4d38fdb2005-04-28 17:35:14 +00001975
paul718e3742002-12-13 20:15:29 +00001976 /* Lookup existing route with type and distance. */
1977 rn = route_node_lookup (table, p);
1978 if (! rn)
1979 return;
1980
1981 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001982 {
1983 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1984 continue;
1985
1986 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1987 break;
1988 }
paul718e3742002-12-13 20:15:29 +00001989
1990 if (! rib)
1991 {
1992 route_unlock_node (rn);
1993 return;
1994 }
1995
1996 /* Lookup nexthop. */
1997 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1998 if (static_ipv4_nexthop_same (nexthop, si))
1999 break;
2000
2001 /* Can't find nexthop. */
2002 if (! nexthop)
2003 {
2004 route_unlock_node (rn);
2005 return;
2006 }
2007
2008 /* Check nexthop. */
2009 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002010 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002011 else
2012 {
paul6baeb982003-10-28 03:47:15 +00002013 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2014 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002015 nexthop_delete (rib, nexthop);
2016 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002017 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002018 }
paul718e3742002-12-13 20:15:29 +00002019 /* Unlock node. */
2020 route_unlock_node (rn);
2021}
2022
2023/* Add static route into static route configuration. */
2024int
hasso39db97e2004-10-12 20:50:58 +00002025static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00002026 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002027{
2028 u_char type = 0;
2029 struct route_node *rn;
2030 struct static_ipv4 *si;
2031 struct static_ipv4 *pp;
2032 struct static_ipv4 *cp;
2033 struct static_ipv4 *update = NULL;
2034 struct route_table *stable;
2035
2036 /* Lookup table. */
2037 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2038 if (! stable)
2039 return -1;
2040
2041 /* Lookup static route prefix. */
2042 rn = route_node_get (stable, p);
2043
2044 /* Make flags. */
2045 if (gate)
2046 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002047 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002048 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002049 else
2050 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002051
2052 /* Do nothing if there is a same static route. */
2053 for (si = rn->info; si; si = si->next)
2054 {
2055 if (type == si->type
2056 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2057 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2058 {
2059 if (distance == si->distance)
2060 {
2061 route_unlock_node (rn);
2062 return 0;
2063 }
2064 else
2065 update = si;
2066 }
2067 }
2068
Paul Jakma3c0755d2006-12-08 00:53:14 +00002069 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002070 if (update)
2071 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2072
2073 /* Make new static route structure. */
2074 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
2075 memset (si, 0, sizeof (struct static_ipv4));
2076
2077 si->type = type;
2078 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002079 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002080
2081 if (gate)
2082 si->gate.ipv4 = *gate;
2083 if (ifname)
2084 si->gate.ifname = XSTRDUP (0, ifname);
2085
2086 /* Add new static route information to the tree with sort by
2087 distance value and gateway address. */
2088 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2089 {
2090 if (si->distance < cp->distance)
2091 break;
2092 if (si->distance > cp->distance)
2093 continue;
2094 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2095 {
2096 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2097 break;
2098 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2099 continue;
2100 }
2101 }
2102
2103 /* Make linked list. */
2104 if (pp)
2105 pp->next = si;
2106 else
2107 rn->info = si;
2108 if (cp)
2109 cp->prev = si;
2110 si->prev = pp;
2111 si->next = cp;
2112
2113 /* Install into rib. */
2114 static_install_ipv4 (p, si);
2115
2116 return 1;
2117}
2118
2119/* Delete static route from static route configuration. */
2120int
hasso39db97e2004-10-12 20:50:58 +00002121static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002122 u_char distance, u_int32_t vrf_id)
2123{
2124 u_char type = 0;
2125 struct route_node *rn;
2126 struct static_ipv4 *si;
2127 struct route_table *stable;
2128
2129 /* Lookup table. */
2130 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2131 if (! stable)
2132 return -1;
2133
2134 /* Lookup static route prefix. */
2135 rn = route_node_lookup (stable, p);
2136 if (! rn)
2137 return 0;
2138
2139 /* Make flags. */
2140 if (gate)
2141 type = STATIC_IPV4_GATEWAY;
2142 else if (ifname)
2143 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002144 else
2145 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002146
2147 /* Find same static route is the tree */
2148 for (si = rn->info; si; si = si->next)
2149 if (type == si->type
2150 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2151 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2152 break;
2153
2154 /* Can't find static route. */
2155 if (! si)
2156 {
2157 route_unlock_node (rn);
2158 return 0;
2159 }
2160
2161 /* Install into rib. */
2162 static_uninstall_ipv4 (p, si);
2163
2164 /* Unlink static route from linked list. */
2165 if (si->prev)
2166 si->prev->next = si->next;
2167 else
2168 rn->info = si->next;
2169 if (si->next)
2170 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002171 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002172
2173 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002174 if (ifname)
2175 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002176 XFREE (MTYPE_STATIC_IPV4, si);
2177
paul143a3852003-09-29 20:06:13 +00002178 route_unlock_node (rn);
2179
paul718e3742002-12-13 20:15:29 +00002180 return 1;
2181}
2182
2183
2184#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002185static int
paul718e3742002-12-13 20:15:29 +00002186rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2187 struct in6_addr *gate, unsigned int ifindex, int table)
2188{
hasso726f9b22003-05-25 21:04:54 +00002189 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2190#if defined (MUSICA) || defined (LINUX)
2191 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2192 if (p->prefixlen == 96)
2193 return 0;
2194#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002195 return 1;
hasso726f9b22003-05-25 21:04:54 +00002196 }
paul718e3742002-12-13 20:15:29 +00002197 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2198 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2199 {
2200 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2201 return 1;
2202 }
2203 return 0;
2204}
2205
2206int
2207rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002208 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
2209 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00002210{
2211 struct rib *rib;
2212 struct rib *same = NULL;
2213 struct route_table *table;
2214 struct route_node *rn;
2215 struct nexthop *nexthop;
2216
paul718e3742002-12-13 20:15:29 +00002217 /* Lookup table. */
2218 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2219 if (! table)
2220 return 0;
2221
2222 /* Make sure mask is applied. */
2223 apply_mask_ipv6 (p);
2224
2225 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002226 if (!distance)
2227 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002228
2229 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2230 distance = 200;
2231
2232 /* Filter bogus route. */
2233 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2234 return 0;
2235
2236 /* Lookup route node.*/
2237 rn = route_node_get (table, (struct prefix *) p);
2238
2239 /* If same type of route are installed, treat it as a implicit
2240 withdraw. */
2241 for (rib = rn->info; rib; rib = rib->next)
2242 {
Paul Jakma6d691122006-07-27 21:49:00 +00002243 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2244 continue;
2245
hassoebf1ead2005-09-21 14:58:20 +00002246 if (rib->type != type)
2247 continue;
2248 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002249 {
2250 same = rib;
paul718e3742002-12-13 20:15:29 +00002251 break;
2252 }
hassoebf1ead2005-09-21 14:58:20 +00002253 else if ((nexthop = rib->nexthop) &&
2254 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2255 nexthop->ifindex == ifindex)
2256 {
2257 rib->refcnt++;
2258 return 0;
2259 }
paul718e3742002-12-13 20:15:29 +00002260 }
2261
2262 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002263 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2264
paul718e3742002-12-13 20:15:29 +00002265 rib->type = type;
2266 rib->distance = distance;
2267 rib->flags = flags;
2268 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002269 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002270 rib->nexthop_num = 0;
2271 rib->uptime = time (NULL);
2272
2273 /* Nexthop settings. */
2274 if (gate)
2275 {
2276 if (ifindex)
2277 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2278 else
2279 nexthop_ipv6_add (rib, gate);
2280 }
2281 else
2282 nexthop_ifindex_add (rib, ifindex);
2283
2284 /* If this route is kernel route, set FIB flag to the route. */
2285 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2286 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2287 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2288
2289 /* Link new rib to node.*/
2290 rib_addnode (rn, rib);
2291
paul718e3742002-12-13 20:15:29 +00002292 /* Free implicit route.*/
2293 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002294 rib_delnode (rn, same);
2295
2296 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002297 return 0;
2298}
2299
hassoebf1ead2005-09-21 14:58:20 +00002300/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002301int
2302rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2303 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
2304{
2305 struct route_table *table;
2306 struct route_node *rn;
2307 struct rib *rib;
2308 struct rib *fib = NULL;
2309 struct rib *same = NULL;
2310 struct nexthop *nexthop;
2311 char buf1[BUFSIZ];
2312 char buf2[BUFSIZ];
2313
2314 /* Apply mask. */
2315 apply_mask_ipv6 (p);
2316
2317 /* Lookup table. */
2318 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2319 if (! table)
2320 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002321
paul718e3742002-12-13 20:15:29 +00002322 /* Lookup route node. */
2323 rn = route_node_lookup (table, (struct prefix *) p);
2324 if (! rn)
2325 {
2326 if (IS_ZEBRA_DEBUG_KERNEL)
2327 {
2328 if (gate)
ajsb6178002004-12-07 21:12:56 +00002329 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002330 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2331 p->prefixlen,
2332 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2333 ifindex);
2334 else
ajsb6178002004-12-07 21:12:56 +00002335 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002336 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2337 p->prefixlen,
2338 ifindex);
2339 }
2340 return ZEBRA_ERR_RTNOEXIST;
2341 }
2342
2343 /* Lookup same type route. */
2344 for (rib = rn->info; rib; rib = rib->next)
2345 {
Paul Jakma6d691122006-07-27 21:49:00 +00002346 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2347 continue;
2348
paul718e3742002-12-13 20:15:29 +00002349 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2350 fib = rib;
2351
hassoebf1ead2005-09-21 14:58:20 +00002352 if (rib->type != type)
2353 continue;
2354 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2355 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002356 {
hassoebf1ead2005-09-21 14:58:20 +00002357 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002358 {
hassoebf1ead2005-09-21 14:58:20 +00002359 rib->refcnt--;
2360 route_unlock_node (rn);
2361 route_unlock_node (rn);
2362 return 0;
paul718e3742002-12-13 20:15:29 +00002363 }
hassoebf1ead2005-09-21 14:58:20 +00002364 same = rib;
2365 break;
paul718e3742002-12-13 20:15:29 +00002366 }
hassoebf1ead2005-09-21 14:58:20 +00002367 /* Make sure that the route found has the same gateway. */
2368 else if (gate == NULL ||
2369 ((nexthop = rib->nexthop) &&
2370 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2371 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002372 {
hassoebf1ead2005-09-21 14:58:20 +00002373 same = rib;
2374 break;
paul718e3742002-12-13 20:15:29 +00002375 }
2376 }
2377
2378 /* If same type of route can't be found and this message is from
2379 kernel. */
2380 if (! same)
2381 {
2382 if (fib && type == ZEBRA_ROUTE_KERNEL)
2383 {
2384 /* Unset flags. */
2385 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2386 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2387
2388 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2389 }
2390 else
2391 {
2392 if (IS_ZEBRA_DEBUG_KERNEL)
2393 {
2394 if (gate)
ajsb6178002004-12-07 21:12:56 +00002395 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002396 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2397 p->prefixlen,
2398 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2399 ifindex,
2400 type);
2401 else
ajsb6178002004-12-07 21:12:56 +00002402 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002403 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2404 p->prefixlen,
2405 ifindex,
2406 type);
2407 }
2408 route_unlock_node (rn);
2409 return ZEBRA_ERR_RTNOEXIST;
2410 }
2411 }
2412
2413 if (same)
2414 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002415
paul718e3742002-12-13 20:15:29 +00002416 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002417 return 0;
2418}
2419
2420/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002421static void
paul718e3742002-12-13 20:15:29 +00002422static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2423{
2424 struct rib *rib;
2425 struct route_table *table;
2426 struct route_node *rn;
2427
2428 /* Lookup table. */
2429 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2430 if (! table)
2431 return;
2432
2433 /* Lookup existing route */
2434 rn = route_node_get (table, p);
2435 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002436 {
2437 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2438 continue;
2439
2440 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2441 break;
2442 }
paul718e3742002-12-13 20:15:29 +00002443
2444 if (rib)
2445 {
2446 /* Same distance static route is there. Update it with new
2447 nexthop. */
paul718e3742002-12-13 20:15:29 +00002448 route_unlock_node (rn);
2449
2450 switch (si->type)
2451 {
2452 case STATIC_IPV6_GATEWAY:
2453 nexthop_ipv6_add (rib, &si->ipv6);
2454 break;
2455 case STATIC_IPV6_IFNAME:
2456 nexthop_ifname_add (rib, si->ifname);
2457 break;
2458 case STATIC_IPV6_GATEWAY_IFNAME:
2459 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2460 break;
2461 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002462 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002463 }
2464 else
2465 {
2466 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002467 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2468
paul718e3742002-12-13 20:15:29 +00002469 rib->type = ZEBRA_ROUTE_STATIC;
2470 rib->distance = si->distance;
2471 rib->metric = 0;
2472 rib->nexthop_num = 0;
2473
2474 switch (si->type)
2475 {
2476 case STATIC_IPV6_GATEWAY:
2477 nexthop_ipv6_add (rib, &si->ipv6);
2478 break;
2479 case STATIC_IPV6_IFNAME:
2480 nexthop_ifname_add (rib, si->ifname);
2481 break;
2482 case STATIC_IPV6_GATEWAY_IFNAME:
2483 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2484 break;
2485 }
2486
hasso81dfcaa2003-05-25 19:21:25 +00002487 /* Save the flags of this static routes (reject, blackhole) */
2488 rib->flags = si->flags;
2489
paul718e3742002-12-13 20:15:29 +00002490 /* Link this rib to the tree. */
2491 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002492 }
2493}
2494
paula1ac18c2005-06-28 17:17:12 +00002495static int
paul718e3742002-12-13 20:15:29 +00002496static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2497{
2498 if (nexthop->type == NEXTHOP_TYPE_IPV6
2499 && si->type == STATIC_IPV6_GATEWAY
2500 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2501 return 1;
2502 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2503 && si->type == STATIC_IPV6_IFNAME
2504 && strcmp (nexthop->ifname, si->ifname) == 0)
2505 return 1;
2506 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2507 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2508 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2509 && strcmp (nexthop->ifname, si->ifname) == 0)
2510 return 1;
paule8e19462006-01-19 20:16:55 +00002511 return 0;
paul718e3742002-12-13 20:15:29 +00002512}
2513
paula1ac18c2005-06-28 17:17:12 +00002514static void
paul718e3742002-12-13 20:15:29 +00002515static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2516{
2517 struct route_table *table;
2518 struct route_node *rn;
2519 struct rib *rib;
2520 struct nexthop *nexthop;
2521
2522 /* Lookup table. */
2523 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2524 if (! table)
2525 return;
2526
2527 /* Lookup existing route with type and distance. */
2528 rn = route_node_lookup (table, (struct prefix *) p);
2529 if (! rn)
2530 return;
2531
2532 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002533 {
2534 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2535 continue;
2536
2537 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2538 break;
2539 }
2540
paul718e3742002-12-13 20:15:29 +00002541 if (! rib)
2542 {
2543 route_unlock_node (rn);
2544 return;
2545 }
2546
2547 /* Lookup nexthop. */
2548 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2549 if (static_ipv6_nexthop_same (nexthop, si))
2550 break;
2551
2552 /* Can't find nexthop. */
2553 if (! nexthop)
2554 {
2555 route_unlock_node (rn);
2556 return;
2557 }
2558
2559 /* Check nexthop. */
2560 if (rib->nexthop_num == 1)
2561 {
2562 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002563 }
2564 else
2565 {
paul6baeb982003-10-28 03:47:15 +00002566 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2567 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002568 nexthop_delete (rib, nexthop);
2569 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002570 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002571 }
paul718e3742002-12-13 20:15:29 +00002572 /* Unlock node. */
2573 route_unlock_node (rn);
2574}
2575
2576/* Add static route into static route configuration. */
2577int
2578static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002579 const char *ifname, u_char flags, u_char distance,
2580 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002581{
2582 struct route_node *rn;
2583 struct static_ipv6 *si;
2584 struct static_ipv6 *pp;
2585 struct static_ipv6 *cp;
2586 struct route_table *stable;
2587
2588 /* Lookup table. */
2589 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2590 if (! stable)
2591 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002592
2593 if (!gate &&
2594 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2595 return -1;
2596
2597 if (!ifname &&
2598 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2599 return -1;
paul718e3742002-12-13 20:15:29 +00002600
2601 /* Lookup static route prefix. */
2602 rn = route_node_get (stable, p);
2603
2604 /* Do nothing if there is a same static route. */
2605 for (si = rn->info; si; si = si->next)
2606 {
2607 if (distance == si->distance
2608 && type == si->type
2609 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2610 && (! ifname || strcmp (ifname, si->ifname) == 0))
2611 {
2612 route_unlock_node (rn);
2613 return 0;
2614 }
2615 }
2616
2617 /* Make new static route structure. */
2618 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2619 memset (si, 0, sizeof (struct static_ipv6));
2620
2621 si->type = type;
2622 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002623 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002624
2625 switch (type)
2626 {
2627 case STATIC_IPV6_GATEWAY:
2628 si->ipv6 = *gate;
2629 break;
2630 case STATIC_IPV6_IFNAME:
2631 si->ifname = XSTRDUP (0, ifname);
2632 break;
2633 case STATIC_IPV6_GATEWAY_IFNAME:
2634 si->ipv6 = *gate;
2635 si->ifname = XSTRDUP (0, ifname);
2636 break;
2637 }
2638
2639 /* Add new static route information to the tree with sort by
2640 distance value and gateway address. */
2641 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2642 {
2643 if (si->distance < cp->distance)
2644 break;
2645 if (si->distance > cp->distance)
2646 continue;
2647 }
2648
2649 /* Make linked list. */
2650 if (pp)
2651 pp->next = si;
2652 else
2653 rn->info = si;
2654 if (cp)
2655 cp->prev = si;
2656 si->prev = pp;
2657 si->next = cp;
2658
2659 /* Install into rib. */
2660 static_install_ipv6 (p, si);
2661
2662 return 1;
2663}
2664
2665/* Delete static route from static route configuration. */
2666int
2667static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002668 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002669{
2670 struct route_node *rn;
2671 struct static_ipv6 *si;
2672 struct route_table *stable;
2673
2674 /* Lookup table. */
2675 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2676 if (! stable)
2677 return -1;
2678
2679 /* Lookup static route prefix. */
2680 rn = route_node_lookup (stable, p);
2681 if (! rn)
2682 return 0;
2683
2684 /* Find same static route is the tree */
2685 for (si = rn->info; si; si = si->next)
2686 if (distance == si->distance
2687 && type == si->type
2688 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2689 && (! ifname || strcmp (ifname, si->ifname) == 0))
2690 break;
2691
2692 /* Can't find static route. */
2693 if (! si)
2694 {
2695 route_unlock_node (rn);
2696 return 0;
2697 }
2698
2699 /* Install into rib. */
2700 static_uninstall_ipv6 (p, si);
2701
2702 /* Unlink static route from linked list. */
2703 if (si->prev)
2704 si->prev->next = si->next;
2705 else
2706 rn->info = si->next;
2707 if (si->next)
2708 si->next->prev = si->prev;
2709
2710 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002711 if (ifname)
2712 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002713 XFREE (MTYPE_STATIC_IPV6, si);
2714
2715 return 1;
2716}
2717#endif /* HAVE_IPV6 */
2718
2719/* RIB update function. */
2720void
paula1ac18c2005-06-28 17:17:12 +00002721rib_update (void)
paul718e3742002-12-13 20:15:29 +00002722{
2723 struct route_node *rn;
2724 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002725
paul718e3742002-12-13 20:15:29 +00002726 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2727 if (table)
2728 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002729 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002730 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002731
2732 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2733 if (table)
2734 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002735 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002736 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002737}
2738
2739/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002740static void
paul718e3742002-12-13 20:15:29 +00002741rib_if_up (struct interface *ifp)
2742{
2743 rib_update ();
2744}
2745
2746/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002747static void
paul718e3742002-12-13 20:15:29 +00002748rib_if_down (struct interface *ifp)
2749{
2750 rib_update ();
2751}
2752
2753/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002754static void
paul718e3742002-12-13 20:15:29 +00002755rib_weed_table (struct route_table *table)
2756{
2757 struct route_node *rn;
2758 struct rib *rib;
2759 struct rib *next;
2760
2761 if (table)
2762 for (rn = route_top (table); rn; rn = route_next (rn))
2763 for (rib = rn->info; rib; rib = next)
2764 {
2765 next = rib->next;
2766
Paul Jakma6d691122006-07-27 21:49:00 +00002767 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2768 continue;
2769
paulb21b19c2003-06-15 01:28:29 +00002770 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002771 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002772 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002773 }
2774}
2775
2776/* Delete all routes from non main table. */
2777void
paula1ac18c2005-06-28 17:17:12 +00002778rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002779{
2780 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2781 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2782}
2783
2784/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002785static void
paul718e3742002-12-13 20:15:29 +00002786rib_sweep_table (struct route_table *table)
2787{
2788 struct route_node *rn;
2789 struct rib *rib;
2790 struct rib *next;
2791 int ret = 0;
2792
2793 if (table)
2794 for (rn = route_top (table); rn; rn = route_next (rn))
2795 for (rib = rn->info; rib; rib = next)
2796 {
2797 next = rib->next;
2798
Paul Jakma6d691122006-07-27 21:49:00 +00002799 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2800 continue;
2801
paul718e3742002-12-13 20:15:29 +00002802 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2803 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2804 {
2805 ret = rib_uninstall_kernel (rn, rib);
2806 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002807 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002808 }
2809 }
2810}
2811
2812/* Sweep all RIB tables. */
2813void
paula1ac18c2005-06-28 17:17:12 +00002814rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002815{
2816 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2817 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2818}
2819
2820/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002821static void
paul718e3742002-12-13 20:15:29 +00002822rib_close_table (struct route_table *table)
2823{
2824 struct route_node *rn;
2825 struct rib *rib;
2826
2827 if (table)
2828 for (rn = route_top (table); rn; rn = route_next (rn))
2829 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002830 {
2831 if (! RIB_SYSTEM_ROUTE (rib)
2832 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2833 rib_uninstall_kernel (rn, rib);
2834 }
paul718e3742002-12-13 20:15:29 +00002835}
2836
2837/* Close all RIB tables. */
2838void
paula1ac18c2005-06-28 17:17:12 +00002839rib_close (void)
paul718e3742002-12-13 20:15:29 +00002840{
2841 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2842 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2843}
2844
2845/* Routing information base initialize. */
2846void
paula1ac18c2005-06-28 17:17:12 +00002847rib_init (void)
paul718e3742002-12-13 20:15:29 +00002848{
paul4d38fdb2005-04-28 17:35:14 +00002849 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002850 /* VRF initialization. */
2851 vrf_init ();
2852}