blob: 7a63c1c147aa6fd650c16521faf19fa2adad65f8 [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;
Paul Jakma93bdada2007-08-06 19:25:11 +0000901 char buf[INET_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +0000902
903 assert (rn);
904
Paul Jakma93bdada2007-08-06 19:25:11 +0000905 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
906 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
907
paul718e3742002-12-13 20:15:29 +0000908 for (rib = rn->info; rib; rib = next)
909 {
910 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000911
paul718e3742002-12-13 20:15:29 +0000912 /* Currently installed rib. */
913 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +0000914 {
915 assert (fib == NULL);
916 fib = rib;
917 }
918
919 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
920 * which we need to do do further work with below.
921 */
922 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
923 {
924 if (rib != fib)
925 {
926 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +0000927 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
928 buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +0000929 rib_unlink (rn, rib);
930 }
931 else
932 del = rib;
933
934 continue;
935 }
paul4d38fdb2005-04-28 17:35:14 +0000936
paul718e3742002-12-13 20:15:29 +0000937 /* Skip unreachable nexthop. */
938 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000939 continue;
paul718e3742002-12-13 20:15:29 +0000940
941 /* Infinit distance. */
942 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000943 continue;
paul718e3742002-12-13 20:15:29 +0000944
paulaf887b52006-01-18 14:52:52 +0000945 /* Newly selected rib, the common case. */
946 if (!select)
947 {
948 select = rib;
949 continue;
950 }
951
952 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +0000953 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +0000954 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +0000955 * - lower metric beats higher for equal distance
956 * - last, hence oldest, route wins tie break.
957 */
paula1038a12006-01-30 14:08:51 +0000958
959 /* Connected routes. Pick the last connected
960 * route of the set of lowest metric connected routes.
961 */
paula8d9c1f2006-01-25 06:31:04 +0000962 if (rib->type == ZEBRA_ROUTE_CONNECT)
963 {
paula1038a12006-01-30 14:08:51 +0000964 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +0000965 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +0000966 select = rib;
967 continue;
paula8d9c1f2006-01-25 06:31:04 +0000968 }
969 else if (select->type == ZEBRA_ROUTE_CONNECT)
970 continue;
971
972 /* higher distance loses */
973 if (rib->distance > select->distance)
974 continue;
975
976 /* lower wins */
977 if (rib->distance < select->distance)
978 {
paulaf887b52006-01-18 14:52:52 +0000979 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000980 continue;
981 }
982
983 /* metric tie-breaks equal distance */
984 if (rib->metric <= select->metric)
985 select = rib;
paul718e3742002-12-13 20:15:29 +0000986 }
paul4d38fdb2005-04-28 17:35:14 +0000987
paul718e3742002-12-13 20:15:29 +0000988 /* Same route is selected. */
989 if (select && select == fib)
990 {
Paul Jakma6d691122006-07-27 21:49:00 +0000991 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +0000992 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
993 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +0000994 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000995 {
996 redistribute_delete (&rn->p, select);
997 if (! RIB_SYSTEM_ROUTE (select))
998 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000999
paul4d38fdb2005-04-28 17:35:14 +00001000 /* Set real nexthop. */
1001 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001002
paul4d38fdb2005-04-28 17:35:14 +00001003 if (! RIB_SYSTEM_ROUTE (select))
1004 rib_install_kernel (rn, select);
1005 redistribute_add (&rn->p, select);
1006 }
pauld753e9e2003-01-22 19:45:50 +00001007 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001008 {
1009 /* Housekeeping code to deal with
1010 race conditions in kernel with linux
1011 netlink reporting interface up before IPv4 or IPv6 protocol
1012 is ready to add routes.
1013 This makes sure the routes are IN the kernel.
1014 */
pauld753e9e2003-01-22 19:45:50 +00001015
paul4d38fdb2005-04-28 17:35:14 +00001016 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1017 {
1018 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1019 installed = 1;
1020 }
1021 if (! installed)
1022 rib_install_kernel (rn, select);
1023 }
Paul Jakma6d691122006-07-27 21:49:00 +00001024 goto end;
paul718e3742002-12-13 20:15:29 +00001025 }
1026
1027 /* Uninstall old rib from forwarding table. */
1028 if (fib)
1029 {
Paul Jakma6d691122006-07-27 21:49:00 +00001030 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001031 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1032 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001033 redistribute_delete (&rn->p, fib);
1034 if (! RIB_SYSTEM_ROUTE (fib))
1035 rib_uninstall_kernel (rn, fib);
1036 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1037
1038 /* Set real nexthop. */
1039 nexthop_active_update (rn, fib, 1);
1040 }
1041
1042 /* Install new rib into forwarding table. */
1043 if (select)
1044 {
Paul Jakma6d691122006-07-27 21:49:00 +00001045 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001046 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1047 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001048 /* Set real nexthop. */
1049 nexthop_active_update (rn, select, 1);
1050
1051 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001052 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001053 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1054 redistribute_add (&rn->p, select);
1055 }
paul4d38fdb2005-04-28 17:35:14 +00001056
Paul Jakma6d691122006-07-27 21:49:00 +00001057 /* FIB route was removed, should be deleted */
1058 if (del)
1059 {
1060 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001061 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1062 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001063 rib_unlink (rn, del);
1064 }
paul4d38fdb2005-04-28 17:35:14 +00001065
Paul Jakma6d691122006-07-27 21:49:00 +00001066end:
1067 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001068 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001069 if (rn->info)
1070 UNSET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1071 route_unlock_node (rn); /* rib queue lock */
1072 return WQ_SUCCESS;
paul4d38fdb2005-04-28 17:35:14 +00001073}
1074
Paul Jakma6d691122006-07-27 21:49:00 +00001075/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001076static void
Paul Jakma6d691122006-07-27 21:49:00 +00001077rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001078{
Paul Jakma93bdada2007-08-06 19:25:11 +00001079 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001080 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001081
Paul Jakma93bdada2007-08-06 19:25:11 +00001082 if (IS_ZEBRA_DEBUG_RIB_Q)
1083 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1084
Paul Jakma6d691122006-07-27 21:49:00 +00001085 /* Pointless to queue a route_node with no RIB entries to add or remove */
1086 if (!rn->info)
1087 {
1088 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1089 __func__, rn, rn->lock);
1090 zlog_backtrace(LOG_DEBUG);
1091 return;
1092 }
paul4d38fdb2005-04-28 17:35:14 +00001093
Paul Jakma6d691122006-07-27 21:49:00 +00001094 /* Route-table node already queued, so nothing to do */
1095 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED))
1096 {
1097 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001098 zlog_debug ("%s: %s/%d: rn %p already queued", __func__, buf,
1099 rn->p.prefixlen, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001100 return;
1101 }
paul4d38fdb2005-04-28 17:35:14 +00001102
Paul Jakma6d691122006-07-27 21:49:00 +00001103 route_lock_node (rn); /* rib queue lock */
1104
1105 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001106 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001107
1108 assert (zebra);
1109
paul4d38fdb2005-04-28 17:35:14 +00001110 if (zebra->ribq == NULL)
1111 {
Paul Jakma6d691122006-07-27 21:49:00 +00001112 zlog_err ("%s: work_queue does not exist!", __func__);
1113 route_unlock_node (rn);
paul4d38fdb2005-04-28 17:35:14 +00001114 return;
1115 }
1116
Paul Jakma6d691122006-07-27 21:49:00 +00001117 work_queue_add (zebra->ribq, rn);
1118
1119 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED);
1120
1121 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001122 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
paul4d38fdb2005-04-28 17:35:14 +00001123
1124 return;
1125}
1126
paul4d38fdb2005-04-28 17:35:14 +00001127/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001128static void
paul4d38fdb2005-04-28 17:35:14 +00001129rib_queue_init (struct zebra_t *zebra)
1130{
1131 assert (zebra);
1132
1133 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001134 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001135 {
Paul Jakma6d691122006-07-27 21:49:00 +00001136 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001137 return;
1138 }
1139
1140 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001141 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001142 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001143 /* XXX: TODO: These should be runtime configurable via vty */
1144 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001145 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001146
1147 return;
paul718e3742002-12-13 20:15:29 +00001148}
1149
Paul Jakma6d691122006-07-27 21:49:00 +00001150/* RIB updates are processed via a queue of pointers to route_nodes.
1151 *
1152 * The queue length is bounded by the maximal size of the routing table,
1153 * as a route_node will not be requeued, if already queued.
1154 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001155 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1156 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1157 * and then submit route_node to queue for best-path selection later.
1158 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001159 *
1160 * Deleted RIBs are reaped during best-path selection.
1161 *
1162 * rib_addnode
1163 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001164 * |-------->| | best RIB, if required
1165 * | |
1166 * static_install->|->rib_addqueue...... -> rib_process
1167 * | |
1168 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001169 * |-> set RIB_ENTRY_REMOVE |
1170 * rib_delnode (RIB freed)
1171 *
1172 *
1173 * Queueing state for a route_node is kept in the head RIB entry, this
1174 * state must be preserved as and when the head RIB entry of a
1175 * route_node is changed by rib_unlink / rib_link. A small complication,
1176 * but saves having to allocate a dedicated object for this.
1177 *
1178 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1179 *
1180 * - route_nodes: refcounted by:
1181 * - RIBs attached to route_node:
1182 * - managed by: rib_link/unlink
1183 * - route_node processing queue
1184 * - managed by: rib_addqueue, rib_process.
1185 *
1186 */
1187
paul718e3742002-12-13 20:15:29 +00001188/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001189static void
Paul Jakma6d691122006-07-27 21:49:00 +00001190rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001191{
1192 struct rib *head;
Paul Jakma93bdada2007-08-06 19:25:11 +00001193 char buf[INET_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001194
1195 assert (rib && rn);
1196
Paul Jakma6d691122006-07-27 21:49:00 +00001197 route_lock_node (rn); /* rn route table reference */
1198
1199 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001200 {
1201 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1202 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1203 buf, rn->p.prefixlen, rn, rib);
1204 }
Paul Jakma6d691122006-07-27 21:49:00 +00001205
paul718e3742002-12-13 20:15:29 +00001206 head = rn->info;
1207 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001208 {
1209 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001210 zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
1211 buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001212 head->prev = rib;
1213 /* Transfer the rn status flags to the new head RIB */
1214 rib->rn_status = head->rn_status;
1215 }
paul718e3742002-12-13 20:15:29 +00001216 rib->next = head;
1217 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001218 rib_queue_add (&zebrad, rn);
1219}
1220
1221static void
1222rib_addnode (struct route_node *rn, struct rib *rib)
1223{
1224 /* RIB node has been un-removed before route-node is processed.
1225 * route_node must hence already be on the queue for processing..
1226 */
1227 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1228 {
1229 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001230 {
1231 char buf[INET_ADDRSTRLEN];
1232 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1233 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1234 __func__, buf, rn->p.prefixlen, rn, rib);
1235 }
Paul Jakma6d691122006-07-27 21:49:00 +00001236 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1237 return;
1238 }
1239 rib_link (rn, rib);
1240}
1241
1242static void
1243rib_unlink (struct route_node *rn, struct rib *rib)
1244{
1245 struct nexthop *nexthop, *next;
Paul Jakma93bdada2007-08-06 19:25:11 +00001246 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001247
1248 assert (rn && rib);
1249
1250 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001251 {
1252 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1253 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1254 __func__, buf, rn->p.prefixlen, rn, rib);
1255 }
Paul Jakma6d691122006-07-27 21:49:00 +00001256
1257 if (rib->next)
1258 rib->next->prev = rib->prev;
1259
1260 if (rib->prev)
1261 rib->prev->next = rib->next;
1262 else
1263 {
1264 rn->info = rib->next;
1265
1266 if (rn->info)
1267 {
1268 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001269 zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
1270 __func__, buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001271 rib->next->rn_status = rib->rn_status;
1272 }
1273 }
1274
1275 /* free RIB and nexthops */
1276 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1277 {
1278 next = nexthop->next;
1279 nexthop_free (nexthop);
1280 }
1281 XFREE (MTYPE_RIB, rib);
1282
1283 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001284}
1285
paula1ac18c2005-06-28 17:17:12 +00001286static void
paul718e3742002-12-13 20:15:29 +00001287rib_delnode (struct route_node *rn, struct rib *rib)
1288{
Paul Jakma6d691122006-07-27 21:49:00 +00001289 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001290 {
1291 char buf[INET_ADDRSTRLEN];
1292 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1293 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1294 buf, rn->p.prefixlen, rn, rib);
1295 }
Paul Jakma6d691122006-07-27 21:49:00 +00001296 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1297 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001298}
1299
1300int
1301rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001302 struct in_addr *gate, struct in_addr *src,
1303 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001304 u_int32_t metric, u_char distance)
1305{
1306 struct rib *rib;
1307 struct rib *same = NULL;
1308 struct route_table *table;
1309 struct route_node *rn;
1310 struct nexthop *nexthop;
1311
1312 /* Lookup table. */
1313 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1314 if (! table)
1315 return 0;
1316
1317 /* Make it sure prefixlen is applied to the prefix. */
1318 apply_mask_ipv4 (p);
1319
1320 /* Set default distance by route type. */
1321 if (distance == 0)
1322 {
1323 distance = route_info[type].distance;
1324
1325 /* iBGP distance is 200. */
1326 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1327 distance = 200;
1328 }
1329
1330 /* Lookup route node.*/
1331 rn = route_node_get (table, (struct prefix *) p);
1332
1333 /* If same type of route are installed, treat it as a implicit
1334 withdraw. */
1335 for (rib = rn->info; rib; rib = rib->next)
1336 {
Paul Jakma6d691122006-07-27 21:49:00 +00001337 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1338 continue;
1339
hassoebf1ead2005-09-21 14:58:20 +00001340 if (rib->type != type)
1341 continue;
1342 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001343 {
1344 same = rib;
1345 break;
1346 }
hassoebf1ead2005-09-21 14:58:20 +00001347 /* Duplicate connected route comes in. */
1348 else if ((nexthop = rib->nexthop) &&
1349 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001350 nexthop->ifindex == ifindex &&
1351 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001352 {
1353 rib->refcnt++;
1354 return 0 ;
1355 }
paul718e3742002-12-13 20:15:29 +00001356 }
1357
1358 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001359 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001360 rib->type = type;
1361 rib->distance = distance;
1362 rib->flags = flags;
1363 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001364 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001365 rib->nexthop_num = 0;
1366 rib->uptime = time (NULL);
1367
1368 /* Nexthop settings. */
1369 if (gate)
1370 {
1371 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001372 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001373 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001374 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001375 }
1376 else
1377 nexthop_ifindex_add (rib, ifindex);
1378
1379 /* If this route is kernel route, set FIB flag to the route. */
1380 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1381 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1382 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1383
1384 /* Link new rib to node.*/
1385 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001386
paul718e3742002-12-13 20:15:29 +00001387 /* Free implicit route.*/
1388 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001389 rib_delnode (rn, same);
1390
1391 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001392 return 0;
1393}
1394
1395int
1396rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1397{
1398 struct route_table *table;
1399 struct route_node *rn;
1400 struct rib *same;
1401 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001402
paul718e3742002-12-13 20:15:29 +00001403 /* Lookup table. */
1404 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1405 if (! table)
1406 return 0;
paul718e3742002-12-13 20:15:29 +00001407 /* Make it sure prefixlen is applied to the prefix. */
1408 apply_mask_ipv4 (p);
1409
1410 /* Set default distance by route type. */
1411 if (rib->distance == 0)
1412 {
1413 rib->distance = route_info[rib->type].distance;
1414
1415 /* iBGP distance is 200. */
1416 if (rib->type == ZEBRA_ROUTE_BGP
1417 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1418 rib->distance = 200;
1419 }
1420
1421 /* Lookup route node.*/
1422 rn = route_node_get (table, (struct prefix *) p);
1423
1424 /* If same type of route are installed, treat it as a implicit
1425 withdraw. */
1426 for (same = rn->info; same; same = same->next)
1427 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001428 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001429 continue;
1430
paul718e3742002-12-13 20:15:29 +00001431 if (same->type == rib->type && same->table == rib->table
1432 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001433 break;
paul718e3742002-12-13 20:15:29 +00001434 }
paul4d38fdb2005-04-28 17:35:14 +00001435
paul718e3742002-12-13 20:15:29 +00001436 /* If this route is kernel route, set FIB flag to the route. */
1437 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1438 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1439 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1440
1441 /* Link new rib to node.*/
1442 rib_addnode (rn, rib);
1443
paul718e3742002-12-13 20:15:29 +00001444 /* Free implicit route.*/
1445 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001446 rib_delnode (rn, same);
1447
1448 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001449 return 0;
1450}
1451
hassoebf1ead2005-09-21 14:58:20 +00001452/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001453int
1454rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1455 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1456{
1457 struct route_table *table;
1458 struct route_node *rn;
1459 struct rib *rib;
1460 struct rib *fib = NULL;
1461 struct rib *same = NULL;
1462 struct nexthop *nexthop;
1463 char buf1[BUFSIZ];
1464 char buf2[BUFSIZ];
1465
1466 /* Lookup table. */
1467 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1468 if (! table)
1469 return 0;
1470
1471 /* Apply mask. */
1472 apply_mask_ipv4 (p);
1473
paul5ec90d22003-06-19 01:41:37 +00001474 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001475 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001476 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1477 p->prefixlen,
1478 inet_ntoa (*gate),
1479 ifindex);
1480
paul718e3742002-12-13 20:15:29 +00001481 /* Lookup route node. */
1482 rn = route_node_lookup (table, (struct prefix *) p);
1483 if (! rn)
1484 {
1485 if (IS_ZEBRA_DEBUG_KERNEL)
1486 {
1487 if (gate)
ajsb6178002004-12-07 21:12:56 +00001488 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001489 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1490 p->prefixlen,
1491 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1492 ifindex);
1493 else
ajsb6178002004-12-07 21:12:56 +00001494 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001495 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1496 p->prefixlen,
1497 ifindex);
1498 }
1499 return ZEBRA_ERR_RTNOEXIST;
1500 }
1501
1502 /* Lookup same type route. */
1503 for (rib = rn->info; rib; rib = rib->next)
1504 {
Paul Jakma6d691122006-07-27 21:49:00 +00001505 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1506 continue;
1507
paul718e3742002-12-13 20:15:29 +00001508 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1509 fib = rib;
1510
hassoebf1ead2005-09-21 14:58:20 +00001511 if (rib->type != type)
1512 continue;
1513 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1514 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001515 {
hassoebf1ead2005-09-21 14:58:20 +00001516 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001517 {
hassoebf1ead2005-09-21 14:58:20 +00001518 rib->refcnt--;
1519 route_unlock_node (rn);
1520 route_unlock_node (rn);
1521 return 0;
paul718e3742002-12-13 20:15:29 +00001522 }
hassoebf1ead2005-09-21 14:58:20 +00001523 same = rib;
1524 break;
paul718e3742002-12-13 20:15:29 +00001525 }
hassoebf1ead2005-09-21 14:58:20 +00001526 /* Make sure that the route found has the same gateway. */
1527 else if (gate == NULL ||
1528 ((nexthop = rib->nexthop) &&
1529 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1530 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001531 {
hassoebf1ead2005-09-21 14:58:20 +00001532 same = rib;
1533 break;
paul718e3742002-12-13 20:15:29 +00001534 }
1535 }
1536
1537 /* If same type of route can't be found and this message is from
1538 kernel. */
1539 if (! same)
1540 {
1541 if (fib && type == ZEBRA_ROUTE_KERNEL)
1542 {
1543 /* Unset flags. */
1544 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1545 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1546
1547 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1548 }
1549 else
1550 {
1551 if (IS_ZEBRA_DEBUG_KERNEL)
1552 {
1553 if (gate)
ajsb6178002004-12-07 21:12:56 +00001554 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001555 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1556 p->prefixlen,
1557 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1558 ifindex,
1559 type);
1560 else
ajsb6178002004-12-07 21:12:56 +00001561 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001562 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1563 p->prefixlen,
1564 ifindex,
1565 type);
1566 }
1567 route_unlock_node (rn);
1568 return ZEBRA_ERR_RTNOEXIST;
1569 }
1570 }
paul4d38fdb2005-04-28 17:35:14 +00001571
paul718e3742002-12-13 20:15:29 +00001572 if (same)
1573 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001574
paul718e3742002-12-13 20:15:29 +00001575 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001576 return 0;
1577}
1578
1579/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001580static void
paul718e3742002-12-13 20:15:29 +00001581static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1582{
1583 struct rib *rib;
1584 struct route_node *rn;
1585 struct route_table *table;
1586
1587 /* Lookup table. */
1588 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1589 if (! table)
1590 return;
1591
1592 /* Lookup existing route */
1593 rn = route_node_get (table, p);
1594 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001595 {
1596 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1597 continue;
1598
1599 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1600 break;
1601 }
paul718e3742002-12-13 20:15:29 +00001602
1603 if (rib)
1604 {
1605 /* Same distance static route is there. Update it with new
1606 nexthop. */
paul718e3742002-12-13 20:15:29 +00001607 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001608 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001609 {
1610 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001611 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001612 break;
1613 case STATIC_IPV4_IFNAME:
1614 nexthop_ifname_add (rib, si->gate.ifname);
1615 break;
1616 case STATIC_IPV4_BLACKHOLE:
1617 nexthop_blackhole_add (rib);
1618 break;
paul4d38fdb2005-04-28 17:35:14 +00001619 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00001620 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001621 }
1622 else
1623 {
1624 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001625 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1626
paul718e3742002-12-13 20:15:29 +00001627 rib->type = ZEBRA_ROUTE_STATIC;
1628 rib->distance = si->distance;
1629 rib->metric = 0;
1630 rib->nexthop_num = 0;
1631
1632 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001633 {
1634 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00001635 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00001636 break;
1637 case STATIC_IPV4_IFNAME:
1638 nexthop_ifname_add (rib, si->gate.ifname);
1639 break;
1640 case STATIC_IPV4_BLACKHOLE:
1641 nexthop_blackhole_add (rib);
1642 break;
1643 }
paul718e3742002-12-13 20:15:29 +00001644
hasso81dfcaa2003-05-25 19:21:25 +00001645 /* Save the flags of this static routes (reject, blackhole) */
1646 rib->flags = si->flags;
1647
paul718e3742002-12-13 20:15:29 +00001648 /* Link this rib to the tree. */
1649 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001650 }
1651}
1652
paula1ac18c2005-06-28 17:17:12 +00001653static int
paul718e3742002-12-13 20:15:29 +00001654static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1655{
1656 if (nexthop->type == NEXTHOP_TYPE_IPV4
1657 && si->type == STATIC_IPV4_GATEWAY
1658 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1659 return 1;
1660 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1661 && si->type == STATIC_IPV4_IFNAME
1662 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1663 return 1;
paul595db7f2003-05-25 21:35:06 +00001664 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1665 && si->type == STATIC_IPV4_BLACKHOLE)
1666 return 1;
paule8e19462006-01-19 20:16:55 +00001667 return 0;
paul718e3742002-12-13 20:15:29 +00001668}
1669
1670/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001671static void
paul718e3742002-12-13 20:15:29 +00001672static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1673{
1674 struct route_node *rn;
1675 struct rib *rib;
1676 struct nexthop *nexthop;
1677 struct route_table *table;
1678
1679 /* Lookup table. */
1680 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1681 if (! table)
1682 return;
paul4d38fdb2005-04-28 17:35:14 +00001683
paul718e3742002-12-13 20:15:29 +00001684 /* Lookup existing route with type and distance. */
1685 rn = route_node_lookup (table, p);
1686 if (! rn)
1687 return;
1688
1689 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001690 {
1691 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1692 continue;
1693
1694 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1695 break;
1696 }
paul718e3742002-12-13 20:15:29 +00001697
1698 if (! rib)
1699 {
1700 route_unlock_node (rn);
1701 return;
1702 }
1703
1704 /* Lookup nexthop. */
1705 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1706 if (static_ipv4_nexthop_same (nexthop, si))
1707 break;
1708
1709 /* Can't find nexthop. */
1710 if (! nexthop)
1711 {
1712 route_unlock_node (rn);
1713 return;
1714 }
1715
1716 /* Check nexthop. */
1717 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00001718 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001719 else
1720 {
paul6baeb982003-10-28 03:47:15 +00001721 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1722 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001723 nexthop_delete (rib, nexthop);
1724 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001725 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001726 }
paul718e3742002-12-13 20:15:29 +00001727 /* Unlock node. */
1728 route_unlock_node (rn);
1729}
1730
1731/* Add static route into static route configuration. */
1732int
hasso39db97e2004-10-12 20:50:58 +00001733static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001734 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001735{
1736 u_char type = 0;
1737 struct route_node *rn;
1738 struct static_ipv4 *si;
1739 struct static_ipv4 *pp;
1740 struct static_ipv4 *cp;
1741 struct static_ipv4 *update = NULL;
1742 struct route_table *stable;
1743
1744 /* Lookup table. */
1745 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1746 if (! stable)
1747 return -1;
1748
1749 /* Lookup static route prefix. */
1750 rn = route_node_get (stable, p);
1751
1752 /* Make flags. */
1753 if (gate)
1754 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001755 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001756 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001757 else
1758 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001759
1760 /* Do nothing if there is a same static route. */
1761 for (si = rn->info; si; si = si->next)
1762 {
1763 if (type == si->type
1764 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1765 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1766 {
1767 if (distance == si->distance)
1768 {
1769 route_unlock_node (rn);
1770 return 0;
1771 }
1772 else
1773 update = si;
1774 }
1775 }
1776
Paul Jakma3c0755d2006-12-08 00:53:14 +00001777 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00001778 if (update)
1779 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1780
1781 /* Make new static route structure. */
1782 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1783 memset (si, 0, sizeof (struct static_ipv4));
1784
1785 si->type = type;
1786 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001787 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001788
1789 if (gate)
1790 si->gate.ipv4 = *gate;
1791 if (ifname)
1792 si->gate.ifname = XSTRDUP (0, ifname);
1793
1794 /* Add new static route information to the tree with sort by
1795 distance value and gateway address. */
1796 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1797 {
1798 if (si->distance < cp->distance)
1799 break;
1800 if (si->distance > cp->distance)
1801 continue;
1802 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1803 {
1804 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1805 break;
1806 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1807 continue;
1808 }
1809 }
1810
1811 /* Make linked list. */
1812 if (pp)
1813 pp->next = si;
1814 else
1815 rn->info = si;
1816 if (cp)
1817 cp->prev = si;
1818 si->prev = pp;
1819 si->next = cp;
1820
1821 /* Install into rib. */
1822 static_install_ipv4 (p, si);
1823
1824 return 1;
1825}
1826
1827/* Delete static route from static route configuration. */
1828int
hasso39db97e2004-10-12 20:50:58 +00001829static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001830 u_char distance, u_int32_t vrf_id)
1831{
1832 u_char type = 0;
1833 struct route_node *rn;
1834 struct static_ipv4 *si;
1835 struct route_table *stable;
1836
1837 /* Lookup table. */
1838 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1839 if (! stable)
1840 return -1;
1841
1842 /* Lookup static route prefix. */
1843 rn = route_node_lookup (stable, p);
1844 if (! rn)
1845 return 0;
1846
1847 /* Make flags. */
1848 if (gate)
1849 type = STATIC_IPV4_GATEWAY;
1850 else if (ifname)
1851 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001852 else
1853 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001854
1855 /* Find same static route is the tree */
1856 for (si = rn->info; si; si = si->next)
1857 if (type == si->type
1858 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1859 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1860 break;
1861
1862 /* Can't find static route. */
1863 if (! si)
1864 {
1865 route_unlock_node (rn);
1866 return 0;
1867 }
1868
1869 /* Install into rib. */
1870 static_uninstall_ipv4 (p, si);
1871
1872 /* Unlink static route from linked list. */
1873 if (si->prev)
1874 si->prev->next = si->next;
1875 else
1876 rn->info = si->next;
1877 if (si->next)
1878 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001879 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001880
1881 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001882 if (ifname)
1883 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001884 XFREE (MTYPE_STATIC_IPV4, si);
1885
paul143a3852003-09-29 20:06:13 +00001886 route_unlock_node (rn);
1887
paul718e3742002-12-13 20:15:29 +00001888 return 1;
1889}
1890
1891
1892#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001893static int
paul718e3742002-12-13 20:15:29 +00001894rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1895 struct in6_addr *gate, unsigned int ifindex, int table)
1896{
hasso726f9b22003-05-25 21:04:54 +00001897 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1898#if defined (MUSICA) || defined (LINUX)
1899 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1900 if (p->prefixlen == 96)
1901 return 0;
1902#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001903 return 1;
hasso726f9b22003-05-25 21:04:54 +00001904 }
paul718e3742002-12-13 20:15:29 +00001905 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1906 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1907 {
1908 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1909 return 1;
1910 }
1911 return 0;
1912}
1913
1914int
1915rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001916 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1917 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001918{
1919 struct rib *rib;
1920 struct rib *same = NULL;
1921 struct route_table *table;
1922 struct route_node *rn;
1923 struct nexthop *nexthop;
1924
paul718e3742002-12-13 20:15:29 +00001925 /* Lookup table. */
1926 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1927 if (! table)
1928 return 0;
1929
1930 /* Make sure mask is applied. */
1931 apply_mask_ipv6 (p);
1932
1933 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001934 if (!distance)
1935 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001936
1937 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1938 distance = 200;
1939
1940 /* Filter bogus route. */
1941 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1942 return 0;
1943
1944 /* Lookup route node.*/
1945 rn = route_node_get (table, (struct prefix *) p);
1946
1947 /* If same type of route are installed, treat it as a implicit
1948 withdraw. */
1949 for (rib = rn->info; rib; rib = rib->next)
1950 {
Paul Jakma6d691122006-07-27 21:49:00 +00001951 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1952 continue;
1953
hassoebf1ead2005-09-21 14:58:20 +00001954 if (rib->type != type)
1955 continue;
1956 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001957 {
1958 same = rib;
paul718e3742002-12-13 20:15:29 +00001959 break;
1960 }
hassoebf1ead2005-09-21 14:58:20 +00001961 else if ((nexthop = rib->nexthop) &&
1962 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1963 nexthop->ifindex == ifindex)
1964 {
1965 rib->refcnt++;
1966 return 0;
1967 }
paul718e3742002-12-13 20:15:29 +00001968 }
1969
1970 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001971 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1972
paul718e3742002-12-13 20:15:29 +00001973 rib->type = type;
1974 rib->distance = distance;
1975 rib->flags = flags;
1976 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001977 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001978 rib->nexthop_num = 0;
1979 rib->uptime = time (NULL);
1980
1981 /* Nexthop settings. */
1982 if (gate)
1983 {
1984 if (ifindex)
1985 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1986 else
1987 nexthop_ipv6_add (rib, gate);
1988 }
1989 else
1990 nexthop_ifindex_add (rib, ifindex);
1991
1992 /* If this route is kernel route, set FIB flag to the route. */
1993 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1994 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1995 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1996
1997 /* Link new rib to node.*/
1998 rib_addnode (rn, rib);
1999
paul718e3742002-12-13 20:15:29 +00002000 /* Free implicit route.*/
2001 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002002 rib_delnode (rn, same);
2003
2004 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002005 return 0;
2006}
2007
hassoebf1ead2005-09-21 14:58:20 +00002008/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002009int
2010rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2011 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
2012{
2013 struct route_table *table;
2014 struct route_node *rn;
2015 struct rib *rib;
2016 struct rib *fib = NULL;
2017 struct rib *same = NULL;
2018 struct nexthop *nexthop;
2019 char buf1[BUFSIZ];
2020 char buf2[BUFSIZ];
2021
2022 /* Apply mask. */
2023 apply_mask_ipv6 (p);
2024
2025 /* Lookup table. */
2026 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2027 if (! table)
2028 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002029
paul718e3742002-12-13 20:15:29 +00002030 /* Lookup route node. */
2031 rn = route_node_lookup (table, (struct prefix *) p);
2032 if (! rn)
2033 {
2034 if (IS_ZEBRA_DEBUG_KERNEL)
2035 {
2036 if (gate)
ajsb6178002004-12-07 21:12:56 +00002037 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002038 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2039 p->prefixlen,
2040 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2041 ifindex);
2042 else
ajsb6178002004-12-07 21:12:56 +00002043 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002044 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2045 p->prefixlen,
2046 ifindex);
2047 }
2048 return ZEBRA_ERR_RTNOEXIST;
2049 }
2050
2051 /* Lookup same type route. */
2052 for (rib = rn->info; rib; rib = rib->next)
2053 {
Paul Jakma6d691122006-07-27 21:49:00 +00002054 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2055 continue;
2056
paul718e3742002-12-13 20:15:29 +00002057 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2058 fib = rib;
2059
hassoebf1ead2005-09-21 14:58:20 +00002060 if (rib->type != type)
2061 continue;
2062 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2063 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002064 {
hassoebf1ead2005-09-21 14:58:20 +00002065 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002066 {
hassoebf1ead2005-09-21 14:58:20 +00002067 rib->refcnt--;
2068 route_unlock_node (rn);
2069 route_unlock_node (rn);
2070 return 0;
paul718e3742002-12-13 20:15:29 +00002071 }
hassoebf1ead2005-09-21 14:58:20 +00002072 same = rib;
2073 break;
paul718e3742002-12-13 20:15:29 +00002074 }
hassoebf1ead2005-09-21 14:58:20 +00002075 /* Make sure that the route found has the same gateway. */
2076 else if (gate == NULL ||
2077 ((nexthop = rib->nexthop) &&
2078 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2079 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002080 {
hassoebf1ead2005-09-21 14:58:20 +00002081 same = rib;
2082 break;
paul718e3742002-12-13 20:15:29 +00002083 }
2084 }
2085
2086 /* If same type of route can't be found and this message is from
2087 kernel. */
2088 if (! same)
2089 {
2090 if (fib && type == ZEBRA_ROUTE_KERNEL)
2091 {
2092 /* Unset flags. */
2093 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2094 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2095
2096 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2097 }
2098 else
2099 {
2100 if (IS_ZEBRA_DEBUG_KERNEL)
2101 {
2102 if (gate)
ajsb6178002004-12-07 21:12:56 +00002103 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002104 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2105 p->prefixlen,
2106 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2107 ifindex,
2108 type);
2109 else
ajsb6178002004-12-07 21:12:56 +00002110 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002111 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2112 p->prefixlen,
2113 ifindex,
2114 type);
2115 }
2116 route_unlock_node (rn);
2117 return ZEBRA_ERR_RTNOEXIST;
2118 }
2119 }
2120
2121 if (same)
2122 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002123
paul718e3742002-12-13 20:15:29 +00002124 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002125 return 0;
2126}
2127
2128/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002129static void
paul718e3742002-12-13 20:15:29 +00002130static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2131{
2132 struct rib *rib;
2133 struct route_table *table;
2134 struct route_node *rn;
2135
2136 /* Lookup table. */
2137 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2138 if (! table)
2139 return;
2140
2141 /* Lookup existing route */
2142 rn = route_node_get (table, p);
2143 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002144 {
2145 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2146 continue;
2147
2148 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2149 break;
2150 }
paul718e3742002-12-13 20:15:29 +00002151
2152 if (rib)
2153 {
2154 /* Same distance static route is there. Update it with new
2155 nexthop. */
paul718e3742002-12-13 20:15:29 +00002156 route_unlock_node (rn);
2157
2158 switch (si->type)
2159 {
2160 case STATIC_IPV6_GATEWAY:
2161 nexthop_ipv6_add (rib, &si->ipv6);
2162 break;
2163 case STATIC_IPV6_IFNAME:
2164 nexthop_ifname_add (rib, si->ifname);
2165 break;
2166 case STATIC_IPV6_GATEWAY_IFNAME:
2167 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2168 break;
2169 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002170 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002171 }
2172 else
2173 {
2174 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002175 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2176
paul718e3742002-12-13 20:15:29 +00002177 rib->type = ZEBRA_ROUTE_STATIC;
2178 rib->distance = si->distance;
2179 rib->metric = 0;
2180 rib->nexthop_num = 0;
2181
2182 switch (si->type)
2183 {
2184 case STATIC_IPV6_GATEWAY:
2185 nexthop_ipv6_add (rib, &si->ipv6);
2186 break;
2187 case STATIC_IPV6_IFNAME:
2188 nexthop_ifname_add (rib, si->ifname);
2189 break;
2190 case STATIC_IPV6_GATEWAY_IFNAME:
2191 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2192 break;
2193 }
2194
hasso81dfcaa2003-05-25 19:21:25 +00002195 /* Save the flags of this static routes (reject, blackhole) */
2196 rib->flags = si->flags;
2197
paul718e3742002-12-13 20:15:29 +00002198 /* Link this rib to the tree. */
2199 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002200 }
2201}
2202
paula1ac18c2005-06-28 17:17:12 +00002203static int
paul718e3742002-12-13 20:15:29 +00002204static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2205{
2206 if (nexthop->type == NEXTHOP_TYPE_IPV6
2207 && si->type == STATIC_IPV6_GATEWAY
2208 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2209 return 1;
2210 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2211 && si->type == STATIC_IPV6_IFNAME
2212 && strcmp (nexthop->ifname, si->ifname) == 0)
2213 return 1;
2214 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2215 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2216 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2217 && strcmp (nexthop->ifname, si->ifname) == 0)
2218 return 1;
paule8e19462006-01-19 20:16:55 +00002219 return 0;
paul718e3742002-12-13 20:15:29 +00002220}
2221
paula1ac18c2005-06-28 17:17:12 +00002222static void
paul718e3742002-12-13 20:15:29 +00002223static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2224{
2225 struct route_table *table;
2226 struct route_node *rn;
2227 struct rib *rib;
2228 struct nexthop *nexthop;
2229
2230 /* Lookup table. */
2231 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2232 if (! table)
2233 return;
2234
2235 /* Lookup existing route with type and distance. */
2236 rn = route_node_lookup (table, (struct prefix *) p);
2237 if (! rn)
2238 return;
2239
2240 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002241 {
2242 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2243 continue;
2244
2245 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2246 break;
2247 }
2248
paul718e3742002-12-13 20:15:29 +00002249 if (! rib)
2250 {
2251 route_unlock_node (rn);
2252 return;
2253 }
2254
2255 /* Lookup nexthop. */
2256 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2257 if (static_ipv6_nexthop_same (nexthop, si))
2258 break;
2259
2260 /* Can't find nexthop. */
2261 if (! nexthop)
2262 {
2263 route_unlock_node (rn);
2264 return;
2265 }
2266
2267 /* Check nexthop. */
2268 if (rib->nexthop_num == 1)
2269 {
2270 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002271 }
2272 else
2273 {
paul6baeb982003-10-28 03:47:15 +00002274 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2275 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002276 nexthop_delete (rib, nexthop);
2277 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002278 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002279 }
paul718e3742002-12-13 20:15:29 +00002280 /* Unlock node. */
2281 route_unlock_node (rn);
2282}
2283
2284/* Add static route into static route configuration. */
2285int
2286static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002287 const char *ifname, u_char flags, u_char distance,
2288 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002289{
2290 struct route_node *rn;
2291 struct static_ipv6 *si;
2292 struct static_ipv6 *pp;
2293 struct static_ipv6 *cp;
2294 struct route_table *stable;
2295
2296 /* Lookup table. */
2297 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2298 if (! stable)
2299 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002300
2301 if (!gate &&
2302 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2303 return -1;
2304
2305 if (!ifname &&
2306 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2307 return -1;
paul718e3742002-12-13 20:15:29 +00002308
2309 /* Lookup static route prefix. */
2310 rn = route_node_get (stable, p);
2311
2312 /* Do nothing if there is a same static route. */
2313 for (si = rn->info; si; si = si->next)
2314 {
2315 if (distance == si->distance
2316 && type == si->type
2317 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2318 && (! ifname || strcmp (ifname, si->ifname) == 0))
2319 {
2320 route_unlock_node (rn);
2321 return 0;
2322 }
2323 }
2324
2325 /* Make new static route structure. */
2326 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2327 memset (si, 0, sizeof (struct static_ipv6));
2328
2329 si->type = type;
2330 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002331 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002332
2333 switch (type)
2334 {
2335 case STATIC_IPV6_GATEWAY:
2336 si->ipv6 = *gate;
2337 break;
2338 case STATIC_IPV6_IFNAME:
2339 si->ifname = XSTRDUP (0, ifname);
2340 break;
2341 case STATIC_IPV6_GATEWAY_IFNAME:
2342 si->ipv6 = *gate;
2343 si->ifname = XSTRDUP (0, ifname);
2344 break;
2345 }
2346
2347 /* Add new static route information to the tree with sort by
2348 distance value and gateway address. */
2349 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2350 {
2351 if (si->distance < cp->distance)
2352 break;
2353 if (si->distance > cp->distance)
2354 continue;
2355 }
2356
2357 /* Make linked list. */
2358 if (pp)
2359 pp->next = si;
2360 else
2361 rn->info = si;
2362 if (cp)
2363 cp->prev = si;
2364 si->prev = pp;
2365 si->next = cp;
2366
2367 /* Install into rib. */
2368 static_install_ipv6 (p, si);
2369
2370 return 1;
2371}
2372
2373/* Delete static route from static route configuration. */
2374int
2375static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002376 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002377{
2378 struct route_node *rn;
2379 struct static_ipv6 *si;
2380 struct route_table *stable;
2381
2382 /* Lookup table. */
2383 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2384 if (! stable)
2385 return -1;
2386
2387 /* Lookup static route prefix. */
2388 rn = route_node_lookup (stable, p);
2389 if (! rn)
2390 return 0;
2391
2392 /* Find same static route is the tree */
2393 for (si = rn->info; si; si = si->next)
2394 if (distance == si->distance
2395 && type == si->type
2396 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2397 && (! ifname || strcmp (ifname, si->ifname) == 0))
2398 break;
2399
2400 /* Can't find static route. */
2401 if (! si)
2402 {
2403 route_unlock_node (rn);
2404 return 0;
2405 }
2406
2407 /* Install into rib. */
2408 static_uninstall_ipv6 (p, si);
2409
2410 /* Unlink static route from linked list. */
2411 if (si->prev)
2412 si->prev->next = si->next;
2413 else
2414 rn->info = si->next;
2415 if (si->next)
2416 si->next->prev = si->prev;
2417
2418 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002419 if (ifname)
2420 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002421 XFREE (MTYPE_STATIC_IPV6, si);
2422
2423 return 1;
2424}
2425#endif /* HAVE_IPV6 */
2426
2427/* RIB update function. */
2428void
paula1ac18c2005-06-28 17:17:12 +00002429rib_update (void)
paul718e3742002-12-13 20:15:29 +00002430{
2431 struct route_node *rn;
2432 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002433
paul718e3742002-12-13 20:15:29 +00002434 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2435 if (table)
2436 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002437 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002438 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002439
2440 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2441 if (table)
2442 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002443 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002444 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002445}
2446
2447/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002448static void
paul718e3742002-12-13 20:15:29 +00002449rib_if_up (struct interface *ifp)
2450{
2451 rib_update ();
2452}
2453
2454/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002455static void
paul718e3742002-12-13 20:15:29 +00002456rib_if_down (struct interface *ifp)
2457{
2458 rib_update ();
2459}
2460
2461/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002462static void
paul718e3742002-12-13 20:15:29 +00002463rib_weed_table (struct route_table *table)
2464{
2465 struct route_node *rn;
2466 struct rib *rib;
2467 struct rib *next;
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
paulb21b19c2003-06-15 01:28:29 +00002478 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002479 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002480 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002481 }
2482}
2483
2484/* Delete all routes from non main table. */
2485void
paula1ac18c2005-06-28 17:17:12 +00002486rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002487{
2488 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2489 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2490}
2491
2492/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002493static void
paul718e3742002-12-13 20:15:29 +00002494rib_sweep_table (struct route_table *table)
2495{
2496 struct route_node *rn;
2497 struct rib *rib;
2498 struct rib *next;
2499 int ret = 0;
2500
2501 if (table)
2502 for (rn = route_top (table); rn; rn = route_next (rn))
2503 for (rib = rn->info; rib; rib = next)
2504 {
2505 next = rib->next;
2506
Paul Jakma6d691122006-07-27 21:49:00 +00002507 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2508 continue;
2509
paul718e3742002-12-13 20:15:29 +00002510 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2511 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2512 {
2513 ret = rib_uninstall_kernel (rn, rib);
2514 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002515 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002516 }
2517 }
2518}
2519
2520/* Sweep all RIB tables. */
2521void
paula1ac18c2005-06-28 17:17:12 +00002522rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002523{
2524 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2525 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2526}
2527
2528/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002529static void
paul718e3742002-12-13 20:15:29 +00002530rib_close_table (struct route_table *table)
2531{
2532 struct route_node *rn;
2533 struct rib *rib;
2534
2535 if (table)
2536 for (rn = route_top (table); rn; rn = route_next (rn))
2537 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002538 {
2539 if (! RIB_SYSTEM_ROUTE (rib)
2540 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2541 rib_uninstall_kernel (rn, rib);
2542 }
paul718e3742002-12-13 20:15:29 +00002543}
2544
2545/* Close all RIB tables. */
2546void
paula1ac18c2005-06-28 17:17:12 +00002547rib_close (void)
paul718e3742002-12-13 20:15:29 +00002548{
2549 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2550 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2551}
2552
2553/* Routing information base initialize. */
2554void
paula1ac18c2005-06-28 17:17:12 +00002555rib_init (void)
paul718e3742002-12-13 20:15:29 +00002556{
paul4d38fdb2005-04-28 17:35:14 +00002557 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002558 /* VRF initialization. */
2559 vrf_init ();
2560}