blob: 1d1876d8117ef5ecf5976a62c4ce9755d666e857 [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. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010054static const struct
paul718e3742002-12-13 20:15:29 +000055{
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. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010073static vector vrf_vector;
paul718e3742002-12-13 20:15:29 +000074
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
Stephen Hemminger393deb92008-08-18 14:13:29 -0700212 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000213 nexthop->type = NEXTHOP_TYPE_IFINDEX;
214 nexthop->ifindex = ifindex;
215
216 nexthop_add (rib, nexthop);
217
218 return nexthop;
219}
220
221struct nexthop *
222nexthop_ifname_add (struct rib *rib, char *ifname)
223{
224 struct nexthop *nexthop;
225
Stephen Hemminger393deb92008-08-18 14:13:29 -0700226 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000227 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000228 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000229
230 nexthop_add (rib, nexthop);
231
232 return nexthop;
233}
234
235struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000236nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000237{
238 struct nexthop *nexthop;
239
Stephen Hemminger393deb92008-08-18 14:13:29 -0700240 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000241 nexthop->type = NEXTHOP_TYPE_IPV4;
242 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000243 if (src)
244 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000245
246 nexthop_add (rib, nexthop);
247
248 return nexthop;
249}
250
paula1ac18c2005-06-28 17:17:12 +0000251static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000252nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000253 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000254{
255 struct nexthop *nexthop;
256
Stephen Hemminger393deb92008-08-18 14:13:29 -0700257 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000258 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
259 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000260 if (src)
261 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000262 nexthop->ifindex = ifindex;
263
264 nexthop_add (rib, nexthop);
265
266 return nexthop;
267}
268
269#ifdef HAVE_IPV6
270struct nexthop *
271nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
272{
273 struct nexthop *nexthop;
274
Stephen Hemminger393deb92008-08-18 14:13:29 -0700275 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000276 nexthop->type = NEXTHOP_TYPE_IPV6;
277 nexthop->gate.ipv6 = *ipv6;
278
279 nexthop_add (rib, nexthop);
280
281 return nexthop;
282}
283
paula1ac18c2005-06-28 17:17:12 +0000284static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000285nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
286 char *ifname)
287{
288 struct nexthop *nexthop;
289
Stephen Hemminger393deb92008-08-18 14:13:29 -0700290 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000291 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
292 nexthop->gate.ipv6 = *ipv6;
293 nexthop->ifname = XSTRDUP (0, ifname);
294
295 nexthop_add (rib, nexthop);
296
297 return nexthop;
298}
299
paula1ac18c2005-06-28 17:17:12 +0000300static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000301nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
302 unsigned int ifindex)
303{
304 struct nexthop *nexthop;
305
Stephen Hemminger393deb92008-08-18 14:13:29 -0700306 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000307 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
308 nexthop->gate.ipv6 = *ipv6;
309 nexthop->ifindex = ifindex;
310
311 nexthop_add (rib, nexthop);
312
313 return nexthop;
314}
315#endif /* HAVE_IPV6 */
316
paul595db7f2003-05-25 21:35:06 +0000317struct nexthop *
318nexthop_blackhole_add (struct rib *rib)
319{
320 struct nexthop *nexthop;
321
Stephen Hemminger393deb92008-08-18 14:13:29 -0700322 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000323 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
324 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
325
326 nexthop_add (rib, nexthop);
327
328 return nexthop;
329}
330
paul718e3742002-12-13 20:15:29 +0000331/* If force flag is not set, do not modify falgs at all for uninstall
332 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000333static int
paul718e3742002-12-13 20:15:29 +0000334nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
335 struct route_node *top)
336{
337 struct prefix_ipv4 p;
338 struct route_table *table;
339 struct route_node *rn;
340 struct rib *match;
341 struct nexthop *newhop;
342
343 if (nexthop->type == NEXTHOP_TYPE_IPV4)
344 nexthop->ifindex = 0;
345
346 if (set)
347 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
348
349 /* Make lookup prefix. */
350 memset (&p, 0, sizeof (struct prefix_ipv4));
351 p.family = AF_INET;
352 p.prefixlen = IPV4_MAX_PREFIXLEN;
353 p.prefix = nexthop->gate.ipv4;
354
355 /* Lookup table. */
356 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
357 if (! table)
358 return 0;
359
360 rn = route_node_match (table, (struct prefix *) &p);
361 while (rn)
362 {
363 route_unlock_node (rn);
364
365 /* If lookup self prefix return immidiately. */
366 if (rn == top)
367 return 0;
368
369 /* Pick up selected route. */
370 for (match = rn->info; match; match = match->next)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100371 {
372 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
373 continue;
374 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
375 break;
376 }
paul718e3742002-12-13 20:15:29 +0000377
378 /* If there is no selected route or matched route is EGP, go up
379 tree. */
380 if (! match
381 || match->type == ZEBRA_ROUTE_BGP)
382 {
383 do {
384 rn = rn->parent;
385 } while (rn && rn->info == NULL);
386 if (rn)
387 route_lock_node (rn);
388 }
389 else
390 {
391 if (match->type == ZEBRA_ROUTE_CONNECT)
392 {
393 /* Directly point connected route. */
394 newhop = match->nexthop;
395 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
396 nexthop->ifindex = newhop->ifindex;
397
398 return 1;
399 }
400 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
401 {
402 for (newhop = match->nexthop; newhop; newhop = newhop->next)
403 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
404 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
405 {
406 if (set)
407 {
408 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
409 nexthop->rtype = newhop->type;
410 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
411 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
412 nexthop->rgate.ipv4 = newhop->gate.ipv4;
413 if (newhop->type == NEXTHOP_TYPE_IFINDEX
414 || newhop->type == NEXTHOP_TYPE_IFNAME
415 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
416 nexthop->rifindex = newhop->ifindex;
417 }
418 return 1;
419 }
420 return 0;
421 }
422 else
423 {
424 return 0;
425 }
426 }
427 }
428 return 0;
429}
430
431#ifdef HAVE_IPV6
432/* If force flag is not set, do not modify falgs at all for uninstall
433 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000434static int
paul718e3742002-12-13 20:15:29 +0000435nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
436 struct route_node *top)
437{
438 struct prefix_ipv6 p;
439 struct route_table *table;
440 struct route_node *rn;
441 struct rib *match;
442 struct nexthop *newhop;
443
444 if (nexthop->type == NEXTHOP_TYPE_IPV6)
445 nexthop->ifindex = 0;
446
447 if (set)
448 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
449
450 /* Make lookup prefix. */
451 memset (&p, 0, sizeof (struct prefix_ipv6));
452 p.family = AF_INET6;
453 p.prefixlen = IPV6_MAX_PREFIXLEN;
454 p.prefix = nexthop->gate.ipv6;
455
456 /* Lookup table. */
457 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
458 if (! table)
459 return 0;
460
461 rn = route_node_match (table, (struct prefix *) &p);
462 while (rn)
463 {
464 route_unlock_node (rn);
465
466 /* If lookup self prefix return immidiately. */
467 if (rn == top)
468 return 0;
469
470 /* Pick up selected route. */
471 for (match = rn->info; match; match = match->next)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100472 {
473 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
474 continue;
475 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
476 break;
477 }
paul718e3742002-12-13 20:15:29 +0000478
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)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100563 {
564 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
565 continue;
566 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
567 break;
568 }
paul718e3742002-12-13 20:15:29 +0000569
570 /* If there is no selected route or matched route is EGP, go up
571 tree. */
572 if (! match
573 || match->type == ZEBRA_ROUTE_BGP)
574 {
575 do {
576 rn = rn->parent;
577 } while (rn && rn->info == NULL);
578 if (rn)
579 route_lock_node (rn);
580 }
581 else
582 {
583 if (match->type == ZEBRA_ROUTE_CONNECT)
584 /* Directly point connected route. */
585 return match;
586 else
587 {
588 for (newhop = match->nexthop; newhop; newhop = newhop->next)
589 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
590 return match;
591 return NULL;
592 }
593 }
594 }
595 return NULL;
596}
597
598struct rib *
599rib_lookup_ipv4 (struct prefix_ipv4 *p)
600{
601 struct route_table *table;
602 struct route_node *rn;
603 struct rib *match;
604 struct nexthop *nexthop;
605
606 /* Lookup table. */
607 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
608 if (! table)
609 return 0;
610
611 rn = route_node_lookup (table, (struct prefix *) p);
612
613 /* No route for this prefix. */
614 if (! rn)
615 return NULL;
616
617 /* Unlock node. */
618 route_unlock_node (rn);
619
paul718e3742002-12-13 20:15:29 +0000620 for (match = rn->info; match; match = match->next)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100621 {
622 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
623 continue;
624 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
625 break;
626 }
paul718e3742002-12-13 20:15:29 +0000627
628 if (! match || match->type == ZEBRA_ROUTE_BGP)
629 return NULL;
630
631 if (match->type == ZEBRA_ROUTE_CONNECT)
632 return match;
633
634 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
635 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
636 return match;
637
638 return NULL;
639}
640
Denis Ovsienkodc958242007-08-13 16:03:06 +0000641/*
642 * This clone function, unlike its original rib_lookup_ipv4(), checks
643 * if specified IPv4 route record (prefix/mask -> gate) exists in
644 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
645 *
646 * Return values:
647 * -1: error
648 * 0: exact match found
649 * 1: a match was found with a different gate
650 * 2: connected route found
651 * 3: no matches found
652 */
653int
654rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
655{
656 struct route_table *table;
657 struct route_node *rn;
658 struct rib *match;
659 struct nexthop *nexthop;
660
661 /* Lookup table. */
662 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
663 if (! table)
664 return ZEBRA_RIB_LOOKUP_ERROR;
665
666 /* Scan the RIB table for exactly matching RIB entry. */
667 rn = route_node_lookup (table, (struct prefix *) p);
668
669 /* No route for this prefix. */
670 if (! rn)
671 return ZEBRA_RIB_NOTFOUND;
672
673 /* Unlock node. */
674 route_unlock_node (rn);
675
676 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
677 for (match = rn->info; match; match = match->next)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100678 {
679 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
680 continue;
681 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
682 break;
683 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000684
685 /* None such found :( */
686 if (!match)
687 return ZEBRA_RIB_NOTFOUND;
688
689 if (match->type == ZEBRA_ROUTE_CONNECT)
690 return ZEBRA_RIB_FOUND_CONNECTED;
691
692 /* Ok, we have a cood candidate, let's check it's nexthop list... */
693 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
694 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
695 {
696 /* We are happy with either direct or recursive hexthop */
697 if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr ||
698 nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr)
699 return ZEBRA_RIB_FOUND_EXACT;
700 else
701 {
702 if (IS_ZEBRA_DEBUG_RIB)
703 {
704 char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
705 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
706 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
707 inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN);
708 zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
709 }
710 return ZEBRA_RIB_FOUND_NOGATE;
711 }
712 }
713
714 return ZEBRA_RIB_NOTFOUND;
715}
716
paul718e3742002-12-13 20:15:29 +0000717#ifdef HAVE_IPV6
718struct rib *
719rib_match_ipv6 (struct in6_addr *addr)
720{
721 struct prefix_ipv6 p;
722 struct route_table *table;
723 struct route_node *rn;
724 struct rib *match;
725 struct nexthop *newhop;
726
727 /* Lookup table. */
728 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
729 if (! table)
730 return 0;
731
732 memset (&p, 0, sizeof (struct prefix_ipv6));
733 p.family = AF_INET6;
734 p.prefixlen = IPV6_MAX_PREFIXLEN;
735 IPV6_ADDR_COPY (&p.prefix, addr);
736
737 rn = route_node_match (table, (struct prefix *) &p);
738
739 while (rn)
740 {
741 route_unlock_node (rn);
742
743 /* Pick up selected route. */
744 for (match = rn->info; match; match = match->next)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100745 {
746 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
747 continue;
748 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
749 break;
750 }
paul718e3742002-12-13 20:15:29 +0000751
752 /* If there is no selected route or matched route is EGP, go up
753 tree. */
754 if (! match
755 || match->type == ZEBRA_ROUTE_BGP)
756 {
757 do {
758 rn = rn->parent;
759 } while (rn && rn->info == NULL);
760 if (rn)
761 route_lock_node (rn);
762 }
763 else
764 {
765 if (match->type == ZEBRA_ROUTE_CONNECT)
766 /* Directly point connected route. */
767 return match;
768 else
769 {
770 for (newhop = match->nexthop; newhop; newhop = newhop->next)
771 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
772 return match;
773 return NULL;
774 }
775 }
776 }
777 return NULL;
778}
779#endif /* HAVE_IPV6 */
780
Paul Jakma7514fb72007-05-02 16:05:35 +0000781#define RIB_SYSTEM_ROUTE(R) \
782 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
783
Denis Ovsienkodc958242007-08-13 16:03:06 +0000784/* This function verifies reachability of one given nexthop, which can be
785 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
786 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
787 * nexthop->ifindex will be updated appropriately as well.
788 * An existing route map can turn (otherwise active) nexthop into inactive, but
789 * not vice versa.
790 *
791 * The return value is the final value of 'ACTIVE' flag.
792 */
793
paula1ac18c2005-06-28 17:17:12 +0000794static int
paul718e3742002-12-13 20:15:29 +0000795nexthop_active_check (struct route_node *rn, struct rib *rib,
796 struct nexthop *nexthop, int set)
797{
798 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000799 route_map_result_t ret = RMAP_MATCH;
800 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
801 struct route_map *rmap;
802 int family;
paul718e3742002-12-13 20:15:29 +0000803
Paul Jakma7514fb72007-05-02 16:05:35 +0000804 family = 0;
paul718e3742002-12-13 20:15:29 +0000805 switch (nexthop->type)
806 {
807 case NEXTHOP_TYPE_IFINDEX:
808 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000809 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000810 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
811 else
812 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
813 break;
paul718e3742002-12-13 20:15:29 +0000814 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000815 family = AFI_IP6;
816 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000817 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000818 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000819 {
820 if (set)
821 nexthop->ifindex = ifp->ifindex;
822 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
823 }
824 else
825 {
826 if (set)
827 nexthop->ifindex = 0;
828 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
829 }
830 break;
831 case NEXTHOP_TYPE_IPV4:
832 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000833 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000834 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
835 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
836 else
837 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
838 break;
839#ifdef HAVE_IPV6
840 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000841 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000842 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
843 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
844 else
845 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
846 break;
847 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000848 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000849 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
850 {
851 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000852 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000853 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
854 else
855 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
856 }
857 else
858 {
859 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
860 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
861 else
862 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
863 }
864 break;
865#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000866 case NEXTHOP_TYPE_BLACKHOLE:
867 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
868 break;
paul718e3742002-12-13 20:15:29 +0000869 default:
870 break;
871 }
Paul Jakma7514fb72007-05-02 16:05:35 +0000872 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
873 return 0;
874
875 if (RIB_SYSTEM_ROUTE(rib) ||
876 (family == AFI_IP && rn->p.family != AF_INET) ||
877 (family == AFI_IP6 && rn->p.family != AF_INET6))
878 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
879
880 rmap = 0;
881 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
882 proto_rm[family][rib->type])
883 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
884 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
885 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
886 if (rmap) {
887 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
888 }
889
890 if (ret == RMAP_DENYMATCH)
891 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000892 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
893}
894
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000895/* Iterate over all nexthops of the given RIB entry and refresh their
896 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
897 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
898 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
899 * transparently passed to nexthop_active_check().
900 *
901 * Return value is the new number of active nexthops.
902 */
903
paula1ac18c2005-06-28 17:17:12 +0000904static int
paul718e3742002-12-13 20:15:29 +0000905nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
906{
907 struct nexthop *nexthop;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200908 int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +0000909
910 rib->nexthop_active_num = 0;
911 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
912
913 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000914 {
915 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200916 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000917 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
918 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200919 if (prev_active != new_active ||
920 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000921 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
922 }
paul718e3742002-12-13 20:15:29 +0000923 return rib->nexthop_active_num;
924}
paul6baeb982003-10-28 03:47:15 +0000925
paul718e3742002-12-13 20:15:29 +0000926
paul718e3742002-12-13 20:15:29 +0000927
paula1ac18c2005-06-28 17:17:12 +0000928static void
paul718e3742002-12-13 20:15:29 +0000929rib_install_kernel (struct route_node *rn, struct rib *rib)
930{
931 int ret = 0;
932 struct nexthop *nexthop;
933
934 switch (PREFIX_FAMILY (&rn->p))
935 {
936 case AF_INET:
937 ret = kernel_add_ipv4 (&rn->p, rib);
938 break;
939#ifdef HAVE_IPV6
940 case AF_INET6:
941 ret = kernel_add_ipv6 (&rn->p, rib);
942 break;
943#endif /* HAVE_IPV6 */
944 }
945
Denis Ovsienkodc958242007-08-13 16:03:06 +0000946 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +0000947 if (ret < 0)
948 {
949 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
950 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
951 }
952}
953
954/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000955static int
paul718e3742002-12-13 20:15:29 +0000956rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
957{
958 int ret = 0;
959 struct nexthop *nexthop;
960
961 switch (PREFIX_FAMILY (&rn->p))
962 {
963 case AF_INET:
964 ret = kernel_delete_ipv4 (&rn->p, rib);
965 break;
966#ifdef HAVE_IPV6
967 case AF_INET6:
968 ret = kernel_delete_ipv6 (&rn->p, rib);
969 break;
970#endif /* HAVE_IPV6 */
971 }
972
973 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
974 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
975
976 return ret;
977}
978
979/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000980static void
paul718e3742002-12-13 20:15:29 +0000981rib_uninstall (struct route_node *rn, struct rib *rib)
982{
983 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
984 {
985 redistribute_delete (&rn->p, rib);
986 if (! RIB_SYSTEM_ROUTE (rib))
987 rib_uninstall_kernel (rn, rib);
988 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
989 }
990}
991
Paul Jakma6d691122006-07-27 21:49:00 +0000992static void rib_unlink (struct route_node *, struct rib *);
993
paul718e3742002-12-13 20:15:29 +0000994/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +0000995static void
996rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +0000997{
998 struct rib *rib;
999 struct rib *next;
1000 struct rib *fib = NULL;
1001 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001002 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001003 int installed = 0;
1004 struct nexthop *nexthop = NULL;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001005 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001006
1007 assert (rn);
1008
Paul Jakma93bdada2007-08-06 19:25:11 +00001009 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001010 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001011
paul718e3742002-12-13 20:15:29 +00001012 for (rib = rn->info; rib; rib = next)
1013 {
Denis Ovsienkodc958242007-08-13 16:03:06 +00001014 /* The next pointer is saved, because current pointer
1015 * may be passed to rib_unlink() in the middle of iteration.
1016 */
paul718e3742002-12-13 20:15:29 +00001017 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +00001018
paul718e3742002-12-13 20:15:29 +00001019 /* Currently installed rib. */
1020 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001021 {
1022 assert (fib == NULL);
1023 fib = rib;
1024 }
1025
1026 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1027 * which we need to do do further work with below.
1028 */
1029 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1030 {
1031 if (rib != fib)
1032 {
1033 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001034 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
1035 buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001036 rib_unlink (rn, rib);
1037 }
1038 else
1039 del = rib;
1040
1041 continue;
1042 }
paul4d38fdb2005-04-28 17:35:14 +00001043
paul718e3742002-12-13 20:15:29 +00001044 /* Skip unreachable nexthop. */
1045 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001046 continue;
paul718e3742002-12-13 20:15:29 +00001047
1048 /* Infinit distance. */
1049 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001050 continue;
paul718e3742002-12-13 20:15:29 +00001051
paulaf887b52006-01-18 14:52:52 +00001052 /* Newly selected rib, the common case. */
1053 if (!select)
1054 {
1055 select = rib;
1056 continue;
1057 }
1058
1059 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001060 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001061 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001062 * - lower metric beats higher for equal distance
1063 * - last, hence oldest, route wins tie break.
1064 */
paula1038a12006-01-30 14:08:51 +00001065
1066 /* Connected routes. Pick the last connected
1067 * route of the set of lowest metric connected routes.
1068 */
paula8d9c1f2006-01-25 06:31:04 +00001069 if (rib->type == ZEBRA_ROUTE_CONNECT)
1070 {
paula1038a12006-01-30 14:08:51 +00001071 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001072 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001073 select = rib;
1074 continue;
paula8d9c1f2006-01-25 06:31:04 +00001075 }
1076 else if (select->type == ZEBRA_ROUTE_CONNECT)
1077 continue;
1078
1079 /* higher distance loses */
1080 if (rib->distance > select->distance)
1081 continue;
1082
1083 /* lower wins */
1084 if (rib->distance < select->distance)
1085 {
paulaf887b52006-01-18 14:52:52 +00001086 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001087 continue;
1088 }
1089
1090 /* metric tie-breaks equal distance */
1091 if (rib->metric <= select->metric)
1092 select = rib;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001093 } /* for (rib = rn->info; rib; rib = next) */
1094
1095 /* After the cycle is finished, the following pointers will be set:
1096 * select --- the winner RIB entry, if any was found, otherwise NULL
1097 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1098 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1099 * rib --- NULL
1100 */
1101
1102 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001103 if (select && select == fib)
1104 {
Paul Jakma6d691122006-07-27 21:49:00 +00001105 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001106 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
1107 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +00001108 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001109 {
1110 redistribute_delete (&rn->p, select);
1111 if (! RIB_SYSTEM_ROUTE (select))
1112 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001113
paul4d38fdb2005-04-28 17:35:14 +00001114 /* Set real nexthop. */
1115 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001116
paul4d38fdb2005-04-28 17:35:14 +00001117 if (! RIB_SYSTEM_ROUTE (select))
1118 rib_install_kernel (rn, select);
1119 redistribute_add (&rn->p, select);
1120 }
pauld753e9e2003-01-22 19:45:50 +00001121 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001122 {
1123 /* Housekeeping code to deal with
1124 race conditions in kernel with linux
1125 netlink reporting interface up before IPv4 or IPv6 protocol
1126 is ready to add routes.
1127 This makes sure the routes are IN the kernel.
1128 */
pauld753e9e2003-01-22 19:45:50 +00001129
paul4d38fdb2005-04-28 17:35:14 +00001130 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001131 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001132 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001133 installed = 1;
1134 break;
paul4d38fdb2005-04-28 17:35:14 +00001135 }
1136 if (! installed)
1137 rib_install_kernel (rn, select);
1138 }
Paul Jakma6d691122006-07-27 21:49:00 +00001139 goto end;
paul718e3742002-12-13 20:15:29 +00001140 }
1141
Denis Ovsienkodc958242007-08-13 16:03:06 +00001142 /* At this point we either haven't found the best RIB entry or it is
1143 * different from what we currently intend to flag with SELECTED. In both
1144 * cases, if a RIB block is present in FIB, it should be withdrawn.
1145 */
paul718e3742002-12-13 20:15:29 +00001146 if (fib)
1147 {
Paul Jakma6d691122006-07-27 21:49:00 +00001148 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001149 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1150 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001151 redistribute_delete (&rn->p, fib);
1152 if (! RIB_SYSTEM_ROUTE (fib))
1153 rib_uninstall_kernel (rn, fib);
1154 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1155
1156 /* Set real nexthop. */
1157 nexthop_active_update (rn, fib, 1);
1158 }
1159
Denis Ovsienkodc958242007-08-13 16:03:06 +00001160 /* Regardless of some RIB entry being SELECTED or not before, now we can
1161 * tell, that if a new winner exists, FIB is still not updated with this
1162 * data, but ready to be.
1163 */
paul718e3742002-12-13 20:15:29 +00001164 if (select)
1165 {
Paul Jakma6d691122006-07-27 21:49:00 +00001166 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001167 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1168 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001169 /* Set real nexthop. */
1170 nexthop_active_update (rn, select, 1);
1171
1172 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001173 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001174 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1175 redistribute_add (&rn->p, select);
1176 }
paul4d38fdb2005-04-28 17:35:14 +00001177
Paul Jakma6d691122006-07-27 21:49:00 +00001178 /* FIB route was removed, should be deleted */
1179 if (del)
1180 {
1181 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001182 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1183 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001184 rib_unlink (rn, del);
1185 }
paul4d38fdb2005-04-28 17:35:14 +00001186
Paul Jakma6d691122006-07-27 21:49:00 +00001187end:
1188 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001189 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001190}
1191
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001192/* Take a list of route_node structs and return 1, if there was a record
1193 * picked from it and processed by rib_process(). Don't process more,
1194 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001195 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001196static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001197process_subq (struct list * subq, u_char qindex)
1198{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001199 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001200 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001201
1202 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001203 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001204
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001205 rnode = listgetdata (lnode);
1206 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001207
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001208 if (rnode->info) /* The first RIB record is holding the flags bitmask. */
1209 UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
Chris Caputo67b94672009-07-18 04:02:26 +00001210#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001211 else
1212 {
1213 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1214 __func__, rnode, rnode->lock);
1215 zlog_backtrace(LOG_DEBUG);
1216 }
Chris Caputo67b94672009-07-18 04:02:26 +00001217#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001218 route_unlock_node (rnode);
1219 list_delete_node (subq, lnode);
1220 return 1;
1221}
1222
1223/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1224 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1225 * is pointed to the meta queue structure.
1226 */
1227static wq_item_status
1228meta_queue_process (struct work_queue *dummy, void *data)
1229{
1230 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001231 unsigned i;
1232
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001233 for (i = 0; i < MQ_SIZE; i++)
1234 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001235 {
1236 mq->size--;
1237 break;
1238 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001239 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1240}
1241
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001242/* Map from rib types to queue type (priority) in meta queue */
1243static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1244 [ZEBRA_ROUTE_SYSTEM] = 4,
1245 [ZEBRA_ROUTE_KERNEL] = 0,
1246 [ZEBRA_ROUTE_CONNECT] = 0,
1247 [ZEBRA_ROUTE_STATIC] = 1,
1248 [ZEBRA_ROUTE_RIP] = 2,
1249 [ZEBRA_ROUTE_RIPNG] = 2,
1250 [ZEBRA_ROUTE_OSPF] = 2,
1251 [ZEBRA_ROUTE_OSPF6] = 2,
1252 [ZEBRA_ROUTE_ISIS] = 2,
1253 [ZEBRA_ROUTE_BGP] = 3,
1254 [ZEBRA_ROUTE_HSLS] = 4,
1255};
1256
1257/* Look into the RN and queue it into one or more priority queues,
1258 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001259 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001260static void
1261rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001262{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001263 struct rib *rib;
1264 char buf[INET6_ADDRSTRLEN];
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001265
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001266 if (IS_ZEBRA_DEBUG_RIB_Q)
1267 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001268
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001269 for (rib = rn->info; rib; rib = rib->next)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001270 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001271 u_char qindex = meta_queue_map[rib->type];
1272
1273 /* Invariant: at this point we always have rn->info set. */
1274 if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)))
1275 {
1276 if (IS_ZEBRA_DEBUG_RIB_Q)
1277 zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
1278 __func__, buf, rn->p.prefixlen, rn, qindex);
1279 continue;
1280 }
1281
1282 SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
1283 listnode_add (mq->subq[qindex], rn);
1284 route_lock_node (rn);
1285 mq->size++;
1286
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001287 if (IS_ZEBRA_DEBUG_RIB_Q)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001288 zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u",
1289 __func__, buf, rn->p.prefixlen, rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001290 }
paul4d38fdb2005-04-28 17:35:14 +00001291}
1292
Paul Jakma6d691122006-07-27 21:49:00 +00001293/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001294static void
Paul Jakma6d691122006-07-27 21:49:00 +00001295rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001296{
Paul Jakma93bdada2007-08-06 19:25:11 +00001297 char buf[INET_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001298 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001299
Paul Jakma93bdada2007-08-06 19:25:11 +00001300 if (IS_ZEBRA_DEBUG_RIB_Q)
1301 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
1302
Paul Jakma6d691122006-07-27 21:49:00 +00001303 /* Pointless to queue a route_node with no RIB entries to add or remove */
1304 if (!rn->info)
1305 {
1306 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1307 __func__, rn, rn->lock);
1308 zlog_backtrace(LOG_DEBUG);
1309 return;
1310 }
paul4d38fdb2005-04-28 17:35:14 +00001311
Paul Jakma6d691122006-07-27 21:49:00 +00001312 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001313 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001314
1315 assert (zebra);
1316
paul4d38fdb2005-04-28 17:35:14 +00001317 if (zebra->ribq == NULL)
1318 {
Paul Jakma6d691122006-07-27 21:49:00 +00001319 zlog_err ("%s: work_queue does not exist!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001320 return;
1321 }
Paul Jakma6d691122006-07-27 21:49:00 +00001322
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001323 /* The RIB queue should normally be either empty or holding the only work_queue_item
1324 * element. In the latter case this element would hold a pointer to the meta queue
1325 * structure, which must be used to actually queue the route nodes to process. So
1326 * create the MQ holder, if necessary, then push the work into it in any case.
1327 * This semantics was introduced after 0.99.9 release.
1328 */
1329
1330 /* Should I invent work_queue_empty() and use it, or it's Ok to do as follows? */
1331 if (!zebra->ribq->items->count)
1332 work_queue_add (zebra->ribq, zebra->mq);
1333
1334 rib_meta_queue_add (zebra->mq, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001335
1336 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001337 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
paul4d38fdb2005-04-28 17:35:14 +00001338
1339 return;
1340}
1341
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001342/* Create new meta queue.
1343 A destructor function doesn't seem to be necessary here.
1344 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001345static struct meta_queue *
1346meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001347{
1348 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001349 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001350
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001351 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1352 assert(new);
1353
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001354 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001355 {
1356 new->subq[i] = list_new ();
1357 assert(new->subq[i]);
1358 }
1359
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001360 return new;
1361}
1362
paul4d38fdb2005-04-28 17:35:14 +00001363/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001364static void
paul4d38fdb2005-04-28 17:35:14 +00001365rib_queue_init (struct zebra_t *zebra)
1366{
1367 assert (zebra);
1368
1369 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001370 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001371 {
Paul Jakma6d691122006-07-27 21:49:00 +00001372 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001373 return;
1374 }
1375
1376 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001377 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001378 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001379 /* XXX: TODO: These should be runtime configurable via vty */
1380 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001381 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001382
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001383 if (!(zebra->mq = meta_queue_new ()))
1384 {
1385 zlog_err ("%s: could not initialise meta queue!", __func__);
1386 return;
1387 }
paul4d38fdb2005-04-28 17:35:14 +00001388 return;
paul718e3742002-12-13 20:15:29 +00001389}
1390
Paul Jakma6d691122006-07-27 21:49:00 +00001391/* RIB updates are processed via a queue of pointers to route_nodes.
1392 *
1393 * The queue length is bounded by the maximal size of the routing table,
1394 * as a route_node will not be requeued, if already queued.
1395 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001396 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1397 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1398 * and then submit route_node to queue for best-path selection later.
1399 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001400 *
1401 * Deleted RIBs are reaped during best-path selection.
1402 *
1403 * rib_addnode
1404 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001405 * |-------->| | best RIB, if required
1406 * | |
1407 * static_install->|->rib_addqueue...... -> rib_process
1408 * | |
1409 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001410 * |-> set RIB_ENTRY_REMOVE |
1411 * rib_delnode (RIB freed)
1412 *
1413 *
1414 * Queueing state for a route_node is kept in the head RIB entry, this
1415 * state must be preserved as and when the head RIB entry of a
1416 * route_node is changed by rib_unlink / rib_link. A small complication,
1417 * but saves having to allocate a dedicated object for this.
1418 *
1419 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1420 *
1421 * - route_nodes: refcounted by:
1422 * - RIBs attached to route_node:
1423 * - managed by: rib_link/unlink
1424 * - route_node processing queue
1425 * - managed by: rib_addqueue, rib_process.
1426 *
1427 */
1428
paul718e3742002-12-13 20:15:29 +00001429/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001430static void
Paul Jakma6d691122006-07-27 21:49:00 +00001431rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001432{
1433 struct rib *head;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001434 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001435
1436 assert (rib && rn);
1437
Paul Jakma6d691122006-07-27 21:49:00 +00001438 route_lock_node (rn); /* rn route table reference */
1439
1440 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001441 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001442 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001443 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1444 buf, rn->p.prefixlen, rn, rib);
1445 }
Paul Jakma6d691122006-07-27 21:49:00 +00001446
paul718e3742002-12-13 20:15:29 +00001447 head = rn->info;
1448 if (head)
Paul Jakma6d691122006-07-27 21:49:00 +00001449 {
1450 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001451 zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
1452 buf, rn->p.prefixlen);
Paul Jakma6d691122006-07-27 21:49:00 +00001453 head->prev = rib;
1454 /* Transfer the rn status flags to the new head RIB */
1455 rib->rn_status = head->rn_status;
1456 }
paul718e3742002-12-13 20:15:29 +00001457 rib->next = head;
1458 rn->info = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001459 rib_queue_add (&zebrad, rn);
1460}
1461
1462static void
1463rib_addnode (struct route_node *rn, struct rib *rib)
1464{
1465 /* RIB node has been un-removed before route-node is processed.
1466 * route_node must hence already be on the queue for processing..
1467 */
1468 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1469 {
1470 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001471 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001472 char buf[INET6_ADDRSTRLEN];
1473 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, un-removed rib %p",
1475 __func__, buf, rn->p.prefixlen, rn, rib);
1476 }
Paul Jakma6d691122006-07-27 21:49:00 +00001477 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1478 return;
1479 }
1480 rib_link (rn, rib);
1481}
1482
1483static void
1484rib_unlink (struct route_node *rn, struct rib *rib)
1485{
1486 struct nexthop *nexthop, *next;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001487 char buf[INET6_ADDRSTRLEN];
Paul Jakma6d691122006-07-27 21:49:00 +00001488
1489 assert (rn && rib);
1490
1491 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001492 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001493 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001494 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1495 __func__, buf, rn->p.prefixlen, rn, rib);
1496 }
Paul Jakma6d691122006-07-27 21:49:00 +00001497
1498 if (rib->next)
1499 rib->next->prev = rib->prev;
1500
1501 if (rib->prev)
1502 rib->prev->next = rib->next;
1503 else
1504 {
1505 rn->info = rib->next;
1506
1507 if (rn->info)
1508 {
1509 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001510 zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
1511 __func__, buf, rn->p.prefixlen, rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001512 rib->next->rn_status = rib->rn_status;
1513 }
1514 }
1515
1516 /* free RIB and nexthops */
1517 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1518 {
1519 next = nexthop->next;
1520 nexthop_free (nexthop);
1521 }
1522 XFREE (MTYPE_RIB, rib);
1523
1524 route_unlock_node (rn); /* rn route table reference */
paul718e3742002-12-13 20:15:29 +00001525}
1526
paula1ac18c2005-06-28 17:17:12 +00001527static void
paul718e3742002-12-13 20:15:29 +00001528rib_delnode (struct route_node *rn, struct rib *rib)
1529{
Paul Jakma6d691122006-07-27 21:49:00 +00001530 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001531 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001532 char buf[INET6_ADDRSTRLEN];
1533 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001534 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1535 buf, rn->p.prefixlen, rn, rib);
1536 }
Paul Jakma6d691122006-07-27 21:49:00 +00001537 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1538 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001539}
1540
1541int
1542rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001543 struct in_addr *gate, struct in_addr *src,
1544 unsigned int ifindex, u_int32_t vrf_id,
paul718e3742002-12-13 20:15:29 +00001545 u_int32_t metric, u_char distance)
1546{
1547 struct rib *rib;
1548 struct rib *same = NULL;
1549 struct route_table *table;
1550 struct route_node *rn;
1551 struct nexthop *nexthop;
1552
1553 /* Lookup table. */
1554 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1555 if (! table)
1556 return 0;
1557
1558 /* Make it sure prefixlen is applied to the prefix. */
1559 apply_mask_ipv4 (p);
1560
1561 /* Set default distance by route type. */
1562 if (distance == 0)
1563 {
1564 distance = route_info[type].distance;
1565
1566 /* iBGP distance is 200. */
1567 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1568 distance = 200;
1569 }
1570
1571 /* Lookup route node.*/
1572 rn = route_node_get (table, (struct prefix *) p);
1573
1574 /* If same type of route are installed, treat it as a implicit
1575 withdraw. */
1576 for (rib = rn->info; rib; rib = rib->next)
1577 {
Paul Jakma6d691122006-07-27 21:49:00 +00001578 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1579 continue;
1580
hassoebf1ead2005-09-21 14:58:20 +00001581 if (rib->type != type)
1582 continue;
1583 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001584 {
1585 same = rib;
1586 break;
1587 }
hassoebf1ead2005-09-21 14:58:20 +00001588 /* Duplicate connected route comes in. */
1589 else if ((nexthop = rib->nexthop) &&
1590 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001591 nexthop->ifindex == ifindex &&
1592 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001593 {
1594 rib->refcnt++;
1595 return 0 ;
1596 }
paul718e3742002-12-13 20:15:29 +00001597 }
1598
1599 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001600 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001601 rib->type = type;
1602 rib->distance = distance;
1603 rib->flags = flags;
1604 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001605 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001606 rib->nexthop_num = 0;
1607 rib->uptime = time (NULL);
1608
1609 /* Nexthop settings. */
1610 if (gate)
1611 {
1612 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001613 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001614 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001615 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001616 }
1617 else
1618 nexthop_ifindex_add (rib, ifindex);
1619
1620 /* If this route is kernel route, set FIB flag to the route. */
1621 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1622 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1623 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1624
1625 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001626 if (IS_ZEBRA_DEBUG_RIB)
1627 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001628 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001629
paul718e3742002-12-13 20:15:29 +00001630 /* Free implicit route.*/
1631 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001632 {
1633 if (IS_ZEBRA_DEBUG_RIB)
1634 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001635 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001636 }
paul4d38fdb2005-04-28 17:35:14 +00001637
1638 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001639 return 0;
1640}
1641
Denis Ovsienkodc958242007-08-13 16:03:06 +00001642/* This function dumps the contents of a given RIB entry into
1643 * standard debug log. Calling function name and IP prefix in
1644 * question are passed as 1st and 2nd arguments.
1645 */
1646
1647void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1648{
1649 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1650 struct nexthop *nexthop;
1651
1652 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1653 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1654 zlog_debug
1655 (
1656 "%s: refcnt == %lu, uptime == %u, type == %u, table == %d",
1657 func,
1658 rib->refcnt,
1659 rib->uptime,
1660 rib->type,
1661 rib->table
1662 );
1663 zlog_debug
1664 (
1665 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1666 func,
1667 rib->metric,
1668 rib->distance,
1669 rib->flags,
1670 rib->status
1671 );
1672 zlog_debug
1673 (
1674 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1675 func,
1676 rib->nexthop_num,
1677 rib->nexthop_active_num,
1678 rib->nexthop_fib_num
1679 );
1680 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1681 {
1682 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1683 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1684 zlog_debug
1685 (
1686 "%s: NH %s (%s) with flags %s%s%s",
1687 func,
1688 straddr1,
1689 straddr2,
1690 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1691 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1692 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1693 );
1694 }
1695 zlog_debug ("%s: dump complete", func);
1696}
1697
1698/* This is an exported helper to rtm_read() to dump the strange
1699 * RIB entry found by rib_lookup_ipv4_route()
1700 */
1701
1702void rib_lookup_and_dump (struct prefix_ipv4 * p)
1703{
1704 struct route_table *table;
1705 struct route_node *rn;
1706 struct rib *rib;
1707 char prefix_buf[INET_ADDRSTRLEN];
1708
1709 /* Lookup table. */
1710 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1711 if (! table)
1712 {
1713 zlog_err ("%s: vrf_table() returned NULL", __func__);
1714 return;
1715 }
1716
1717 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1718 /* Scan the RIB table for exactly matching RIB entry. */
1719 rn = route_node_lookup (table, (struct prefix *) p);
1720
1721 /* No route for this prefix. */
1722 if (! rn)
1723 {
1724 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1725 return;
1726 }
1727
1728 /* Unlock node. */
1729 route_unlock_node (rn);
1730
1731 /* let's go */
1732 for (rib = rn->info; rib; rib = rib->next)
1733 {
1734 zlog_debug
1735 (
1736 "%s: rn %p, rib %p: %s, %s",
1737 __func__,
1738 rn,
1739 rib,
1740 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1741 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1742 );
1743 rib_dump (__func__, p, rib);
1744 }
1745}
1746
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001747/* Check if requested address assignment will fail due to another
1748 * route being installed by zebra in FIB already. Take necessary
1749 * actions, if needed: remove such a route from FIB and deSELECT
1750 * corresponding RIB entry. Then put affected RN into RIBQ head.
1751 */
1752void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1753{
1754 struct route_table *table;
1755 struct route_node *rn;
1756 struct rib *rib;
1757 unsigned changed = 0;
1758
1759 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
1760 {
1761 zlog_err ("%s: vrf_table() returned NULL", __func__);
1762 return;
1763 }
1764
1765 /* No matches would be the simplest case. */
1766 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1767 return;
1768
1769 /* Unlock node. */
1770 route_unlock_node (rn);
1771
1772 /* Check all RIB entries. In case any changes have to be done, requeue
1773 * the RN into RIBQ head. If the routing message about the new connected
1774 * route (generated by the IP address we are going to assign very soon)
1775 * comes before the RIBQ is processed, the new RIB entry will join
1776 * RIBQ record already on head. This is necessary for proper revalidation
1777 * of the rest of the RIB.
1778 */
1779 for (rib = rn->info; rib; rib = rib->next)
1780 {
1781 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1782 ! RIB_SYSTEM_ROUTE (rib))
1783 {
1784 changed = 1;
1785 if (IS_ZEBRA_DEBUG_RIB)
1786 {
1787 char buf[INET_ADDRSTRLEN];
1788 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
1789 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
1790 rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
1791 }
1792 rib_uninstall (rn, rib);
1793 }
1794 }
1795 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001796 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001797}
1798
paul718e3742002-12-13 20:15:29 +00001799int
1800rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1801{
1802 struct route_table *table;
1803 struct route_node *rn;
1804 struct rib *same;
1805 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001806
paul718e3742002-12-13 20:15:29 +00001807 /* Lookup table. */
1808 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1809 if (! table)
1810 return 0;
paul718e3742002-12-13 20:15:29 +00001811 /* Make it sure prefixlen is applied to the prefix. */
1812 apply_mask_ipv4 (p);
1813
1814 /* Set default distance by route type. */
1815 if (rib->distance == 0)
1816 {
1817 rib->distance = route_info[rib->type].distance;
1818
1819 /* iBGP distance is 200. */
1820 if (rib->type == ZEBRA_ROUTE_BGP
1821 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1822 rib->distance = 200;
1823 }
1824
1825 /* Lookup route node.*/
1826 rn = route_node_get (table, (struct prefix *) p);
1827
1828 /* If same type of route are installed, treat it as a implicit
1829 withdraw. */
1830 for (same = rn->info; same; same = same->next)
1831 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001832 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001833 continue;
1834
paul718e3742002-12-13 20:15:29 +00001835 if (same->type == rib->type && same->table == rib->table
1836 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001837 break;
paul718e3742002-12-13 20:15:29 +00001838 }
paul4d38fdb2005-04-28 17:35:14 +00001839
paul718e3742002-12-13 20:15:29 +00001840 /* If this route is kernel route, set FIB flag to the route. */
1841 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1842 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1843 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1844
1845 /* Link new rib to node.*/
1846 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001847 if (IS_ZEBRA_DEBUG_RIB)
1848 {
1849 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1850 __func__, rn, rib);
1851 rib_dump (__func__, p, rib);
1852 }
paul718e3742002-12-13 20:15:29 +00001853
paul718e3742002-12-13 20:15:29 +00001854 /* Free implicit route.*/
1855 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001856 {
1857 if (IS_ZEBRA_DEBUG_RIB)
1858 {
1859 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1860 __func__, rn, same);
1861 rib_dump (__func__, p, same);
1862 }
paul4d38fdb2005-04-28 17:35:14 +00001863 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001864 }
paul4d38fdb2005-04-28 17:35:14 +00001865
1866 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001867 return 0;
1868}
1869
hassoebf1ead2005-09-21 14:58:20 +00001870/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001871int
1872rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1873 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1874{
1875 struct route_table *table;
1876 struct route_node *rn;
1877 struct rib *rib;
1878 struct rib *fib = NULL;
1879 struct rib *same = NULL;
1880 struct nexthop *nexthop;
Stephen Hemminger81cce012009-04-28 14:28:00 -07001881 char buf1[INET_ADDRSTRLEN];
1882 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00001883
1884 /* Lookup table. */
1885 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1886 if (! table)
1887 return 0;
1888
1889 /* Apply mask. */
1890 apply_mask_ipv4 (p);
1891
paul5ec90d22003-06-19 01:41:37 +00001892 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001893 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001894 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul5ec90d22003-06-19 01:41:37 +00001895 p->prefixlen,
1896 inet_ntoa (*gate),
1897 ifindex);
1898
paul718e3742002-12-13 20:15:29 +00001899 /* Lookup route node. */
1900 rn = route_node_lookup (table, (struct prefix *) p);
1901 if (! rn)
1902 {
1903 if (IS_ZEBRA_DEBUG_KERNEL)
1904 {
1905 if (gate)
ajsb6178002004-12-07 21:12:56 +00001906 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001907 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001908 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07001909 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001910 ifindex);
1911 else
ajsb6178002004-12-07 21:12:56 +00001912 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001913 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001914 p->prefixlen,
1915 ifindex);
1916 }
1917 return ZEBRA_ERR_RTNOEXIST;
1918 }
1919
1920 /* Lookup same type route. */
1921 for (rib = rn->info; rib; rib = rib->next)
1922 {
Paul Jakma6d691122006-07-27 21:49:00 +00001923 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1924 continue;
1925
paul718e3742002-12-13 20:15:29 +00001926 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1927 fib = rib;
1928
hassoebf1ead2005-09-21 14:58:20 +00001929 if (rib->type != type)
1930 continue;
1931 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1932 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001933 {
hassoebf1ead2005-09-21 14:58:20 +00001934 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001935 {
hassoebf1ead2005-09-21 14:58:20 +00001936 rib->refcnt--;
1937 route_unlock_node (rn);
1938 route_unlock_node (rn);
1939 return 0;
paul718e3742002-12-13 20:15:29 +00001940 }
hassoebf1ead2005-09-21 14:58:20 +00001941 same = rib;
1942 break;
paul718e3742002-12-13 20:15:29 +00001943 }
hassoebf1ead2005-09-21 14:58:20 +00001944 /* Make sure that the route found has the same gateway. */
1945 else if (gate == NULL ||
1946 ((nexthop = rib->nexthop) &&
1947 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1948 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001949 {
hassoebf1ead2005-09-21 14:58:20 +00001950 same = rib;
1951 break;
paul718e3742002-12-13 20:15:29 +00001952 }
1953 }
1954
1955 /* If same type of route can't be found and this message is from
1956 kernel. */
1957 if (! same)
1958 {
1959 if (fib && type == ZEBRA_ROUTE_KERNEL)
1960 {
1961 /* Unset flags. */
1962 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1963 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1964
1965 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1966 }
1967 else
1968 {
1969 if (IS_ZEBRA_DEBUG_KERNEL)
1970 {
1971 if (gate)
ajsb6178002004-12-07 21:12:56 +00001972 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001973 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001974 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07001975 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001976 ifindex,
1977 type);
1978 else
ajsb6178002004-12-07 21:12:56 +00001979 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001980 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001981 p->prefixlen,
1982 ifindex,
1983 type);
1984 }
1985 route_unlock_node (rn);
1986 return ZEBRA_ERR_RTNOEXIST;
1987 }
1988 }
paul4d38fdb2005-04-28 17:35:14 +00001989
paul718e3742002-12-13 20:15:29 +00001990 if (same)
1991 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001992
paul718e3742002-12-13 20:15:29 +00001993 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001994 return 0;
1995}
1996
1997/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001998static void
paul718e3742002-12-13 20:15:29 +00001999static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
2000{
2001 struct rib *rib;
2002 struct route_node *rn;
2003 struct route_table *table;
2004
2005 /* Lookup table. */
2006 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2007 if (! table)
2008 return;
2009
2010 /* Lookup existing route */
2011 rn = route_node_get (table, p);
2012 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002013 {
2014 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2015 continue;
2016
2017 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2018 break;
2019 }
paul718e3742002-12-13 20:15:29 +00002020
2021 if (rib)
2022 {
2023 /* Same distance static route is there. Update it with new
2024 nexthop. */
paul718e3742002-12-13 20:15:29 +00002025 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002026 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002027 {
2028 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002029 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002030 break;
2031 case STATIC_IPV4_IFNAME:
2032 nexthop_ifname_add (rib, si->gate.ifname);
2033 break;
2034 case STATIC_IPV4_BLACKHOLE:
2035 nexthop_blackhole_add (rib);
2036 break;
paul4d38fdb2005-04-28 17:35:14 +00002037 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002038 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002039 }
2040 else
2041 {
2042 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002043 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2044
paul718e3742002-12-13 20:15:29 +00002045 rib->type = ZEBRA_ROUTE_STATIC;
2046 rib->distance = si->distance;
2047 rib->metric = 0;
2048 rib->nexthop_num = 0;
2049
2050 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002051 {
2052 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002053 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002054 break;
2055 case STATIC_IPV4_IFNAME:
2056 nexthop_ifname_add (rib, si->gate.ifname);
2057 break;
2058 case STATIC_IPV4_BLACKHOLE:
2059 nexthop_blackhole_add (rib);
2060 break;
2061 }
paul718e3742002-12-13 20:15:29 +00002062
hasso81dfcaa2003-05-25 19:21:25 +00002063 /* Save the flags of this static routes (reject, blackhole) */
2064 rib->flags = si->flags;
2065
paul718e3742002-12-13 20:15:29 +00002066 /* Link this rib to the tree. */
2067 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002068 }
2069}
2070
paula1ac18c2005-06-28 17:17:12 +00002071static int
paul718e3742002-12-13 20:15:29 +00002072static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2073{
2074 if (nexthop->type == NEXTHOP_TYPE_IPV4
2075 && si->type == STATIC_IPV4_GATEWAY
2076 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2077 return 1;
2078 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2079 && si->type == STATIC_IPV4_IFNAME
2080 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2081 return 1;
paul595db7f2003-05-25 21:35:06 +00002082 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2083 && si->type == STATIC_IPV4_BLACKHOLE)
2084 return 1;
paule8e19462006-01-19 20:16:55 +00002085 return 0;
paul718e3742002-12-13 20:15:29 +00002086}
2087
2088/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002089static void
paul718e3742002-12-13 20:15:29 +00002090static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
2091{
2092 struct route_node *rn;
2093 struct rib *rib;
2094 struct nexthop *nexthop;
2095 struct route_table *table;
2096
2097 /* Lookup table. */
2098 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2099 if (! table)
2100 return;
paul4d38fdb2005-04-28 17:35:14 +00002101
paul718e3742002-12-13 20:15:29 +00002102 /* Lookup existing route with type and distance. */
2103 rn = route_node_lookup (table, p);
2104 if (! rn)
2105 return;
2106
2107 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002108 {
2109 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2110 continue;
2111
2112 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2113 break;
2114 }
paul718e3742002-12-13 20:15:29 +00002115
2116 if (! rib)
2117 {
2118 route_unlock_node (rn);
2119 return;
2120 }
2121
2122 /* Lookup nexthop. */
2123 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2124 if (static_ipv4_nexthop_same (nexthop, si))
2125 break;
2126
2127 /* Can't find nexthop. */
2128 if (! nexthop)
2129 {
2130 route_unlock_node (rn);
2131 return;
2132 }
2133
2134 /* Check nexthop. */
2135 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002136 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002137 else
2138 {
paul6baeb982003-10-28 03:47:15 +00002139 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2140 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002141 nexthop_delete (rib, nexthop);
2142 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002143 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002144 }
paul718e3742002-12-13 20:15:29 +00002145 /* Unlock node. */
2146 route_unlock_node (rn);
2147}
2148
2149/* Add static route into static route configuration. */
2150int
hasso39db97e2004-10-12 20:50:58 +00002151static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00002152 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002153{
2154 u_char type = 0;
2155 struct route_node *rn;
2156 struct static_ipv4 *si;
2157 struct static_ipv4 *pp;
2158 struct static_ipv4 *cp;
2159 struct static_ipv4 *update = NULL;
2160 struct route_table *stable;
2161
2162 /* Lookup table. */
2163 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2164 if (! stable)
2165 return -1;
2166
2167 /* Lookup static route prefix. */
2168 rn = route_node_get (stable, p);
2169
2170 /* Make flags. */
2171 if (gate)
2172 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002173 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002174 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002175 else
2176 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002177
2178 /* Do nothing if there is a same static route. */
2179 for (si = rn->info; si; si = si->next)
2180 {
2181 if (type == si->type
2182 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2183 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2184 {
2185 if (distance == si->distance)
2186 {
2187 route_unlock_node (rn);
2188 return 0;
2189 }
2190 else
2191 update = si;
2192 }
2193 }
2194
Paul Jakma3c0755d2006-12-08 00:53:14 +00002195 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002196 if (update)
2197 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2198
2199 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002200 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002201
2202 si->type = type;
2203 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002204 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002205
2206 if (gate)
2207 si->gate.ipv4 = *gate;
2208 if (ifname)
2209 si->gate.ifname = XSTRDUP (0, ifname);
2210
2211 /* Add new static route information to the tree with sort by
2212 distance value and gateway address. */
2213 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2214 {
2215 if (si->distance < cp->distance)
2216 break;
2217 if (si->distance > cp->distance)
2218 continue;
2219 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2220 {
2221 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2222 break;
2223 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2224 continue;
2225 }
2226 }
2227
2228 /* Make linked list. */
2229 if (pp)
2230 pp->next = si;
2231 else
2232 rn->info = si;
2233 if (cp)
2234 cp->prev = si;
2235 si->prev = pp;
2236 si->next = cp;
2237
2238 /* Install into rib. */
2239 static_install_ipv4 (p, si);
2240
2241 return 1;
2242}
2243
2244/* Delete static route from static route configuration. */
2245int
hasso39db97e2004-10-12 20:50:58 +00002246static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002247 u_char distance, u_int32_t vrf_id)
2248{
2249 u_char type = 0;
2250 struct route_node *rn;
2251 struct static_ipv4 *si;
2252 struct route_table *stable;
2253
2254 /* Lookup table. */
2255 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2256 if (! stable)
2257 return -1;
2258
2259 /* Lookup static route prefix. */
2260 rn = route_node_lookup (stable, p);
2261 if (! rn)
2262 return 0;
2263
2264 /* Make flags. */
2265 if (gate)
2266 type = STATIC_IPV4_GATEWAY;
2267 else if (ifname)
2268 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002269 else
2270 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002271
2272 /* Find same static route is the tree */
2273 for (si = rn->info; si; si = si->next)
2274 if (type == si->type
2275 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2276 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2277 break;
2278
2279 /* Can't find static route. */
2280 if (! si)
2281 {
2282 route_unlock_node (rn);
2283 return 0;
2284 }
2285
2286 /* Install into rib. */
2287 static_uninstall_ipv4 (p, si);
2288
2289 /* Unlink static route from linked list. */
2290 if (si->prev)
2291 si->prev->next = si->next;
2292 else
2293 rn->info = si->next;
2294 if (si->next)
2295 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002296 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002297
2298 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002299 if (ifname)
2300 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002301 XFREE (MTYPE_STATIC_IPV4, si);
2302
paul143a3852003-09-29 20:06:13 +00002303 route_unlock_node (rn);
2304
paul718e3742002-12-13 20:15:29 +00002305 return 1;
2306}
2307
2308
2309#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002310static int
paul718e3742002-12-13 20:15:29 +00002311rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2312 struct in6_addr *gate, unsigned int ifindex, int table)
2313{
hasso726f9b22003-05-25 21:04:54 +00002314 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2315#if defined (MUSICA) || defined (LINUX)
2316 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2317 if (p->prefixlen == 96)
2318 return 0;
2319#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002320 return 1;
hasso726f9b22003-05-25 21:04:54 +00002321 }
paul718e3742002-12-13 20:15:29 +00002322 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2323 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2324 {
2325 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2326 return 1;
2327 }
2328 return 0;
2329}
2330
2331int
2332rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002333 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
2334 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00002335{
2336 struct rib *rib;
2337 struct rib *same = NULL;
2338 struct route_table *table;
2339 struct route_node *rn;
2340 struct nexthop *nexthop;
2341
paul718e3742002-12-13 20:15:29 +00002342 /* Lookup table. */
2343 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2344 if (! table)
2345 return 0;
2346
2347 /* Make sure mask is applied. */
2348 apply_mask_ipv6 (p);
2349
2350 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002351 if (!distance)
2352 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002353
2354 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2355 distance = 200;
2356
2357 /* Filter bogus route. */
2358 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2359 return 0;
2360
2361 /* Lookup route node.*/
2362 rn = route_node_get (table, (struct prefix *) p);
2363
2364 /* If same type of route are installed, treat it as a implicit
2365 withdraw. */
2366 for (rib = rn->info; rib; rib = rib->next)
2367 {
Paul Jakma6d691122006-07-27 21:49:00 +00002368 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2369 continue;
2370
hassoebf1ead2005-09-21 14:58:20 +00002371 if (rib->type != type)
2372 continue;
2373 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002374 {
2375 same = rib;
paul718e3742002-12-13 20:15:29 +00002376 break;
2377 }
hassoebf1ead2005-09-21 14:58:20 +00002378 else if ((nexthop = rib->nexthop) &&
2379 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2380 nexthop->ifindex == ifindex)
2381 {
2382 rib->refcnt++;
2383 return 0;
2384 }
paul718e3742002-12-13 20:15:29 +00002385 }
2386
2387 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002388 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2389
paul718e3742002-12-13 20:15:29 +00002390 rib->type = type;
2391 rib->distance = distance;
2392 rib->flags = flags;
2393 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002394 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002395 rib->nexthop_num = 0;
2396 rib->uptime = time (NULL);
2397
2398 /* Nexthop settings. */
2399 if (gate)
2400 {
2401 if (ifindex)
2402 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2403 else
2404 nexthop_ipv6_add (rib, gate);
2405 }
2406 else
2407 nexthop_ifindex_add (rib, ifindex);
2408
2409 /* If this route is kernel route, set FIB flag to the route. */
2410 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2411 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2412 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2413
2414 /* Link new rib to node.*/
2415 rib_addnode (rn, rib);
2416
paul718e3742002-12-13 20:15:29 +00002417 /* Free implicit route.*/
2418 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002419 rib_delnode (rn, same);
2420
2421 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002422 return 0;
2423}
2424
hassoebf1ead2005-09-21 14:58:20 +00002425/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002426int
2427rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
2428 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
2429{
2430 struct route_table *table;
2431 struct route_node *rn;
2432 struct rib *rib;
2433 struct rib *fib = NULL;
2434 struct rib *same = NULL;
2435 struct nexthop *nexthop;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002436 char buf1[INET6_ADDRSTRLEN];
2437 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002438
2439 /* Apply mask. */
2440 apply_mask_ipv6 (p);
2441
2442 /* Lookup table. */
2443 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2444 if (! table)
2445 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002446
paul718e3742002-12-13 20:15:29 +00002447 /* Lookup route node. */
2448 rn = route_node_lookup (table, (struct prefix *) p);
2449 if (! rn)
2450 {
2451 if (IS_ZEBRA_DEBUG_KERNEL)
2452 {
2453 if (gate)
ajsb6178002004-12-07 21:12:56 +00002454 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002455 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002456 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002457 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002458 ifindex);
2459 else
ajsb6178002004-12-07 21:12:56 +00002460 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002461 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002462 p->prefixlen,
2463 ifindex);
2464 }
2465 return ZEBRA_ERR_RTNOEXIST;
2466 }
2467
2468 /* Lookup same type route. */
2469 for (rib = rn->info; rib; rib = rib->next)
2470 {
Paul Jakma6d691122006-07-27 21:49:00 +00002471 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2472 continue;
2473
paul718e3742002-12-13 20:15:29 +00002474 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2475 fib = rib;
2476
hassoebf1ead2005-09-21 14:58:20 +00002477 if (rib->type != type)
2478 continue;
2479 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
2480 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00002481 {
hassoebf1ead2005-09-21 14:58:20 +00002482 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002483 {
hassoebf1ead2005-09-21 14:58:20 +00002484 rib->refcnt--;
2485 route_unlock_node (rn);
2486 route_unlock_node (rn);
2487 return 0;
paul718e3742002-12-13 20:15:29 +00002488 }
hassoebf1ead2005-09-21 14:58:20 +00002489 same = rib;
2490 break;
paul718e3742002-12-13 20:15:29 +00002491 }
hassoebf1ead2005-09-21 14:58:20 +00002492 /* Make sure that the route found has the same gateway. */
2493 else if (gate == NULL ||
2494 ((nexthop = rib->nexthop) &&
2495 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2496 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002497 {
hassoebf1ead2005-09-21 14:58:20 +00002498 same = rib;
2499 break;
paul718e3742002-12-13 20:15:29 +00002500 }
2501 }
2502
2503 /* If same type of route can't be found and this message is from
2504 kernel. */
2505 if (! same)
2506 {
2507 if (fib && type == ZEBRA_ROUTE_KERNEL)
2508 {
2509 /* Unset flags. */
2510 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2511 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2512
2513 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2514 }
2515 else
2516 {
2517 if (IS_ZEBRA_DEBUG_KERNEL)
2518 {
2519 if (gate)
ajsb6178002004-12-07 21:12:56 +00002520 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002521 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002522 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002523 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002524 ifindex,
2525 type);
2526 else
ajsb6178002004-12-07 21:12:56 +00002527 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002528 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002529 p->prefixlen,
2530 ifindex,
2531 type);
2532 }
2533 route_unlock_node (rn);
2534 return ZEBRA_ERR_RTNOEXIST;
2535 }
2536 }
2537
2538 if (same)
2539 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002540
paul718e3742002-12-13 20:15:29 +00002541 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002542 return 0;
2543}
2544
2545/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002546static void
paul718e3742002-12-13 20:15:29 +00002547static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2548{
2549 struct rib *rib;
2550 struct route_table *table;
2551 struct route_node *rn;
2552
2553 /* Lookup table. */
2554 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2555 if (! table)
2556 return;
2557
2558 /* Lookup existing route */
2559 rn = route_node_get (table, p);
2560 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002561 {
2562 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2563 continue;
2564
2565 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2566 break;
2567 }
paul718e3742002-12-13 20:15:29 +00002568
2569 if (rib)
2570 {
2571 /* Same distance static route is there. Update it with new
2572 nexthop. */
paul718e3742002-12-13 20:15:29 +00002573 route_unlock_node (rn);
2574
2575 switch (si->type)
2576 {
2577 case STATIC_IPV6_GATEWAY:
2578 nexthop_ipv6_add (rib, &si->ipv6);
2579 break;
2580 case STATIC_IPV6_IFNAME:
2581 nexthop_ifname_add (rib, si->ifname);
2582 break;
2583 case STATIC_IPV6_GATEWAY_IFNAME:
2584 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2585 break;
2586 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002587 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002588 }
2589 else
2590 {
2591 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002592 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2593
paul718e3742002-12-13 20:15:29 +00002594 rib->type = ZEBRA_ROUTE_STATIC;
2595 rib->distance = si->distance;
2596 rib->metric = 0;
2597 rib->nexthop_num = 0;
2598
2599 switch (si->type)
2600 {
2601 case STATIC_IPV6_GATEWAY:
2602 nexthop_ipv6_add (rib, &si->ipv6);
2603 break;
2604 case STATIC_IPV6_IFNAME:
2605 nexthop_ifname_add (rib, si->ifname);
2606 break;
2607 case STATIC_IPV6_GATEWAY_IFNAME:
2608 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2609 break;
2610 }
2611
hasso81dfcaa2003-05-25 19:21:25 +00002612 /* Save the flags of this static routes (reject, blackhole) */
2613 rib->flags = si->flags;
2614
paul718e3742002-12-13 20:15:29 +00002615 /* Link this rib to the tree. */
2616 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002617 }
2618}
2619
paula1ac18c2005-06-28 17:17:12 +00002620static int
paul718e3742002-12-13 20:15:29 +00002621static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2622{
2623 if (nexthop->type == NEXTHOP_TYPE_IPV6
2624 && si->type == STATIC_IPV6_GATEWAY
2625 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2626 return 1;
2627 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2628 && si->type == STATIC_IPV6_IFNAME
2629 && strcmp (nexthop->ifname, si->ifname) == 0)
2630 return 1;
2631 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2632 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2633 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2634 && strcmp (nexthop->ifname, si->ifname) == 0)
2635 return 1;
paule8e19462006-01-19 20:16:55 +00002636 return 0;
paul718e3742002-12-13 20:15:29 +00002637}
2638
paula1ac18c2005-06-28 17:17:12 +00002639static void
paul718e3742002-12-13 20:15:29 +00002640static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2641{
2642 struct route_table *table;
2643 struct route_node *rn;
2644 struct rib *rib;
2645 struct nexthop *nexthop;
2646
2647 /* Lookup table. */
2648 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2649 if (! table)
2650 return;
2651
2652 /* Lookup existing route with type and distance. */
2653 rn = route_node_lookup (table, (struct prefix *) p);
2654 if (! rn)
2655 return;
2656
2657 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002658 {
2659 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2660 continue;
2661
2662 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2663 break;
2664 }
2665
paul718e3742002-12-13 20:15:29 +00002666 if (! rib)
2667 {
2668 route_unlock_node (rn);
2669 return;
2670 }
2671
2672 /* Lookup nexthop. */
2673 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2674 if (static_ipv6_nexthop_same (nexthop, si))
2675 break;
2676
2677 /* Can't find nexthop. */
2678 if (! nexthop)
2679 {
2680 route_unlock_node (rn);
2681 return;
2682 }
2683
2684 /* Check nexthop. */
2685 if (rib->nexthop_num == 1)
2686 {
2687 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002688 }
2689 else
2690 {
paul6baeb982003-10-28 03:47:15 +00002691 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2692 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002693 nexthop_delete (rib, nexthop);
2694 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002695 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002696 }
paul718e3742002-12-13 20:15:29 +00002697 /* Unlock node. */
2698 route_unlock_node (rn);
2699}
2700
2701/* Add static route into static route configuration. */
2702int
2703static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002704 const char *ifname, u_char flags, u_char distance,
2705 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002706{
2707 struct route_node *rn;
2708 struct static_ipv6 *si;
2709 struct static_ipv6 *pp;
2710 struct static_ipv6 *cp;
2711 struct route_table *stable;
2712
2713 /* Lookup table. */
2714 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2715 if (! stable)
2716 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002717
2718 if (!gate &&
2719 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2720 return -1;
2721
2722 if (!ifname &&
2723 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2724 return -1;
paul718e3742002-12-13 20:15:29 +00002725
2726 /* Lookup static route prefix. */
2727 rn = route_node_get (stable, p);
2728
2729 /* Do nothing if there is a same static route. */
2730 for (si = rn->info; si; si = si->next)
2731 {
2732 if (distance == si->distance
2733 && type == si->type
2734 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2735 && (! ifname || strcmp (ifname, si->ifname) == 0))
2736 {
2737 route_unlock_node (rn);
2738 return 0;
2739 }
2740 }
2741
2742 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002743 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00002744
2745 si->type = type;
2746 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002747 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002748
2749 switch (type)
2750 {
2751 case STATIC_IPV6_GATEWAY:
2752 si->ipv6 = *gate;
2753 break;
2754 case STATIC_IPV6_IFNAME:
2755 si->ifname = XSTRDUP (0, ifname);
2756 break;
2757 case STATIC_IPV6_GATEWAY_IFNAME:
2758 si->ipv6 = *gate;
2759 si->ifname = XSTRDUP (0, ifname);
2760 break;
2761 }
2762
2763 /* Add new static route information to the tree with sort by
2764 distance value and gateway address. */
2765 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2766 {
2767 if (si->distance < cp->distance)
2768 break;
2769 if (si->distance > cp->distance)
2770 continue;
2771 }
2772
2773 /* Make linked list. */
2774 if (pp)
2775 pp->next = si;
2776 else
2777 rn->info = si;
2778 if (cp)
2779 cp->prev = si;
2780 si->prev = pp;
2781 si->next = cp;
2782
2783 /* Install into rib. */
2784 static_install_ipv6 (p, si);
2785
2786 return 1;
2787}
2788
2789/* Delete static route from static route configuration. */
2790int
2791static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002792 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002793{
2794 struct route_node *rn;
2795 struct static_ipv6 *si;
2796 struct route_table *stable;
2797
2798 /* Lookup table. */
2799 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2800 if (! stable)
2801 return -1;
2802
2803 /* Lookup static route prefix. */
2804 rn = route_node_lookup (stable, p);
2805 if (! rn)
2806 return 0;
2807
2808 /* Find same static route is the tree */
2809 for (si = rn->info; si; si = si->next)
2810 if (distance == si->distance
2811 && type == si->type
2812 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2813 && (! ifname || strcmp (ifname, si->ifname) == 0))
2814 break;
2815
2816 /* Can't find static route. */
2817 if (! si)
2818 {
2819 route_unlock_node (rn);
2820 return 0;
2821 }
2822
2823 /* Install into rib. */
2824 static_uninstall_ipv6 (p, si);
2825
2826 /* Unlink static route from linked list. */
2827 if (si->prev)
2828 si->prev->next = si->next;
2829 else
2830 rn->info = si->next;
2831 if (si->next)
2832 si->next->prev = si->prev;
2833
2834 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002835 if (ifname)
2836 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002837 XFREE (MTYPE_STATIC_IPV6, si);
2838
2839 return 1;
2840}
2841#endif /* HAVE_IPV6 */
2842
2843/* RIB update function. */
2844void
paula1ac18c2005-06-28 17:17:12 +00002845rib_update (void)
paul718e3742002-12-13 20:15:29 +00002846{
2847 struct route_node *rn;
2848 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002849
paul718e3742002-12-13 20:15:29 +00002850 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2851 if (table)
2852 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002853 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002854 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002855
2856 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2857 if (table)
2858 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002859 if (rn->info)
Paul Jakma6d691122006-07-27 21:49:00 +00002860 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002861}
2862
2863/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002864static void
paul718e3742002-12-13 20:15:29 +00002865rib_if_up (struct interface *ifp)
2866{
2867 rib_update ();
2868}
2869
2870/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002871static void
paul718e3742002-12-13 20:15:29 +00002872rib_if_down (struct interface *ifp)
2873{
2874 rib_update ();
2875}
2876
2877/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002878static void
paul718e3742002-12-13 20:15:29 +00002879rib_weed_table (struct route_table *table)
2880{
2881 struct route_node *rn;
2882 struct rib *rib;
2883 struct rib *next;
2884
2885 if (table)
2886 for (rn = route_top (table); rn; rn = route_next (rn))
2887 for (rib = rn->info; rib; rib = next)
2888 {
2889 next = rib->next;
2890
Paul Jakma6d691122006-07-27 21:49:00 +00002891 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2892 continue;
2893
paulb21b19c2003-06-15 01:28:29 +00002894 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002895 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002896 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002897 }
2898}
2899
2900/* Delete all routes from non main table. */
2901void
paula1ac18c2005-06-28 17:17:12 +00002902rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002903{
2904 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2905 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2906}
2907
2908/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002909static void
paul718e3742002-12-13 20:15:29 +00002910rib_sweep_table (struct route_table *table)
2911{
2912 struct route_node *rn;
2913 struct rib *rib;
2914 struct rib *next;
2915 int ret = 0;
2916
2917 if (table)
2918 for (rn = route_top (table); rn; rn = route_next (rn))
2919 for (rib = rn->info; rib; rib = next)
2920 {
2921 next = rib->next;
2922
Paul Jakma6d691122006-07-27 21:49:00 +00002923 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2924 continue;
2925
paul718e3742002-12-13 20:15:29 +00002926 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2927 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2928 {
2929 ret = rib_uninstall_kernel (rn, rib);
2930 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002931 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002932 }
2933 }
2934}
2935
2936/* Sweep all RIB tables. */
2937void
paula1ac18c2005-06-28 17:17:12 +00002938rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002939{
2940 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2941 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2942}
2943
2944/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002945static void
paul718e3742002-12-13 20:15:29 +00002946rib_close_table (struct route_table *table)
2947{
2948 struct route_node *rn;
2949 struct rib *rib;
2950
2951 if (table)
2952 for (rn = route_top (table); rn; rn = route_next (rn))
2953 for (rib = rn->info; rib; rib = rib->next)
Paul Jakma6d691122006-07-27 21:49:00 +00002954 {
2955 if (! RIB_SYSTEM_ROUTE (rib)
2956 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2957 rib_uninstall_kernel (rn, rib);
2958 }
paul718e3742002-12-13 20:15:29 +00002959}
2960
2961/* Close all RIB tables. */
2962void
paula1ac18c2005-06-28 17:17:12 +00002963rib_close (void)
paul718e3742002-12-13 20:15:29 +00002964{
2965 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2966 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2967}
2968
2969/* Routing information base initialize. */
2970void
paula1ac18c2005-06-28 17:17:12 +00002971rib_init (void)
paul718e3742002-12-13 20:15:29 +00002972{
paul4d38fdb2005-04-28 17:35:14 +00002973 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002974 /* VRF initialization. */
2975 vrf_init ();
2976}