blob: 2cbee9355759a7563313af02209d8b20c01e12cf [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;
Paul Jakma57345092011-12-25 17:52:09 +010058} route_info[ZEBRA_ROUTE_MAX] =
paul718e3742002-12-13 20:15:29 +000059{
Paul Jakma57345092011-12-25 17:52:09 +010060 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
61 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
62 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
63 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
64 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
65 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
66 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
67 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
68 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
69 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
70 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
David Lamparter7052f222009-08-27 00:28:28 +020071 /* no entry/default: 150 */
paul718e3742002-12-13 20:15:29 +000072};
73
74/* Vector for routing table. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010075static vector vrf_vector;
paul718e3742002-12-13 20:15:29 +000076
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +000077/*
78 * vrf_table_create
79 */
80static void
81vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
82{
83 rib_table_info_t *info;
84 struct route_table *table;
85
86 assert (!vrf->table[afi][safi]);
87
88 table = route_table_init ();
89 vrf->table[afi][safi] = table;
90
91 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
92 info->vrf = vrf;
93 info->afi = afi;
94 info->safi = safi;
95 table->info = info;
96}
97
paul718e3742002-12-13 20:15:29 +000098/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +000099static struct vrf *
hassofce954f2004-10-07 20:29:24 +0000100vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +0000101{
102 struct vrf *vrf;
103
104 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
105
106 /* Put name. */
107 if (name)
108 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
109
110 /* Allocate routing table and static table. */
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000111 vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
112 vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000113 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
114 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000115 vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
116 vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
G.Balajicddf3912011-11-26 21:59:32 +0400117 vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
118 vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
119
paul718e3742002-12-13 20:15:29 +0000120
121 return vrf;
122}
123
paul718e3742002-12-13 20:15:29 +0000124/* Lookup VRF by identifier. */
125struct vrf *
126vrf_lookup (u_int32_t id)
127{
128 return vector_lookup (vrf_vector, id);
129}
130
paul718e3742002-12-13 20:15:29 +0000131/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000132static void
133vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000134{
135 struct vrf *default_table;
136
137 /* Allocate VRF vector. */
138 vrf_vector = vector_init (1);
139
140 /* Allocate default main table. */
141 default_table = vrf_alloc ("Default-IP-Routing-Table");
142
143 /* Default table index must be 0. */
144 vector_set_index (vrf_vector, 0, default_table);
145}
146
147/* Lookup route table. */
148struct route_table *
149vrf_table (afi_t afi, safi_t safi, u_int32_t id)
150{
151 struct vrf *vrf;
152
153 vrf = vrf_lookup (id);
154 if (! vrf)
155 return NULL;
156
157 return vrf->table[afi][safi];
158}
159
160/* Lookup static route table. */
161struct route_table *
162vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
163{
164 struct vrf *vrf;
165
166 vrf = vrf_lookup (id);
167 if (! vrf)
168 return NULL;
169
170 return vrf->stable[afi][safi];
171}
172
173/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000174static void
paul718e3742002-12-13 20:15:29 +0000175nexthop_add (struct rib *rib, struct nexthop *nexthop)
176{
177 struct nexthop *last;
178
179 for (last = rib->nexthop; last && last->next; last = last->next)
180 ;
181 if (last)
182 last->next = nexthop;
183 else
184 rib->nexthop = nexthop;
185 nexthop->prev = last;
186
187 rib->nexthop_num++;
188}
189
190/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000191static void
paul718e3742002-12-13 20:15:29 +0000192nexthop_delete (struct rib *rib, struct nexthop *nexthop)
193{
194 if (nexthop->next)
195 nexthop->next->prev = nexthop->prev;
196 if (nexthop->prev)
197 nexthop->prev->next = nexthop->next;
198 else
199 rib->nexthop = nexthop->next;
200 rib->nexthop_num--;
201}
202
203/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000204static void
paul718e3742002-12-13 20:15:29 +0000205nexthop_free (struct nexthop *nexthop)
206{
paula4b70762003-05-16 17:19:48 +0000207 if (nexthop->ifname)
208 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000209 XFREE (MTYPE_NEXTHOP, nexthop);
210}
211
212struct nexthop *
213nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
214{
215 struct nexthop *nexthop;
216
Stephen Hemminger393deb92008-08-18 14:13:29 -0700217 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000218 nexthop->type = NEXTHOP_TYPE_IFINDEX;
219 nexthop->ifindex = ifindex;
220
221 nexthop_add (rib, nexthop);
222
223 return nexthop;
224}
225
226struct nexthop *
227nexthop_ifname_add (struct rib *rib, char *ifname)
228{
229 struct nexthop *nexthop;
230
Stephen Hemminger393deb92008-08-18 14:13:29 -0700231 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000232 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000233 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000234
235 nexthop_add (rib, nexthop);
236
237 return nexthop;
238}
239
240struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000241nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000242{
243 struct nexthop *nexthop;
244
Stephen Hemminger393deb92008-08-18 14:13:29 -0700245 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000246 nexthop->type = NEXTHOP_TYPE_IPV4;
247 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000248 if (src)
249 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000250
251 nexthop_add (rib, nexthop);
252
253 return nexthop;
254}
255
Josh Bailey26e2ae32012-03-22 01:09:21 -0700256struct nexthop *
paul718e3742002-12-13 20:15:29 +0000257nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000258 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000259{
260 struct nexthop *nexthop;
261
Stephen Hemminger393deb92008-08-18 14:13:29 -0700262 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000263 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
264 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000265 if (src)
266 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000267 nexthop->ifindex = ifindex;
268
269 nexthop_add (rib, nexthop);
270
271 return nexthop;
272}
273
274#ifdef HAVE_IPV6
275struct nexthop *
276nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
277{
278 struct nexthop *nexthop;
279
Stephen Hemminger393deb92008-08-18 14:13:29 -0700280 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000281 nexthop->type = NEXTHOP_TYPE_IPV6;
282 nexthop->gate.ipv6 = *ipv6;
283
284 nexthop_add (rib, nexthop);
285
286 return nexthop;
287}
288
paula1ac18c2005-06-28 17:17:12 +0000289static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000290nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
291 char *ifname)
292{
293 struct nexthop *nexthop;
294
Stephen Hemminger393deb92008-08-18 14:13:29 -0700295 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000296 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
297 nexthop->gate.ipv6 = *ipv6;
298 nexthop->ifname = XSTRDUP (0, ifname);
299
300 nexthop_add (rib, nexthop);
301
302 return nexthop;
303}
304
paula1ac18c2005-06-28 17:17:12 +0000305static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000306nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
307 unsigned int ifindex)
308{
309 struct nexthop *nexthop;
310
Stephen Hemminger393deb92008-08-18 14:13:29 -0700311 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000312 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
313 nexthop->gate.ipv6 = *ipv6;
314 nexthop->ifindex = ifindex;
315
316 nexthop_add (rib, nexthop);
317
318 return nexthop;
319}
320#endif /* HAVE_IPV6 */
321
paul595db7f2003-05-25 21:35:06 +0000322struct nexthop *
323nexthop_blackhole_add (struct rib *rib)
324{
325 struct nexthop *nexthop;
326
Stephen Hemminger393deb92008-08-18 14:13:29 -0700327 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000328 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
329 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
330
331 nexthop_add (rib, nexthop);
332
333 return nexthop;
334}
335
paul718e3742002-12-13 20:15:29 +0000336/* If force flag is not set, do not modify falgs at all for uninstall
337 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000338static int
paul718e3742002-12-13 20:15:29 +0000339nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
340 struct route_node *top)
341{
342 struct prefix_ipv4 p;
343 struct route_table *table;
344 struct route_node *rn;
345 struct rib *match;
346 struct nexthop *newhop;
347
348 if (nexthop->type == NEXTHOP_TYPE_IPV4)
349 nexthop->ifindex = 0;
350
351 if (set)
352 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
353
354 /* Make lookup prefix. */
355 memset (&p, 0, sizeof (struct prefix_ipv4));
356 p.family = AF_INET;
357 p.prefixlen = IPV4_MAX_PREFIXLEN;
358 p.prefix = nexthop->gate.ipv4;
359
360 /* Lookup table. */
361 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
362 if (! table)
363 return 0;
364
365 rn = route_node_match (table, (struct prefix *) &p);
366 while (rn)
367 {
368 route_unlock_node (rn);
369
David Warda50c1072009-12-03 15:34:39 +0300370 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000371 if (rn == top)
372 return 0;
373
374 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000375 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100376 {
377 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
378 continue;
379 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
380 break;
381 }
paul718e3742002-12-13 20:15:29 +0000382
383 /* If there is no selected route or matched route is EGP, go up
384 tree. */
385 if (! match
386 || match->type == ZEBRA_ROUTE_BGP)
387 {
388 do {
389 rn = rn->parent;
390 } while (rn && rn->info == NULL);
391 if (rn)
392 route_lock_node (rn);
393 }
394 else
395 {
396 if (match->type == ZEBRA_ROUTE_CONNECT)
397 {
398 /* Directly point connected route. */
399 newhop = match->nexthop;
400 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
401 nexthop->ifindex = newhop->ifindex;
402
403 return 1;
404 }
405 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
406 {
407 for (newhop = match->nexthop; newhop; newhop = newhop->next)
408 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
409 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
410 {
411 if (set)
412 {
413 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
414 nexthop->rtype = newhop->type;
415 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
416 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
417 nexthop->rgate.ipv4 = newhop->gate.ipv4;
418 if (newhop->type == NEXTHOP_TYPE_IFINDEX
419 || newhop->type == NEXTHOP_TYPE_IFNAME
420 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
421 nexthop->rifindex = newhop->ifindex;
422 }
423 return 1;
424 }
425 return 0;
426 }
427 else
428 {
429 return 0;
430 }
431 }
432 }
433 return 0;
434}
435
436#ifdef HAVE_IPV6
437/* If force flag is not set, do not modify falgs at all for uninstall
438 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000439static int
paul718e3742002-12-13 20:15:29 +0000440nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
441 struct route_node *top)
442{
443 struct prefix_ipv6 p;
444 struct route_table *table;
445 struct route_node *rn;
446 struct rib *match;
447 struct nexthop *newhop;
448
449 if (nexthop->type == NEXTHOP_TYPE_IPV6)
450 nexthop->ifindex = 0;
451
452 if (set)
453 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
454
455 /* Make lookup prefix. */
456 memset (&p, 0, sizeof (struct prefix_ipv6));
457 p.family = AF_INET6;
458 p.prefixlen = IPV6_MAX_PREFIXLEN;
459 p.prefix = nexthop->gate.ipv6;
460
461 /* Lookup table. */
462 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
463 if (! table)
464 return 0;
465
466 rn = route_node_match (table, (struct prefix *) &p);
467 while (rn)
468 {
469 route_unlock_node (rn);
470
David Warda50c1072009-12-03 15:34:39 +0300471 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000472 if (rn == top)
473 return 0;
474
475 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000476 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100477 {
478 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
479 continue;
480 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
481 break;
482 }
paul718e3742002-12-13 20:15:29 +0000483
484 /* If there is no selected route or matched route is EGP, go up
485 tree. */
486 if (! match
487 || match->type == ZEBRA_ROUTE_BGP)
488 {
489 do {
490 rn = rn->parent;
491 } while (rn && rn->info == NULL);
492 if (rn)
493 route_lock_node (rn);
494 }
495 else
496 {
497 if (match->type == ZEBRA_ROUTE_CONNECT)
498 {
499 /* Directly point connected route. */
500 newhop = match->nexthop;
501
502 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
503 nexthop->ifindex = newhop->ifindex;
504
505 return 1;
506 }
507 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
508 {
509 for (newhop = match->nexthop; newhop; newhop = newhop->next)
510 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
511 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
512 {
513 if (set)
514 {
515 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
516 nexthop->rtype = newhop->type;
517 if (newhop->type == NEXTHOP_TYPE_IPV6
518 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
519 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
520 nexthop->rgate.ipv6 = newhop->gate.ipv6;
521 if (newhop->type == NEXTHOP_TYPE_IFINDEX
522 || newhop->type == NEXTHOP_TYPE_IFNAME
523 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
524 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
525 nexthop->rifindex = newhop->ifindex;
526 }
527 return 1;
528 }
529 return 0;
530 }
531 else
532 {
533 return 0;
534 }
535 }
536 }
537 return 0;
538}
539#endif /* HAVE_IPV6 */
540
541struct rib *
542rib_match_ipv4 (struct in_addr addr)
543{
544 struct prefix_ipv4 p;
545 struct route_table *table;
546 struct route_node *rn;
547 struct rib *match;
548 struct nexthop *newhop;
549
550 /* Lookup table. */
551 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
552 if (! table)
553 return 0;
554
555 memset (&p, 0, sizeof (struct prefix_ipv4));
556 p.family = AF_INET;
557 p.prefixlen = IPV4_MAX_PREFIXLEN;
558 p.prefix = addr;
559
560 rn = route_node_match (table, (struct prefix *) &p);
561
562 while (rn)
563 {
564 route_unlock_node (rn);
565
566 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000567 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100568 {
569 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
570 continue;
571 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
572 break;
573 }
paul718e3742002-12-13 20:15:29 +0000574
575 /* If there is no selected route or matched route is EGP, go up
576 tree. */
577 if (! match
578 || match->type == ZEBRA_ROUTE_BGP)
579 {
580 do {
581 rn = rn->parent;
582 } while (rn && rn->info == NULL);
583 if (rn)
584 route_lock_node (rn);
585 }
586 else
587 {
588 if (match->type == ZEBRA_ROUTE_CONNECT)
589 /* Directly point connected route. */
590 return match;
591 else
592 {
593 for (newhop = match->nexthop; newhop; newhop = newhop->next)
594 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
595 return match;
596 return NULL;
597 }
598 }
599 }
600 return NULL;
601}
602
603struct rib *
604rib_lookup_ipv4 (struct prefix_ipv4 *p)
605{
606 struct route_table *table;
607 struct route_node *rn;
608 struct rib *match;
609 struct nexthop *nexthop;
610
611 /* Lookup table. */
612 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
613 if (! table)
614 return 0;
615
616 rn = route_node_lookup (table, (struct prefix *) p);
617
618 /* No route for this prefix. */
619 if (! rn)
620 return NULL;
621
622 /* Unlock node. */
623 route_unlock_node (rn);
624
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000625 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100626 {
627 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
628 continue;
629 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
630 break;
631 }
paul718e3742002-12-13 20:15:29 +0000632
633 if (! match || match->type == ZEBRA_ROUTE_BGP)
634 return NULL;
635
636 if (match->type == ZEBRA_ROUTE_CONNECT)
637 return match;
638
639 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
640 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
641 return match;
642
643 return NULL;
644}
645
Denis Ovsienkodc958242007-08-13 16:03:06 +0000646/*
647 * This clone function, unlike its original rib_lookup_ipv4(), checks
648 * if specified IPv4 route record (prefix/mask -> gate) exists in
649 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
650 *
651 * Return values:
652 * -1: error
653 * 0: exact match found
654 * 1: a match was found with a different gate
655 * 2: connected route found
656 * 3: no matches found
657 */
658int
659rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
660{
661 struct route_table *table;
662 struct route_node *rn;
663 struct rib *match;
664 struct nexthop *nexthop;
665
666 /* Lookup table. */
667 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
668 if (! table)
669 return ZEBRA_RIB_LOOKUP_ERROR;
670
671 /* Scan the RIB table for exactly matching RIB entry. */
672 rn = route_node_lookup (table, (struct prefix *) p);
673
674 /* No route for this prefix. */
675 if (! rn)
676 return ZEBRA_RIB_NOTFOUND;
677
678 /* Unlock node. */
679 route_unlock_node (rn);
680
681 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000682 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100683 {
684 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
685 continue;
686 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
687 break;
688 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000689
690 /* None such found :( */
691 if (!match)
692 return ZEBRA_RIB_NOTFOUND;
693
694 if (match->type == ZEBRA_ROUTE_CONNECT)
695 return ZEBRA_RIB_FOUND_CONNECTED;
696
697 /* Ok, we have a cood candidate, let's check it's nexthop list... */
698 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
699 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
700 {
701 /* We are happy with either direct or recursive hexthop */
Jorge Boncompte [DTI2]12829322012-04-10 16:57:25 +0200702 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate) ||
703 nexthop->rgate.ipv4.s_addr == sockunion2ip (qgate))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000704 return ZEBRA_RIB_FOUND_EXACT;
705 else
706 {
707 if (IS_ZEBRA_DEBUG_RIB)
708 {
709 char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
710 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
711 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
Jorge Boncompte [DTI2]12829322012-04-10 16:57:25 +0200712 inet_ntop (AF_INET, &sockunion2ip (qgate), qgate_buf, INET_ADDRSTRLEN);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000713 zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
714 }
715 return ZEBRA_RIB_FOUND_NOGATE;
716 }
717 }
718
719 return ZEBRA_RIB_NOTFOUND;
720}
721
paul718e3742002-12-13 20:15:29 +0000722#ifdef HAVE_IPV6
723struct rib *
724rib_match_ipv6 (struct in6_addr *addr)
725{
726 struct prefix_ipv6 p;
727 struct route_table *table;
728 struct route_node *rn;
729 struct rib *match;
730 struct nexthop *newhop;
731
732 /* Lookup table. */
733 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
734 if (! table)
735 return 0;
736
737 memset (&p, 0, sizeof (struct prefix_ipv6));
738 p.family = AF_INET6;
739 p.prefixlen = IPV6_MAX_PREFIXLEN;
740 IPV6_ADDR_COPY (&p.prefix, addr);
741
742 rn = route_node_match (table, (struct prefix *) &p);
743
744 while (rn)
745 {
746 route_unlock_node (rn);
747
748 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000749 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100750 {
751 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
752 continue;
753 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
754 break;
755 }
paul718e3742002-12-13 20:15:29 +0000756
757 /* If there is no selected route or matched route is EGP, go up
758 tree. */
759 if (! match
760 || match->type == ZEBRA_ROUTE_BGP)
761 {
762 do {
763 rn = rn->parent;
764 } while (rn && rn->info == NULL);
765 if (rn)
766 route_lock_node (rn);
767 }
768 else
769 {
770 if (match->type == ZEBRA_ROUTE_CONNECT)
771 /* Directly point connected route. */
772 return match;
773 else
774 {
775 for (newhop = match->nexthop; newhop; newhop = newhop->next)
776 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
777 return match;
778 return NULL;
779 }
780 }
781 }
782 return NULL;
783}
784#endif /* HAVE_IPV6 */
785
Paul Jakma7514fb72007-05-02 16:05:35 +0000786#define RIB_SYSTEM_ROUTE(R) \
787 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
788
Denis Ovsienkodc958242007-08-13 16:03:06 +0000789/* This function verifies reachability of one given nexthop, which can be
790 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
791 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
792 * nexthop->ifindex will be updated appropriately as well.
793 * An existing route map can turn (otherwise active) nexthop into inactive, but
794 * not vice versa.
795 *
796 * The return value is the final value of 'ACTIVE' flag.
797 */
798
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300799static unsigned
paul718e3742002-12-13 20:15:29 +0000800nexthop_active_check (struct route_node *rn, struct rib *rib,
801 struct nexthop *nexthop, int set)
802{
803 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000804 route_map_result_t ret = RMAP_MATCH;
805 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
806 struct route_map *rmap;
807 int family;
paul718e3742002-12-13 20:15:29 +0000808
Paul Jakma7514fb72007-05-02 16:05:35 +0000809 family = 0;
paul718e3742002-12-13 20:15:29 +0000810 switch (nexthop->type)
811 {
812 case NEXTHOP_TYPE_IFINDEX:
813 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000814 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000815 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
816 else
817 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
818 break;
paul718e3742002-12-13 20:15:29 +0000819 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000820 family = AFI_IP6;
821 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000822 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000823 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000824 {
825 if (set)
826 nexthop->ifindex = ifp->ifindex;
827 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
828 }
829 else
830 {
831 if (set)
832 nexthop->ifindex = 0;
833 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
834 }
835 break;
836 case NEXTHOP_TYPE_IPV4:
837 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000838 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000839 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
840 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
841 else
842 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
843 break;
844#ifdef HAVE_IPV6
845 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000846 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000847 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
848 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
849 else
850 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
851 break;
852 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000853 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000854 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
855 {
856 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000857 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000858 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
859 else
860 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
861 }
862 else
863 {
864 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
865 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
866 else
867 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
868 }
869 break;
870#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000871 case NEXTHOP_TYPE_BLACKHOLE:
872 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
873 break;
paul718e3742002-12-13 20:15:29 +0000874 default:
875 break;
876 }
Paul Jakma7514fb72007-05-02 16:05:35 +0000877 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
878 return 0;
879
880 if (RIB_SYSTEM_ROUTE(rib) ||
881 (family == AFI_IP && rn->p.family != AF_INET) ||
882 (family == AFI_IP6 && rn->p.family != AF_INET6))
883 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
884
885 rmap = 0;
886 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
887 proto_rm[family][rib->type])
888 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
889 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
890 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
891 if (rmap) {
892 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
893 }
894
895 if (ret == RMAP_DENYMATCH)
896 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000897 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
898}
899
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000900/* Iterate over all nexthops of the given RIB entry and refresh their
901 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
902 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
903 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
904 * transparently passed to nexthop_active_check().
905 *
906 * Return value is the new number of active nexthops.
907 */
908
paula1ac18c2005-06-28 17:17:12 +0000909static int
paul718e3742002-12-13 20:15:29 +0000910nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
911{
912 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300913 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +0000914
915 rib->nexthop_active_num = 0;
916 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
917
918 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000919 {
920 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200921 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000922 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
923 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200924 if (prev_active != new_active ||
925 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000926 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
927 }
paul718e3742002-12-13 20:15:29 +0000928 return rib->nexthop_active_num;
929}
paul6baeb982003-10-28 03:47:15 +0000930
paul718e3742002-12-13 20:15:29 +0000931
paul718e3742002-12-13 20:15:29 +0000932
paula1ac18c2005-06-28 17:17:12 +0000933static void
paul718e3742002-12-13 20:15:29 +0000934rib_install_kernel (struct route_node *rn, struct rib *rib)
935{
936 int ret = 0;
937 struct nexthop *nexthop;
938
939 switch (PREFIX_FAMILY (&rn->p))
940 {
941 case AF_INET:
942 ret = kernel_add_ipv4 (&rn->p, rib);
943 break;
944#ifdef HAVE_IPV6
945 case AF_INET6:
946 ret = kernel_add_ipv6 (&rn->p, rib);
947 break;
948#endif /* HAVE_IPV6 */
949 }
950
Denis Ovsienkodc958242007-08-13 16:03:06 +0000951 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +0000952 if (ret < 0)
953 {
954 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
955 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
956 }
957}
958
959/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000960static int
paul718e3742002-12-13 20:15:29 +0000961rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
962{
963 int ret = 0;
964 struct nexthop *nexthop;
965
966 switch (PREFIX_FAMILY (&rn->p))
967 {
968 case AF_INET:
969 ret = kernel_delete_ipv4 (&rn->p, rib);
970 break;
971#ifdef HAVE_IPV6
972 case AF_INET6:
973 ret = kernel_delete_ipv6 (&rn->p, rib);
974 break;
975#endif /* HAVE_IPV6 */
976 }
977
978 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
979 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
980
981 return ret;
982}
983
984/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000985static void
paul718e3742002-12-13 20:15:29 +0000986rib_uninstall (struct route_node *rn, struct rib *rib)
987{
988 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
989 {
990 redistribute_delete (&rn->p, rib);
991 if (! RIB_SYSTEM_ROUTE (rib))
992 rib_uninstall_kernel (rn, rib);
993 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
994 }
995}
996
Paul Jakma6d691122006-07-27 21:49:00 +0000997static void rib_unlink (struct route_node *, struct rib *);
998
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000999/*
1000 * rib_can_delete_dest
1001 *
1002 * Returns TRUE if the given dest can be deleted from the table.
1003 */
1004static int
1005rib_can_delete_dest (rib_dest_t *dest)
1006{
1007 if (dest->routes)
1008 {
1009 return 0;
1010 }
1011
1012 return 1;
1013}
1014
1015/*
1016 * rib_gc_dest
1017 *
1018 * Garbage collect the rib dest corresponding to the given route node
1019 * if appropriate.
1020 *
1021 * Returns TRUE if the dest was deleted, FALSE otherwise.
1022 */
1023int
1024rib_gc_dest (struct route_node *rn)
1025{
1026 rib_dest_t *dest;
1027 char buf[INET6_ADDRSTRLEN];
1028
1029 dest = rib_dest_from_rnode (rn);
1030 if (!dest)
1031 return 0;
1032
1033 if (!rib_can_delete_dest (dest))
1034 return 0;
1035
1036 if (IS_ZEBRA_DEBUG_RIB)
1037 {
1038 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf));
1039 zlog_debug ("%s: %s/%d: removing dest from table", __func__,
1040 buf, rn->p.prefixlen);
1041 }
1042
1043 dest->rnode = NULL;
1044 XFREE (MTYPE_RIB_DEST, dest);
1045 rn->info = NULL;
1046
1047 /*
1048 * Release the one reference that we keep on the route node.
1049 */
1050 route_unlock_node (rn);
1051 return 1;
1052}
1053
paul718e3742002-12-13 20:15:29 +00001054/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001055static void
1056rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001057{
1058 struct rib *rib;
1059 struct rib *next;
1060 struct rib *fib = NULL;
1061 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001062 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001063 int installed = 0;
1064 struct nexthop *nexthop = NULL;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001065 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001066
1067 assert (rn);
1068
Paul Jakma93bdada2007-08-06 19:25:11 +00001069 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001070 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001071
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001072 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001073 {
paul718e3742002-12-13 20:15:29 +00001074 /* Currently installed rib. */
1075 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001076 {
1077 assert (fib == NULL);
1078 fib = rib;
1079 }
1080
1081 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1082 * which we need to do do further work with below.
1083 */
1084 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1085 {
1086 if (rib != fib)
1087 {
1088 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001089 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
1090 buf, rn->p.prefixlen, rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001091 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001092 }
1093 else
1094 del = rib;
1095
1096 continue;
1097 }
paul4d38fdb2005-04-28 17:35:14 +00001098
paul718e3742002-12-13 20:15:29 +00001099 /* Skip unreachable nexthop. */
1100 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001101 continue;
paul718e3742002-12-13 20:15:29 +00001102
1103 /* Infinit distance. */
1104 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001105 continue;
paul718e3742002-12-13 20:15:29 +00001106
paulaf887b52006-01-18 14:52:52 +00001107 /* Newly selected rib, the common case. */
1108 if (!select)
1109 {
1110 select = rib;
1111 continue;
1112 }
1113
1114 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001115 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001116 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001117 * - lower metric beats higher for equal distance
1118 * - last, hence oldest, route wins tie break.
1119 */
paula1038a12006-01-30 14:08:51 +00001120
1121 /* Connected routes. Pick the last connected
1122 * route of the set of lowest metric connected routes.
1123 */
paula8d9c1f2006-01-25 06:31:04 +00001124 if (rib->type == ZEBRA_ROUTE_CONNECT)
1125 {
paula1038a12006-01-30 14:08:51 +00001126 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001127 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001128 select = rib;
1129 continue;
paula8d9c1f2006-01-25 06:31:04 +00001130 }
1131 else if (select->type == ZEBRA_ROUTE_CONNECT)
1132 continue;
1133
1134 /* higher distance loses */
1135 if (rib->distance > select->distance)
1136 continue;
1137
1138 /* lower wins */
1139 if (rib->distance < select->distance)
1140 {
paulaf887b52006-01-18 14:52:52 +00001141 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001142 continue;
1143 }
1144
1145 /* metric tie-breaks equal distance */
1146 if (rib->metric <= select->metric)
1147 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001148 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001149
1150 /* After the cycle is finished, the following pointers will be set:
1151 * select --- the winner RIB entry, if any was found, otherwise NULL
1152 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1153 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1154 * rib --- NULL
1155 */
1156
1157 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001158 if (select && select == fib)
1159 {
Paul Jakma6d691122006-07-27 21:49:00 +00001160 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001161 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
1162 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +00001163 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001164 {
1165 redistribute_delete (&rn->p, select);
1166 if (! RIB_SYSTEM_ROUTE (select))
1167 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001168
paul4d38fdb2005-04-28 17:35:14 +00001169 /* Set real nexthop. */
1170 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001171
paul4d38fdb2005-04-28 17:35:14 +00001172 if (! RIB_SYSTEM_ROUTE (select))
1173 rib_install_kernel (rn, select);
1174 redistribute_add (&rn->p, select);
1175 }
pauld753e9e2003-01-22 19:45:50 +00001176 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001177 {
1178 /* Housekeeping code to deal with
1179 race conditions in kernel with linux
1180 netlink reporting interface up before IPv4 or IPv6 protocol
1181 is ready to add routes.
1182 This makes sure the routes are IN the kernel.
1183 */
pauld753e9e2003-01-22 19:45:50 +00001184
paul4d38fdb2005-04-28 17:35:14 +00001185 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001186 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001187 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001188 installed = 1;
1189 break;
paul4d38fdb2005-04-28 17:35:14 +00001190 }
1191 if (! installed)
1192 rib_install_kernel (rn, select);
1193 }
Paul Jakma6d691122006-07-27 21:49:00 +00001194 goto end;
paul718e3742002-12-13 20:15:29 +00001195 }
1196
Denis Ovsienkodc958242007-08-13 16:03:06 +00001197 /* At this point we either haven't found the best RIB entry or it is
1198 * different from what we currently intend to flag with SELECTED. In both
1199 * cases, if a RIB block is present in FIB, it should be withdrawn.
1200 */
paul718e3742002-12-13 20:15:29 +00001201 if (fib)
1202 {
Paul Jakma6d691122006-07-27 21:49:00 +00001203 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001204 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1205 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001206 redistribute_delete (&rn->p, fib);
1207 if (! RIB_SYSTEM_ROUTE (fib))
1208 rib_uninstall_kernel (rn, fib);
1209 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1210
1211 /* Set real nexthop. */
1212 nexthop_active_update (rn, fib, 1);
1213 }
1214
Denis Ovsienkodc958242007-08-13 16:03:06 +00001215 /* Regardless of some RIB entry being SELECTED or not before, now we can
1216 * tell, that if a new winner exists, FIB is still not updated with this
1217 * data, but ready to be.
1218 */
paul718e3742002-12-13 20:15:29 +00001219 if (select)
1220 {
Paul Jakma6d691122006-07-27 21:49:00 +00001221 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001222 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1223 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001224 /* Set real nexthop. */
1225 nexthop_active_update (rn, select, 1);
1226
1227 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001228 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001229 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1230 redistribute_add (&rn->p, select);
1231 }
paul4d38fdb2005-04-28 17:35:14 +00001232
Paul Jakma6d691122006-07-27 21:49:00 +00001233 /* FIB route was removed, should be deleted */
1234 if (del)
1235 {
1236 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001237 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1238 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001239 rib_unlink (rn, del);
1240 }
paul4d38fdb2005-04-28 17:35:14 +00001241
Paul Jakma6d691122006-07-27 21:49:00 +00001242end:
1243 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001244 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001245
1246 /*
1247 * Check if the dest can be deleted now.
1248 */
1249 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001250}
1251
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001252/* Take a list of route_node structs and return 1, if there was a record
1253 * picked from it and processed by rib_process(). Don't process more,
1254 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001255 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001256static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001257process_subq (struct list * subq, u_char qindex)
1258{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001259 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001260 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001261
1262 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001263 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001264
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001265 rnode = listgetdata (lnode);
1266 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001267
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001268 if (rnode->info)
1269 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1270
Chris Caputo67b94672009-07-18 04:02:26 +00001271#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001272 else
1273 {
1274 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1275 __func__, rnode, rnode->lock);
1276 zlog_backtrace(LOG_DEBUG);
1277 }
Chris Caputo67b94672009-07-18 04:02:26 +00001278#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001279 route_unlock_node (rnode);
1280 list_delete_node (subq, lnode);
1281 return 1;
1282}
1283
1284/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1285 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1286 * is pointed to the meta queue structure.
1287 */
1288static wq_item_status
1289meta_queue_process (struct work_queue *dummy, void *data)
1290{
1291 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001292 unsigned i;
1293
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001294 for (i = 0; i < MQ_SIZE; i++)
1295 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001296 {
1297 mq->size--;
1298 break;
1299 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001300 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1301}
1302
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001303/*
1304 * Map from rib types to queue type (priority) in meta queue
1305 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001306static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1307 [ZEBRA_ROUTE_SYSTEM] = 4,
1308 [ZEBRA_ROUTE_KERNEL] = 0,
1309 [ZEBRA_ROUTE_CONNECT] = 0,
1310 [ZEBRA_ROUTE_STATIC] = 1,
1311 [ZEBRA_ROUTE_RIP] = 2,
1312 [ZEBRA_ROUTE_RIPNG] = 2,
1313 [ZEBRA_ROUTE_OSPF] = 2,
1314 [ZEBRA_ROUTE_OSPF6] = 2,
1315 [ZEBRA_ROUTE_ISIS] = 2,
1316 [ZEBRA_ROUTE_BGP] = 3,
1317 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001318 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001319};
1320
1321/* Look into the RN and queue it into one or more priority queues,
1322 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001323 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001324static void
1325rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001326{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001327 struct rib *rib;
1328 char buf[INET6_ADDRSTRLEN];
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001329
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001330 if (IS_ZEBRA_DEBUG_RIB_Q)
1331 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001332
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001333 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001334 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001335 u_char qindex = meta_queue_map[rib->type];
1336
1337 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001338 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1339 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001340 {
1341 if (IS_ZEBRA_DEBUG_RIB_Q)
1342 zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
1343 __func__, buf, rn->p.prefixlen, rn, qindex);
1344 continue;
1345 }
1346
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001347 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001348 listnode_add (mq->subq[qindex], rn);
1349 route_lock_node (rn);
1350 mq->size++;
1351
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001352 if (IS_ZEBRA_DEBUG_RIB_Q)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001353 zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u",
1354 __func__, buf, rn->p.prefixlen, rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001355 }
paul4d38fdb2005-04-28 17:35:14 +00001356}
1357
Paul Jakma6d691122006-07-27 21:49:00 +00001358/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001359static void
Paul Jakma6d691122006-07-27 21:49:00 +00001360rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001361{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001362 char buf[INET_ADDRSTRLEN];
1363 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001364
Paul Jakma93bdada2007-08-06 19:25:11 +00001365 if (IS_ZEBRA_DEBUG_RIB_Q)
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001366 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001367
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001368 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001369 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001370 {
1371 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1372 __func__, rn, rn->lock);
1373 zlog_backtrace(LOG_DEBUG);
1374 return;
1375 }
1376
1377 if (IS_ZEBRA_DEBUG_RIB_Q)
1378 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
1379
1380 assert (zebra);
1381
1382 if (zebra->ribq == NULL)
1383 {
1384 zlog_err ("%s: work_queue does not exist!", __func__);
1385 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001386 }
paul4d38fdb2005-04-28 17:35:14 +00001387
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001388 /*
1389 * The RIB queue should normally be either empty or holding the only
1390 * work_queue_item element. In the latter case this element would
1391 * hold a pointer to the meta queue structure, which must be used to
1392 * actually queue the route nodes to process. So create the MQ
1393 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001394 * This semantics was introduced after 0.99.9 release.
1395 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001396 if (!zebra->ribq->items->count)
1397 work_queue_add (zebra->ribq, zebra->mq);
1398
1399 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001400
1401 if (IS_ZEBRA_DEBUG_RIB_Q)
1402 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
1403
1404 return;
paul4d38fdb2005-04-28 17:35:14 +00001405}
1406
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001407/* Create new meta queue.
1408 A destructor function doesn't seem to be necessary here.
1409 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001410static struct meta_queue *
1411meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001412{
1413 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001414 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001415
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001416 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1417 assert(new);
1418
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001419 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001420 {
1421 new->subq[i] = list_new ();
1422 assert(new->subq[i]);
1423 }
1424
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001425 return new;
1426}
1427
paul4d38fdb2005-04-28 17:35:14 +00001428/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001429static void
paul4d38fdb2005-04-28 17:35:14 +00001430rib_queue_init (struct zebra_t *zebra)
1431{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001432 assert (zebra);
1433
paul4d38fdb2005-04-28 17:35:14 +00001434 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001435 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001436 {
Paul Jakma6d691122006-07-27 21:49:00 +00001437 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001438 return;
1439 }
1440
1441 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001442 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001443 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001444 /* XXX: TODO: These should be runtime configurable via vty */
1445 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001446 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001447
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001448 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001449 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001450 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001451 return;
1452 }
1453 return;
paul718e3742002-12-13 20:15:29 +00001454}
1455
Paul Jakma6d691122006-07-27 21:49:00 +00001456/* RIB updates are processed via a queue of pointers to route_nodes.
1457 *
1458 * The queue length is bounded by the maximal size of the routing table,
1459 * as a route_node will not be requeued, if already queued.
1460 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001461 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1462 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1463 * and then submit route_node to queue for best-path selection later.
1464 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001465 *
1466 * Deleted RIBs are reaped during best-path selection.
1467 *
1468 * rib_addnode
1469 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001470 * |-------->| | best RIB, if required
1471 * | |
1472 * static_install->|->rib_addqueue...... -> rib_process
1473 * | |
1474 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001475 * |-> set RIB_ENTRY_REMOVE |
1476 * rib_delnode (RIB freed)
1477 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001478 * The 'info' pointer of a route_node points to a rib_dest_t
1479 * ('dest'). Queueing state for a route_node is kept on the dest. The
1480 * dest is created on-demand by rib_link() and is kept around at least
1481 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001482 *
1483 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1484 *
1485 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001486 * - dest attached to route_node:
1487 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001488 * - route_node processing queue
1489 * - managed by: rib_addqueue, rib_process.
1490 *
1491 */
1492
paul718e3742002-12-13 20:15:29 +00001493/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001494static void
Paul Jakma6d691122006-07-27 21:49:00 +00001495rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001496{
1497 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001498 rib_dest_t *dest;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001499 char buf[INET6_ADDRSTRLEN];
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001500
paul4d38fdb2005-04-28 17:35:14 +00001501 assert (rib && rn);
1502
Paul Jakma6d691122006-07-27 21:49:00 +00001503 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001504 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001505 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001506 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1507 buf, rn->p.prefixlen, rn, rib);
1508 }
Paul Jakma6d691122006-07-27 21:49:00 +00001509
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001510 dest = rib_dest_from_rnode (rn);
1511 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001512 {
1513 if (IS_ZEBRA_DEBUG_RIB)
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001514 {
1515 zlog_debug ("%s: %s/%d: adding dest to table", __func__,
1516 buf, rn->p.prefixlen);
1517 }
1518
1519 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1520 route_lock_node (rn); /* rn route table reference */
1521 rn->info = dest;
1522 dest->rnode = rn;
1523 }
1524
1525 head = dest->routes;
1526 if (head)
1527 {
Paul Jakma6d691122006-07-27 21:49:00 +00001528 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001529 }
paul718e3742002-12-13 20:15:29 +00001530 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001531 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001532 rib_queue_add (&zebrad, rn);
1533}
1534
1535static void
1536rib_addnode (struct route_node *rn, struct rib *rib)
1537{
1538 /* RIB node has been un-removed before route-node is processed.
1539 * route_node must hence already be on the queue for processing..
1540 */
1541 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1542 {
1543 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001544 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001545 char buf[INET6_ADDRSTRLEN];
1546 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001547 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1548 __func__, buf, rn->p.prefixlen, rn, rib);
1549 }
Paul Jakma6d691122006-07-27 21:49:00 +00001550 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1551 return;
1552 }
1553 rib_link (rn, rib);
1554}
1555
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001556/*
1557 * rib_unlink
1558 *
1559 * Detach a rib structure from a route_node.
1560 *
1561 * Note that a call to rib_unlink() should be followed by a call to
1562 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1563 * longer required to be deleted.
1564 */
Paul Jakma6d691122006-07-27 21:49:00 +00001565static void
1566rib_unlink (struct route_node *rn, struct rib *rib)
1567{
1568 struct nexthop *nexthop, *next;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001569 char buf[INET6_ADDRSTRLEN];
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001570 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001571
1572 assert (rn && rib);
1573
1574 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001575 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001576 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001577 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1578 __func__, buf, rn->p.prefixlen, rn, rib);
1579 }
Paul Jakma6d691122006-07-27 21:49:00 +00001580
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001581 dest = rib_dest_from_rnode (rn);
1582
Paul Jakma6d691122006-07-27 21:49:00 +00001583 if (rib->next)
1584 rib->next->prev = rib->prev;
1585
1586 if (rib->prev)
1587 rib->prev->next = rib->next;
1588 else
1589 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001590 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001591 }
1592
1593 /* free RIB and nexthops */
1594 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1595 {
1596 next = nexthop->next;
1597 nexthop_free (nexthop);
1598 }
1599 XFREE (MTYPE_RIB, rib);
1600
paul718e3742002-12-13 20:15:29 +00001601}
1602
paula1ac18c2005-06-28 17:17:12 +00001603static void
paul718e3742002-12-13 20:15:29 +00001604rib_delnode (struct route_node *rn, struct rib *rib)
1605{
Paul Jakma6d691122006-07-27 21:49:00 +00001606 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001607 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001608 char buf[INET6_ADDRSTRLEN];
1609 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001610 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1611 buf, rn->p.prefixlen, rn, rib);
1612 }
Paul Jakma6d691122006-07-27 21:49:00 +00001613 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1614 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001615}
1616
1617int
1618rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001619 struct in_addr *gate, struct in_addr *src,
1620 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001621 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001622{
1623 struct rib *rib;
1624 struct rib *same = NULL;
1625 struct route_table *table;
1626 struct route_node *rn;
1627 struct nexthop *nexthop;
1628
1629 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001630 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001631 if (! table)
1632 return 0;
1633
1634 /* Make it sure prefixlen is applied to the prefix. */
1635 apply_mask_ipv4 (p);
1636
1637 /* Set default distance by route type. */
1638 if (distance == 0)
1639 {
Balaji.G837d16c2012-09-26 14:09:10 +05301640 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001641 distance = 150;
1642 else
1643 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001644
1645 /* iBGP distance is 200. */
1646 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1647 distance = 200;
1648 }
1649
1650 /* Lookup route node.*/
1651 rn = route_node_get (table, (struct prefix *) p);
1652
1653 /* If same type of route are installed, treat it as a implicit
1654 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001655 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001656 {
Paul Jakma6d691122006-07-27 21:49:00 +00001657 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1658 continue;
1659
hassoebf1ead2005-09-21 14:58:20 +00001660 if (rib->type != type)
1661 continue;
1662 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001663 {
1664 same = rib;
1665 break;
1666 }
hassoebf1ead2005-09-21 14:58:20 +00001667 /* Duplicate connected route comes in. */
1668 else if ((nexthop = rib->nexthop) &&
1669 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001670 nexthop->ifindex == ifindex &&
1671 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001672 {
1673 rib->refcnt++;
1674 return 0 ;
1675 }
paul718e3742002-12-13 20:15:29 +00001676 }
1677
1678 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001679 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001680 rib->type = type;
1681 rib->distance = distance;
1682 rib->flags = flags;
1683 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001684 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001685 rib->nexthop_num = 0;
1686 rib->uptime = time (NULL);
1687
1688 /* Nexthop settings. */
1689 if (gate)
1690 {
1691 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001692 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001693 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001694 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001695 }
1696 else
1697 nexthop_ifindex_add (rib, ifindex);
1698
1699 /* If this route is kernel route, set FIB flag to the route. */
1700 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1701 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1702 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1703
1704 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001705 if (IS_ZEBRA_DEBUG_RIB)
1706 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001707 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001708
paul718e3742002-12-13 20:15:29 +00001709 /* Free implicit route.*/
1710 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001711 {
1712 if (IS_ZEBRA_DEBUG_RIB)
1713 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001714 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001715 }
paul4d38fdb2005-04-28 17:35:14 +00001716
1717 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001718 return 0;
1719}
1720
Denis Ovsienkodc958242007-08-13 16:03:06 +00001721/* This function dumps the contents of a given RIB entry into
1722 * standard debug log. Calling function name and IP prefix in
1723 * question are passed as 1st and 2nd arguments.
1724 */
1725
1726void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1727{
1728 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1729 struct nexthop *nexthop;
1730
1731 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1732 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1733 zlog_debug
1734 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001735 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001736 func,
1737 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001738 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001739 rib->type,
1740 rib->table
1741 );
1742 zlog_debug
1743 (
1744 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1745 func,
1746 rib->metric,
1747 rib->distance,
1748 rib->flags,
1749 rib->status
1750 );
1751 zlog_debug
1752 (
1753 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1754 func,
1755 rib->nexthop_num,
1756 rib->nexthop_active_num,
1757 rib->nexthop_fib_num
1758 );
1759 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1760 {
1761 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1762 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1763 zlog_debug
1764 (
1765 "%s: NH %s (%s) with flags %s%s%s",
1766 func,
1767 straddr1,
1768 straddr2,
1769 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1770 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1771 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1772 );
1773 }
1774 zlog_debug ("%s: dump complete", func);
1775}
1776
1777/* This is an exported helper to rtm_read() to dump the strange
1778 * RIB entry found by rib_lookup_ipv4_route()
1779 */
1780
1781void rib_lookup_and_dump (struct prefix_ipv4 * p)
1782{
1783 struct route_table *table;
1784 struct route_node *rn;
1785 struct rib *rib;
1786 char prefix_buf[INET_ADDRSTRLEN];
1787
1788 /* Lookup table. */
1789 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1790 if (! table)
1791 {
1792 zlog_err ("%s: vrf_table() returned NULL", __func__);
1793 return;
1794 }
1795
1796 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1797 /* Scan the RIB table for exactly matching RIB entry. */
1798 rn = route_node_lookup (table, (struct prefix *) p);
1799
1800 /* No route for this prefix. */
1801 if (! rn)
1802 {
1803 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1804 return;
1805 }
1806
1807 /* Unlock node. */
1808 route_unlock_node (rn);
1809
1810 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001811 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001812 {
1813 zlog_debug
1814 (
1815 "%s: rn %p, rib %p: %s, %s",
1816 __func__,
1817 rn,
1818 rib,
1819 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1820 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1821 );
1822 rib_dump (__func__, p, rib);
1823 }
1824}
1825
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001826/* Check if requested address assignment will fail due to another
1827 * route being installed by zebra in FIB already. Take necessary
1828 * actions, if needed: remove such a route from FIB and deSELECT
1829 * corresponding RIB entry. Then put affected RN into RIBQ head.
1830 */
1831void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1832{
1833 struct route_table *table;
1834 struct route_node *rn;
1835 struct rib *rib;
1836 unsigned changed = 0;
1837
1838 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
1839 {
1840 zlog_err ("%s: vrf_table() returned NULL", __func__);
1841 return;
1842 }
1843
1844 /* No matches would be the simplest case. */
1845 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1846 return;
1847
1848 /* Unlock node. */
1849 route_unlock_node (rn);
1850
1851 /* Check all RIB entries. In case any changes have to be done, requeue
1852 * the RN into RIBQ head. If the routing message about the new connected
1853 * route (generated by the IP address we are going to assign very soon)
1854 * comes before the RIBQ is processed, the new RIB entry will join
1855 * RIBQ record already on head. This is necessary for proper revalidation
1856 * of the rest of the RIB.
1857 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001858 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001859 {
1860 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1861 ! RIB_SYSTEM_ROUTE (rib))
1862 {
1863 changed = 1;
1864 if (IS_ZEBRA_DEBUG_RIB)
1865 {
1866 char buf[INET_ADDRSTRLEN];
1867 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
1868 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
1869 rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
1870 }
1871 rib_uninstall (rn, rib);
1872 }
1873 }
1874 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001875 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001876}
1877
paul718e3742002-12-13 20:15:29 +00001878int
G.Balajicddf3912011-11-26 21:59:32 +04001879rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001880{
1881 struct route_table *table;
1882 struct route_node *rn;
1883 struct rib *same;
1884 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001885
paul718e3742002-12-13 20:15:29 +00001886 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001887 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001888 if (! table)
1889 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04001890
paul718e3742002-12-13 20:15:29 +00001891 /* Make it sure prefixlen is applied to the prefix. */
1892 apply_mask_ipv4 (p);
1893
1894 /* Set default distance by route type. */
1895 if (rib->distance == 0)
1896 {
1897 rib->distance = route_info[rib->type].distance;
1898
1899 /* iBGP distance is 200. */
1900 if (rib->type == ZEBRA_ROUTE_BGP
1901 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1902 rib->distance = 200;
1903 }
1904
1905 /* Lookup route node.*/
1906 rn = route_node_get (table, (struct prefix *) p);
1907
1908 /* If same type of route are installed, treat it as a implicit
1909 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001910 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00001911 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001912 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001913 continue;
1914
paul718e3742002-12-13 20:15:29 +00001915 if (same->type == rib->type && same->table == rib->table
1916 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001917 break;
paul718e3742002-12-13 20:15:29 +00001918 }
paul4d38fdb2005-04-28 17:35:14 +00001919
paul718e3742002-12-13 20:15:29 +00001920 /* If this route is kernel route, set FIB flag to the route. */
1921 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1922 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1923 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1924
1925 /* Link new rib to node.*/
1926 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001927 if (IS_ZEBRA_DEBUG_RIB)
1928 {
1929 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1930 __func__, rn, rib);
1931 rib_dump (__func__, p, rib);
1932 }
paul718e3742002-12-13 20:15:29 +00001933
paul718e3742002-12-13 20:15:29 +00001934 /* Free implicit route.*/
1935 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001936 {
1937 if (IS_ZEBRA_DEBUG_RIB)
1938 {
1939 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1940 __func__, rn, same);
1941 rib_dump (__func__, p, same);
1942 }
paul4d38fdb2005-04-28 17:35:14 +00001943 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001944 }
paul4d38fdb2005-04-28 17:35:14 +00001945
1946 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001947 return 0;
1948}
1949
hassoebf1ead2005-09-21 14:58:20 +00001950/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001951int
1952rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04001953 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001954{
1955 struct route_table *table;
1956 struct route_node *rn;
1957 struct rib *rib;
1958 struct rib *fib = NULL;
1959 struct rib *same = NULL;
1960 struct nexthop *nexthop;
Stephen Hemminger81cce012009-04-28 14:28:00 -07001961 char buf1[INET_ADDRSTRLEN];
1962 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00001963
1964 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001965 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001966 if (! table)
1967 return 0;
1968
1969 /* Apply mask. */
1970 apply_mask_ipv4 (p);
1971
paul5ec90d22003-06-19 01:41:37 +00001972 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001973 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001974 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul5ec90d22003-06-19 01:41:37 +00001975 p->prefixlen,
1976 inet_ntoa (*gate),
1977 ifindex);
1978
paul718e3742002-12-13 20:15:29 +00001979 /* Lookup route node. */
1980 rn = route_node_lookup (table, (struct prefix *) p);
1981 if (! rn)
1982 {
1983 if (IS_ZEBRA_DEBUG_KERNEL)
1984 {
1985 if (gate)
ajsb6178002004-12-07 21:12:56 +00001986 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001987 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001988 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07001989 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001990 ifindex);
1991 else
ajsb6178002004-12-07 21:12:56 +00001992 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001993 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00001994 p->prefixlen,
1995 ifindex);
1996 }
1997 return ZEBRA_ERR_RTNOEXIST;
1998 }
1999
2000 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002001 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002002 {
Paul Jakma6d691122006-07-27 21:49:00 +00002003 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2004 continue;
2005
paul718e3742002-12-13 20:15:29 +00002006 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2007 fib = rib;
2008
hassoebf1ead2005-09-21 14:58:20 +00002009 if (rib->type != type)
2010 continue;
2011 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002012 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002013 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002014 if (nexthop->ifindex != ifindex)
2015 continue;
hassoebf1ead2005-09-21 14:58:20 +00002016 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002017 {
hassoebf1ead2005-09-21 14:58:20 +00002018 rib->refcnt--;
2019 route_unlock_node (rn);
2020 route_unlock_node (rn);
2021 return 0;
paul718e3742002-12-13 20:15:29 +00002022 }
hassoebf1ead2005-09-21 14:58:20 +00002023 same = rib;
2024 break;
paul718e3742002-12-13 20:15:29 +00002025 }
hassoebf1ead2005-09-21 14:58:20 +00002026 /* Make sure that the route found has the same gateway. */
2027 else if (gate == NULL ||
2028 ((nexthop = rib->nexthop) &&
2029 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
2030 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00002031 {
hassoebf1ead2005-09-21 14:58:20 +00002032 same = rib;
2033 break;
paul718e3742002-12-13 20:15:29 +00002034 }
2035 }
2036
2037 /* If same type of route can't be found and this message is from
2038 kernel. */
2039 if (! same)
2040 {
2041 if (fib && type == ZEBRA_ROUTE_KERNEL)
2042 {
2043 /* Unset flags. */
2044 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2045 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2046
2047 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2048 }
2049 else
2050 {
2051 if (IS_ZEBRA_DEBUG_KERNEL)
2052 {
2053 if (gate)
ajsb6178002004-12-07 21:12:56 +00002054 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002055 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002056 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002057 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002058 ifindex,
2059 type);
2060 else
ajsb6178002004-12-07 21:12:56 +00002061 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002062 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002063 p->prefixlen,
2064 ifindex,
2065 type);
2066 }
2067 route_unlock_node (rn);
2068 return ZEBRA_ERR_RTNOEXIST;
2069 }
2070 }
paul4d38fdb2005-04-28 17:35:14 +00002071
paul718e3742002-12-13 20:15:29 +00002072 if (same)
2073 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002074
paul718e3742002-12-13 20:15:29 +00002075 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002076 return 0;
2077}
2078
2079/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002080static void
paul718e3742002-12-13 20:15:29 +00002081static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
2082{
2083 struct rib *rib;
2084 struct route_node *rn;
2085 struct route_table *table;
2086
2087 /* Lookup table. */
2088 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2089 if (! table)
2090 return;
2091
2092 /* Lookup existing route */
2093 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002094 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002095 {
2096 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2097 continue;
2098
2099 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2100 break;
2101 }
paul718e3742002-12-13 20:15:29 +00002102
2103 if (rib)
2104 {
2105 /* Same distance static route is there. Update it with new
2106 nexthop. */
paul718e3742002-12-13 20:15:29 +00002107 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002108 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002109 {
2110 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002111 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002112 break;
2113 case STATIC_IPV4_IFNAME:
2114 nexthop_ifname_add (rib, si->gate.ifname);
2115 break;
2116 case STATIC_IPV4_BLACKHOLE:
2117 nexthop_blackhole_add (rib);
2118 break;
paul4d38fdb2005-04-28 17:35:14 +00002119 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002120 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002121 }
2122 else
2123 {
2124 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002125 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2126
paul718e3742002-12-13 20:15:29 +00002127 rib->type = ZEBRA_ROUTE_STATIC;
2128 rib->distance = si->distance;
2129 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002130 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002131 rib->nexthop_num = 0;
2132
2133 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002134 {
2135 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002136 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002137 break;
2138 case STATIC_IPV4_IFNAME:
2139 nexthop_ifname_add (rib, si->gate.ifname);
2140 break;
2141 case STATIC_IPV4_BLACKHOLE:
2142 nexthop_blackhole_add (rib);
2143 break;
2144 }
paul718e3742002-12-13 20:15:29 +00002145
hasso81dfcaa2003-05-25 19:21:25 +00002146 /* Save the flags of this static routes (reject, blackhole) */
2147 rib->flags = si->flags;
2148
paul718e3742002-12-13 20:15:29 +00002149 /* Link this rib to the tree. */
2150 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002151 }
2152}
2153
paula1ac18c2005-06-28 17:17:12 +00002154static int
paul718e3742002-12-13 20:15:29 +00002155static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2156{
2157 if (nexthop->type == NEXTHOP_TYPE_IPV4
2158 && si->type == STATIC_IPV4_GATEWAY
2159 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2160 return 1;
2161 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2162 && si->type == STATIC_IPV4_IFNAME
2163 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2164 return 1;
paul595db7f2003-05-25 21:35:06 +00002165 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2166 && si->type == STATIC_IPV4_BLACKHOLE)
2167 return 1;
paule8e19462006-01-19 20:16:55 +00002168 return 0;
paul718e3742002-12-13 20:15:29 +00002169}
2170
2171/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002172static void
paul718e3742002-12-13 20:15:29 +00002173static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
2174{
2175 struct route_node *rn;
2176 struct rib *rib;
2177 struct nexthop *nexthop;
2178 struct route_table *table;
2179
2180 /* Lookup table. */
2181 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2182 if (! table)
2183 return;
paul4d38fdb2005-04-28 17:35:14 +00002184
paul718e3742002-12-13 20:15:29 +00002185 /* Lookup existing route with type and distance. */
2186 rn = route_node_lookup (table, p);
2187 if (! rn)
2188 return;
2189
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002190 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002191 {
2192 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2193 continue;
2194
2195 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2196 break;
2197 }
paul718e3742002-12-13 20:15:29 +00002198
2199 if (! rib)
2200 {
2201 route_unlock_node (rn);
2202 return;
2203 }
2204
2205 /* Lookup nexthop. */
2206 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2207 if (static_ipv4_nexthop_same (nexthop, si))
2208 break;
2209
2210 /* Can't find nexthop. */
2211 if (! nexthop)
2212 {
2213 route_unlock_node (rn);
2214 return;
2215 }
2216
2217 /* Check nexthop. */
2218 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002219 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002220 else
2221 {
paul6baeb982003-10-28 03:47:15 +00002222 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2223 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002224 nexthop_delete (rib, nexthop);
2225 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002226 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002227 }
paul718e3742002-12-13 20:15:29 +00002228 /* Unlock node. */
2229 route_unlock_node (rn);
2230}
2231
2232/* Add static route into static route configuration. */
2233int
hasso39db97e2004-10-12 20:50:58 +00002234static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00002235 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002236{
2237 u_char type = 0;
2238 struct route_node *rn;
2239 struct static_ipv4 *si;
2240 struct static_ipv4 *pp;
2241 struct static_ipv4 *cp;
2242 struct static_ipv4 *update = NULL;
2243 struct route_table *stable;
2244
2245 /* Lookup table. */
2246 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2247 if (! stable)
2248 return -1;
2249
2250 /* Lookup static route prefix. */
2251 rn = route_node_get (stable, p);
2252
2253 /* Make flags. */
2254 if (gate)
2255 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002256 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002257 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002258 else
2259 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002260
2261 /* Do nothing if there is a same static route. */
2262 for (si = rn->info; si; si = si->next)
2263 {
2264 if (type == si->type
2265 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2266 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2267 {
2268 if (distance == si->distance)
2269 {
2270 route_unlock_node (rn);
2271 return 0;
2272 }
2273 else
2274 update = si;
2275 }
2276 }
2277
Paul Jakma3c0755d2006-12-08 00:53:14 +00002278 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002279 if (update)
2280 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2281
2282 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002283 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002284
2285 si->type = type;
2286 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002287 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002288
2289 if (gate)
2290 si->gate.ipv4 = *gate;
2291 if (ifname)
2292 si->gate.ifname = XSTRDUP (0, ifname);
2293
2294 /* Add new static route information to the tree with sort by
2295 distance value and gateway address. */
2296 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2297 {
2298 if (si->distance < cp->distance)
2299 break;
2300 if (si->distance > cp->distance)
2301 continue;
2302 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2303 {
2304 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2305 break;
2306 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2307 continue;
2308 }
2309 }
2310
2311 /* Make linked list. */
2312 if (pp)
2313 pp->next = si;
2314 else
2315 rn->info = si;
2316 if (cp)
2317 cp->prev = si;
2318 si->prev = pp;
2319 si->next = cp;
2320
2321 /* Install into rib. */
2322 static_install_ipv4 (p, si);
2323
2324 return 1;
2325}
2326
2327/* Delete static route from static route configuration. */
2328int
hasso39db97e2004-10-12 20:50:58 +00002329static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002330 u_char distance, u_int32_t vrf_id)
2331{
2332 u_char type = 0;
2333 struct route_node *rn;
2334 struct static_ipv4 *si;
2335 struct route_table *stable;
2336
2337 /* Lookup table. */
2338 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2339 if (! stable)
2340 return -1;
2341
2342 /* Lookup static route prefix. */
2343 rn = route_node_lookup (stable, p);
2344 if (! rn)
2345 return 0;
2346
2347 /* Make flags. */
2348 if (gate)
2349 type = STATIC_IPV4_GATEWAY;
2350 else if (ifname)
2351 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002352 else
2353 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002354
2355 /* Find same static route is the tree */
2356 for (si = rn->info; si; si = si->next)
2357 if (type == si->type
2358 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2359 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2360 break;
2361
2362 /* Can't find static route. */
2363 if (! si)
2364 {
2365 route_unlock_node (rn);
2366 return 0;
2367 }
2368
2369 /* Install into rib. */
2370 static_uninstall_ipv4 (p, si);
2371
2372 /* Unlink static route from linked list. */
2373 if (si->prev)
2374 si->prev->next = si->next;
2375 else
2376 rn->info = si->next;
2377 if (si->next)
2378 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002379 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002380
2381 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002382 if (ifname)
2383 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002384 XFREE (MTYPE_STATIC_IPV4, si);
2385
paul143a3852003-09-29 20:06:13 +00002386 route_unlock_node (rn);
2387
paul718e3742002-12-13 20:15:29 +00002388 return 1;
2389}
2390
2391
2392#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002393static int
paul718e3742002-12-13 20:15:29 +00002394rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2395 struct in6_addr *gate, unsigned int ifindex, int table)
2396{
hasso726f9b22003-05-25 21:04:54 +00002397 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2398#if defined (MUSICA) || defined (LINUX)
2399 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2400 if (p->prefixlen == 96)
2401 return 0;
2402#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002403 return 1;
hasso726f9b22003-05-25 21:04:54 +00002404 }
paul718e3742002-12-13 20:15:29 +00002405 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2406 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2407 {
2408 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2409 return 1;
2410 }
2411 return 0;
2412}
2413
2414int
2415rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002416 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002417 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002418{
2419 struct rib *rib;
2420 struct rib *same = NULL;
2421 struct route_table *table;
2422 struct route_node *rn;
2423 struct nexthop *nexthop;
2424
paul718e3742002-12-13 20:15:29 +00002425 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002426 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002427 if (! table)
2428 return 0;
2429
2430 /* Make sure mask is applied. */
2431 apply_mask_ipv6 (p);
2432
2433 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002434 if (!distance)
2435 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002436
2437 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2438 distance = 200;
2439
2440 /* Filter bogus route. */
2441 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2442 return 0;
2443
2444 /* Lookup route node.*/
2445 rn = route_node_get (table, (struct prefix *) p);
2446
2447 /* If same type of route are installed, treat it as a implicit
2448 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002449 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002450 {
Paul Jakma6d691122006-07-27 21:49:00 +00002451 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2452 continue;
2453
hassoebf1ead2005-09-21 14:58:20 +00002454 if (rib->type != type)
2455 continue;
2456 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002457 {
2458 same = rib;
paul718e3742002-12-13 20:15:29 +00002459 break;
2460 }
hassoebf1ead2005-09-21 14:58:20 +00002461 else if ((nexthop = rib->nexthop) &&
2462 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2463 nexthop->ifindex == ifindex)
2464 {
2465 rib->refcnt++;
2466 return 0;
2467 }
paul718e3742002-12-13 20:15:29 +00002468 }
2469
2470 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002471 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2472
paul718e3742002-12-13 20:15:29 +00002473 rib->type = type;
2474 rib->distance = distance;
2475 rib->flags = flags;
2476 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002477 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002478 rib->nexthop_num = 0;
2479 rib->uptime = time (NULL);
2480
2481 /* Nexthop settings. */
2482 if (gate)
2483 {
2484 if (ifindex)
2485 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2486 else
2487 nexthop_ipv6_add (rib, gate);
2488 }
2489 else
2490 nexthop_ifindex_add (rib, ifindex);
2491
2492 /* If this route is kernel route, set FIB flag to the route. */
2493 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2494 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2495 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2496
2497 /* Link new rib to node.*/
2498 rib_addnode (rn, rib);
2499
paul718e3742002-12-13 20:15:29 +00002500 /* Free implicit route.*/
2501 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002502 rib_delnode (rn, same);
2503
2504 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002505 return 0;
2506}
2507
hassoebf1ead2005-09-21 14:58:20 +00002508/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002509int
2510rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002511 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002512{
2513 struct route_table *table;
2514 struct route_node *rn;
2515 struct rib *rib;
2516 struct rib *fib = NULL;
2517 struct rib *same = NULL;
2518 struct nexthop *nexthop;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002519 char buf1[INET6_ADDRSTRLEN];
2520 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002521
2522 /* Apply mask. */
2523 apply_mask_ipv6 (p);
2524
2525 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002526 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002527 if (! table)
2528 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002529
paul718e3742002-12-13 20:15:29 +00002530 /* Lookup route node. */
2531 rn = route_node_lookup (table, (struct prefix *) p);
2532 if (! rn)
2533 {
2534 if (IS_ZEBRA_DEBUG_KERNEL)
2535 {
2536 if (gate)
ajsb6178002004-12-07 21:12:56 +00002537 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002538 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002539 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002540 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002541 ifindex);
2542 else
ajsb6178002004-12-07 21:12:56 +00002543 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002544 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002545 p->prefixlen,
2546 ifindex);
2547 }
2548 return ZEBRA_ERR_RTNOEXIST;
2549 }
2550
2551 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002552 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002553 {
Paul Jakma6d691122006-07-27 21:49:00 +00002554 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2555 continue;
2556
paul718e3742002-12-13 20:15:29 +00002557 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2558 fib = rib;
2559
hassoebf1ead2005-09-21 14:58:20 +00002560 if (rib->type != type)
2561 continue;
2562 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002563 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002564 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002565 if (nexthop->ifindex != ifindex)
2566 continue;
hassoebf1ead2005-09-21 14:58:20 +00002567 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002568 {
hassoebf1ead2005-09-21 14:58:20 +00002569 rib->refcnt--;
2570 route_unlock_node (rn);
2571 route_unlock_node (rn);
2572 return 0;
paul718e3742002-12-13 20:15:29 +00002573 }
hassoebf1ead2005-09-21 14:58:20 +00002574 same = rib;
2575 break;
paul718e3742002-12-13 20:15:29 +00002576 }
hassoebf1ead2005-09-21 14:58:20 +00002577 /* Make sure that the route found has the same gateway. */
2578 else if (gate == NULL ||
2579 ((nexthop = rib->nexthop) &&
2580 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2581 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002582 {
hassoebf1ead2005-09-21 14:58:20 +00002583 same = rib;
2584 break;
paul718e3742002-12-13 20:15:29 +00002585 }
2586 }
2587
2588 /* If same type of route can't be found and this message is from
2589 kernel. */
2590 if (! same)
2591 {
2592 if (fib && type == ZEBRA_ROUTE_KERNEL)
2593 {
2594 /* Unset flags. */
2595 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2596 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2597
2598 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2599 }
2600 else
2601 {
2602 if (IS_ZEBRA_DEBUG_KERNEL)
2603 {
2604 if (gate)
ajsb6178002004-12-07 21:12:56 +00002605 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002606 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002607 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002608 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002609 ifindex,
2610 type);
2611 else
ajsb6178002004-12-07 21:12:56 +00002612 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002613 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002614 p->prefixlen,
2615 ifindex,
2616 type);
2617 }
2618 route_unlock_node (rn);
2619 return ZEBRA_ERR_RTNOEXIST;
2620 }
2621 }
2622
2623 if (same)
2624 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002625
paul718e3742002-12-13 20:15:29 +00002626 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002627 return 0;
2628}
2629
2630/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002631static void
paul718e3742002-12-13 20:15:29 +00002632static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2633{
2634 struct rib *rib;
2635 struct route_table *table;
2636 struct route_node *rn;
2637
2638 /* Lookup table. */
2639 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2640 if (! table)
2641 return;
2642
2643 /* Lookup existing route */
2644 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002645 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002646 {
2647 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2648 continue;
2649
2650 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2651 break;
2652 }
paul718e3742002-12-13 20:15:29 +00002653
2654 if (rib)
2655 {
2656 /* Same distance static route is there. Update it with new
2657 nexthop. */
paul718e3742002-12-13 20:15:29 +00002658 route_unlock_node (rn);
2659
2660 switch (si->type)
2661 {
2662 case STATIC_IPV6_GATEWAY:
2663 nexthop_ipv6_add (rib, &si->ipv6);
2664 break;
2665 case STATIC_IPV6_IFNAME:
2666 nexthop_ifname_add (rib, si->ifname);
2667 break;
2668 case STATIC_IPV6_GATEWAY_IFNAME:
2669 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2670 break;
2671 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002672 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002673 }
2674 else
2675 {
2676 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002677 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2678
paul718e3742002-12-13 20:15:29 +00002679 rib->type = ZEBRA_ROUTE_STATIC;
2680 rib->distance = si->distance;
2681 rib->metric = 0;
2682 rib->nexthop_num = 0;
2683
2684 switch (si->type)
2685 {
2686 case STATIC_IPV6_GATEWAY:
2687 nexthop_ipv6_add (rib, &si->ipv6);
2688 break;
2689 case STATIC_IPV6_IFNAME:
2690 nexthop_ifname_add (rib, si->ifname);
2691 break;
2692 case STATIC_IPV6_GATEWAY_IFNAME:
2693 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2694 break;
2695 }
2696
hasso81dfcaa2003-05-25 19:21:25 +00002697 /* Save the flags of this static routes (reject, blackhole) */
2698 rib->flags = si->flags;
2699
paul718e3742002-12-13 20:15:29 +00002700 /* Link this rib to the tree. */
2701 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002702 }
2703}
2704
paula1ac18c2005-06-28 17:17:12 +00002705static int
paul718e3742002-12-13 20:15:29 +00002706static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2707{
2708 if (nexthop->type == NEXTHOP_TYPE_IPV6
2709 && si->type == STATIC_IPV6_GATEWAY
2710 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2711 return 1;
2712 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2713 && si->type == STATIC_IPV6_IFNAME
2714 && strcmp (nexthop->ifname, si->ifname) == 0)
2715 return 1;
2716 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2717 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2718 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2719 && strcmp (nexthop->ifname, si->ifname) == 0)
2720 return 1;
paule8e19462006-01-19 20:16:55 +00002721 return 0;
paul718e3742002-12-13 20:15:29 +00002722}
2723
paula1ac18c2005-06-28 17:17:12 +00002724static void
paul718e3742002-12-13 20:15:29 +00002725static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2726{
2727 struct route_table *table;
2728 struct route_node *rn;
2729 struct rib *rib;
2730 struct nexthop *nexthop;
2731
2732 /* Lookup table. */
2733 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2734 if (! table)
2735 return;
2736
2737 /* Lookup existing route with type and distance. */
2738 rn = route_node_lookup (table, (struct prefix *) p);
2739 if (! rn)
2740 return;
2741
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002742 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002743 {
2744 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2745 continue;
2746
2747 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2748 break;
2749 }
2750
paul718e3742002-12-13 20:15:29 +00002751 if (! rib)
2752 {
2753 route_unlock_node (rn);
2754 return;
2755 }
2756
2757 /* Lookup nexthop. */
2758 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2759 if (static_ipv6_nexthop_same (nexthop, si))
2760 break;
2761
2762 /* Can't find nexthop. */
2763 if (! nexthop)
2764 {
2765 route_unlock_node (rn);
2766 return;
2767 }
2768
2769 /* Check nexthop. */
2770 if (rib->nexthop_num == 1)
2771 {
2772 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002773 }
2774 else
2775 {
paul6baeb982003-10-28 03:47:15 +00002776 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2777 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002778 nexthop_delete (rib, nexthop);
2779 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002780 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002781 }
paul718e3742002-12-13 20:15:29 +00002782 /* Unlock node. */
2783 route_unlock_node (rn);
2784}
2785
2786/* Add static route into static route configuration. */
2787int
2788static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002789 const char *ifname, u_char flags, u_char distance,
2790 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002791{
2792 struct route_node *rn;
2793 struct static_ipv6 *si;
2794 struct static_ipv6 *pp;
2795 struct static_ipv6 *cp;
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;
Paul Jakma27b47252006-07-02 16:38:54 +00002802
2803 if (!gate &&
2804 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2805 return -1;
2806
2807 if (!ifname &&
2808 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2809 return -1;
paul718e3742002-12-13 20:15:29 +00002810
2811 /* Lookup static route prefix. */
2812 rn = route_node_get (stable, p);
2813
2814 /* Do nothing if there is a same static route. */
2815 for (si = rn->info; si; si = si->next)
2816 {
2817 if (distance == si->distance
2818 && type == si->type
2819 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2820 && (! ifname || strcmp (ifname, si->ifname) == 0))
2821 {
2822 route_unlock_node (rn);
2823 return 0;
2824 }
2825 }
2826
2827 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002828 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00002829
2830 si->type = type;
2831 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002832 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002833
2834 switch (type)
2835 {
2836 case STATIC_IPV6_GATEWAY:
2837 si->ipv6 = *gate;
2838 break;
2839 case STATIC_IPV6_IFNAME:
2840 si->ifname = XSTRDUP (0, ifname);
2841 break;
2842 case STATIC_IPV6_GATEWAY_IFNAME:
2843 si->ipv6 = *gate;
2844 si->ifname = XSTRDUP (0, ifname);
2845 break;
2846 }
2847
2848 /* Add new static route information to the tree with sort by
2849 distance value and gateway address. */
2850 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2851 {
2852 if (si->distance < cp->distance)
2853 break;
2854 if (si->distance > cp->distance)
2855 continue;
2856 }
2857
2858 /* Make linked list. */
2859 if (pp)
2860 pp->next = si;
2861 else
2862 rn->info = si;
2863 if (cp)
2864 cp->prev = si;
2865 si->prev = pp;
2866 si->next = cp;
2867
2868 /* Install into rib. */
2869 static_install_ipv6 (p, si);
2870
2871 return 1;
2872}
2873
2874/* Delete static route from static route configuration. */
2875int
2876static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002877 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002878{
2879 struct route_node *rn;
2880 struct static_ipv6 *si;
2881 struct route_table *stable;
2882
2883 /* Lookup table. */
2884 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2885 if (! stable)
2886 return -1;
2887
2888 /* Lookup static route prefix. */
2889 rn = route_node_lookup (stable, p);
2890 if (! rn)
2891 return 0;
2892
2893 /* Find same static route is the tree */
2894 for (si = rn->info; si; si = si->next)
2895 if (distance == si->distance
2896 && type == si->type
2897 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2898 && (! ifname || strcmp (ifname, si->ifname) == 0))
2899 break;
2900
2901 /* Can't find static route. */
2902 if (! si)
2903 {
2904 route_unlock_node (rn);
2905 return 0;
2906 }
2907
2908 /* Install into rib. */
2909 static_uninstall_ipv6 (p, si);
2910
2911 /* Unlink static route from linked list. */
2912 if (si->prev)
2913 si->prev->next = si->next;
2914 else
2915 rn->info = si->next;
2916 if (si->next)
2917 si->next->prev = si->prev;
2918
2919 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002920 if (ifname)
2921 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002922 XFREE (MTYPE_STATIC_IPV6, si);
2923
2924 return 1;
2925}
2926#endif /* HAVE_IPV6 */
2927
2928/* RIB update function. */
2929void
paula1ac18c2005-06-28 17:17:12 +00002930rib_update (void)
paul718e3742002-12-13 20:15:29 +00002931{
2932 struct route_node *rn;
2933 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002934
paul718e3742002-12-13 20:15:29 +00002935 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2936 if (table)
2937 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002938 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002939 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002940
2941 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2942 if (table)
2943 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002944 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002945 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002946}
2947
paul718e3742002-12-13 20:15:29 +00002948
2949/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002950static void
paul718e3742002-12-13 20:15:29 +00002951rib_weed_table (struct route_table *table)
2952{
2953 struct route_node *rn;
2954 struct rib *rib;
2955 struct rib *next;
2956
2957 if (table)
2958 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002959 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002960 {
Paul Jakma6d691122006-07-27 21:49:00 +00002961 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2962 continue;
2963
paulb21b19c2003-06-15 01:28:29 +00002964 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002965 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002966 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002967 }
2968}
2969
2970/* Delete all routes from non main table. */
2971void
paula1ac18c2005-06-28 17:17:12 +00002972rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002973{
2974 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2975 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2976}
2977
2978/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002979static void
paul718e3742002-12-13 20:15:29 +00002980rib_sweep_table (struct route_table *table)
2981{
2982 struct route_node *rn;
2983 struct rib *rib;
2984 struct rib *next;
2985 int ret = 0;
2986
2987 if (table)
2988 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002989 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002990 {
Paul Jakma6d691122006-07-27 21:49:00 +00002991 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2992 continue;
2993
paul718e3742002-12-13 20:15:29 +00002994 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2995 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2996 {
2997 ret = rib_uninstall_kernel (rn, rib);
2998 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002999 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003000 }
3001 }
3002}
3003
3004/* Sweep all RIB tables. */
3005void
paula1ac18c2005-06-28 17:17:12 +00003006rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003007{
3008 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3009 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3010}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003011
3012/* Remove specific by protocol routes from 'table'. */
3013static unsigned long
3014rib_score_proto_table (u_char proto, struct route_table *table)
3015{
3016 struct route_node *rn;
3017 struct rib *rib;
3018 struct rib *next;
3019 unsigned long n = 0;
3020
3021 if (table)
3022 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003023 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003024 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003025 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3026 continue;
3027 if (rib->type == proto)
3028 {
3029 rib_delnode (rn, rib);
3030 n++;
3031 }
3032 }
3033
3034 return n;
3035}
3036
3037/* Remove specific by protocol routes. */
3038unsigned long
3039rib_score_proto (u_char proto)
3040{
3041 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3042 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3043}
3044
paul718e3742002-12-13 20:15:29 +00003045/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003046static void
paul718e3742002-12-13 20:15:29 +00003047rib_close_table (struct route_table *table)
3048{
3049 struct route_node *rn;
3050 struct rib *rib;
3051
3052 if (table)
3053 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003054 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003055 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003056 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3057 continue;
3058
3059 if (! RIB_SYSTEM_ROUTE (rib))
3060 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003061 }
paul718e3742002-12-13 20:15:29 +00003062}
3063
3064/* Close all RIB tables. */
3065void
paula1ac18c2005-06-28 17:17:12 +00003066rib_close (void)
paul718e3742002-12-13 20:15:29 +00003067{
3068 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3069 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3070}
3071
3072/* Routing information base initialize. */
3073void
paula1ac18c2005-06-28 17:17:12 +00003074rib_init (void)
paul718e3742002-12-13 20:15:29 +00003075{
paul4d38fdb2005-04-28 17:35:14 +00003076 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003077 /* VRF initialization. */
3078 vrf_init ();
3079}