blob: 693b3331389776ab6c0509ee32eab61274c58aaf [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
634#ifdef HAVE_IPV6
635struct rib *
636rib_match_ipv6 (struct in6_addr *addr)
637{
638 struct prefix_ipv6 p;
639 struct route_table *table;
640 struct route_node *rn;
641 struct rib *match;
642 struct nexthop *newhop;
643
644 /* Lookup table. */
645 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
646 if (! table)
647 return 0;
648
649 memset (&p, 0, sizeof (struct prefix_ipv6));
650 p.family = AF_INET6;
651 p.prefixlen = IPV6_MAX_PREFIXLEN;
652 IPV6_ADDR_COPY (&p.prefix, addr);
653
654 rn = route_node_match (table, (struct prefix *) &p);
655
656 while (rn)
657 {
658 route_unlock_node (rn);
659
660 /* Pick up selected route. */
661 for (match = rn->info; match; match = match->next)
662 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
663 break;
664
665 /* If there is no selected route or matched route is EGP, go up
666 tree. */
667 if (! match
668 || match->type == ZEBRA_ROUTE_BGP)
669 {
670 do {
671 rn = rn->parent;
672 } while (rn && rn->info == NULL);
673 if (rn)
674 route_lock_node (rn);
675 }
676 else
677 {
678 if (match->type == ZEBRA_ROUTE_CONNECT)
679 /* Directly point connected route. */
680 return match;
681 else
682 {
683 for (newhop = match->nexthop; newhop; newhop = newhop->next)
684 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
685 return match;
686 return NULL;
687 }
688 }
689 }
690 return NULL;
691}
692#endif /* HAVE_IPV6 */
693
Paul Jakma7514fb72007-05-02 16:05:35 +0000694#define RIB_SYSTEM_ROUTE(R) \
695 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
696
paula1ac18c2005-06-28 17:17:12 +0000697static int
paul718e3742002-12-13 20:15:29 +0000698nexthop_active_check (struct route_node *rn, struct rib *rib,
699 struct nexthop *nexthop, int set)
700{
701 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000702 route_map_result_t ret = RMAP_MATCH;
703 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
704 struct route_map *rmap;
705 int family;
paul718e3742002-12-13 20:15:29 +0000706
Paul Jakma7514fb72007-05-02 16:05:35 +0000707 family = 0;
paul718e3742002-12-13 20:15:29 +0000708 switch (nexthop->type)
709 {
710 case NEXTHOP_TYPE_IFINDEX:
711 ifp = if_lookup_by_index (nexthop->ifindex);
712 if (ifp && if_is_up (ifp))
713 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
714 else
715 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
716 break;
paul718e3742002-12-13 20:15:29 +0000717 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000718 family = AFI_IP6;
719 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000720 ifp = if_lookup_by_name (nexthop->ifname);
721 if (ifp && if_is_up (ifp))
722 {
723 if (set)
724 nexthop->ifindex = ifp->ifindex;
725 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
726 }
727 else
728 {
729 if (set)
730 nexthop->ifindex = 0;
731 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
732 }
733 break;
734 case NEXTHOP_TYPE_IPV4:
735 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000736 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000737 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
738 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
739 else
740 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
741 break;
742#ifdef HAVE_IPV6
743 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000744 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000745 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
746 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
747 else
748 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
749 break;
750 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000751 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000752 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
753 {
754 ifp = if_lookup_by_index (nexthop->ifindex);
755 if (ifp && if_is_up (ifp))
756 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
757 else
758 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
759 }
760 else
761 {
762 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
763 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
764 else
765 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
766 }
767 break;
768#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000769 case NEXTHOP_TYPE_BLACKHOLE:
770 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
771 break;
paul718e3742002-12-13 20:15:29 +0000772 default:
773 break;
774 }
Paul Jakma7514fb72007-05-02 16:05:35 +0000775 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
776 return 0;
777
778 if (RIB_SYSTEM_ROUTE(rib) ||
779 (family == AFI_IP && rn->p.family != AF_INET) ||
780 (family == AFI_IP6 && rn->p.family != AF_INET6))
781 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
782
783 rmap = 0;
784 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
785 proto_rm[family][rib->type])
786 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
787 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
788 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
789 if (rmap) {
790 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
791 }
792
793 if (ret == RMAP_DENYMATCH)
794 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000795 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
796}
797
paula1ac18c2005-06-28 17:17:12 +0000798static int
paul718e3742002-12-13 20:15:29 +0000799nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
800{
801 struct nexthop *nexthop;
802 int active;
803
804 rib->nexthop_active_num = 0;
805 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
806
807 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
808 {
809 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul6baeb982003-10-28 03:47:15 +0000810
811 nexthop_active_check (rn, rib, nexthop, set);
812 if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM)
813 && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
814 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
815
816 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
817 rib->nexthop_active_num++;
paul718e3742002-12-13 20:15:29 +0000818 }
819 return rib->nexthop_active_num;
820}
paul6baeb982003-10-28 03:47:15 +0000821
paul718e3742002-12-13 20:15:29 +0000822
paul718e3742002-12-13 20:15:29 +0000823
paula1ac18c2005-06-28 17:17:12 +0000824static void
paul718e3742002-12-13 20:15:29 +0000825rib_install_kernel (struct route_node *rn, struct rib *rib)
826{
827 int ret = 0;
828 struct nexthop *nexthop;
829
830 switch (PREFIX_FAMILY (&rn->p))
831 {
832 case AF_INET:
833 ret = kernel_add_ipv4 (&rn->p, rib);
834 break;
835#ifdef HAVE_IPV6
836 case AF_INET6:
837 ret = kernel_add_ipv6 (&rn->p, rib);
838 break;
839#endif /* HAVE_IPV6 */
840 }
841
842 if (ret < 0)
843 {
844 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
845 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
846 }
847}
848
849/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000850static int
paul718e3742002-12-13 20:15:29 +0000851rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
852{
853 int ret = 0;
854 struct nexthop *nexthop;
855
856 switch (PREFIX_FAMILY (&rn->p))
857 {
858 case AF_INET:
859 ret = kernel_delete_ipv4 (&rn->p, rib);
860 break;
861#ifdef HAVE_IPV6
862 case AF_INET6:
863 ret = kernel_delete_ipv6 (&rn->p, rib);
864 break;
865#endif /* HAVE_IPV6 */
866 }
867
868 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
869 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
870
871 return ret;
872}
873
874/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000875static void
paul718e3742002-12-13 20:15:29 +0000876rib_uninstall (struct route_node *rn, struct rib *rib)
877{
878 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
879 {
880 redistribute_delete (&rn->p, rib);
881 if (! RIB_SYSTEM_ROUTE (rib))
882 rib_uninstall_kernel (rn, rib);
883 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
884 }
885}
886
Paul Jakma6d691122006-07-27 21:49:00 +0000887static void rib_unlink (struct route_node *, struct rib *);
888
paul718e3742002-12-13 20:15:29 +0000889/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000890static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000891rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000892{
893 struct rib *rib;
894 struct rib *next;
895 struct rib *fib = NULL;
896 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +0000897 struct rib *del = NULL;
898 struct route_node *rn = data;
pauld753e9e2003-01-22 19:45:50 +0000899 int installed = 0;
900 struct nexthop *nexthop = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000901
902 assert (rn);
903
paul718e3742002-12-13 20:15:29 +0000904 for (rib = rn->info; rib; rib = next)
905 {
906 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000907
paul718e3742002-12-13 20:15:29 +0000908 /* Currently installed rib. */
909 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +0000910 {
911 assert (fib == NULL);
912 fib = rib;
913 }
914
915 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
916 * which we need to do do further work with below.
917 */
918 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
919 {
920 if (rib != fib)
921 {
922 if (IS_ZEBRA_DEBUG_RIB)
923 zlog_debug ("%s: rn %p, removing rib %p", __func__, rn, rib);
924 rib_unlink (rn, rib);
925 }
926 else
927 del = rib;
928
929 continue;
930 }
paul4d38fdb2005-04-28 17:35:14 +0000931
paul718e3742002-12-13 20:15:29 +0000932 /* Skip unreachable nexthop. */
933 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000934 continue;
paul718e3742002-12-13 20:15:29 +0000935
936 /* Infinit distance. */
937 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000938 continue;
paul718e3742002-12-13 20:15:29 +0000939
paulaf887b52006-01-18 14:52:52 +0000940 /* Newly selected rib, the common case. */
941 if (!select)
942 {
943 select = rib;
944 continue;
945 }
946
947 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +0000948 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +0000949 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +0000950 * - lower metric beats higher for equal distance
951 * - last, hence oldest, route wins tie break.
952 */
paula1038a12006-01-30 14:08:51 +0000953
954 /* Connected routes. Pick the last connected
955 * route of the set of lowest metric connected routes.
956 */
paula8d9c1f2006-01-25 06:31:04 +0000957 if (rib->type == ZEBRA_ROUTE_CONNECT)
958 {
paula1038a12006-01-30 14:08:51 +0000959 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +0000960 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +0000961 select = rib;
962 continue;
paula8d9c1f2006-01-25 06:31:04 +0000963 }
964 else if (select->type == ZEBRA_ROUTE_CONNECT)
965 continue;
966
967 /* higher distance loses */
968 if (rib->distance > select->distance)
969 continue;
970
971 /* lower wins */
972 if (rib->distance < select->distance)
973 {
paulaf887b52006-01-18 14:52:52 +0000974 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000975 continue;
976 }
977
978 /* metric tie-breaks equal distance */
979 if (rib->metric <= select->metric)
980 select = rib;
paul718e3742002-12-13 20:15:29 +0000981 }
paul4d38fdb2005-04-28 17:35:14 +0000982
paul718e3742002-12-13 20:15:29 +0000983 /* Same route is selected. */
984 if (select && select == fib)
985 {
Paul Jakma6d691122006-07-27 21:49:00 +0000986 if (IS_ZEBRA_DEBUG_RIB)
987 zlog_debug ("%s: Updating existing route, select %p, fib %p",
988 __func__, select, fib);
paul718e3742002-12-13 20:15:29 +0000989 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000990 {
991 redistribute_delete (&rn->p, select);
992 if (! RIB_SYSTEM_ROUTE (select))
993 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000994
paul4d38fdb2005-04-28 17:35:14 +0000995 /* Set real nexthop. */
996 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +0000997
paul4d38fdb2005-04-28 17:35:14 +0000998 if (! RIB_SYSTEM_ROUTE (select))
999 rib_install_kernel (rn, select);
1000 redistribute_add (&rn->p, select);
1001 }
pauld753e9e2003-01-22 19:45:50 +00001002 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001003 {
1004 /* Housekeeping code to deal with
1005 race conditions in kernel with linux
1006 netlink reporting interface up before IPv4 or IPv6 protocol
1007 is ready to add routes.
1008 This makes sure the routes are IN the kernel.
1009 */
pauld753e9e2003-01-22 19:45:50 +00001010
paul4d38fdb2005-04-28 17:35:14 +00001011 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1012 {
1013 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1014 installed = 1;
1015 }
1016 if (! installed)
1017 rib_install_kernel (rn, select);
1018 }
Paul Jakma6d691122006-07-27 21:49:00 +00001019 goto end;
paul718e3742002-12-13 20:15:29 +00001020 }
1021
1022 /* Uninstall old rib from forwarding table. */
1023 if (fib)
1024 {
Paul Jakma6d691122006-07-27 21:49:00 +00001025 if (IS_ZEBRA_DEBUG_RIB)
1026 zlog_debug ("%s: Removing existing route, fib %p", __func__, fib);
paul718e3742002-12-13 20:15:29 +00001027 redistribute_delete (&rn->p, fib);
1028 if (! RIB_SYSTEM_ROUTE (fib))
1029 rib_uninstall_kernel (rn, fib);
1030 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1031
1032 /* Set real nexthop. */
1033 nexthop_active_update (rn, fib, 1);
1034 }
1035
1036 /* Install new rib into forwarding table. */
1037 if (select)
1038 {
Paul Jakma6d691122006-07-27 21:49:00 +00001039 if (IS_ZEBRA_DEBUG_RIB)
1040 zlog_debug ("%s: Adding route, select %p", __func__, select);
paul718e3742002-12-13 20:15:29 +00001041 /* Set real nexthop. */
1042 nexthop_active_update (rn, select, 1);
1043
1044 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001045 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001046 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1047 redistribute_add (&rn->p, select);
1048 }
paul4d38fdb2005-04-28 17:35:14 +00001049
Paul Jakma6d691122006-07-27 21:49:00 +00001050 /* FIB route was removed, should be deleted */
1051 if (del)
1052 {
1053 if (IS_ZEBRA_DEBUG_RIB)
1054 zlog_debug ("%s: Deleting fib %p, rn %p", __func__, del, rn);
1055 rib_unlink (rn, del);
1056 }
paul4d38fdb2005-04-28 17:35:14 +00001057
Paul Jakma6d691122006-07-27 21:49:00 +00001058end:
1059 if (IS_ZEBRA_DEBUG_RIB_Q)
1060 zlog_debug ("%s: rn %p dequeued", __func__, rn);
1061 if (rn->info)
1062 UNSET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1063 route_unlock_node (rn); /* rib queue lock */
1064 return WQ_SUCCESS;
paul4d38fdb2005-04-28 17:35:14 +00001065}
1066
Paul Jakma6d691122006-07-27 21:49:00 +00001067/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001068static void
Paul Jakma6d691122006-07-27 21:49:00 +00001069rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001070{
Paul Jakma6d691122006-07-27 21:49:00 +00001071 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001072
Paul Jakma6d691122006-07-27 21:49:00 +00001073 /* Pointless to queue a route_node with no RIB entries to add or remove */
1074 if (!rn->info)
1075 {
1076 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1077 __func__, rn, rn->lock);
1078 zlog_backtrace(LOG_DEBUG);
1079 return;
1080 }
paul4d38fdb2005-04-28 17:35:14 +00001081
Paul Jakma6d691122006-07-27 21:49:00 +00001082 /* Route-table node already queued, so nothing to do */
1083 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED))
1084 {
1085 if (IS_ZEBRA_DEBUG_RIB_Q)
1086 zlog_debug ("%s: rn %p already queued", __func__, rn);
1087 return;
1088 }
paul4d38fdb2005-04-28 17:35:14 +00001089
Paul Jakma6d691122006-07-27 21:49:00 +00001090 route_lock_node (rn); /* rib queue lock */
1091
1092 if (IS_ZEBRA_DEBUG_RIB_Q)
1093 zlog_info ("%s: work queue added", __func__);
1094
1095 assert (zebra);
1096
paul4d38fdb2005-04-28 17:35:14 +00001097 if (zebra->ribq == NULL)
1098 {
Paul Jakma6d691122006-07-27 21:49:00 +00001099 zlog_err ("%s: work_queue does not exist!", __func__);
1100 route_unlock_node (rn);
paul4d38fdb2005-04-28 17:35:14 +00001101 return;
1102 }
1103
Paul Jakma6d691122006-07-27 21:49:00 +00001104 work_queue_add (zebra->ribq, rn);
1105
1106 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1107
1108 if (IS_ZEBRA_DEBUG_RIB_Q)
1109 zlog_debug ("%s: rn %p queued", __func__, rn);
paul4d38fdb2005-04-28 17:35:14 +00001110
1111 return;
1112}
1113
paul4d38fdb2005-04-28 17:35:14 +00001114/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001115static void
paul4d38fdb2005-04-28 17:35:14 +00001116rib_queue_init (struct zebra_t *zebra)
1117{
1118 assert (zebra);
1119
1120 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001121 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001122 {
Paul Jakma6d691122006-07-27 21:49:00 +00001123 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001124 return;
1125 }
1126
1127 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001128 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001129 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001130 /* XXX: TODO: These should be runtime configurable via vty */
1131 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001132 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001133
1134 return;
paul718e3742002-12-13 20:15:29 +00001135}
1136
Paul Jakma6d691122006-07-27 21:49:00 +00001137/* RIB updates are processed via a queue of pointers to route_nodes.
1138 *
1139 * The queue length is bounded by the maximal size of the routing table,
1140 * as a route_node will not be requeued, if already queued.
1141 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001142 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1143 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1144 * and then submit route_node to queue for best-path selection later.
1145 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001146 *
1147 * Deleted RIBs are reaped during best-path selection.
1148 *
1149 * rib_addnode
1150 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001151 * |-------->| | best RIB, if required
1152 * | |
1153 * static_install->|->rib_addqueue...... -> rib_process
1154 * | |
1155 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001156 * |-> set RIB_ENTRY_REMOVE |
1157 * rib_delnode (RIB freed)
1158 *
1159 *
1160 * Queueing state for a route_node is kept in the head RIB entry, this
1161 * state must be preserved as and when the head RIB entry of a
1162 * route_node is changed by rib_unlink / rib_link. A small complication,
1163 * but saves having to allocate a dedicated object for this.
1164 *
1165 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1166 *
1167 * - route_nodes: refcounted by:
1168 * - RIBs attached to route_node:
1169 * - managed by: rib_link/unlink
1170 * - route_node processing queue
1171 * - managed by: rib_addqueue, rib_process.
1172 *
1173 */
1174
paul718e3742002-12-13 20:15:29 +00001175/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001176static void
Paul Jakma6d691122006-07-27 21:49:00 +00001177rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001178{
1179 struct rib *head;
paul4d38fdb2005-04-28 17:35:14 +00001180
1181 assert (rib && rn);
1182
Paul Jakma6d691122006-07-27 21:49:00 +00001183 route_lock_node (rn); /* rn route table reference */
1184
1185 if (IS_ZEBRA_DEBUG_RIB)
1186 zlog_debug ("%s: rn %p, rib %p", __func__, rn, rib);
1187
paul718e3742002-12-13 20:15:29 +00001188 head = rn->info;
1189 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001190 {
1191 if (IS_ZEBRA_DEBUG_RIB)
1192 zlog_debug ("%s: new head, rn_status copied over", __func__);
1193 head->prev = rib;
1194 /* Transfer the rn status flags to the new head RIB */
1195 rib->rn_status = head->rn_status;
1196 }
paul718e3742002-12-13 20:15:29 +00001197 rib->next = head;
1198 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001199 rib_queue_add (&zebrad, rn);
1200}
1201
1202static void
1203rib_addnode (struct route_node *rn, struct rib *rib)
1204{
1205 /* RIB node has been un-removed before route-node is processed.
1206 * route_node must hence already be on the queue for processing..
1207 */
1208 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1209 {
1210 if (IS_ZEBRA_DEBUG_RIB)
1211 zlog_debug ("%s: rn %p, un-removed rib %p",
1212 __func__, rn, rib);
1213 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1214 return;
1215 }
1216 rib_link (rn, rib);
1217}
1218
1219static void
1220rib_unlink (struct route_node *rn, struct rib *rib)
1221{
1222 struct nexthop *nexthop, *next;
1223
1224 assert (rn && rib);
1225
1226 if (IS_ZEBRA_DEBUG_RIB)
1227 zlog_debug ("%s: rn %p, rib %p",
1228 __func__, rn, rib);
1229
1230 if (rib->next)
1231 rib->next->prev = rib->prev;
1232
1233 if (rib->prev)
1234 rib->prev->next = rib->next;
1235 else
1236 {
1237 rn->info = rib->next;
1238
1239 if (rn->info)
1240 {
1241 if (IS_ZEBRA_DEBUG_RIB)
1242 zlog_debug ("%s: rn %p, rib %p, new head copy",
1243 __func__, rn, rib);
1244 rib->next->rn_status = rib->rn_status;
1245 }
1246 }
1247
1248 /* free RIB and nexthops */
1249 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1250 {
1251 next = nexthop->next;
1252 nexthop_free (nexthop);
1253 }
1254 XFREE (MTYPE_RIB, rib);
1255
1256 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001257}
1258
paula1ac18c2005-06-28 17:17:12 +00001259static void
paul718e3742002-12-13 20:15:29 +00001260rib_delnode (struct route_node *rn, struct rib *rib)
1261{
Paul Jakma6d691122006-07-27 21:49:00 +00001262 if (IS_ZEBRA_DEBUG_RIB)
1263 zlog_debug ("%s: rn %p, rib %p, removing", __func__, rn, rib);
1264 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1265 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001266}
1267
1268int
1269rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001270 struct in_addr *gate, struct in_addr *src,
1271 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001272 u_int32_t metric, u_char distance)
1273{
1274 struct rib *rib;
1275 struct rib *same = NULL;
1276 struct route_table *table;
1277 struct route_node *rn;
1278 struct nexthop *nexthop;
1279
1280 /* Lookup table. */
1281 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1282 if (! table)
1283 return 0;
1284
1285 /* Make it sure prefixlen is applied to the prefix. */
1286 apply_mask_ipv4 (p);
1287
1288 /* Set default distance by route type. */
1289 if (distance == 0)
1290 {
1291 distance = route_info[type].distance;
1292
1293 /* iBGP distance is 200. */
1294 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1295 distance = 200;
1296 }
1297
1298 /* Lookup route node.*/
1299 rn = route_node_get (table, (struct prefix *) p);
1300
1301 /* If same type of route are installed, treat it as a implicit
1302 withdraw. */
1303 for (rib = rn->info; rib; rib = rib->next)
1304 {
Paul Jakma6d691122006-07-27 21:49:00 +00001305 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1306 continue;
1307
hassoebf1ead2005-09-21 14:58:20 +00001308 if (rib->type != type)
1309 continue;
1310 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001311 {
1312 same = rib;
1313 break;
1314 }
hassoebf1ead2005-09-21 14:58:20 +00001315 /* Duplicate connected route comes in. */
1316 else if ((nexthop = rib->nexthop) &&
1317 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001318 nexthop->ifindex == ifindex &&
1319 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001320 {
1321 rib->refcnt++;
1322 return 0 ;
1323 }
paul718e3742002-12-13 20:15:29 +00001324 }
1325
1326 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001327 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001328 rib->type = type;
1329 rib->distance = distance;
1330 rib->flags = flags;
1331 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001332 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001333 rib->nexthop_num = 0;
1334 rib->uptime = time (NULL);
1335
1336 /* Nexthop settings. */
1337 if (gate)
1338 {
1339 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001340 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001341 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001342 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001343 }
1344 else
1345 nexthop_ifindex_add (rib, ifindex);
1346
1347 /* If this route is kernel route, set FIB flag to the route. */
1348 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1349 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1350 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1351
1352 /* Link new rib to node.*/
1353 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001354
paul718e3742002-12-13 20:15:29 +00001355 /* Free implicit route.*/
1356 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001357 rib_delnode (rn, same);
1358
1359 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001360 return 0;
1361}
1362
1363int
1364rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1365{
1366 struct route_table *table;
1367 struct route_node *rn;
1368 struct rib *same;
1369 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001370
paul718e3742002-12-13 20:15:29 +00001371 /* Lookup table. */
1372 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1373 if (! table)
1374 return 0;
paul718e3742002-12-13 20:15:29 +00001375 /* Make it sure prefixlen is applied to the prefix. */
1376 apply_mask_ipv4 (p);
1377
1378 /* Set default distance by route type. */
1379 if (rib->distance == 0)
1380 {
1381 rib->distance = route_info[rib->type].distance;
1382
1383 /* iBGP distance is 200. */
1384 if (rib->type == ZEBRA_ROUTE_BGP
1385 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1386 rib->distance = 200;
1387 }
1388
1389 /* Lookup route node.*/
1390 rn = route_node_get (table, (struct prefix *) p);
1391
1392 /* If same type of route are installed, treat it as a implicit
1393 withdraw. */
1394 for (same = rn->info; same; same = same->next)
1395 {
Paul Jakma6d691122006-07-27 21:49:00 +00001396 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1397 continue;
1398
paul718e3742002-12-13 20:15:29 +00001399 if (same->type == rib->type && same->table == rib->table
1400 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001401 break;
paul718e3742002-12-13 20:15:29 +00001402 }
paul4d38fdb2005-04-28 17:35:14 +00001403
paul718e3742002-12-13 20:15:29 +00001404 /* If this route is kernel route, set FIB flag to the route. */
1405 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1406 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1407 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1408
1409 /* Link new rib to node.*/
1410 rib_addnode (rn, rib);
1411
paul718e3742002-12-13 20:15:29 +00001412 /* Free implicit route.*/
1413 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001414 rib_delnode (rn, same);
1415
1416 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001417 return 0;
1418}
1419
hassoebf1ead2005-09-21 14:58:20 +00001420/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001421int
1422rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1423 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1424{
1425 struct route_table *table;
1426 struct route_node *rn;
1427 struct rib *rib;
1428 struct rib *fib = NULL;
1429 struct rib *same = NULL;
1430 struct nexthop *nexthop;
1431 char buf1[BUFSIZ];
1432 char buf2[BUFSIZ];
1433
1434 /* Lookup table. */
1435 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1436 if (! table)
1437 return 0;
1438
1439 /* Apply mask. */
1440 apply_mask_ipv4 (p);
1441
paul5ec90d22003-06-19 01:41:37 +00001442 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001443 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001444 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1445 p->prefixlen,
1446 inet_ntoa (*gate),
1447 ifindex);
1448
paul718e3742002-12-13 20:15:29 +00001449 /* Lookup route node. */
1450 rn = route_node_lookup (table, (struct prefix *) p);
1451 if (! rn)
1452 {
1453 if (IS_ZEBRA_DEBUG_KERNEL)
1454 {
1455 if (gate)
ajsb6178002004-12-07 21:12:56 +00001456 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001457 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1458 p->prefixlen,
1459 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1460 ifindex);
1461 else
ajsb6178002004-12-07 21:12:56 +00001462 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001463 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1464 p->prefixlen,
1465 ifindex);
1466 }
1467 return ZEBRA_ERR_RTNOEXIST;
1468 }
1469
1470 /* Lookup same type route. */
1471 for (rib = rn->info; rib; rib = rib->next)
1472 {
Paul Jakma6d691122006-07-27 21:49:00 +00001473 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1474 continue;
1475
paul718e3742002-12-13 20:15:29 +00001476 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1477 fib = rib;
1478
hassoebf1ead2005-09-21 14:58:20 +00001479 if (rib->type != type)
1480 continue;
1481 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1482 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001483 {
hassoebf1ead2005-09-21 14:58:20 +00001484 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001485 {
hassoebf1ead2005-09-21 14:58:20 +00001486 rib->refcnt--;
1487 route_unlock_node (rn);
1488 route_unlock_node (rn);
1489 return 0;
paul718e3742002-12-13 20:15:29 +00001490 }
hassoebf1ead2005-09-21 14:58:20 +00001491 same = rib;
1492 break;
paul718e3742002-12-13 20:15:29 +00001493 }
hassoebf1ead2005-09-21 14:58:20 +00001494 /* Make sure that the route found has the same gateway. */
1495 else if (gate == NULL ||
1496 ((nexthop = rib->nexthop) &&
1497 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1498 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001499 {
hassoebf1ead2005-09-21 14:58:20 +00001500 same = rib;
1501 break;
paul718e3742002-12-13 20:15:29 +00001502 }
1503 }
1504
1505 /* If same type of route can't be found and this message is from
1506 kernel. */
1507 if (! same)
1508 {
1509 if (fib && type == ZEBRA_ROUTE_KERNEL)
1510 {
1511 /* Unset flags. */
1512 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1513 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1514
1515 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1516 }
1517 else
1518 {
1519 if (IS_ZEBRA_DEBUG_KERNEL)
1520 {
1521 if (gate)
ajsb6178002004-12-07 21:12:56 +00001522 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001523 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1524 p->prefixlen,
1525 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1526 ifindex,
1527 type);
1528 else
ajsb6178002004-12-07 21:12:56 +00001529 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001530 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1531 p->prefixlen,
1532 ifindex,
1533 type);
1534 }
1535 route_unlock_node (rn);
1536 return ZEBRA_ERR_RTNOEXIST;
1537 }
1538 }
paul4d38fdb2005-04-28 17:35:14 +00001539
paul718e3742002-12-13 20:15:29 +00001540 if (same)
1541 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001542
paul718e3742002-12-13 20:15:29 +00001543 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001544 return 0;
1545}
1546
1547/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001548static void
paul718e3742002-12-13 20:15:29 +00001549static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1550{
1551 struct rib *rib;
1552 struct route_node *rn;
1553 struct route_table *table;
1554
1555 /* Lookup table. */
1556 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1557 if (! table)
1558 return;
1559
1560 /* Lookup existing route */
1561 rn = route_node_get (table, p);
1562 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001563 {
1564 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1565 continue;
1566
1567 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1568 break;
1569 }
paul718e3742002-12-13 20:15:29 +00001570
1571 if (rib)
1572 {
1573 /* Same distance static route is there. Update it with new
1574 nexthop. */
paul718e3742002-12-13 20:15:29 +00001575 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001576 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001577 {
1578 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001579 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001580 break;
1581 case STATIC_IPV4_IFNAME:
1582 nexthop_ifname_add (rib, si->gate.ifname);
1583 break;
1584 case STATIC_IPV4_BLACKHOLE:
1585 nexthop_blackhole_add (rib);
1586 break;
paul4d38fdb2005-04-28 17:35:14 +00001587 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00001588 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001589 }
1590 else
1591 {
1592 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001593 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1594
paul718e3742002-12-13 20:15:29 +00001595 rib->type = ZEBRA_ROUTE_STATIC;
1596 rib->distance = si->distance;
1597 rib->metric = 0;
1598 rib->nexthop_num = 0;
1599
1600 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001601 {
1602 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001603 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001604 break;
1605 case STATIC_IPV4_IFNAME:
1606 nexthop_ifname_add (rib, si->gate.ifname);
1607 break;
1608 case STATIC_IPV4_BLACKHOLE:
1609 nexthop_blackhole_add (rib);
1610 break;
1611 }
paul718e3742002-12-13 20:15:29 +00001612
hasso81dfcaa2003-05-25 19:21:25 +00001613 /* Save the flags of this static routes (reject, blackhole) */
1614 rib->flags = si->flags;
1615
paul718e3742002-12-13 20:15:29 +00001616 /* Link this rib to the tree. */
1617 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001618 }
1619}
1620
paula1ac18c2005-06-28 17:17:12 +00001621static int
paul718e3742002-12-13 20:15:29 +00001622static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1623{
1624 if (nexthop->type == NEXTHOP_TYPE_IPV4
1625 && si->type == STATIC_IPV4_GATEWAY
1626 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1627 return 1;
1628 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1629 && si->type == STATIC_IPV4_IFNAME
1630 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1631 return 1;
paul595db7f2003-05-25 21:35:06 +00001632 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1633 && si->type == STATIC_IPV4_BLACKHOLE)
1634 return 1;
paule8e19462006-01-19 20:16:55 +00001635 return 0;
paul718e3742002-12-13 20:15:29 +00001636}
1637
1638/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001639static void
paul718e3742002-12-13 20:15:29 +00001640static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1641{
1642 struct route_node *rn;
1643 struct rib *rib;
1644 struct nexthop *nexthop;
1645 struct route_table *table;
1646
1647 /* Lookup table. */
1648 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1649 if (! table)
1650 return;
paul4d38fdb2005-04-28 17:35:14 +00001651
paul718e3742002-12-13 20:15:29 +00001652 /* Lookup existing route with type and distance. */
1653 rn = route_node_lookup (table, p);
1654 if (! rn)
1655 return;
1656
1657 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001658 {
1659 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1660 continue;
1661
1662 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1663 break;
1664 }
paul718e3742002-12-13 20:15:29 +00001665
1666 if (! rib)
1667 {
1668 route_unlock_node (rn);
1669 return;
1670 }
1671
1672 /* Lookup nexthop. */
1673 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1674 if (static_ipv4_nexthop_same (nexthop, si))
1675 break;
1676
1677 /* Can't find nexthop. */
1678 if (! nexthop)
1679 {
1680 route_unlock_node (rn);
1681 return;
1682 }
1683
1684 /* Check nexthop. */
1685 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00001686 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001687 else
1688 {
paul6baeb982003-10-28 03:47:15 +00001689 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1690 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001691 nexthop_delete (rib, nexthop);
1692 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001693 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001694 }
paul718e3742002-12-13 20:15:29 +00001695 /* Unlock node. */
1696 route_unlock_node (rn);
1697}
1698
1699/* Add static route into static route configuration. */
1700int
hasso39db97e2004-10-12 20:50:58 +00001701static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001702 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001703{
1704 u_char type = 0;
1705 struct route_node *rn;
1706 struct static_ipv4 *si;
1707 struct static_ipv4 *pp;
1708 struct static_ipv4 *cp;
1709 struct static_ipv4 *update = NULL;
1710 struct route_table *stable;
1711
1712 /* Lookup table. */
1713 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1714 if (! stable)
1715 return -1;
1716
1717 /* Lookup static route prefix. */
1718 rn = route_node_get (stable, p);
1719
1720 /* Make flags. */
1721 if (gate)
1722 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001723 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001724 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001725 else
1726 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001727
1728 /* Do nothing if there is a same static route. */
1729 for (si = rn->info; si; si = si->next)
1730 {
1731 if (type == si->type
1732 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1733 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1734 {
1735 if (distance == si->distance)
1736 {
1737 route_unlock_node (rn);
1738 return 0;
1739 }
1740 else
1741 update = si;
1742 }
1743 }
1744
Paul Jakma3c0755d2006-12-08 00:53:14 +00001745 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00001746 if (update)
1747 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1748
1749 /* Make new static route structure. */
1750 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1751 memset (si, 0, sizeof (struct static_ipv4));
1752
1753 si->type = type;
1754 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001755 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001756
1757 if (gate)
1758 si->gate.ipv4 = *gate;
1759 if (ifname)
1760 si->gate.ifname = XSTRDUP (0, ifname);
1761
1762 /* Add new static route information to the tree with sort by
1763 distance value and gateway address. */
1764 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1765 {
1766 if (si->distance < cp->distance)
1767 break;
1768 if (si->distance > cp->distance)
1769 continue;
1770 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1771 {
1772 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1773 break;
1774 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1775 continue;
1776 }
1777 }
1778
1779 /* Make linked list. */
1780 if (pp)
1781 pp->next = si;
1782 else
1783 rn->info = si;
1784 if (cp)
1785 cp->prev = si;
1786 si->prev = pp;
1787 si->next = cp;
1788
1789 /* Install into rib. */
1790 static_install_ipv4 (p, si);
1791
1792 return 1;
1793}
1794
1795/* Delete static route from static route configuration. */
1796int
hasso39db97e2004-10-12 20:50:58 +00001797static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001798 u_char distance, u_int32_t vrf_id)
1799{
1800 u_char type = 0;
1801 struct route_node *rn;
1802 struct static_ipv4 *si;
1803 struct route_table *stable;
1804
1805 /* Lookup table. */
1806 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1807 if (! stable)
1808 return -1;
1809
1810 /* Lookup static route prefix. */
1811 rn = route_node_lookup (stable, p);
1812 if (! rn)
1813 return 0;
1814
1815 /* Make flags. */
1816 if (gate)
1817 type = STATIC_IPV4_GATEWAY;
1818 else if (ifname)
1819 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001820 else
1821 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001822
1823 /* Find same static route is the tree */
1824 for (si = rn->info; si; si = si->next)
1825 if (type == si->type
1826 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1827 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1828 break;
1829
1830 /* Can't find static route. */
1831 if (! si)
1832 {
1833 route_unlock_node (rn);
1834 return 0;
1835 }
1836
1837 /* Install into rib. */
1838 static_uninstall_ipv4 (p, si);
1839
1840 /* Unlink static route from linked list. */
1841 if (si->prev)
1842 si->prev->next = si->next;
1843 else
1844 rn->info = si->next;
1845 if (si->next)
1846 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001847 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001848
1849 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001850 if (ifname)
1851 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001852 XFREE (MTYPE_STATIC_IPV4, si);
1853
paul143a3852003-09-29 20:06:13 +00001854 route_unlock_node (rn);
1855
paul718e3742002-12-13 20:15:29 +00001856 return 1;
1857}
1858
1859
1860#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001861static int
paul718e3742002-12-13 20:15:29 +00001862rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1863 struct in6_addr *gate, unsigned int ifindex, int table)
1864{
hasso726f9b22003-05-25 21:04:54 +00001865 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1866#if defined (MUSICA) || defined (LINUX)
1867 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1868 if (p->prefixlen == 96)
1869 return 0;
1870#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001871 return 1;
hasso726f9b22003-05-25 21:04:54 +00001872 }
paul718e3742002-12-13 20:15:29 +00001873 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1874 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1875 {
1876 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1877 return 1;
1878 }
1879 return 0;
1880}
1881
1882int
1883rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001884 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1885 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001886{
1887 struct rib *rib;
1888 struct rib *same = NULL;
1889 struct route_table *table;
1890 struct route_node *rn;
1891 struct nexthop *nexthop;
1892
paul718e3742002-12-13 20:15:29 +00001893 /* Lookup table. */
1894 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1895 if (! table)
1896 return 0;
1897
1898 /* Make sure mask is applied. */
1899 apply_mask_ipv6 (p);
1900
1901 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001902 if (!distance)
1903 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001904
1905 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1906 distance = 200;
1907
1908 /* Filter bogus route. */
1909 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1910 return 0;
1911
1912 /* Lookup route node.*/
1913 rn = route_node_get (table, (struct prefix *) p);
1914
1915 /* If same type of route are installed, treat it as a implicit
1916 withdraw. */
1917 for (rib = rn->info; rib; rib = rib->next)
1918 {
Paul Jakma6d691122006-07-27 21:49:00 +00001919 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1920 continue;
1921
hassoebf1ead2005-09-21 14:58:20 +00001922 if (rib->type != type)
1923 continue;
1924 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001925 {
1926 same = rib;
paul718e3742002-12-13 20:15:29 +00001927 break;
1928 }
hassoebf1ead2005-09-21 14:58:20 +00001929 else if ((nexthop = rib->nexthop) &&
1930 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1931 nexthop->ifindex == ifindex)
1932 {
1933 rib->refcnt++;
1934 return 0;
1935 }
paul718e3742002-12-13 20:15:29 +00001936 }
1937
1938 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001939 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1940
paul718e3742002-12-13 20:15:29 +00001941 rib->type = type;
1942 rib->distance = distance;
1943 rib->flags = flags;
1944 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001945 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001946 rib->nexthop_num = 0;
1947 rib->uptime = time (NULL);
1948
1949 /* Nexthop settings. */
1950 if (gate)
1951 {
1952 if (ifindex)
1953 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1954 else
1955 nexthop_ipv6_add (rib, gate);
1956 }
1957 else
1958 nexthop_ifindex_add (rib, ifindex);
1959
1960 /* If this route is kernel route, set FIB flag to the route. */
1961 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1962 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1963 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1964
1965 /* Link new rib to node.*/
1966 rib_addnode (rn, rib);
1967
paul718e3742002-12-13 20:15:29 +00001968 /* Free implicit route.*/
1969 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001970 rib_delnode (rn, same);
1971
1972 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001973 return 0;
1974}
1975
hassoebf1ead2005-09-21 14:58:20 +00001976/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001977int
1978rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1979 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1980{
1981 struct route_table *table;
1982 struct route_node *rn;
1983 struct rib *rib;
1984 struct rib *fib = NULL;
1985 struct rib *same = NULL;
1986 struct nexthop *nexthop;
1987 char buf1[BUFSIZ];
1988 char buf2[BUFSIZ];
1989
1990 /* Apply mask. */
1991 apply_mask_ipv6 (p);
1992
1993 /* Lookup table. */
1994 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1995 if (! table)
1996 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001997
paul718e3742002-12-13 20:15:29 +00001998 /* Lookup route node. */
1999 rn = route_node_lookup (table, (struct prefix *) p);
2000 if (! rn)
2001 {
2002 if (IS_ZEBRA_DEBUG_KERNEL)
2003 {
2004 if (gate)
ajsb6178002004-12-07 21:12:56 +00002005 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002006 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2007 p->prefixlen,
2008 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2009 ifindex);
2010 else
ajsb6178002004-12-07 21:12:56 +00002011 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002012 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2013 p->prefixlen,
2014 ifindex);
2015 }
2016 return ZEBRA_ERR_RTNOEXIST;
2017 }
2018
2019 /* Lookup same type route. */
2020 for (rib = rn->info; rib; rib = rib->next)
2021 {
Paul Jakma6d691122006-07-27 21:49:00 +00002022 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2023 continue;
2024
paul718e3742002-12-13 20:15:29 +00002025 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2026 fib = rib;
2027
hassoebf1ead2005-09-21 14:58:20 +00002028 if (rib->type != type)
2029 continue;
2030 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2031 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002032 {
hassoebf1ead2005-09-21 14:58:20 +00002033 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002034 {
hassoebf1ead2005-09-21 14:58:20 +00002035 rib->refcnt--;
2036 route_unlock_node (rn);
2037 route_unlock_node (rn);
2038 return 0;
paul718e3742002-12-13 20:15:29 +00002039 }
hassoebf1ead2005-09-21 14:58:20 +00002040 same = rib;
2041 break;
paul718e3742002-12-13 20:15:29 +00002042 }
hassoebf1ead2005-09-21 14:58:20 +00002043 /* Make sure that the route found has the same gateway. */
2044 else if (gate == NULL ||
2045 ((nexthop = rib->nexthop) &&
2046 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2047 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002048 {
hassoebf1ead2005-09-21 14:58:20 +00002049 same = rib;
2050 break;
paul718e3742002-12-13 20:15:29 +00002051 }
2052 }
2053
2054 /* If same type of route can't be found and this message is from
2055 kernel. */
2056 if (! same)
2057 {
2058 if (fib && type == ZEBRA_ROUTE_KERNEL)
2059 {
2060 /* Unset flags. */
2061 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2062 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2063
2064 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2065 }
2066 else
2067 {
2068 if (IS_ZEBRA_DEBUG_KERNEL)
2069 {
2070 if (gate)
ajsb6178002004-12-07 21:12:56 +00002071 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002072 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2073 p->prefixlen,
2074 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2075 ifindex,
2076 type);
2077 else
ajsb6178002004-12-07 21:12:56 +00002078 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002079 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2080 p->prefixlen,
2081 ifindex,
2082 type);
2083 }
2084 route_unlock_node (rn);
2085 return ZEBRA_ERR_RTNOEXIST;
2086 }
2087 }
2088
2089 if (same)
2090 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002091
paul718e3742002-12-13 20:15:29 +00002092 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002093 return 0;
2094}
2095
2096/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002097static void
paul718e3742002-12-13 20:15:29 +00002098static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2099{
2100 struct rib *rib;
2101 struct route_table *table;
2102 struct route_node *rn;
2103
2104 /* Lookup table. */
2105 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2106 if (! table)
2107 return;
2108
2109 /* Lookup existing route */
2110 rn = route_node_get (table, p);
2111 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002112 {
2113 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2114 continue;
2115
2116 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2117 break;
2118 }
paul718e3742002-12-13 20:15:29 +00002119
2120 if (rib)
2121 {
2122 /* Same distance static route is there. Update it with new
2123 nexthop. */
paul718e3742002-12-13 20:15:29 +00002124 route_unlock_node (rn);
2125
2126 switch (si->type)
2127 {
2128 case STATIC_IPV6_GATEWAY:
2129 nexthop_ipv6_add (rib, &si->ipv6);
2130 break;
2131 case STATIC_IPV6_IFNAME:
2132 nexthop_ifname_add (rib, si->ifname);
2133 break;
2134 case STATIC_IPV6_GATEWAY_IFNAME:
2135 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2136 break;
2137 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002138 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002139 }
2140 else
2141 {
2142 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002143 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2144
paul718e3742002-12-13 20:15:29 +00002145 rib->type = ZEBRA_ROUTE_STATIC;
2146 rib->distance = si->distance;
2147 rib->metric = 0;
2148 rib->nexthop_num = 0;
2149
2150 switch (si->type)
2151 {
2152 case STATIC_IPV6_GATEWAY:
2153 nexthop_ipv6_add (rib, &si->ipv6);
2154 break;
2155 case STATIC_IPV6_IFNAME:
2156 nexthop_ifname_add (rib, si->ifname);
2157 break;
2158 case STATIC_IPV6_GATEWAY_IFNAME:
2159 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2160 break;
2161 }
2162
hasso81dfcaa2003-05-25 19:21:25 +00002163 /* Save the flags of this static routes (reject, blackhole) */
2164 rib->flags = si->flags;
2165
paul718e3742002-12-13 20:15:29 +00002166 /* Link this rib to the tree. */
2167 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002168 }
2169}
2170
paula1ac18c2005-06-28 17:17:12 +00002171static int
paul718e3742002-12-13 20:15:29 +00002172static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2173{
2174 if (nexthop->type == NEXTHOP_TYPE_IPV6
2175 && si->type == STATIC_IPV6_GATEWAY
2176 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2177 return 1;
2178 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2179 && si->type == STATIC_IPV6_IFNAME
2180 && strcmp (nexthop->ifname, si->ifname) == 0)
2181 return 1;
2182 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2183 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2184 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2185 && strcmp (nexthop->ifname, si->ifname) == 0)
2186 return 1;
paule8e19462006-01-19 20:16:55 +00002187 return 0;
paul718e3742002-12-13 20:15:29 +00002188}
2189
paula1ac18c2005-06-28 17:17:12 +00002190static void
paul718e3742002-12-13 20:15:29 +00002191static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2192{
2193 struct route_table *table;
2194 struct route_node *rn;
2195 struct rib *rib;
2196 struct nexthop *nexthop;
2197
2198 /* Lookup table. */
2199 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2200 if (! table)
2201 return;
2202
2203 /* Lookup existing route with type and distance. */
2204 rn = route_node_lookup (table, (struct prefix *) p);
2205 if (! rn)
2206 return;
2207
2208 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002209 {
2210 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2211 continue;
2212
2213 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2214 break;
2215 }
2216
paul718e3742002-12-13 20:15:29 +00002217 if (! rib)
2218 {
2219 route_unlock_node (rn);
2220 return;
2221 }
2222
2223 /* Lookup nexthop. */
2224 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2225 if (static_ipv6_nexthop_same (nexthop, si))
2226 break;
2227
2228 /* Can't find nexthop. */
2229 if (! nexthop)
2230 {
2231 route_unlock_node (rn);
2232 return;
2233 }
2234
2235 /* Check nexthop. */
2236 if (rib->nexthop_num == 1)
2237 {
2238 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002239 }
2240 else
2241 {
paul6baeb982003-10-28 03:47:15 +00002242 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2243 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002244 nexthop_delete (rib, nexthop);
2245 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002246 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002247 }
paul718e3742002-12-13 20:15:29 +00002248 /* Unlock node. */
2249 route_unlock_node (rn);
2250}
2251
2252/* Add static route into static route configuration. */
2253int
2254static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002255 const char *ifname, u_char flags, u_char distance,
2256 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002257{
2258 struct route_node *rn;
2259 struct static_ipv6 *si;
2260 struct static_ipv6 *pp;
2261 struct static_ipv6 *cp;
2262 struct route_table *stable;
2263
2264 /* Lookup table. */
2265 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2266 if (! stable)
2267 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002268
2269 if (!gate &&
2270 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2271 return -1;
2272
2273 if (!ifname &&
2274 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2275 return -1;
paul718e3742002-12-13 20:15:29 +00002276
2277 /* Lookup static route prefix. */
2278 rn = route_node_get (stable, p);
2279
2280 /* Do nothing if there is a same static route. */
2281 for (si = rn->info; si; si = si->next)
2282 {
2283 if (distance == si->distance
2284 && type == si->type
2285 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2286 && (! ifname || strcmp (ifname, si->ifname) == 0))
2287 {
2288 route_unlock_node (rn);
2289 return 0;
2290 }
2291 }
2292
2293 /* Make new static route structure. */
2294 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2295 memset (si, 0, sizeof (struct static_ipv6));
2296
2297 si->type = type;
2298 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002299 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002300
2301 switch (type)
2302 {
2303 case STATIC_IPV6_GATEWAY:
2304 si->ipv6 = *gate;
2305 break;
2306 case STATIC_IPV6_IFNAME:
2307 si->ifname = XSTRDUP (0, ifname);
2308 break;
2309 case STATIC_IPV6_GATEWAY_IFNAME:
2310 si->ipv6 = *gate;
2311 si->ifname = XSTRDUP (0, ifname);
2312 break;
2313 }
2314
2315 /* Add new static route information to the tree with sort by
2316 distance value and gateway address. */
2317 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2318 {
2319 if (si->distance < cp->distance)
2320 break;
2321 if (si->distance > cp->distance)
2322 continue;
2323 }
2324
2325 /* Make linked list. */
2326 if (pp)
2327 pp->next = si;
2328 else
2329 rn->info = si;
2330 if (cp)
2331 cp->prev = si;
2332 si->prev = pp;
2333 si->next = cp;
2334
2335 /* Install into rib. */
2336 static_install_ipv6 (p, si);
2337
2338 return 1;
2339}
2340
2341/* Delete static route from static route configuration. */
2342int
2343static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002344 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002345{
2346 struct route_node *rn;
2347 struct static_ipv6 *si;
2348 struct route_table *stable;
2349
2350 /* Lookup table. */
2351 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2352 if (! stable)
2353 return -1;
2354
2355 /* Lookup static route prefix. */
2356 rn = route_node_lookup (stable, p);
2357 if (! rn)
2358 return 0;
2359
2360 /* Find same static route is the tree */
2361 for (si = rn->info; si; si = si->next)
2362 if (distance == si->distance
2363 && type == si->type
2364 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2365 && (! ifname || strcmp (ifname, si->ifname) == 0))
2366 break;
2367
2368 /* Can't find static route. */
2369 if (! si)
2370 {
2371 route_unlock_node (rn);
2372 return 0;
2373 }
2374
2375 /* Install into rib. */
2376 static_uninstall_ipv6 (p, si);
2377
2378 /* Unlink static route from linked list. */
2379 if (si->prev)
2380 si->prev->next = si->next;
2381 else
2382 rn->info = si->next;
2383 if (si->next)
2384 si->next->prev = si->prev;
2385
2386 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002387 if (ifname)
2388 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002389 XFREE (MTYPE_STATIC_IPV6, si);
2390
2391 return 1;
2392}
2393#endif /* HAVE_IPV6 */
2394
2395/* RIB update function. */
2396void
paula1ac18c2005-06-28 17:17:12 +00002397rib_update (void)
paul718e3742002-12-13 20:15:29 +00002398{
2399 struct route_node *rn;
2400 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002401
paul718e3742002-12-13 20:15:29 +00002402 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2403 if (table)
2404 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002405 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002406 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002407
2408 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2409 if (table)
2410 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002411 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002412 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002413}
2414
2415/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002416static void
paul718e3742002-12-13 20:15:29 +00002417rib_if_up (struct interface *ifp)
2418{
2419 rib_update ();
2420}
2421
2422/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002423static void
paul718e3742002-12-13 20:15:29 +00002424rib_if_down (struct interface *ifp)
2425{
2426 rib_update ();
2427}
2428
2429/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002430static void
paul718e3742002-12-13 20:15:29 +00002431rib_weed_table (struct route_table *table)
2432{
2433 struct route_node *rn;
2434 struct rib *rib;
2435 struct rib *next;
2436
2437 if (table)
2438 for (rn = route_top (table); rn; rn = route_next (rn))
2439 for (rib = rn->info; rib; rib = next)
2440 {
2441 next = rib->next;
2442
Paul Jakma6d691122006-07-27 21:49:00 +00002443 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2444 continue;
2445
paulb21b19c2003-06-15 01:28:29 +00002446 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002447 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002448 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002449 }
2450}
2451
2452/* Delete all routes from non main table. */
2453void
paula1ac18c2005-06-28 17:17:12 +00002454rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002455{
2456 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2457 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2458}
2459
2460/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002461static void
paul718e3742002-12-13 20:15:29 +00002462rib_sweep_table (struct route_table *table)
2463{
2464 struct route_node *rn;
2465 struct rib *rib;
2466 struct rib *next;
2467 int ret = 0;
2468
2469 if (table)
2470 for (rn = route_top (table); rn; rn = route_next (rn))
2471 for (rib = rn->info; rib; rib = next)
2472 {
2473 next = rib->next;
2474
Paul Jakma6d691122006-07-27 21:49:00 +00002475 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2476 continue;
2477
paul718e3742002-12-13 20:15:29 +00002478 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2479 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2480 {
2481 ret = rib_uninstall_kernel (rn, rib);
2482 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002483 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002484 }
2485 }
2486}
2487
2488/* Sweep all RIB tables. */
2489void
paula1ac18c2005-06-28 17:17:12 +00002490rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002491{
2492 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2493 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2494}
2495
2496/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002497static void
paul718e3742002-12-13 20:15:29 +00002498rib_close_table (struct route_table *table)
2499{
2500 struct route_node *rn;
2501 struct rib *rib;
2502
2503 if (table)
2504 for (rn = route_top (table); rn; rn = route_next (rn))
2505 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002506 {
2507 if (! RIB_SYSTEM_ROUTE (rib)
2508 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2509 rib_uninstall_kernel (rn, rib);
2510 }
paul718e3742002-12-13 20:15:29 +00002511}
2512
2513/* Close all RIB tables. */
2514void
paula1ac18c2005-06-28 17:17:12 +00002515rib_close (void)
paul718e3742002-12-13 20:15:29 +00002516{
2517 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2518 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2519}
2520
2521/* Routing information base initialize. */
2522void
paula1ac18c2005-06-28 17:17:12 +00002523rib_init (void)
paul718e3742002-12-13 20:15:29 +00002524{
paul4d38fdb2005-04-28 17:35:14 +00002525 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002526 /* VRF initialization. */
2527 vrf_init ();
2528}