blob: 4cb72ba8c8ed3c3146c0689a0d906842dba2883d [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "str.h"
28#include "command.h"
29#include "if.h"
30#include "log.h"
31#include "sockunion.h"
paul4d38fdb2005-04-28 17:35:14 +000032#include "linklist.h"
33#include "thread.h"
34#include "workqueue.h"
Paul Jakma7514fb72007-05-02 16:05:35 +000035#include "prefix.h"
36#include "routemap.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "zebra/rib.h"
39#include "zebra/rt.h"
40#include "zebra/zserv.h"
41#include "zebra/redistribute.h"
42#include "zebra/debug.h"
43
44/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000045extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000046
Paul Jakma457eb9a2006-07-27 19:59:58 +000047/* Hold time for RIB process, should be very minimal.
48 * it is useful to able to set it otherwise for testing, hence exported
49 * as global here for test-rig code.
50 */
51int rib_process_hold_time = 10;
52
paul718e3742002-12-13 20:15:29 +000053/* Each route type's string and default distance value. */
54struct
55{
56 int key;
57 int distance;
58} route_info[] =
59{
60 {ZEBRA_ROUTE_SYSTEM, 0},
61 {ZEBRA_ROUTE_KERNEL, 0},
62 {ZEBRA_ROUTE_CONNECT, 0},
63 {ZEBRA_ROUTE_STATIC, 1},
64 {ZEBRA_ROUTE_RIP, 120},
65 {ZEBRA_ROUTE_RIPNG, 120},
66 {ZEBRA_ROUTE_OSPF, 110},
67 {ZEBRA_ROUTE_OSPF6, 110},
jardin9e867fe2003-12-23 08:56:18 +000068 {ZEBRA_ROUTE_ISIS, 115},
paul718e3742002-12-13 20:15:29 +000069 {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
70};
71
72/* Vector for routing table. */
73vector vrf_vector;
74
75/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +000076static struct vrf *
hassofce954f2004-10-07 20:29:24 +000077vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +000078{
79 struct vrf *vrf;
80
81 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
82
83 /* Put name. */
84 if (name)
85 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
86
87 /* Allocate routing table and static table. */
88 vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
89 vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
90 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
91 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
92
93 return vrf;
94}
95
96/* Free VRF. */
paula1ac18c2005-06-28 17:17:12 +000097static void
paul718e3742002-12-13 20:15:29 +000098vrf_free (struct vrf *vrf)
99{
100 if (vrf->name)
101 XFREE (MTYPE_VRF_NAME, vrf->name);
102 XFREE (MTYPE_VRF, vrf);
103}
104
105/* Lookup VRF by identifier. */
106struct vrf *
107vrf_lookup (u_int32_t id)
108{
109 return vector_lookup (vrf_vector, id);
110}
111
112/* Lookup VRF by name. */
paula1ac18c2005-06-28 17:17:12 +0000113static struct vrf *
paul718e3742002-12-13 20:15:29 +0000114vrf_lookup_by_name (char *name)
115{
hassofce954f2004-10-07 20:29:24 +0000116 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000117 struct vrf *vrf;
118
paul55468c82005-03-14 20:19:01 +0000119 for (i = 0; i < vector_active (vrf_vector); i++)
paul718e3742002-12-13 20:15:29 +0000120 if ((vrf = vector_slot (vrf_vector, i)) != NULL)
121 if (vrf->name && name && strcmp (vrf->name, name) == 0)
122 return vrf;
123 return NULL;
124}
125
126/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000127static void
128vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000129{
130 struct vrf *default_table;
131
132 /* Allocate VRF vector. */
133 vrf_vector = vector_init (1);
134
135 /* Allocate default main table. */
136 default_table = vrf_alloc ("Default-IP-Routing-Table");
137
138 /* Default table index must be 0. */
139 vector_set_index (vrf_vector, 0, default_table);
140}
141
142/* Lookup route table. */
143struct route_table *
144vrf_table (afi_t afi, safi_t safi, u_int32_t id)
145{
146 struct vrf *vrf;
147
148 vrf = vrf_lookup (id);
149 if (! vrf)
150 return NULL;
151
152 return vrf->table[afi][safi];
153}
154
155/* Lookup static route table. */
156struct route_table *
157vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
158{
159 struct vrf *vrf;
160
161 vrf = vrf_lookup (id);
162 if (! vrf)
163 return NULL;
164
165 return vrf->stable[afi][safi];
166}
167
168/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000169static void
paul718e3742002-12-13 20:15:29 +0000170nexthop_add (struct rib *rib, struct nexthop *nexthop)
171{
172 struct nexthop *last;
173
174 for (last = rib->nexthop; last && last->next; last = last->next)
175 ;
176 if (last)
177 last->next = nexthop;
178 else
179 rib->nexthop = nexthop;
180 nexthop->prev = last;
181
182 rib->nexthop_num++;
183}
184
185/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000186static void
paul718e3742002-12-13 20:15:29 +0000187nexthop_delete (struct rib *rib, struct nexthop *nexthop)
188{
189 if (nexthop->next)
190 nexthop->next->prev = nexthop->prev;
191 if (nexthop->prev)
192 nexthop->prev->next = nexthop->next;
193 else
194 rib->nexthop = nexthop->next;
195 rib->nexthop_num--;
196}
197
198/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000199static void
paul718e3742002-12-13 20:15:29 +0000200nexthop_free (struct nexthop *nexthop)
201{
paula4b70762003-05-16 17:19:48 +0000202 if (nexthop->ifname)
203 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000204 XFREE (MTYPE_NEXTHOP, nexthop);
205}
206
207struct nexthop *
208nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
209{
210 struct nexthop *nexthop;
211
212 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
213 memset (nexthop, 0, sizeof (struct nexthop));
214 nexthop->type = NEXTHOP_TYPE_IFINDEX;
215 nexthop->ifindex = ifindex;
216
217 nexthop_add (rib, nexthop);
218
219 return nexthop;
220}
221
222struct nexthop *
223nexthop_ifname_add (struct rib *rib, char *ifname)
224{
225 struct nexthop *nexthop;
226
227 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
228 memset (nexthop, 0, sizeof (struct nexthop));
229 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000230 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000231
232 nexthop_add (rib, nexthop);
233
234 return nexthop;
235}
236
237struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000238nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000239{
240 struct nexthop *nexthop;
241
242 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
243 memset (nexthop, 0, sizeof (struct nexthop));
244 nexthop->type = NEXTHOP_TYPE_IPV4;
245 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000246 if (src)
247 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000248
249 nexthop_add (rib, nexthop);
250
251 return nexthop;
252}
253
paula1ac18c2005-06-28 17:17:12 +0000254static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000255nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000256 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000257{
258 struct nexthop *nexthop;
259
260 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
261 memset (nexthop, 0, sizeof (struct nexthop));
262 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
263 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000264 if (src)
265 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000266 nexthop->ifindex = ifindex;
267
268 nexthop_add (rib, nexthop);
269
270 return nexthop;
271}
272
273#ifdef HAVE_IPV6
274struct nexthop *
275nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
276{
277 struct nexthop *nexthop;
278
279 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
280 memset (nexthop, 0, sizeof (struct nexthop));
281 nexthop->type = NEXTHOP_TYPE_IPV6;
282 nexthop->gate.ipv6 = *ipv6;
283
284 nexthop_add (rib, nexthop);
285
286 return nexthop;
287}
288
paula1ac18c2005-06-28 17:17:12 +0000289static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000290nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
291 char *ifname)
292{
293 struct nexthop *nexthop;
294
295 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
296 memset (nexthop, 0, sizeof (struct nexthop));
297 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
298 nexthop->gate.ipv6 = *ipv6;
299 nexthop->ifname = XSTRDUP (0, ifname);
300
301 nexthop_add (rib, nexthop);
302
303 return nexthop;
304}
305
paula1ac18c2005-06-28 17:17:12 +0000306static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000307nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
308 unsigned int ifindex)
309{
310 struct nexthop *nexthop;
311
312 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
313 memset (nexthop, 0, sizeof (struct nexthop));
314 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
315 nexthop->gate.ipv6 = *ipv6;
316 nexthop->ifindex = ifindex;
317
318 nexthop_add (rib, nexthop);
319
320 return nexthop;
321}
322#endif /* HAVE_IPV6 */
323
paul595db7f2003-05-25 21:35:06 +0000324struct nexthop *
325nexthop_blackhole_add (struct rib *rib)
326{
327 struct nexthop *nexthop;
328
329 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
330 memset (nexthop, 0, sizeof (struct nexthop));
331 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
332 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
333
334 nexthop_add (rib, nexthop);
335
336 return nexthop;
337}
338
paul718e3742002-12-13 20:15:29 +0000339/* If force flag is not set, do not modify falgs at all for uninstall
340 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000341static int
paul718e3742002-12-13 20:15:29 +0000342nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
343 struct route_node *top)
344{
345 struct prefix_ipv4 p;
346 struct route_table *table;
347 struct route_node *rn;
348 struct rib *match;
349 struct nexthop *newhop;
350
351 if (nexthop->type == NEXTHOP_TYPE_IPV4)
352 nexthop->ifindex = 0;
353
354 if (set)
355 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
356
357 /* Make lookup prefix. */
358 memset (&p, 0, sizeof (struct prefix_ipv4));
359 p.family = AF_INET;
360 p.prefixlen = IPV4_MAX_PREFIXLEN;
361 p.prefix = nexthop->gate.ipv4;
362
363 /* Lookup table. */
364 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
365 if (! table)
366 return 0;
367
368 rn = route_node_match (table, (struct prefix *) &p);
369 while (rn)
370 {
371 route_unlock_node (rn);
372
373 /* If lookup self prefix return immidiately. */
374 if (rn == top)
375 return 0;
376
377 /* Pick up selected route. */
378 for (match = rn->info; match; match = match->next)
379 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
380 break;
381
382 /* If there is no selected route or matched route is EGP, go up
383 tree. */
384 if (! match
385 || match->type == ZEBRA_ROUTE_BGP)
386 {
387 do {
388 rn = rn->parent;
389 } while (rn && rn->info == NULL);
390 if (rn)
391 route_lock_node (rn);
392 }
393 else
394 {
395 if (match->type == ZEBRA_ROUTE_CONNECT)
396 {
397 /* Directly point connected route. */
398 newhop = match->nexthop;
399 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
400 nexthop->ifindex = newhop->ifindex;
401
402 return 1;
403 }
404 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
405 {
406 for (newhop = match->nexthop; newhop; newhop = newhop->next)
407 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
408 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
409 {
410 if (set)
411 {
412 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
413 nexthop->rtype = newhop->type;
414 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
415 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
416 nexthop->rgate.ipv4 = newhop->gate.ipv4;
417 if (newhop->type == NEXTHOP_TYPE_IFINDEX
418 || newhop->type == NEXTHOP_TYPE_IFNAME
419 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
420 nexthop->rifindex = newhop->ifindex;
421 }
422 return 1;
423 }
424 return 0;
425 }
426 else
427 {
428 return 0;
429 }
430 }
431 }
432 return 0;
433}
434
435#ifdef HAVE_IPV6
436/* If force flag is not set, do not modify falgs at all for uninstall
437 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000438static int
paul718e3742002-12-13 20:15:29 +0000439nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
440 struct route_node *top)
441{
442 struct prefix_ipv6 p;
443 struct route_table *table;
444 struct route_node *rn;
445 struct rib *match;
446 struct nexthop *newhop;
447
448 if (nexthop->type == NEXTHOP_TYPE_IPV6)
449 nexthop->ifindex = 0;
450
451 if (set)
452 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
453
454 /* Make lookup prefix. */
455 memset (&p, 0, sizeof (struct prefix_ipv6));
456 p.family = AF_INET6;
457 p.prefixlen = IPV6_MAX_PREFIXLEN;
458 p.prefix = nexthop->gate.ipv6;
459
460 /* Lookup table. */
461 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
462 if (! table)
463 return 0;
464
465 rn = route_node_match (table, (struct prefix *) &p);
466 while (rn)
467 {
468 route_unlock_node (rn);
469
470 /* If lookup self prefix return immidiately. */
471 if (rn == top)
472 return 0;
473
474 /* Pick up selected route. */
475 for (match = rn->info; match; match = match->next)
476 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
477 break;
478
479 /* If there is no selected route or matched route is EGP, go up
480 tree. */
481 if (! match
482 || match->type == ZEBRA_ROUTE_BGP)
483 {
484 do {
485 rn = rn->parent;
486 } while (rn && rn->info == NULL);
487 if (rn)
488 route_lock_node (rn);
489 }
490 else
491 {
492 if (match->type == ZEBRA_ROUTE_CONNECT)
493 {
494 /* Directly point connected route. */
495 newhop = match->nexthop;
496
497 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
498 nexthop->ifindex = newhop->ifindex;
499
500 return 1;
501 }
502 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
503 {
504 for (newhop = match->nexthop; newhop; newhop = newhop->next)
505 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
506 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
507 {
508 if (set)
509 {
510 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
511 nexthop->rtype = newhop->type;
512 if (newhop->type == NEXTHOP_TYPE_IPV6
513 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
514 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
515 nexthop->rgate.ipv6 = newhop->gate.ipv6;
516 if (newhop->type == NEXTHOP_TYPE_IFINDEX
517 || newhop->type == NEXTHOP_TYPE_IFNAME
518 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
519 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
520 nexthop->rifindex = newhop->ifindex;
521 }
522 return 1;
523 }
524 return 0;
525 }
526 else
527 {
528 return 0;
529 }
530 }
531 }
532 return 0;
533}
534#endif /* HAVE_IPV6 */
535
536struct rib *
537rib_match_ipv4 (struct in_addr addr)
538{
539 struct prefix_ipv4 p;
540 struct route_table *table;
541 struct route_node *rn;
542 struct rib *match;
543 struct nexthop *newhop;
544
545 /* Lookup table. */
546 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
547 if (! table)
548 return 0;
549
550 memset (&p, 0, sizeof (struct prefix_ipv4));
551 p.family = AF_INET;
552 p.prefixlen = IPV4_MAX_PREFIXLEN;
553 p.prefix = addr;
554
555 rn = route_node_match (table, (struct prefix *) &p);
556
557 while (rn)
558 {
559 route_unlock_node (rn);
560
561 /* Pick up selected route. */
562 for (match = rn->info; match; match = match->next)
563 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
564 break;
565
566 /* If there is no selected route or matched route is EGP, go up
567 tree. */
568 if (! match
569 || match->type == ZEBRA_ROUTE_BGP)
570 {
571 do {
572 rn = rn->parent;
573 } while (rn && rn->info == NULL);
574 if (rn)
575 route_lock_node (rn);
576 }
577 else
578 {
579 if (match->type == ZEBRA_ROUTE_CONNECT)
580 /* Directly point connected route. */
581 return match;
582 else
583 {
584 for (newhop = match->nexthop; newhop; newhop = newhop->next)
585 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
586 return match;
587 return NULL;
588 }
589 }
590 }
591 return NULL;
592}
593
594struct rib *
595rib_lookup_ipv4 (struct prefix_ipv4 *p)
596{
597 struct route_table *table;
598 struct route_node *rn;
599 struct rib *match;
600 struct nexthop *nexthop;
601
602 /* Lookup table. */
603 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
604 if (! table)
605 return 0;
606
607 rn = route_node_lookup (table, (struct prefix *) p);
608
609 /* No route for this prefix. */
610 if (! rn)
611 return NULL;
612
613 /* Unlock node. */
614 route_unlock_node (rn);
615
616 /* Pick up selected route. */
617 for (match = rn->info; match; match = match->next)
618 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
619 break;
620
621 if (! match || match->type == ZEBRA_ROUTE_BGP)
622 return NULL;
623
624 if (match->type == ZEBRA_ROUTE_CONNECT)
625 return match;
626
627 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
628 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
629 return match;
630
631 return NULL;
632}
633
Denis Ovsienkodc958242007-08-13 16:03:06 +0000634/*
635 * This clone function, unlike its original rib_lookup_ipv4(), checks
636 * if specified IPv4 route record (prefix/mask -> gate) exists in
637 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
638 *
639 * Return values:
640 * -1: error
641 * 0: exact match found
642 * 1: a match was found with a different gate
643 * 2: connected route found
644 * 3: no matches found
645 */
646int
647rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
648{
649 struct route_table *table;
650 struct route_node *rn;
651 struct rib *match;
652 struct nexthop *nexthop;
653
654 /* Lookup table. */
655 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
656 if (! table)
657 return ZEBRA_RIB_LOOKUP_ERROR;
658
659 /* Scan the RIB table for exactly matching RIB entry. */
660 rn = route_node_lookup (table, (struct prefix *) p);
661
662 /* No route for this prefix. */
663 if (! rn)
664 return ZEBRA_RIB_NOTFOUND;
665
666 /* Unlock node. */
667 route_unlock_node (rn);
668
669 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
670 for (match = rn->info; match; match = match->next)
671 {
672 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
673 continue;
674 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
675 break;
676 }
677
678 /* None such found :( */
679 if (!match)
680 return ZEBRA_RIB_NOTFOUND;
681
682 if (match->type == ZEBRA_ROUTE_CONNECT)
683 return ZEBRA_RIB_FOUND_CONNECTED;
684
685 /* Ok, we have a cood candidate, let's check it's nexthop list... */
686 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
687 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
688 {
689 /* We are happy with either direct or recursive hexthop */
690 if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr ||
691 nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr)
692 return ZEBRA_RIB_FOUND_EXACT;
693 else
694 {
695 if (IS_ZEBRA_DEBUG_RIB)
696 {
697 char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
698 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
699 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
700 inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN);
701 zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
702 }
703 return ZEBRA_RIB_FOUND_NOGATE;
704 }
705 }
706
707 return ZEBRA_RIB_NOTFOUND;
708}
709
paul718e3742002-12-13 20:15:29 +0000710#ifdef HAVE_IPV6
711struct rib *
712rib_match_ipv6 (struct in6_addr *addr)
713{
714 struct prefix_ipv6 p;
715 struct route_table *table;
716 struct route_node *rn;
717 struct rib *match;
718 struct nexthop *newhop;
719
720 /* Lookup table. */
721 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
722 if (! table)
723 return 0;
724
725 memset (&p, 0, sizeof (struct prefix_ipv6));
726 p.family = AF_INET6;
727 p.prefixlen = IPV6_MAX_PREFIXLEN;
728 IPV6_ADDR_COPY (&p.prefix, addr);
729
730 rn = route_node_match (table, (struct prefix *) &p);
731
732 while (rn)
733 {
734 route_unlock_node (rn);
735
736 /* Pick up selected route. */
737 for (match = rn->info; match; match = match->next)
738 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
739 break;
740
741 /* If there is no selected route or matched route is EGP, go up
742 tree. */
743 if (! match
744 || match->type == ZEBRA_ROUTE_BGP)
745 {
746 do {
747 rn = rn->parent;
748 } while (rn && rn->info == NULL);
749 if (rn)
750 route_lock_node (rn);
751 }
752 else
753 {
754 if (match->type == ZEBRA_ROUTE_CONNECT)
755 /* Directly point connected route. */
756 return match;
757 else
758 {
759 for (newhop = match->nexthop; newhop; newhop = newhop->next)
760 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
761 return match;
762 return NULL;
763 }
764 }
765 }
766 return NULL;
767}
768#endif /* HAVE_IPV6 */
769
Paul Jakma7514fb72007-05-02 16:05:35 +0000770#define RIB_SYSTEM_ROUTE(R) \
771 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
772
Denis Ovsienkodc958242007-08-13 16:03:06 +0000773/* This function verifies reachability of one given nexthop, which can be
774 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
775 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
776 * nexthop->ifindex will be updated appropriately as well.
777 * An existing route map can turn (otherwise active) nexthop into inactive, but
778 * not vice versa.
779 *
780 * The return value is the final value of 'ACTIVE' flag.
781 */
782
paula1ac18c2005-06-28 17:17:12 +0000783static int
paul718e3742002-12-13 20:15:29 +0000784nexthop_active_check (struct route_node *rn, struct rib *rib,
785 struct nexthop *nexthop, int set)
786{
787 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000788 route_map_result_t ret = RMAP_MATCH;
789 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
790 struct route_map *rmap;
791 int family;
paul718e3742002-12-13 20:15:29 +0000792
Paul Jakma7514fb72007-05-02 16:05:35 +0000793 family = 0;
paul718e3742002-12-13 20:15:29 +0000794 switch (nexthop->type)
795 {
796 case NEXTHOP_TYPE_IFINDEX:
797 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000798 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000799 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
800 else
801 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
802 break;
paul718e3742002-12-13 20:15:29 +0000803 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000804 family = AFI_IP6;
805 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000806 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000807 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000808 {
809 if (set)
810 nexthop->ifindex = ifp->ifindex;
811 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
812 }
813 else
814 {
815 if (set)
816 nexthop->ifindex = 0;
817 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
818 }
819 break;
820 case NEXTHOP_TYPE_IPV4:
821 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000822 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000823 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
824 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
825 else
826 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
827 break;
828#ifdef HAVE_IPV6
829 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000830 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000831 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
832 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
833 else
834 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
835 break;
836 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000837 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000838 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
839 {
840 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000841 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000842 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
843 else
844 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
845 }
846 else
847 {
848 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
849 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
850 else
851 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
852 }
853 break;
854#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000855 case NEXTHOP_TYPE_BLACKHOLE:
856 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
857 break;
paul718e3742002-12-13 20:15:29 +0000858 default:
859 break;
860 }
Paul Jakma7514fb72007-05-02 16:05:35 +0000861 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
862 return 0;
863
864 if (RIB_SYSTEM_ROUTE(rib) ||
865 (family == AFI_IP && rn->p.family != AF_INET) ||
866 (family == AFI_IP6 && rn->p.family != AF_INET6))
867 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
868
869 rmap = 0;
870 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
871 proto_rm[family][rib->type])
872 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
873 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
874 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
875 if (rmap) {
876 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
877 }
878
879 if (ret == RMAP_DENYMATCH)
880 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000881 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
882}
883
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000884/* Iterate over all nexthops of the given RIB entry and refresh their
885 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
886 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
887 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
888 * transparently passed to nexthop_active_check().
889 *
890 * Return value is the new number of active nexthops.
891 */
892
paula1ac18c2005-06-28 17:17:12 +0000893static int
paul718e3742002-12-13 20:15:29 +0000894nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
895{
896 struct nexthop *nexthop;
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000897 int prev_active, new_active;
paul718e3742002-12-13 20:15:29 +0000898
899 rib->nexthop_active_num = 0;
900 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
901
902 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000903 {
904 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
905 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
906 rib->nexthop_active_num++;
907 if (prev_active != new_active)
908 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
909 }
paul718e3742002-12-13 20:15:29 +0000910 return rib->nexthop_active_num;
911}
paul6baeb982003-10-28 03:47:15 +0000912
paul718e3742002-12-13 20:15:29 +0000913
paul718e3742002-12-13 20:15:29 +0000914
paula1ac18c2005-06-28 17:17:12 +0000915static void
paul718e3742002-12-13 20:15:29 +0000916rib_install_kernel (struct route_node *rn, struct rib *rib)
917{
918 int ret = 0;
919 struct nexthop *nexthop;
920
921 switch (PREFIX_FAMILY (&rn->p))
922 {
923 case AF_INET:
924 ret = kernel_add_ipv4 (&rn->p, rib);
925 break;
926#ifdef HAVE_IPV6
927 case AF_INET6:
928 ret = kernel_add_ipv6 (&rn->p, rib);
929 break;
930#endif /* HAVE_IPV6 */
931 }
932
Denis Ovsienkodc958242007-08-13 16:03:06 +0000933 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +0000934 if (ret < 0)
935 {
936 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
937 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
938 }
939}
940
941/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000942static int
paul718e3742002-12-13 20:15:29 +0000943rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
944{
945 int ret = 0;
946 struct nexthop *nexthop;
947
948 switch (PREFIX_FAMILY (&rn->p))
949 {
950 case AF_INET:
951 ret = kernel_delete_ipv4 (&rn->p, rib);
952 break;
953#ifdef HAVE_IPV6
954 case AF_INET6:
Denis Ovsienkodc958242007-08-13 16:03:06 +0000955 if (IS_ZEBRA_DEBUG_RIB)
956 zlog_debug ("%s: calling kernel_delete_ipv4 (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +0000957 ret = kernel_delete_ipv6 (&rn->p, rib);
958 break;
959#endif /* HAVE_IPV6 */
960 }
961
962 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
963 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
964
965 return ret;
966}
967
968/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000969static void
paul718e3742002-12-13 20:15:29 +0000970rib_uninstall (struct route_node *rn, struct rib *rib)
971{
972 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
973 {
974 redistribute_delete (&rn->p, rib);
975 if (! RIB_SYSTEM_ROUTE (rib))
976 rib_uninstall_kernel (rn, rib);
977 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
978 }
979}
980
Paul Jakma6d691122006-07-27 21:49:00 +0000981static void rib_unlink (struct route_node *, struct rib *);
982
paul718e3742002-12-13 20:15:29 +0000983/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +0000984static void
985rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +0000986{
987 struct rib *rib;
988 struct rib *next;
989 struct rib *fib = NULL;
990 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +0000991 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +0000992 int installed = 0;
993 struct nexthop *nexthop = NULL;
Denis Ovsienkof304cb42007-10-03 12:27:16 +0000994 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +0000995
996 assert (rn);
997
Paul Jakma93bdada2007-08-06 19:25:11 +0000998 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
Denis Ovsienkof304cb42007-10-03 12:27:16 +0000999 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001000
paul718e3742002-12-13 20:15:29 +00001001 for (rib = rn->info; rib; rib = next)
1002 {
Denis Ovsienkodc958242007-08-13 16:03:06 +00001003 /* The next pointer is saved, because current pointer
1004 * may be passed to rib_unlink() in the middle of iteration.
1005 */
paul718e3742002-12-13 20:15:29 +00001006 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +00001007
paul718e3742002-12-13 20:15:29 +00001008 /* Currently installed rib. */
1009 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001010 {
1011 assert (fib == NULL);
1012 fib = rib;
1013 }
1014
1015 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1016 * which we need to do do further work with below.
1017 */
1018 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1019 {
1020 if (rib != fib)
1021 {
1022 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001023 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
1024 buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001025 rib_unlink (rn, rib);
1026 }
1027 else
1028 del = rib;
1029
1030 continue;
1031 }
paul4d38fdb2005-04-28 17:35:14 +00001032
paul718e3742002-12-13 20:15:29 +00001033 /* Skip unreachable nexthop. */
1034 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001035 continue;
paul718e3742002-12-13 20:15:29 +00001036
1037 /* Infinit distance. */
1038 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001039 continue;
paul718e3742002-12-13 20:15:29 +00001040
paulaf887b52006-01-18 14:52:52 +00001041 /* Newly selected rib, the common case. */
1042 if (!select)
1043 {
1044 select = rib;
1045 continue;
1046 }
1047
1048 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001049 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001050 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001051 * - lower metric beats higher for equal distance
1052 * - last, hence oldest, route wins tie break.
1053 */
paula1038a12006-01-30 14:08:51 +00001054
1055 /* Connected routes. Pick the last connected
1056 * route of the set of lowest metric connected routes.
1057 */
paula8d9c1f2006-01-25 06:31:04 +00001058 if (rib->type == ZEBRA_ROUTE_CONNECT)
1059 {
paula1038a12006-01-30 14:08:51 +00001060 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001061 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001062 select = rib;
1063 continue;
paula8d9c1f2006-01-25 06:31:04 +00001064 }
1065 else if (select->type == ZEBRA_ROUTE_CONNECT)
1066 continue;
1067
1068 /* higher distance loses */
1069 if (rib->distance > select->distance)
1070 continue;
1071
1072 /* lower wins */
1073 if (rib->distance < select->distance)
1074 {
paulaf887b52006-01-18 14:52:52 +00001075 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001076 continue;
1077 }
1078
1079 /* metric tie-breaks equal distance */
1080 if (rib->metric <= select->metric)
1081 select = rib;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001082 } /* for (rib = rn->info; rib; rib = next) */
1083
1084 /* After the cycle is finished, the following pointers will be set:
1085 * select --- the winner RIB entry, if any was found, otherwise NULL
1086 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1087 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1088 * rib --- NULL
1089 */
1090
1091 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001092 if (select && select == fib)
1093 {
Paul Jakma6d691122006-07-27 21:49:00 +00001094 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001095 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
1096 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +00001097 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001098 {
1099 redistribute_delete (&rn->p, select);
1100 if (! RIB_SYSTEM_ROUTE (select))
1101 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001102
paul4d38fdb2005-04-28 17:35:14 +00001103 /* Set real nexthop. */
1104 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001105
paul4d38fdb2005-04-28 17:35:14 +00001106 if (! RIB_SYSTEM_ROUTE (select))
1107 rib_install_kernel (rn, select);
1108 redistribute_add (&rn->p, select);
1109 }
pauld753e9e2003-01-22 19:45:50 +00001110 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001111 {
1112 /* Housekeeping code to deal with
1113 race conditions in kernel with linux
1114 netlink reporting interface up before IPv4 or IPv6 protocol
1115 is ready to add routes.
1116 This makes sure the routes are IN the kernel.
1117 */
pauld753e9e2003-01-22 19:45:50 +00001118
paul4d38fdb2005-04-28 17:35:14 +00001119 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001120 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001121 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001122 installed = 1;
1123 break;
paul4d38fdb2005-04-28 17:35:14 +00001124 }
1125 if (! installed)
1126 rib_install_kernel (rn, select);
1127 }
Paul Jakma6d691122006-07-27 21:49:00 +00001128 goto end;
paul718e3742002-12-13 20:15:29 +00001129 }
1130
Denis Ovsienkodc958242007-08-13 16:03:06 +00001131 /* At this point we either haven't found the best RIB entry or it is
1132 * different from what we currently intend to flag with SELECTED. In both
1133 * cases, if a RIB block is present in FIB, it should be withdrawn.
1134 */
paul718e3742002-12-13 20:15:29 +00001135 if (fib)
1136 {
Paul Jakma6d691122006-07-27 21:49:00 +00001137 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001138 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1139 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001140 redistribute_delete (&rn->p, fib);
1141 if (! RIB_SYSTEM_ROUTE (fib))
1142 rib_uninstall_kernel (rn, fib);
1143 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1144
1145 /* Set real nexthop. */
1146 nexthop_active_update (rn, fib, 1);
1147 }
1148
Denis Ovsienkodc958242007-08-13 16:03:06 +00001149 /* Regardless of some RIB entry being SELECTED or not before, now we can
1150 * tell, that if a new winner exists, FIB is still not updated with this
1151 * data, but ready to be.
1152 */
paul718e3742002-12-13 20:15:29 +00001153 if (select)
1154 {
Paul Jakma6d691122006-07-27 21:49:00 +00001155 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001156 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1157 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001158 /* Set real nexthop. */
1159 nexthop_active_update (rn, select, 1);
1160
1161 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001162 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001163 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1164 redistribute_add (&rn->p, select);
1165 }
paul4d38fdb2005-04-28 17:35:14 +00001166
Paul Jakma6d691122006-07-27 21:49:00 +00001167 /* FIB route was removed, should be deleted */
1168 if (del)
1169 {
1170 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001171 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1172 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001173 rib_unlink (rn, del);
1174 }
paul4d38fdb2005-04-28 17:35:14 +00001175
Paul Jakma6d691122006-07-27 21:49:00 +00001176end:
1177 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001178 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001179}
1180
1181/* Take a list of route_node structs and return 1, if there was a record picked from
1182 * it and processed by rib_process(). Don't process more, than one RN record; operate
1183 * only in the specified sub-queue.
1184 */
1185unsigned int
1186process_subq (struct list * subq, u_char qindex)
1187{
1188 struct listnode *lnode;
1189 struct route_node *rnode;
1190 if (!(lnode = listhead (subq)))
1191 return 0;
1192 rnode = listgetdata (lnode);
1193 rib_process (rnode);
1194 if (rnode->info) /* The first RIB record is holding the flags bitmask. */
1195 UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
1196 route_unlock_node (rnode);
1197 list_delete_node (subq, lnode);
1198 return 1;
1199}
1200
1201/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1202 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1203 * is pointed to the meta queue structure.
1204 */
1205static wq_item_status
1206meta_queue_process (struct work_queue *dummy, void *data)
1207{
1208 struct meta_queue * mq = data;
1209 u_char i;
1210 for (i = 0; i < MQ_SIZE; i++)
1211 if (process_subq (mq->subq[i], i))
1212 {
1213 mq->size--;
1214 break;
1215 }
1216 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1217}
1218
1219/* Look into the RN and queue it into one or more priority queues, increasing the size
1220 * for each data push done.
1221 */
1222void rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
1223{
1224 u_char qindex;
1225 struct rib *rib;
1226 char buf[INET6_ADDRSTRLEN];
1227 if (IS_ZEBRA_DEBUG_RIB_Q)
1228 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
1229 for (rib = rn->info; rib; rib = rib->next)
1230 {
1231 switch (rib->type)
1232 {
1233 case ZEBRA_ROUTE_KERNEL:
1234 case ZEBRA_ROUTE_CONNECT:
1235 qindex = 0;
1236 break;
1237 case ZEBRA_ROUTE_STATIC:
1238 qindex = 1;
1239 break;
1240 case ZEBRA_ROUTE_RIP:
1241 case ZEBRA_ROUTE_RIPNG:
1242 case ZEBRA_ROUTE_OSPF:
1243 case ZEBRA_ROUTE_OSPF6:
1244 case ZEBRA_ROUTE_ISIS:
1245 qindex = 2;
1246 break;
1247 case ZEBRA_ROUTE_BGP:
1248 qindex = 3;
1249 break;
1250 default:
1251 qindex = 4;
1252 break;
1253 }
1254 /* Invariant: at this point we always have rn->info set. */
1255 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)))
1256 {
1257 if (IS_ZEBRA_DEBUG_RIB_Q)
1258 zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex);
1259 continue;
1260 }
1261 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
1262 listnode_add (mq->subq[qindex], rn);
1263 route_lock_node (rn);
1264 mq->size++;
1265 if (IS_ZEBRA_DEBUG_RIB_Q)
1266 zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex);
1267 }
paul4d38fdb2005-04-28 17:35:14 +00001268}
1269
Paul Jakma6d691122006-07-27 21:49:00 +00001270/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001271static void
Paul Jakma6d691122006-07-27 21:49:00 +00001272rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001273{
Paul Jakma93bdada2007-08-06 19:25:11 +00001274 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001275 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001276
Paul Jakma93bdada2007-08-06 19:25:11 +00001277 if (IS_ZEBRA_DEBUG_RIB_Q)
1278 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1279
Paul Jakma6d691122006-07-27 21:49:00 +00001280 /* Pointless to queue a route_node with no RIB entries to add or remove */
1281 if (!rn->info)
1282 {
1283 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1284 __func__, rn, rn->lock);
1285 zlog_backtrace(LOG_DEBUG);
1286 return;
1287 }
paul4d38fdb2005-04-28 17:35:14 +00001288
Paul Jakma6d691122006-07-27 21:49:00 +00001289 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001290 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001291
1292 assert (zebra);
1293
paul4d38fdb2005-04-28 17:35:14 +00001294 if (zebra->ribq == NULL)
1295 {
Paul Jakma6d691122006-07-27 21:49:00 +00001296 zlog_err ("%s: work_queue does not exist!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001297 return;
1298 }
Paul Jakma6d691122006-07-27 21:49:00 +00001299
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001300 /* The RIB queue should normally be either empty or holding the only work_queue_item
1301 * element. In the latter case this element would hold a pointer to the meta queue
1302 * structure, which must be used to actually queue the route nodes to process. So
1303 * create the MQ holder, if necessary, then push the work into it in any case.
1304 * This semantics was introduced after 0.99.9 release.
1305 */
1306
1307 /* Should I invent work_queue_empty() and use it, or it's Ok to do as follows? */
1308 if (!zebra->ribq->items->count)
1309 work_queue_add (zebra->ribq, zebra->mq);
1310
1311 rib_meta_queue_add (zebra->mq, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001312
1313 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001314 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
paul4d38fdb2005-04-28 17:35:14 +00001315
1316 return;
1317}
1318
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001319/* Create new meta queue. A destructor function doesn't seem to be necessary here. */
1320struct meta_queue *
1321meta_queue_new ()
1322{
1323 struct meta_queue *new;
1324 unsigned i, failed = 0;
1325
1326 if ((new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue))) == NULL)
1327 return NULL;
1328 for (i = 0; i < MQ_SIZE; i++)
1329 if ((new->subq[i] = list_new ()) == NULL)
1330 failed = 1;
1331 if (failed)
1332 {
1333 for (i = 0; i < MQ_SIZE; i++)
1334 if (new->subq[i])
1335 list_delete (new->subq[i]);
1336 XFREE (MTYPE_WORK_QUEUE, new);
1337 return NULL;
1338 }
1339 new->size = 0;
1340 return new;
1341}
1342
paul4d38fdb2005-04-28 17:35:14 +00001343/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001344static void
paul4d38fdb2005-04-28 17:35:14 +00001345rib_queue_init (struct zebra_t *zebra)
1346{
1347 assert (zebra);
1348
1349 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001350 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001351 {
Paul Jakma6d691122006-07-27 21:49:00 +00001352 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001353 return;
1354 }
1355
1356 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001357 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001358 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001359 /* XXX: TODO: These should be runtime configurable via vty */
1360 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001361 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001362
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001363 if (!(zebra->mq = meta_queue_new ()))
1364 {
1365 zlog_err ("%s: could not initialise meta queue!", __func__);
1366 return;
1367 }
paul4d38fdb2005-04-28 17:35:14 +00001368 return;
paul718e3742002-12-13 20:15:29 +00001369}
1370
Paul Jakma6d691122006-07-27 21:49:00 +00001371/* RIB updates are processed via a queue of pointers to route_nodes.
1372 *
1373 * The queue length is bounded by the maximal size of the routing table,
1374 * as a route_node will not be requeued, if already queued.
1375 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001376 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1377 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1378 * and then submit route_node to queue for best-path selection later.
1379 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001380 *
1381 * Deleted RIBs are reaped during best-path selection.
1382 *
1383 * rib_addnode
1384 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001385 * |-------->| | best RIB, if required
1386 * | |
1387 * static_install->|->rib_addqueue...... -> rib_process
1388 * | |
1389 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001390 * |-> set RIB_ENTRY_REMOVE |
1391 * rib_delnode (RIB freed)
1392 *
1393 *
1394 * Queueing state for a route_node is kept in the head RIB entry, this
1395 * state must be preserved as and when the head RIB entry of a
1396 * route_node is changed by rib_unlink / rib_link. A small complication,
1397 * but saves having to allocate a dedicated object for this.
1398 *
1399 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1400 *
1401 * - route_nodes: refcounted by:
1402 * - RIBs attached to route_node:
1403 * - managed by: rib_link/unlink
1404 * - route_node processing queue
1405 * - managed by: rib_addqueue, rib_process.
1406 *
1407 */
1408
paul718e3742002-12-13 20:15:29 +00001409/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001410static void
Paul Jakma6d691122006-07-27 21:49:00 +00001411rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001412{
1413 struct rib *head;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001414 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001415
1416 assert (rib && rn);
1417
Paul Jakma6d691122006-07-27 21:49:00 +00001418 route_lock_node (rn); /* rn route table reference */
1419
1420 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001421 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001422 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001423 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1424 buf, rn->p.prefixlen, rn, rib);
1425 }
Paul Jakma6d691122006-07-27 21:49:00 +00001426
paul718e3742002-12-13 20:15:29 +00001427 head = rn->info;
1428 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001429 {
1430 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001431 zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
1432 buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001433 head->prev = rib;
1434 /* Transfer the rn status flags to the new head RIB */
1435 rib->rn_status = head->rn_status;
1436 }
paul718e3742002-12-13 20:15:29 +00001437 rib->next = head;
1438 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001439 rib_queue_add (&zebrad, rn);
1440}
1441
1442static void
1443rib_addnode (struct route_node *rn, struct rib *rib)
1444{
1445 /* RIB node has been un-removed before route-node is processed.
1446 * route_node must hence already be on the queue for processing..
1447 */
1448 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1449 {
1450 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001451 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001452 char buf[INET6_ADDRSTRLEN];
1453 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001454 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1455 __func__, buf, rn->p.prefixlen, rn, rib);
1456 }
Paul Jakma6d691122006-07-27 21:49:00 +00001457 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1458 return;
1459 }
1460 rib_link (rn, rib);
1461}
1462
1463static void
1464rib_unlink (struct route_node *rn, struct rib *rib)
1465{
1466 struct nexthop *nexthop, *next;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001467 char buf[INET6_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001468
1469 assert (rn && rib);
1470
1471 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001472 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001473 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001474 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1475 __func__, buf, rn->p.prefixlen, rn, rib);
1476 }
Paul Jakma6d691122006-07-27 21:49:00 +00001477
1478 if (rib->next)
1479 rib->next->prev = rib->prev;
1480
1481 if (rib->prev)
1482 rib->prev->next = rib->next;
1483 else
1484 {
1485 rn->info = rib->next;
1486
1487 if (rn->info)
1488 {
1489 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001490 zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
1491 __func__, buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001492 rib->next->rn_status = rib->rn_status;
1493 }
1494 }
1495
1496 /* free RIB and nexthops */
1497 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1498 {
1499 next = nexthop->next;
1500 nexthop_free (nexthop);
1501 }
1502 XFREE (MTYPE_RIB, rib);
1503
1504 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001505}
1506
paula1ac18c2005-06-28 17:17:12 +00001507static void
paul718e3742002-12-13 20:15:29 +00001508rib_delnode (struct route_node *rn, struct rib *rib)
1509{
Paul Jakma6d691122006-07-27 21:49:00 +00001510 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001511 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001512 char buf[INET6_ADDRSTRLEN];
1513 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001514 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1515 buf, rn->p.prefixlen, rn, rib);
1516 }
Paul Jakma6d691122006-07-27 21:49:00 +00001517 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1518 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001519}
1520
1521int
1522rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001523 struct in_addr *gate, struct in_addr *src,
1524 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001525 u_int32_t metric, u_char distance)
1526{
1527 struct rib *rib;
1528 struct rib *same = NULL;
1529 struct route_table *table;
1530 struct route_node *rn;
1531 struct nexthop *nexthop;
1532
1533 /* Lookup table. */
1534 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1535 if (! table)
1536 return 0;
1537
1538 /* Make it sure prefixlen is applied to the prefix. */
1539 apply_mask_ipv4 (p);
1540
1541 /* Set default distance by route type. */
1542 if (distance == 0)
1543 {
1544 distance = route_info[type].distance;
1545
1546 /* iBGP distance is 200. */
1547 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1548 distance = 200;
1549 }
1550
1551 /* Lookup route node.*/
1552 rn = route_node_get (table, (struct prefix *) p);
1553
1554 /* If same type of route are installed, treat it as a implicit
1555 withdraw. */
1556 for (rib = rn->info; rib; rib = rib->next)
1557 {
Paul Jakma6d691122006-07-27 21:49:00 +00001558 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1559 continue;
1560
hassoebf1ead2005-09-21 14:58:20 +00001561 if (rib->type != type)
1562 continue;
1563 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001564 {
1565 same = rib;
1566 break;
1567 }
hassoebf1ead2005-09-21 14:58:20 +00001568 /* Duplicate connected route comes in. */
1569 else if ((nexthop = rib->nexthop) &&
1570 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001571 nexthop->ifindex == ifindex &&
1572 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001573 {
1574 rib->refcnt++;
1575 return 0 ;
1576 }
paul718e3742002-12-13 20:15:29 +00001577 }
1578
1579 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001580 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001581 rib->type = type;
1582 rib->distance = distance;
1583 rib->flags = flags;
1584 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001585 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001586 rib->nexthop_num = 0;
1587 rib->uptime = time (NULL);
1588
1589 /* Nexthop settings. */
1590 if (gate)
1591 {
1592 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001593 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001594 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001595 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001596 }
1597 else
1598 nexthop_ifindex_add (rib, ifindex);
1599
1600 /* If this route is kernel route, set FIB flag to the route. */
1601 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1602 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1603 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1604
1605 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001606 if (IS_ZEBRA_DEBUG_RIB)
1607 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001608 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001609
paul718e3742002-12-13 20:15:29 +00001610 /* Free implicit route.*/
1611 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001612 {
1613 if (IS_ZEBRA_DEBUG_RIB)
1614 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001615 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001616 }
paul4d38fdb2005-04-28 17:35:14 +00001617
1618 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001619 return 0;
1620}
1621
Denis Ovsienkodc958242007-08-13 16:03:06 +00001622/* This function dumps the contents of a given RIB entry into
1623 * standard debug log. Calling function name and IP prefix in
1624 * question are passed as 1st and 2nd arguments.
1625 */
1626
1627void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1628{
1629 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1630 struct nexthop *nexthop;
1631
1632 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1633 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1634 zlog_debug
1635 (
1636 "%s: refcnt == %lu, uptime == %u, type == %u, table == %d",
1637 func,
1638 rib->refcnt,
1639 rib->uptime,
1640 rib->type,
1641 rib->table
1642 );
1643 zlog_debug
1644 (
1645 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1646 func,
1647 rib->metric,
1648 rib->distance,
1649 rib->flags,
1650 rib->status
1651 );
1652 zlog_debug
1653 (
1654 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1655 func,
1656 rib->nexthop_num,
1657 rib->nexthop_active_num,
1658 rib->nexthop_fib_num
1659 );
1660 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1661 {
1662 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1663 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1664 zlog_debug
1665 (
1666 "%s: NH %s (%s) with flags %s%s%s",
1667 func,
1668 straddr1,
1669 straddr2,
1670 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1671 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1672 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1673 );
1674 }
1675 zlog_debug ("%s: dump complete", func);
1676}
1677
1678/* This is an exported helper to rtm_read() to dump the strange
1679 * RIB entry found by rib_lookup_ipv4_route()
1680 */
1681
1682void rib_lookup_and_dump (struct prefix_ipv4 * p)
1683{
1684 struct route_table *table;
1685 struct route_node *rn;
1686 struct rib *rib;
1687 char prefix_buf[INET_ADDRSTRLEN];
1688
1689 /* Lookup table. */
1690 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1691 if (! table)
1692 {
1693 zlog_err ("%s: vrf_table() returned NULL", __func__);
1694 return;
1695 }
1696
1697 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1698 /* Scan the RIB table for exactly matching RIB entry. */
1699 rn = route_node_lookup (table, (struct prefix *) p);
1700
1701 /* No route for this prefix. */
1702 if (! rn)
1703 {
1704 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1705 return;
1706 }
1707
1708 /* Unlock node. */
1709 route_unlock_node (rn);
1710
1711 /* let's go */
1712 for (rib = rn->info; rib; rib = rib->next)
1713 {
1714 zlog_debug
1715 (
1716 "%s: rn %p, rib %p: %s, %s",
1717 __func__,
1718 rn,
1719 rib,
1720 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1721 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1722 );
1723 rib_dump (__func__, p, rib);
1724 }
1725}
1726
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001727/* Check if requested address assignment will fail due to another
1728 * route being installed by zebra in FIB already. Take necessary
1729 * actions, if needed: remove such a route from FIB and deSELECT
1730 * corresponding RIB entry. Then put affected RN into RIBQ head.
1731 */
1732void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1733{
1734 struct route_table *table;
1735 struct route_node *rn;
1736 struct rib *rib;
1737 unsigned changed = 0;
1738
1739 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
1740 {
1741 zlog_err ("%s: vrf_table() returned NULL", __func__);
1742 return;
1743 }
1744
1745 /* No matches would be the simplest case. */
1746 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1747 return;
1748
1749 /* Unlock node. */
1750 route_unlock_node (rn);
1751
1752 /* Check all RIB entries. In case any changes have to be done, requeue
1753 * the RN into RIBQ head. If the routing message about the new connected
1754 * route (generated by the IP address we are going to assign very soon)
1755 * comes before the RIBQ is processed, the new RIB entry will join
1756 * RIBQ record already on head. This is necessary for proper revalidation
1757 * of the rest of the RIB.
1758 */
1759 for (rib = rn->info; rib; rib = rib->next)
1760 {
1761 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1762 ! RIB_SYSTEM_ROUTE (rib))
1763 {
1764 changed = 1;
1765 if (IS_ZEBRA_DEBUG_RIB)
1766 {
1767 char buf[INET_ADDRSTRLEN];
1768 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
1769 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
1770 rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
1771 }
1772 rib_uninstall (rn, rib);
1773 }
1774 }
1775 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001776 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001777}
1778
paul718e3742002-12-13 20:15:29 +00001779int
1780rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1781{
1782 struct route_table *table;
1783 struct route_node *rn;
1784 struct rib *same;
1785 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001786
paul718e3742002-12-13 20:15:29 +00001787 /* Lookup table. */
1788 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1789 if (! table)
1790 return 0;
paul718e3742002-12-13 20:15:29 +00001791 /* Make it sure prefixlen is applied to the prefix. */
1792 apply_mask_ipv4 (p);
1793
1794 /* Set default distance by route type. */
1795 if (rib->distance == 0)
1796 {
1797 rib->distance = route_info[rib->type].distance;
1798
1799 /* iBGP distance is 200. */
1800 if (rib->type == ZEBRA_ROUTE_BGP
1801 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1802 rib->distance = 200;
1803 }
1804
1805 /* Lookup route node.*/
1806 rn = route_node_get (table, (struct prefix *) p);
1807
1808 /* If same type of route are installed, treat it as a implicit
1809 withdraw. */
1810 for (same = rn->info; same; same = same->next)
1811 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001812 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001813 continue;
1814
paul718e3742002-12-13 20:15:29 +00001815 if (same->type == rib->type && same->table == rib->table
1816 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001817 break;
paul718e3742002-12-13 20:15:29 +00001818 }
paul4d38fdb2005-04-28 17:35:14 +00001819
paul718e3742002-12-13 20:15:29 +00001820 /* If this route is kernel route, set FIB flag to the route. */
1821 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1822 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1823 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1824
1825 /* Link new rib to node.*/
1826 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001827 if (IS_ZEBRA_DEBUG_RIB)
1828 {
1829 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1830 __func__, rn, rib);
1831 rib_dump (__func__, p, rib);
1832 }
paul718e3742002-12-13 20:15:29 +00001833
paul718e3742002-12-13 20:15:29 +00001834 /* Free implicit route.*/
1835 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001836 {
1837 if (IS_ZEBRA_DEBUG_RIB)
1838 {
1839 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1840 __func__, rn, same);
1841 rib_dump (__func__, p, same);
1842 }
paul4d38fdb2005-04-28 17:35:14 +00001843 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001844 }
paul4d38fdb2005-04-28 17:35:14 +00001845
1846 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001847 return 0;
1848}
1849
hassoebf1ead2005-09-21 14:58:20 +00001850/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001851int
1852rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1853 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1854{
1855 struct route_table *table;
1856 struct route_node *rn;
1857 struct rib *rib;
1858 struct rib *fib = NULL;
1859 struct rib *same = NULL;
1860 struct nexthop *nexthop;
1861 char buf1[BUFSIZ];
1862 char buf2[BUFSIZ];
1863
1864 /* Lookup table. */
1865 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1866 if (! table)
1867 return 0;
1868
1869 /* Apply mask. */
1870 apply_mask_ipv4 (p);
1871
paul5ec90d22003-06-19 01:41:37 +00001872 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001873 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001874 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1875 p->prefixlen,
1876 inet_ntoa (*gate),
1877 ifindex);
1878
paul718e3742002-12-13 20:15:29 +00001879 /* Lookup route node. */
1880 rn = route_node_lookup (table, (struct prefix *) p);
1881 if (! rn)
1882 {
1883 if (IS_ZEBRA_DEBUG_KERNEL)
1884 {
1885 if (gate)
ajsb6178002004-12-07 21:12:56 +00001886 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001887 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1888 p->prefixlen,
1889 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1890 ifindex);
1891 else
ajsb6178002004-12-07 21:12:56 +00001892 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001893 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1894 p->prefixlen,
1895 ifindex);
1896 }
1897 return ZEBRA_ERR_RTNOEXIST;
1898 }
1899
1900 /* Lookup same type route. */
1901 for (rib = rn->info; rib; rib = rib->next)
1902 {
Paul Jakma6d691122006-07-27 21:49:00 +00001903 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1904 continue;
1905
paul718e3742002-12-13 20:15:29 +00001906 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1907 fib = rib;
1908
hassoebf1ead2005-09-21 14:58:20 +00001909 if (rib->type != type)
1910 continue;
1911 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1912 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001913 {
hassoebf1ead2005-09-21 14:58:20 +00001914 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001915 {
hassoebf1ead2005-09-21 14:58:20 +00001916 rib->refcnt--;
1917 route_unlock_node (rn);
1918 route_unlock_node (rn);
1919 return 0;
paul718e3742002-12-13 20:15:29 +00001920 }
hassoebf1ead2005-09-21 14:58:20 +00001921 same = rib;
1922 break;
paul718e3742002-12-13 20:15:29 +00001923 }
hassoebf1ead2005-09-21 14:58:20 +00001924 /* Make sure that the route found has the same gateway. */
1925 else if (gate == NULL ||
1926 ((nexthop = rib->nexthop) &&
1927 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1928 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001929 {
hassoebf1ead2005-09-21 14:58:20 +00001930 same = rib;
1931 break;
paul718e3742002-12-13 20:15:29 +00001932 }
1933 }
1934
1935 /* If same type of route can't be found and this message is from
1936 kernel. */
1937 if (! same)
1938 {
1939 if (fib && type == ZEBRA_ROUTE_KERNEL)
1940 {
1941 /* Unset flags. */
1942 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1943 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1944
1945 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1946 }
1947 else
1948 {
1949 if (IS_ZEBRA_DEBUG_KERNEL)
1950 {
1951 if (gate)
ajsb6178002004-12-07 21:12:56 +00001952 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001953 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1954 p->prefixlen,
1955 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1956 ifindex,
1957 type);
1958 else
ajsb6178002004-12-07 21:12:56 +00001959 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001960 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1961 p->prefixlen,
1962 ifindex,
1963 type);
1964 }
1965 route_unlock_node (rn);
1966 return ZEBRA_ERR_RTNOEXIST;
1967 }
1968 }
paul4d38fdb2005-04-28 17:35:14 +00001969
paul718e3742002-12-13 20:15:29 +00001970 if (same)
1971 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001972
paul718e3742002-12-13 20:15:29 +00001973 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001974 return 0;
1975}
1976
1977/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001978static void
paul718e3742002-12-13 20:15:29 +00001979static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1980{
1981 struct rib *rib;
1982 struct route_node *rn;
1983 struct route_table *table;
1984
1985 /* Lookup table. */
1986 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1987 if (! table)
1988 return;
1989
1990 /* Lookup existing route */
1991 rn = route_node_get (table, p);
1992 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00001993 {
1994 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1995 continue;
1996
1997 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1998 break;
1999 }
paul718e3742002-12-13 20:15:29 +00002000
2001 if (rib)
2002 {
2003 /* Same distance static route is there. Update it with new
2004 nexthop. */
paul718e3742002-12-13 20:15:29 +00002005 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002006 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002007 {
2008 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002009 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002010 break;
2011 case STATIC_IPV4_IFNAME:
2012 nexthop_ifname_add (rib, si->gate.ifname);
2013 break;
2014 case STATIC_IPV4_BLACKHOLE:
2015 nexthop_blackhole_add (rib);
2016 break;
paul4d38fdb2005-04-28 17:35:14 +00002017 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002018 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002019 }
2020 else
2021 {
2022 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002023 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2024
paul718e3742002-12-13 20:15:29 +00002025 rib->type = ZEBRA_ROUTE_STATIC;
2026 rib->distance = si->distance;
2027 rib->metric = 0;
2028 rib->nexthop_num = 0;
2029
2030 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002031 {
2032 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002033 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002034 break;
2035 case STATIC_IPV4_IFNAME:
2036 nexthop_ifname_add (rib, si->gate.ifname);
2037 break;
2038 case STATIC_IPV4_BLACKHOLE:
2039 nexthop_blackhole_add (rib);
2040 break;
2041 }
paul718e3742002-12-13 20:15:29 +00002042
hasso81dfcaa2003-05-25 19:21:25 +00002043 /* Save the flags of this static routes (reject, blackhole) */
2044 rib->flags = si->flags;
2045
paul718e3742002-12-13 20:15:29 +00002046 /* Link this rib to the tree. */
2047 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002048 }
2049}
2050
paula1ac18c2005-06-28 17:17:12 +00002051static int
paul718e3742002-12-13 20:15:29 +00002052static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2053{
2054 if (nexthop->type == NEXTHOP_TYPE_IPV4
2055 && si->type == STATIC_IPV4_GATEWAY
2056 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2057 return 1;
2058 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2059 && si->type == STATIC_IPV4_IFNAME
2060 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2061 return 1;
paul595db7f2003-05-25 21:35:06 +00002062 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2063 && si->type == STATIC_IPV4_BLACKHOLE)
2064 return 1;
paule8e19462006-01-19 20:16:55 +00002065 return 0;
paul718e3742002-12-13 20:15:29 +00002066}
2067
2068/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002069static void
paul718e3742002-12-13 20:15:29 +00002070static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
2071{
2072 struct route_node *rn;
2073 struct rib *rib;
2074 struct nexthop *nexthop;
2075 struct route_table *table;
2076
2077 /* Lookup table. */
2078 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2079 if (! table)
2080 return;
paul4d38fdb2005-04-28 17:35:14 +00002081
paul718e3742002-12-13 20:15:29 +00002082 /* Lookup existing route with type and distance. */
2083 rn = route_node_lookup (table, p);
2084 if (! rn)
2085 return;
2086
2087 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002088 {
2089 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2090 continue;
2091
2092 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2093 break;
2094 }
paul718e3742002-12-13 20:15:29 +00002095
2096 if (! rib)
2097 {
2098 route_unlock_node (rn);
2099 return;
2100 }
2101
2102 /* Lookup nexthop. */
2103 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2104 if (static_ipv4_nexthop_same (nexthop, si))
2105 break;
2106
2107 /* Can't find nexthop. */
2108 if (! nexthop)
2109 {
2110 route_unlock_node (rn);
2111 return;
2112 }
2113
2114 /* Check nexthop. */
2115 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002116 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002117 else
2118 {
paul6baeb982003-10-28 03:47:15 +00002119 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2120 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002121 nexthop_delete (rib, nexthop);
2122 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002123 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002124 }
paul718e3742002-12-13 20:15:29 +00002125 /* Unlock node. */
2126 route_unlock_node (rn);
2127}
2128
2129/* Add static route into static route configuration. */
2130int
hasso39db97e2004-10-12 20:50:58 +00002131static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00002132 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002133{
2134 u_char type = 0;
2135 struct route_node *rn;
2136 struct static_ipv4 *si;
2137 struct static_ipv4 *pp;
2138 struct static_ipv4 *cp;
2139 struct static_ipv4 *update = NULL;
2140 struct route_table *stable;
2141
2142 /* Lookup table. */
2143 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2144 if (! stable)
2145 return -1;
2146
2147 /* Lookup static route prefix. */
2148 rn = route_node_get (stable, p);
2149
2150 /* Make flags. */
2151 if (gate)
2152 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002153 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002154 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002155 else
2156 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002157
2158 /* Do nothing if there is a same static route. */
2159 for (si = rn->info; si; si = si->next)
2160 {
2161 if (type == si->type
2162 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2163 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2164 {
2165 if (distance == si->distance)
2166 {
2167 route_unlock_node (rn);
2168 return 0;
2169 }
2170 else
2171 update = si;
2172 }
2173 }
2174
Paul Jakma3c0755d2006-12-08 00:53:14 +00002175 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002176 if (update)
2177 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2178
2179 /* Make new static route structure. */
2180 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
2181 memset (si, 0, sizeof (struct static_ipv4));
2182
2183 si->type = type;
2184 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002185 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002186
2187 if (gate)
2188 si->gate.ipv4 = *gate;
2189 if (ifname)
2190 si->gate.ifname = XSTRDUP (0, ifname);
2191
2192 /* Add new static route information to the tree with sort by
2193 distance value and gateway address. */
2194 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2195 {
2196 if (si->distance < cp->distance)
2197 break;
2198 if (si->distance > cp->distance)
2199 continue;
2200 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2201 {
2202 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2203 break;
2204 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2205 continue;
2206 }
2207 }
2208
2209 /* Make linked list. */
2210 if (pp)
2211 pp->next = si;
2212 else
2213 rn->info = si;
2214 if (cp)
2215 cp->prev = si;
2216 si->prev = pp;
2217 si->next = cp;
2218
2219 /* Install into rib. */
2220 static_install_ipv4 (p, si);
2221
2222 return 1;
2223}
2224
2225/* Delete static route from static route configuration. */
2226int
hasso39db97e2004-10-12 20:50:58 +00002227static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002228 u_char distance, u_int32_t vrf_id)
2229{
2230 u_char type = 0;
2231 struct route_node *rn;
2232 struct static_ipv4 *si;
2233 struct route_table *stable;
2234
2235 /* Lookup table. */
2236 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2237 if (! stable)
2238 return -1;
2239
2240 /* Lookup static route prefix. */
2241 rn = route_node_lookup (stable, p);
2242 if (! rn)
2243 return 0;
2244
2245 /* Make flags. */
2246 if (gate)
2247 type = STATIC_IPV4_GATEWAY;
2248 else if (ifname)
2249 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002250 else
2251 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002252
2253 /* Find same static route is the tree */
2254 for (si = rn->info; si; si = si->next)
2255 if (type == si->type
2256 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2257 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2258 break;
2259
2260 /* Can't find static route. */
2261 if (! si)
2262 {
2263 route_unlock_node (rn);
2264 return 0;
2265 }
2266
2267 /* Install into rib. */
2268 static_uninstall_ipv4 (p, si);
2269
2270 /* Unlink static route from linked list. */
2271 if (si->prev)
2272 si->prev->next = si->next;
2273 else
2274 rn->info = si->next;
2275 if (si->next)
2276 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002277 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002278
2279 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002280 if (ifname)
2281 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002282 XFREE (MTYPE_STATIC_IPV4, si);
2283
paul143a3852003-09-29 20:06:13 +00002284 route_unlock_node (rn);
2285
paul718e3742002-12-13 20:15:29 +00002286 return 1;
2287}
2288
2289
2290#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002291static int
paul718e3742002-12-13 20:15:29 +00002292rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2293 struct in6_addr *gate, unsigned int ifindex, int table)
2294{
hasso726f9b22003-05-25 21:04:54 +00002295 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2296#if defined (MUSICA) || defined (LINUX)
2297 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2298 if (p->prefixlen == 96)
2299 return 0;
2300#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002301 return 1;
hasso726f9b22003-05-25 21:04:54 +00002302 }
paul718e3742002-12-13 20:15:29 +00002303 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2304 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2305 {
2306 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2307 return 1;
2308 }
2309 return 0;
2310}
2311
2312int
2313rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002314 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
2315 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00002316{
2317 struct rib *rib;
2318 struct rib *same = NULL;
2319 struct route_table *table;
2320 struct route_node *rn;
2321 struct nexthop *nexthop;
2322
paul718e3742002-12-13 20:15:29 +00002323 /* Lookup table. */
2324 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2325 if (! table)
2326 return 0;
2327
2328 /* Make sure mask is applied. */
2329 apply_mask_ipv6 (p);
2330
2331 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002332 if (!distance)
2333 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002334
2335 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2336 distance = 200;
2337
2338 /* Filter bogus route. */
2339 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2340 return 0;
2341
2342 /* Lookup route node.*/
2343 rn = route_node_get (table, (struct prefix *) p);
2344
2345 /* If same type of route are installed, treat it as a implicit
2346 withdraw. */
2347 for (rib = rn->info; rib; rib = rib->next)
2348 {
Paul Jakma6d691122006-07-27 21:49:00 +00002349 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2350 continue;
2351
hassoebf1ead2005-09-21 14:58:20 +00002352 if (rib->type != type)
2353 continue;
2354 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002355 {
2356 same = rib;
paul718e3742002-12-13 20:15:29 +00002357 break;
2358 }
hassoebf1ead2005-09-21 14:58:20 +00002359 else if ((nexthop = rib->nexthop) &&
2360 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2361 nexthop->ifindex == ifindex)
2362 {
2363 rib->refcnt++;
2364 return 0;
2365 }
paul718e3742002-12-13 20:15:29 +00002366 }
2367
2368 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002369 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2370
paul718e3742002-12-13 20:15:29 +00002371 rib->type = type;
2372 rib->distance = distance;
2373 rib->flags = flags;
2374 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002375 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002376 rib->nexthop_num = 0;
2377 rib->uptime = time (NULL);
2378
2379 /* Nexthop settings. */
2380 if (gate)
2381 {
2382 if (ifindex)
2383 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2384 else
2385 nexthop_ipv6_add (rib, gate);
2386 }
2387 else
2388 nexthop_ifindex_add (rib, ifindex);
2389
2390 /* If this route is kernel route, set FIB flag to the route. */
2391 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2392 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2393 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2394
2395 /* Link new rib to node.*/
2396 rib_addnode (rn, rib);
2397
paul718e3742002-12-13 20:15:29 +00002398 /* Free implicit route.*/
2399 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002400 rib_delnode (rn, same);
2401
2402 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002403 return 0;
2404}
2405
hassoebf1ead2005-09-21 14:58:20 +00002406/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002407int
2408rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2409 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
2410{
2411 struct route_table *table;
2412 struct route_node *rn;
2413 struct rib *rib;
2414 struct rib *fib = NULL;
2415 struct rib *same = NULL;
2416 struct nexthop *nexthop;
2417 char buf1[BUFSIZ];
2418 char buf2[BUFSIZ];
2419
2420 /* Apply mask. */
2421 apply_mask_ipv6 (p);
2422
2423 /* Lookup table. */
2424 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2425 if (! table)
2426 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002427
paul718e3742002-12-13 20:15:29 +00002428 /* Lookup route node. */
2429 rn = route_node_lookup (table, (struct prefix *) p);
2430 if (! rn)
2431 {
2432 if (IS_ZEBRA_DEBUG_KERNEL)
2433 {
2434 if (gate)
ajsb6178002004-12-07 21:12:56 +00002435 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002436 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2437 p->prefixlen,
2438 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2439 ifindex);
2440 else
ajsb6178002004-12-07 21:12:56 +00002441 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002442 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2443 p->prefixlen,
2444 ifindex);
2445 }
2446 return ZEBRA_ERR_RTNOEXIST;
2447 }
2448
2449 /* Lookup same type route. */
2450 for (rib = rn->info; rib; rib = rib->next)
2451 {
Paul Jakma6d691122006-07-27 21:49:00 +00002452 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2453 continue;
2454
paul718e3742002-12-13 20:15:29 +00002455 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2456 fib = rib;
2457
hassoebf1ead2005-09-21 14:58:20 +00002458 if (rib->type != type)
2459 continue;
2460 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2461 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002462 {
hassoebf1ead2005-09-21 14:58:20 +00002463 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002464 {
hassoebf1ead2005-09-21 14:58:20 +00002465 rib->refcnt--;
2466 route_unlock_node (rn);
2467 route_unlock_node (rn);
2468 return 0;
paul718e3742002-12-13 20:15:29 +00002469 }
hassoebf1ead2005-09-21 14:58:20 +00002470 same = rib;
2471 break;
paul718e3742002-12-13 20:15:29 +00002472 }
hassoebf1ead2005-09-21 14:58:20 +00002473 /* Make sure that the route found has the same gateway. */
2474 else if (gate == NULL ||
2475 ((nexthop = rib->nexthop) &&
2476 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2477 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002478 {
hassoebf1ead2005-09-21 14:58:20 +00002479 same = rib;
2480 break;
paul718e3742002-12-13 20:15:29 +00002481 }
2482 }
2483
2484 /* If same type of route can't be found and this message is from
2485 kernel. */
2486 if (! same)
2487 {
2488 if (fib && type == ZEBRA_ROUTE_KERNEL)
2489 {
2490 /* Unset flags. */
2491 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2492 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2493
2494 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2495 }
2496 else
2497 {
2498 if (IS_ZEBRA_DEBUG_KERNEL)
2499 {
2500 if (gate)
ajsb6178002004-12-07 21:12:56 +00002501 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002502 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2503 p->prefixlen,
2504 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
2505 ifindex,
2506 type);
2507 else
ajsb6178002004-12-07 21:12:56 +00002508 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00002509 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
2510 p->prefixlen,
2511 ifindex,
2512 type);
2513 }
2514 route_unlock_node (rn);
2515 return ZEBRA_ERR_RTNOEXIST;
2516 }
2517 }
2518
2519 if (same)
2520 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002521
paul718e3742002-12-13 20:15:29 +00002522 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002523 return 0;
2524}
2525
2526/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002527static void
paul718e3742002-12-13 20:15:29 +00002528static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2529{
2530 struct rib *rib;
2531 struct route_table *table;
2532 struct route_node *rn;
2533
2534 /* Lookup table. */
2535 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2536 if (! table)
2537 return;
2538
2539 /* Lookup existing route */
2540 rn = route_node_get (table, p);
2541 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002542 {
2543 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2544 continue;
2545
2546 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2547 break;
2548 }
paul718e3742002-12-13 20:15:29 +00002549
2550 if (rib)
2551 {
2552 /* Same distance static route is there. Update it with new
2553 nexthop. */
paul718e3742002-12-13 20:15:29 +00002554 route_unlock_node (rn);
2555
2556 switch (si->type)
2557 {
2558 case STATIC_IPV6_GATEWAY:
2559 nexthop_ipv6_add (rib, &si->ipv6);
2560 break;
2561 case STATIC_IPV6_IFNAME:
2562 nexthop_ifname_add (rib, si->ifname);
2563 break;
2564 case STATIC_IPV6_GATEWAY_IFNAME:
2565 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2566 break;
2567 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002568 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002569 }
2570 else
2571 {
2572 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002573 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2574
paul718e3742002-12-13 20:15:29 +00002575 rib->type = ZEBRA_ROUTE_STATIC;
2576 rib->distance = si->distance;
2577 rib->metric = 0;
2578 rib->nexthop_num = 0;
2579
2580 switch (si->type)
2581 {
2582 case STATIC_IPV6_GATEWAY:
2583 nexthop_ipv6_add (rib, &si->ipv6);
2584 break;
2585 case STATIC_IPV6_IFNAME:
2586 nexthop_ifname_add (rib, si->ifname);
2587 break;
2588 case STATIC_IPV6_GATEWAY_IFNAME:
2589 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2590 break;
2591 }
2592
hasso81dfcaa2003-05-25 19:21:25 +00002593 /* Save the flags of this static routes (reject, blackhole) */
2594 rib->flags = si->flags;
2595
paul718e3742002-12-13 20:15:29 +00002596 /* Link this rib to the tree. */
2597 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002598 }
2599}
2600
paula1ac18c2005-06-28 17:17:12 +00002601static int
paul718e3742002-12-13 20:15:29 +00002602static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2603{
2604 if (nexthop->type == NEXTHOP_TYPE_IPV6
2605 && si->type == STATIC_IPV6_GATEWAY
2606 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2607 return 1;
2608 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2609 && si->type == STATIC_IPV6_IFNAME
2610 && strcmp (nexthop->ifname, si->ifname) == 0)
2611 return 1;
2612 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2613 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2614 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2615 && strcmp (nexthop->ifname, si->ifname) == 0)
2616 return 1;
paule8e19462006-01-19 20:16:55 +00002617 return 0;
paul718e3742002-12-13 20:15:29 +00002618}
2619
paula1ac18c2005-06-28 17:17:12 +00002620static void
paul718e3742002-12-13 20:15:29 +00002621static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2622{
2623 struct route_table *table;
2624 struct route_node *rn;
2625 struct rib *rib;
2626 struct nexthop *nexthop;
2627
2628 /* Lookup table. */
2629 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2630 if (! table)
2631 return;
2632
2633 /* Lookup existing route with type and distance. */
2634 rn = route_node_lookup (table, (struct prefix *) p);
2635 if (! rn)
2636 return;
2637
2638 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002639 {
2640 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2641 continue;
2642
2643 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2644 break;
2645 }
2646
paul718e3742002-12-13 20:15:29 +00002647 if (! rib)
2648 {
2649 route_unlock_node (rn);
2650 return;
2651 }
2652
2653 /* Lookup nexthop. */
2654 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2655 if (static_ipv6_nexthop_same (nexthop, si))
2656 break;
2657
2658 /* Can't find nexthop. */
2659 if (! nexthop)
2660 {
2661 route_unlock_node (rn);
2662 return;
2663 }
2664
2665 /* Check nexthop. */
2666 if (rib->nexthop_num == 1)
2667 {
2668 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002669 }
2670 else
2671 {
paul6baeb982003-10-28 03:47:15 +00002672 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2673 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002674 nexthop_delete (rib, nexthop);
2675 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002676 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002677 }
paul718e3742002-12-13 20:15:29 +00002678 /* Unlock node. */
2679 route_unlock_node (rn);
2680}
2681
2682/* Add static route into static route configuration. */
2683int
2684static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002685 const char *ifname, u_char flags, u_char distance,
2686 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002687{
2688 struct route_node *rn;
2689 struct static_ipv6 *si;
2690 struct static_ipv6 *pp;
2691 struct static_ipv6 *cp;
2692 struct route_table *stable;
2693
2694 /* Lookup table. */
2695 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2696 if (! stable)
2697 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002698
2699 if (!gate &&
2700 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2701 return -1;
2702
2703 if (!ifname &&
2704 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2705 return -1;
paul718e3742002-12-13 20:15:29 +00002706
2707 /* Lookup static route prefix. */
2708 rn = route_node_get (stable, p);
2709
2710 /* Do nothing if there is a same static route. */
2711 for (si = rn->info; si; si = si->next)
2712 {
2713 if (distance == si->distance
2714 && type == si->type
2715 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2716 && (! ifname || strcmp (ifname, si->ifname) == 0))
2717 {
2718 route_unlock_node (rn);
2719 return 0;
2720 }
2721 }
2722
2723 /* Make new static route structure. */
2724 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2725 memset (si, 0, sizeof (struct static_ipv6));
2726
2727 si->type = type;
2728 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002729 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002730
2731 switch (type)
2732 {
2733 case STATIC_IPV6_GATEWAY:
2734 si->ipv6 = *gate;
2735 break;
2736 case STATIC_IPV6_IFNAME:
2737 si->ifname = XSTRDUP (0, ifname);
2738 break;
2739 case STATIC_IPV6_GATEWAY_IFNAME:
2740 si->ipv6 = *gate;
2741 si->ifname = XSTRDUP (0, ifname);
2742 break;
2743 }
2744
2745 /* Add new static route information to the tree with sort by
2746 distance value and gateway address. */
2747 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2748 {
2749 if (si->distance < cp->distance)
2750 break;
2751 if (si->distance > cp->distance)
2752 continue;
2753 }
2754
2755 /* Make linked list. */
2756 if (pp)
2757 pp->next = si;
2758 else
2759 rn->info = si;
2760 if (cp)
2761 cp->prev = si;
2762 si->prev = pp;
2763 si->next = cp;
2764
2765 /* Install into rib. */
2766 static_install_ipv6 (p, si);
2767
2768 return 1;
2769}
2770
2771/* Delete static route from static route configuration. */
2772int
2773static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002774 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002775{
2776 struct route_node *rn;
2777 struct static_ipv6 *si;
2778 struct route_table *stable;
2779
2780 /* Lookup table. */
2781 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2782 if (! stable)
2783 return -1;
2784
2785 /* Lookup static route prefix. */
2786 rn = route_node_lookup (stable, p);
2787 if (! rn)
2788 return 0;
2789
2790 /* Find same static route is the tree */
2791 for (si = rn->info; si; si = si->next)
2792 if (distance == si->distance
2793 && type == si->type
2794 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2795 && (! ifname || strcmp (ifname, si->ifname) == 0))
2796 break;
2797
2798 /* Can't find static route. */
2799 if (! si)
2800 {
2801 route_unlock_node (rn);
2802 return 0;
2803 }
2804
2805 /* Install into rib. */
2806 static_uninstall_ipv6 (p, si);
2807
2808 /* Unlink static route from linked list. */
2809 if (si->prev)
2810 si->prev->next = si->next;
2811 else
2812 rn->info = si->next;
2813 if (si->next)
2814 si->next->prev = si->prev;
2815
2816 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002817 if (ifname)
2818 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002819 XFREE (MTYPE_STATIC_IPV6, si);
2820
2821 return 1;
2822}
2823#endif /* HAVE_IPV6 */
2824
2825/* RIB update function. */
2826void
paula1ac18c2005-06-28 17:17:12 +00002827rib_update (void)
paul718e3742002-12-13 20:15:29 +00002828{
2829 struct route_node *rn;
2830 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002831
paul718e3742002-12-13 20:15:29 +00002832 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2833 if (table)
2834 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002835 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002836 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002837
2838 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2839 if (table)
2840 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002841 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002842 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002843}
2844
2845/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002846static void
paul718e3742002-12-13 20:15:29 +00002847rib_if_up (struct interface *ifp)
2848{
2849 rib_update ();
2850}
2851
2852/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002853static void
paul718e3742002-12-13 20:15:29 +00002854rib_if_down (struct interface *ifp)
2855{
2856 rib_update ();
2857}
2858
2859/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002860static void
paul718e3742002-12-13 20:15:29 +00002861rib_weed_table (struct route_table *table)
2862{
2863 struct route_node *rn;
2864 struct rib *rib;
2865 struct rib *next;
2866
2867 if (table)
2868 for (rn = route_top (table); rn; rn = route_next (rn))
2869 for (rib = rn->info; rib; rib = next)
2870 {
2871 next = rib->next;
2872
Paul Jakma6d691122006-07-27 21:49:00 +00002873 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2874 continue;
2875
paulb21b19c2003-06-15 01:28:29 +00002876 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002877 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002878 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002879 }
2880}
2881
2882/* Delete all routes from non main table. */
2883void
paula1ac18c2005-06-28 17:17:12 +00002884rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002885{
2886 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2887 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2888}
2889
2890/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002891static void
paul718e3742002-12-13 20:15:29 +00002892rib_sweep_table (struct route_table *table)
2893{
2894 struct route_node *rn;
2895 struct rib *rib;
2896 struct rib *next;
2897 int ret = 0;
2898
2899 if (table)
2900 for (rn = route_top (table); rn; rn = route_next (rn))
2901 for (rib = rn->info; rib; rib = next)
2902 {
2903 next = rib->next;
2904
Paul Jakma6d691122006-07-27 21:49:00 +00002905 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2906 continue;
2907
paul718e3742002-12-13 20:15:29 +00002908 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2909 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2910 {
2911 ret = rib_uninstall_kernel (rn, rib);
2912 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002913 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002914 }
2915 }
2916}
2917
2918/* Sweep all RIB tables. */
2919void
paula1ac18c2005-06-28 17:17:12 +00002920rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002921{
2922 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2923 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2924}
2925
2926/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002927static void
paul718e3742002-12-13 20:15:29 +00002928rib_close_table (struct route_table *table)
2929{
2930 struct route_node *rn;
2931 struct rib *rib;
2932
2933 if (table)
2934 for (rn = route_top (table); rn; rn = route_next (rn))
2935 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002936 {
2937 if (! RIB_SYSTEM_ROUTE (rib)
2938 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2939 rib_uninstall_kernel (rn, rib);
2940 }
paul718e3742002-12-13 20:15:29 +00002941}
2942
2943/* Close all RIB tables. */
2944void
paula1ac18c2005-06-28 17:17:12 +00002945rib_close (void)
paul718e3742002-12-13 20:15:29 +00002946{
2947 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2948 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2949}
2950
2951/* Routing information base initialize. */
2952void
paula1ac18c2005-06-28 17:17:12 +00002953rib_init (void)
paul718e3742002-12-13 20:15:29 +00002954{
paul4d38fdb2005-04-28 17:35:14 +00002955 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002956 /* VRF initialization. */
2957 vrf_init ();
2958}