blob: 299771234a519553400a77022ced34ba850211db [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
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000173/*
174 * nexthop_type_to_str
175 */
176const char *
177nexthop_type_to_str (enum nexthop_types_t nh_type)
178{
179 static const char *desc[] = {
180 "none",
181 "Directly connected",
182 "Interface route",
183 "IPv4 nexthop",
184 "IPv4 nexthop with ifindex",
185 "IPv4 nexthop with ifname",
186 "IPv6 nexthop",
187 "IPv6 nexthop with ifindex",
188 "IPv6 nexthop with ifname",
189 "Null0 nexthop",
190 };
191
192 if (nh_type >= ZEBRA_NUM_OF (desc))
193 return "<Invalid nh type>";
194
195 return desc[nh_type];
196}
197
paul718e3742002-12-13 20:15:29 +0000198/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000199static void
paul718e3742002-12-13 20:15:29 +0000200nexthop_add (struct rib *rib, struct nexthop *nexthop)
201{
202 struct nexthop *last;
203
204 for (last = rib->nexthop; last && last->next; last = last->next)
205 ;
206 if (last)
207 last->next = nexthop;
208 else
209 rib->nexthop = nexthop;
210 nexthop->prev = last;
211
212 rib->nexthop_num++;
213}
214
215/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000216static void
paul718e3742002-12-13 20:15:29 +0000217nexthop_delete (struct rib *rib, struct nexthop *nexthop)
218{
219 if (nexthop->next)
220 nexthop->next->prev = nexthop->prev;
221 if (nexthop->prev)
222 nexthop->prev->next = nexthop->next;
223 else
224 rib->nexthop = nexthop->next;
225 rib->nexthop_num--;
226}
227
228/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000229static void
paul718e3742002-12-13 20:15:29 +0000230nexthop_free (struct nexthop *nexthop)
231{
paula4b70762003-05-16 17:19:48 +0000232 if (nexthop->ifname)
233 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000234 XFREE (MTYPE_NEXTHOP, nexthop);
235}
236
237struct nexthop *
238nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
239{
240 struct nexthop *nexthop;
241
Stephen Hemminger393deb92008-08-18 14:13:29 -0700242 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000243 nexthop->type = NEXTHOP_TYPE_IFINDEX;
244 nexthop->ifindex = ifindex;
245
246 nexthop_add (rib, nexthop);
247
248 return nexthop;
249}
250
251struct nexthop *
252nexthop_ifname_add (struct rib *rib, char *ifname)
253{
254 struct nexthop *nexthop;
255
Stephen Hemminger393deb92008-08-18 14:13:29 -0700256 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000257 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000258 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000259
260 nexthop_add (rib, nexthop);
261
262 return nexthop;
263}
264
265struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000266nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000267{
268 struct nexthop *nexthop;
269
Stephen Hemminger393deb92008-08-18 14:13:29 -0700270 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000271 nexthop->type = NEXTHOP_TYPE_IPV4;
272 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000273 if (src)
274 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000275
276 nexthop_add (rib, nexthop);
277
278 return nexthop;
279}
280
Josh Bailey26e2ae32012-03-22 01:09:21 -0700281struct nexthop *
paul718e3742002-12-13 20:15:29 +0000282nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000283 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000284{
285 struct nexthop *nexthop;
286
Stephen Hemminger393deb92008-08-18 14:13:29 -0700287 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000288 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
289 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000290 if (src)
291 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000292 nexthop->ifindex = ifindex;
293
294 nexthop_add (rib, nexthop);
295
296 return nexthop;
297}
298
299#ifdef HAVE_IPV6
300struct nexthop *
301nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
302{
303 struct nexthop *nexthop;
304
Stephen Hemminger393deb92008-08-18 14:13:29 -0700305 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000306 nexthop->type = NEXTHOP_TYPE_IPV6;
307 nexthop->gate.ipv6 = *ipv6;
308
309 nexthop_add (rib, nexthop);
310
311 return nexthop;
312}
313
paula1ac18c2005-06-28 17:17:12 +0000314static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000315nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
316 char *ifname)
317{
318 struct nexthop *nexthop;
319
Stephen Hemminger393deb92008-08-18 14:13:29 -0700320 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000321 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
322 nexthop->gate.ipv6 = *ipv6;
323 nexthop->ifname = XSTRDUP (0, ifname);
324
325 nexthop_add (rib, nexthop);
326
327 return nexthop;
328}
329
paula1ac18c2005-06-28 17:17:12 +0000330static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000331nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
332 unsigned int ifindex)
333{
334 struct nexthop *nexthop;
335
Stephen Hemminger393deb92008-08-18 14:13:29 -0700336 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000337 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
338 nexthop->gate.ipv6 = *ipv6;
339 nexthop->ifindex = ifindex;
340
341 nexthop_add (rib, nexthop);
342
343 return nexthop;
344}
345#endif /* HAVE_IPV6 */
346
paul595db7f2003-05-25 21:35:06 +0000347struct nexthop *
348nexthop_blackhole_add (struct rib *rib)
349{
350 struct nexthop *nexthop;
351
Stephen Hemminger393deb92008-08-18 14:13:29 -0700352 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000353 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
354 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
355
356 nexthop_add (rib, nexthop);
357
358 return nexthop;
359}
360
paul718e3742002-12-13 20:15:29 +0000361/* If force flag is not set, do not modify falgs at all for uninstall
362 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000363static int
paul718e3742002-12-13 20:15:29 +0000364nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
365 struct route_node *top)
366{
367 struct prefix_ipv4 p;
368 struct route_table *table;
369 struct route_node *rn;
370 struct rib *match;
371 struct nexthop *newhop;
372
373 if (nexthop->type == NEXTHOP_TYPE_IPV4)
374 nexthop->ifindex = 0;
375
376 if (set)
377 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
378
379 /* Make lookup prefix. */
380 memset (&p, 0, sizeof (struct prefix_ipv4));
381 p.family = AF_INET;
382 p.prefixlen = IPV4_MAX_PREFIXLEN;
383 p.prefix = nexthop->gate.ipv4;
384
385 /* Lookup table. */
386 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
387 if (! table)
388 return 0;
389
390 rn = route_node_match (table, (struct prefix *) &p);
391 while (rn)
392 {
393 route_unlock_node (rn);
394
David Warda50c1072009-12-03 15:34:39 +0300395 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000396 if (rn == top)
397 return 0;
398
399 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000400 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100401 {
402 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
403 continue;
404 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
405 break;
406 }
paul718e3742002-12-13 20:15:29 +0000407
408 /* If there is no selected route or matched route is EGP, go up
409 tree. */
410 if (! match
411 || match->type == ZEBRA_ROUTE_BGP)
412 {
413 do {
414 rn = rn->parent;
415 } while (rn && rn->info == NULL);
416 if (rn)
417 route_lock_node (rn);
418 }
419 else
420 {
421 if (match->type == ZEBRA_ROUTE_CONNECT)
422 {
423 /* Directly point connected route. */
424 newhop = match->nexthop;
425 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
426 nexthop->ifindex = newhop->ifindex;
427
428 return 1;
429 }
430 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
431 {
432 for (newhop = match->nexthop; newhop; newhop = newhop->next)
433 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
434 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
435 {
436 if (set)
437 {
438 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
439 nexthop->rtype = newhop->type;
440 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
441 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
442 nexthop->rgate.ipv4 = newhop->gate.ipv4;
443 if (newhop->type == NEXTHOP_TYPE_IFINDEX
444 || newhop->type == NEXTHOP_TYPE_IFNAME
445 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
446 nexthop->rifindex = newhop->ifindex;
447 }
448 return 1;
449 }
450 return 0;
451 }
452 else
453 {
454 return 0;
455 }
456 }
457 }
458 return 0;
459}
460
461#ifdef HAVE_IPV6
462/* If force flag is not set, do not modify falgs at all for uninstall
463 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000464static int
paul718e3742002-12-13 20:15:29 +0000465nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
466 struct route_node *top)
467{
468 struct prefix_ipv6 p;
469 struct route_table *table;
470 struct route_node *rn;
471 struct rib *match;
472 struct nexthop *newhop;
473
474 if (nexthop->type == NEXTHOP_TYPE_IPV6)
475 nexthop->ifindex = 0;
476
477 if (set)
478 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
479
480 /* Make lookup prefix. */
481 memset (&p, 0, sizeof (struct prefix_ipv6));
482 p.family = AF_INET6;
483 p.prefixlen = IPV6_MAX_PREFIXLEN;
484 p.prefix = nexthop->gate.ipv6;
485
486 /* Lookup table. */
487 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
488 if (! table)
489 return 0;
490
491 rn = route_node_match (table, (struct prefix *) &p);
492 while (rn)
493 {
494 route_unlock_node (rn);
495
David Warda50c1072009-12-03 15:34:39 +0300496 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000497 if (rn == top)
498 return 0;
499
500 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000501 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100502 {
503 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
504 continue;
505 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
506 break;
507 }
paul718e3742002-12-13 20:15:29 +0000508
509 /* If there is no selected route or matched route is EGP, go up
510 tree. */
511 if (! match
512 || match->type == ZEBRA_ROUTE_BGP)
513 {
514 do {
515 rn = rn->parent;
516 } while (rn && rn->info == NULL);
517 if (rn)
518 route_lock_node (rn);
519 }
520 else
521 {
522 if (match->type == ZEBRA_ROUTE_CONNECT)
523 {
524 /* Directly point connected route. */
525 newhop = match->nexthop;
526
527 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
528 nexthop->ifindex = newhop->ifindex;
529
530 return 1;
531 }
532 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
533 {
534 for (newhop = match->nexthop; newhop; newhop = newhop->next)
535 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
536 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
537 {
538 if (set)
539 {
540 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
541 nexthop->rtype = newhop->type;
542 if (newhop->type == NEXTHOP_TYPE_IPV6
543 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
544 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
545 nexthop->rgate.ipv6 = newhop->gate.ipv6;
546 if (newhop->type == NEXTHOP_TYPE_IFINDEX
547 || newhop->type == NEXTHOP_TYPE_IFNAME
548 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
549 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
550 nexthop->rifindex = newhop->ifindex;
551 }
552 return 1;
553 }
554 return 0;
555 }
556 else
557 {
558 return 0;
559 }
560 }
561 }
562 return 0;
563}
564#endif /* HAVE_IPV6 */
565
566struct rib *
567rib_match_ipv4 (struct in_addr addr)
568{
569 struct prefix_ipv4 p;
570 struct route_table *table;
571 struct route_node *rn;
572 struct rib *match;
573 struct nexthop *newhop;
574
575 /* Lookup table. */
576 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
577 if (! table)
578 return 0;
579
580 memset (&p, 0, sizeof (struct prefix_ipv4));
581 p.family = AF_INET;
582 p.prefixlen = IPV4_MAX_PREFIXLEN;
583 p.prefix = addr;
584
585 rn = route_node_match (table, (struct prefix *) &p);
586
587 while (rn)
588 {
589 route_unlock_node (rn);
590
591 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000592 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100593 {
594 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
595 continue;
596 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
597 break;
598 }
paul718e3742002-12-13 20:15:29 +0000599
600 /* If there is no selected route or matched route is EGP, go up
601 tree. */
602 if (! match
603 || match->type == ZEBRA_ROUTE_BGP)
604 {
605 do {
606 rn = rn->parent;
607 } while (rn && rn->info == NULL);
608 if (rn)
609 route_lock_node (rn);
610 }
611 else
612 {
613 if (match->type == ZEBRA_ROUTE_CONNECT)
614 /* Directly point connected route. */
615 return match;
616 else
617 {
618 for (newhop = match->nexthop; newhop; newhop = newhop->next)
619 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
620 return match;
621 return NULL;
622 }
623 }
624 }
625 return NULL;
626}
627
628struct rib *
629rib_lookup_ipv4 (struct prefix_ipv4 *p)
630{
631 struct route_table *table;
632 struct route_node *rn;
633 struct rib *match;
634 struct nexthop *nexthop;
635
636 /* Lookup table. */
637 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
638 if (! table)
639 return 0;
640
641 rn = route_node_lookup (table, (struct prefix *) p);
642
643 /* No route for this prefix. */
644 if (! rn)
645 return NULL;
646
647 /* Unlock node. */
648 route_unlock_node (rn);
649
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000650 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100651 {
652 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
653 continue;
654 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
655 break;
656 }
paul718e3742002-12-13 20:15:29 +0000657
658 if (! match || match->type == ZEBRA_ROUTE_BGP)
659 return NULL;
660
661 if (match->type == ZEBRA_ROUTE_CONNECT)
662 return match;
663
664 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
665 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
666 return match;
667
668 return NULL;
669}
670
Denis Ovsienkodc958242007-08-13 16:03:06 +0000671/*
672 * This clone function, unlike its original rib_lookup_ipv4(), checks
673 * if specified IPv4 route record (prefix/mask -> gate) exists in
674 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
675 *
676 * Return values:
677 * -1: error
678 * 0: exact match found
679 * 1: a match was found with a different gate
680 * 2: connected route found
681 * 3: no matches found
682 */
683int
684rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
685{
686 struct route_table *table;
687 struct route_node *rn;
688 struct rib *match;
689 struct nexthop *nexthop;
690
691 /* Lookup table. */
692 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
693 if (! table)
694 return ZEBRA_RIB_LOOKUP_ERROR;
695
696 /* Scan the RIB table for exactly matching RIB entry. */
697 rn = route_node_lookup (table, (struct prefix *) p);
698
699 /* No route for this prefix. */
700 if (! rn)
701 return ZEBRA_RIB_NOTFOUND;
702
703 /* Unlock node. */
704 route_unlock_node (rn);
705
706 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000707 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100708 {
709 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
710 continue;
711 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
712 break;
713 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000714
715 /* None such found :( */
716 if (!match)
717 return ZEBRA_RIB_NOTFOUND;
718
719 if (match->type == ZEBRA_ROUTE_CONNECT)
720 return ZEBRA_RIB_FOUND_CONNECTED;
721
722 /* Ok, we have a cood candidate, let's check it's nexthop list... */
723 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
724 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
725 {
726 /* We are happy with either direct or recursive hexthop */
Jorge Boncompte [DTI2]12829322012-04-10 16:57:25 +0200727 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate) ||
728 nexthop->rgate.ipv4.s_addr == sockunion2ip (qgate))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000729 return ZEBRA_RIB_FOUND_EXACT;
730 else
731 {
732 if (IS_ZEBRA_DEBUG_RIB)
733 {
734 char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
735 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
736 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
Jorge Boncompte [DTI2]12829322012-04-10 16:57:25 +0200737 inet_ntop (AF_INET, &sockunion2ip (qgate), qgate_buf, INET_ADDRSTRLEN);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000738 zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
739 }
740 return ZEBRA_RIB_FOUND_NOGATE;
741 }
742 }
743
744 return ZEBRA_RIB_NOTFOUND;
745}
746
paul718e3742002-12-13 20:15:29 +0000747#ifdef HAVE_IPV6
748struct rib *
749rib_match_ipv6 (struct in6_addr *addr)
750{
751 struct prefix_ipv6 p;
752 struct route_table *table;
753 struct route_node *rn;
754 struct rib *match;
755 struct nexthop *newhop;
756
757 /* Lookup table. */
758 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
759 if (! table)
760 return 0;
761
762 memset (&p, 0, sizeof (struct prefix_ipv6));
763 p.family = AF_INET6;
764 p.prefixlen = IPV6_MAX_PREFIXLEN;
765 IPV6_ADDR_COPY (&p.prefix, addr);
766
767 rn = route_node_match (table, (struct prefix *) &p);
768
769 while (rn)
770 {
771 route_unlock_node (rn);
772
773 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000774 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100775 {
776 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
777 continue;
778 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
779 break;
780 }
paul718e3742002-12-13 20:15:29 +0000781
782 /* If there is no selected route or matched route is EGP, go up
783 tree. */
784 if (! match
785 || match->type == ZEBRA_ROUTE_BGP)
786 {
787 do {
788 rn = rn->parent;
789 } while (rn && rn->info == NULL);
790 if (rn)
791 route_lock_node (rn);
792 }
793 else
794 {
795 if (match->type == ZEBRA_ROUTE_CONNECT)
796 /* Directly point connected route. */
797 return match;
798 else
799 {
800 for (newhop = match->nexthop; newhop; newhop = newhop->next)
801 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
802 return match;
803 return NULL;
804 }
805 }
806 }
807 return NULL;
808}
809#endif /* HAVE_IPV6 */
810
Paul Jakma7514fb72007-05-02 16:05:35 +0000811#define RIB_SYSTEM_ROUTE(R) \
812 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
813
Denis Ovsienkodc958242007-08-13 16:03:06 +0000814/* This function verifies reachability of one given nexthop, which can be
815 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
816 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
817 * nexthop->ifindex will be updated appropriately as well.
818 * An existing route map can turn (otherwise active) nexthop into inactive, but
819 * not vice versa.
820 *
821 * The return value is the final value of 'ACTIVE' flag.
822 */
823
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300824static unsigned
paul718e3742002-12-13 20:15:29 +0000825nexthop_active_check (struct route_node *rn, struct rib *rib,
826 struct nexthop *nexthop, int set)
827{
828 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000829 route_map_result_t ret = RMAP_MATCH;
830 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
831 struct route_map *rmap;
832 int family;
paul718e3742002-12-13 20:15:29 +0000833
Paul Jakma7514fb72007-05-02 16:05:35 +0000834 family = 0;
paul718e3742002-12-13 20:15:29 +0000835 switch (nexthop->type)
836 {
837 case NEXTHOP_TYPE_IFINDEX:
838 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000839 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000840 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
841 else
842 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
843 break;
paul718e3742002-12-13 20:15:29 +0000844 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000845 family = AFI_IP6;
846 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000847 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000848 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000849 {
850 if (set)
851 nexthop->ifindex = ifp->ifindex;
852 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
853 }
854 else
855 {
856 if (set)
857 nexthop->ifindex = 0;
858 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
859 }
860 break;
861 case NEXTHOP_TYPE_IPV4:
862 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000863 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000864 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
865 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
866 else
867 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
868 break;
869#ifdef HAVE_IPV6
870 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000871 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000872 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
873 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
874 else
875 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
876 break;
877 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000878 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +0000879 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
880 {
881 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000882 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000883 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
884 else
885 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
886 }
887 else
888 {
889 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
890 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
891 else
892 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
893 }
894 break;
895#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000896 case NEXTHOP_TYPE_BLACKHOLE:
897 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
898 break;
paul718e3742002-12-13 20:15:29 +0000899 default:
900 break;
901 }
Paul Jakma7514fb72007-05-02 16:05:35 +0000902 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
903 return 0;
904
905 if (RIB_SYSTEM_ROUTE(rib) ||
906 (family == AFI_IP && rn->p.family != AF_INET) ||
907 (family == AFI_IP6 && rn->p.family != AF_INET6))
908 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
909
910 rmap = 0;
911 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
912 proto_rm[family][rib->type])
913 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
914 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
915 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
916 if (rmap) {
917 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
918 }
919
920 if (ret == RMAP_DENYMATCH)
921 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000922 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
923}
924
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000925/* Iterate over all nexthops of the given RIB entry and refresh their
926 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
927 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
928 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
929 * transparently passed to nexthop_active_check().
930 *
931 * Return value is the new number of active nexthops.
932 */
933
paula1ac18c2005-06-28 17:17:12 +0000934static int
paul718e3742002-12-13 20:15:29 +0000935nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
936{
937 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300938 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +0000939
940 rib->nexthop_active_num = 0;
941 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
942
943 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000944 {
945 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200946 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000947 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
948 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +0200949 if (prev_active != new_active ||
950 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +0000951 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
952 }
paul718e3742002-12-13 20:15:29 +0000953 return rib->nexthop_active_num;
954}
paul6baeb982003-10-28 03:47:15 +0000955
paul718e3742002-12-13 20:15:29 +0000956
paul718e3742002-12-13 20:15:29 +0000957
paula1ac18c2005-06-28 17:17:12 +0000958static void
paul718e3742002-12-13 20:15:29 +0000959rib_install_kernel (struct route_node *rn, struct rib *rib)
960{
961 int ret = 0;
962 struct nexthop *nexthop;
963
964 switch (PREFIX_FAMILY (&rn->p))
965 {
966 case AF_INET:
967 ret = kernel_add_ipv4 (&rn->p, rib);
968 break;
969#ifdef HAVE_IPV6
970 case AF_INET6:
971 ret = kernel_add_ipv6 (&rn->p, rib);
972 break;
973#endif /* HAVE_IPV6 */
974 }
975
Denis Ovsienkodc958242007-08-13 16:03:06 +0000976 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +0000977 if (ret < 0)
978 {
979 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
980 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
981 }
982}
983
984/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000985static int
paul718e3742002-12-13 20:15:29 +0000986rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
987{
988 int ret = 0;
989 struct nexthop *nexthop;
990
991 switch (PREFIX_FAMILY (&rn->p))
992 {
993 case AF_INET:
994 ret = kernel_delete_ipv4 (&rn->p, rib);
995 break;
996#ifdef HAVE_IPV6
997 case AF_INET6:
998 ret = kernel_delete_ipv6 (&rn->p, rib);
999 break;
1000#endif /* HAVE_IPV6 */
1001 }
1002
1003 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1004 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1005
1006 return ret;
1007}
1008
1009/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001010static void
paul718e3742002-12-13 20:15:29 +00001011rib_uninstall (struct route_node *rn, struct rib *rib)
1012{
1013 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1014 {
1015 redistribute_delete (&rn->p, rib);
1016 if (! RIB_SYSTEM_ROUTE (rib))
1017 rib_uninstall_kernel (rn, rib);
1018 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1019 }
1020}
1021
Paul Jakma6d691122006-07-27 21:49:00 +00001022static void rib_unlink (struct route_node *, struct rib *);
1023
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001024/*
1025 * rib_can_delete_dest
1026 *
1027 * Returns TRUE if the given dest can be deleted from the table.
1028 */
1029static int
1030rib_can_delete_dest (rib_dest_t *dest)
1031{
1032 if (dest->routes)
1033 {
1034 return 0;
1035 }
1036
1037 return 1;
1038}
1039
1040/*
1041 * rib_gc_dest
1042 *
1043 * Garbage collect the rib dest corresponding to the given route node
1044 * if appropriate.
1045 *
1046 * Returns TRUE if the dest was deleted, FALSE otherwise.
1047 */
1048int
1049rib_gc_dest (struct route_node *rn)
1050{
1051 rib_dest_t *dest;
1052 char buf[INET6_ADDRSTRLEN];
1053
1054 dest = rib_dest_from_rnode (rn);
1055 if (!dest)
1056 return 0;
1057
1058 if (!rib_can_delete_dest (dest))
1059 return 0;
1060
1061 if (IS_ZEBRA_DEBUG_RIB)
1062 {
1063 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf));
1064 zlog_debug ("%s: %s/%d: removing dest from table", __func__,
1065 buf, rn->p.prefixlen);
1066 }
1067
1068 dest->rnode = NULL;
1069 XFREE (MTYPE_RIB_DEST, dest);
1070 rn->info = NULL;
1071
1072 /*
1073 * Release the one reference that we keep on the route node.
1074 */
1075 route_unlock_node (rn);
1076 return 1;
1077}
1078
paul718e3742002-12-13 20:15:29 +00001079/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001080static void
1081rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001082{
1083 struct rib *rib;
1084 struct rib *next;
1085 struct rib *fib = NULL;
1086 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001087 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001088 int installed = 0;
1089 struct nexthop *nexthop = NULL;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001090 char buf[INET6_ADDRSTRLEN];
paul4d38fdb2005-04-28 17:35:14 +00001091
1092 assert (rn);
1093
Paul Jakma93bdada2007-08-06 19:25:11 +00001094 if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001095 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001096
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001097 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001098 {
paul718e3742002-12-13 20:15:29 +00001099 /* Currently installed rib. */
1100 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001101 {
1102 assert (fib == NULL);
1103 fib = rib;
1104 }
1105
1106 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1107 * which we need to do do further work with below.
1108 */
1109 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1110 {
1111 if (rib != fib)
1112 {
1113 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001114 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
1115 buf, rn->p.prefixlen, rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001116 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001117 }
1118 else
1119 del = rib;
1120
1121 continue;
1122 }
paul4d38fdb2005-04-28 17:35:14 +00001123
paul718e3742002-12-13 20:15:29 +00001124 /* Skip unreachable nexthop. */
1125 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001126 continue;
paul718e3742002-12-13 20:15:29 +00001127
1128 /* Infinit distance. */
1129 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001130 continue;
paul718e3742002-12-13 20:15:29 +00001131
paulaf887b52006-01-18 14:52:52 +00001132 /* Newly selected rib, the common case. */
1133 if (!select)
1134 {
1135 select = rib;
1136 continue;
1137 }
1138
1139 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001140 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001141 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001142 * - lower metric beats higher for equal distance
1143 * - last, hence oldest, route wins tie break.
1144 */
paula1038a12006-01-30 14:08:51 +00001145
1146 /* Connected routes. Pick the last connected
1147 * route of the set of lowest metric connected routes.
1148 */
paula8d9c1f2006-01-25 06:31:04 +00001149 if (rib->type == ZEBRA_ROUTE_CONNECT)
1150 {
paula1038a12006-01-30 14:08:51 +00001151 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001152 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001153 select = rib;
1154 continue;
paula8d9c1f2006-01-25 06:31:04 +00001155 }
1156 else if (select->type == ZEBRA_ROUTE_CONNECT)
1157 continue;
1158
1159 /* higher distance loses */
1160 if (rib->distance > select->distance)
1161 continue;
1162
1163 /* lower wins */
1164 if (rib->distance < select->distance)
1165 {
paulaf887b52006-01-18 14:52:52 +00001166 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001167 continue;
1168 }
1169
1170 /* metric tie-breaks equal distance */
1171 if (rib->metric <= select->metric)
1172 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001173 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001174
1175 /* After the cycle is finished, the following pointers will be set:
1176 * select --- the winner RIB entry, if any was found, otherwise NULL
1177 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1178 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1179 * rib --- NULL
1180 */
1181
1182 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001183 if (select && select == fib)
1184 {
Paul Jakma6d691122006-07-27 21:49:00 +00001185 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001186 zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
1187 __func__, buf, rn->p.prefixlen, select, fib);
paul718e3742002-12-13 20:15:29 +00001188 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001189 {
1190 redistribute_delete (&rn->p, select);
1191 if (! RIB_SYSTEM_ROUTE (select))
1192 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001193
paul4d38fdb2005-04-28 17:35:14 +00001194 /* Set real nexthop. */
1195 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001196
paul4d38fdb2005-04-28 17:35:14 +00001197 if (! RIB_SYSTEM_ROUTE (select))
1198 rib_install_kernel (rn, select);
1199 redistribute_add (&rn->p, select);
1200 }
pauld753e9e2003-01-22 19:45:50 +00001201 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001202 {
1203 /* Housekeeping code to deal with
1204 race conditions in kernel with linux
1205 netlink reporting interface up before IPv4 or IPv6 protocol
1206 is ready to add routes.
1207 This makes sure the routes are IN the kernel.
1208 */
pauld753e9e2003-01-22 19:45:50 +00001209
paul4d38fdb2005-04-28 17:35:14 +00001210 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001211 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001212 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001213 installed = 1;
1214 break;
paul4d38fdb2005-04-28 17:35:14 +00001215 }
1216 if (! installed)
1217 rib_install_kernel (rn, select);
1218 }
Paul Jakma6d691122006-07-27 21:49:00 +00001219 goto end;
paul718e3742002-12-13 20:15:29 +00001220 }
1221
Denis Ovsienkodc958242007-08-13 16:03:06 +00001222 /* At this point we either haven't found the best RIB entry or it is
1223 * different from what we currently intend to flag with SELECTED. In both
1224 * cases, if a RIB block is present in FIB, it should be withdrawn.
1225 */
paul718e3742002-12-13 20:15:29 +00001226 if (fib)
1227 {
Paul Jakma6d691122006-07-27 21:49:00 +00001228 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001229 zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
1230 buf, rn->p.prefixlen, fib);
paul718e3742002-12-13 20:15:29 +00001231 redistribute_delete (&rn->p, fib);
1232 if (! RIB_SYSTEM_ROUTE (fib))
1233 rib_uninstall_kernel (rn, fib);
1234 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1235
1236 /* Set real nexthop. */
1237 nexthop_active_update (rn, fib, 1);
1238 }
1239
Denis Ovsienkodc958242007-08-13 16:03:06 +00001240 /* Regardless of some RIB entry being SELECTED or not before, now we can
1241 * tell, that if a new winner exists, FIB is still not updated with this
1242 * data, but ready to be.
1243 */
paul718e3742002-12-13 20:15:29 +00001244 if (select)
1245 {
Paul Jakma6d691122006-07-27 21:49:00 +00001246 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001247 zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
1248 rn->p.prefixlen, select);
paul718e3742002-12-13 20:15:29 +00001249 /* Set real nexthop. */
1250 nexthop_active_update (rn, select, 1);
1251
1252 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001253 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001254 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1255 redistribute_add (&rn->p, select);
1256 }
paul4d38fdb2005-04-28 17:35:14 +00001257
Paul Jakma6d691122006-07-27 21:49:00 +00001258 /* FIB route was removed, should be deleted */
1259 if (del)
1260 {
1261 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001262 zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
1263 rn->p.prefixlen, del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001264 rib_unlink (rn, del);
1265 }
paul4d38fdb2005-04-28 17:35:14 +00001266
Paul Jakma6d691122006-07-27 21:49:00 +00001267end:
1268 if (IS_ZEBRA_DEBUG_RIB_Q)
Paul Jakma93bdada2007-08-06 19:25:11 +00001269 zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001270
1271 /*
1272 * Check if the dest can be deleted now.
1273 */
1274 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001275}
1276
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001277/* Take a list of route_node structs and return 1, if there was a record
1278 * picked from it and processed by rib_process(). Don't process more,
1279 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001280 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001281static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001282process_subq (struct list * subq, u_char qindex)
1283{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001284 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001285 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001286
1287 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001288 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001289
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001290 rnode = listgetdata (lnode);
1291 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001292
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001293 if (rnode->info)
1294 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1295
Chris Caputo67b94672009-07-18 04:02:26 +00001296#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001297 else
1298 {
1299 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1300 __func__, rnode, rnode->lock);
1301 zlog_backtrace(LOG_DEBUG);
1302 }
Chris Caputo67b94672009-07-18 04:02:26 +00001303#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001304 route_unlock_node (rnode);
1305 list_delete_node (subq, lnode);
1306 return 1;
1307}
1308
1309/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1310 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1311 * is pointed to the meta queue structure.
1312 */
1313static wq_item_status
1314meta_queue_process (struct work_queue *dummy, void *data)
1315{
1316 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001317 unsigned i;
1318
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001319 for (i = 0; i < MQ_SIZE; i++)
1320 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001321 {
1322 mq->size--;
1323 break;
1324 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001325 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1326}
1327
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001328/*
1329 * Map from rib types to queue type (priority) in meta queue
1330 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001331static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1332 [ZEBRA_ROUTE_SYSTEM] = 4,
1333 [ZEBRA_ROUTE_KERNEL] = 0,
1334 [ZEBRA_ROUTE_CONNECT] = 0,
1335 [ZEBRA_ROUTE_STATIC] = 1,
1336 [ZEBRA_ROUTE_RIP] = 2,
1337 [ZEBRA_ROUTE_RIPNG] = 2,
1338 [ZEBRA_ROUTE_OSPF] = 2,
1339 [ZEBRA_ROUTE_OSPF6] = 2,
1340 [ZEBRA_ROUTE_ISIS] = 2,
1341 [ZEBRA_ROUTE_BGP] = 3,
1342 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001343 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001344};
1345
1346/* Look into the RN and queue it into one or more priority queues,
1347 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001348 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001349static void
1350rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001351{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001352 struct rib *rib;
1353 char buf[INET6_ADDRSTRLEN];
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001354
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001355 if (IS_ZEBRA_DEBUG_RIB_Q)
1356 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001357
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001358 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001359 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001360 u_char qindex = meta_queue_map[rib->type];
1361
1362 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001363 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1364 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001365 {
1366 if (IS_ZEBRA_DEBUG_RIB_Q)
1367 zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
1368 __func__, buf, rn->p.prefixlen, rn, qindex);
1369 continue;
1370 }
1371
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001372 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001373 listnode_add (mq->subq[qindex], rn);
1374 route_lock_node (rn);
1375 mq->size++;
1376
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001377 if (IS_ZEBRA_DEBUG_RIB_Q)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001378 zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u",
1379 __func__, buf, rn->p.prefixlen, rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001380 }
paul4d38fdb2005-04-28 17:35:14 +00001381}
1382
Paul Jakma6d691122006-07-27 21:49:00 +00001383/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001384static void
Paul Jakma6d691122006-07-27 21:49:00 +00001385rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001386{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001387 char buf[INET_ADDRSTRLEN];
1388 assert (zebra && rn);
paul4d38fdb2005-04-28 17:35:14 +00001389
Paul Jakma93bdada2007-08-06 19:25:11 +00001390 if (IS_ZEBRA_DEBUG_RIB_Q)
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001391 inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001392
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001393 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001394 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001395 {
1396 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1397 __func__, rn, rn->lock);
1398 zlog_backtrace(LOG_DEBUG);
1399 return;
1400 }
1401
1402 if (IS_ZEBRA_DEBUG_RIB_Q)
1403 zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
1404
1405 assert (zebra);
1406
1407 if (zebra->ribq == NULL)
1408 {
1409 zlog_err ("%s: work_queue does not exist!", __func__);
1410 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001411 }
paul4d38fdb2005-04-28 17:35:14 +00001412
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001413 /*
1414 * The RIB queue should normally be either empty or holding the only
1415 * work_queue_item element. In the latter case this element would
1416 * hold a pointer to the meta queue structure, which must be used to
1417 * actually queue the route nodes to process. So create the MQ
1418 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001419 * This semantics was introduced after 0.99.9 release.
1420 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001421 if (!zebra->ribq->items->count)
1422 work_queue_add (zebra->ribq, zebra->mq);
1423
1424 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001425
1426 if (IS_ZEBRA_DEBUG_RIB_Q)
1427 zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
1428
1429 return;
paul4d38fdb2005-04-28 17:35:14 +00001430}
1431
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001432/* Create new meta queue.
1433 A destructor function doesn't seem to be necessary here.
1434 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001435static struct meta_queue *
1436meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001437{
1438 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001439 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001440
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001441 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1442 assert(new);
1443
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001444 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001445 {
1446 new->subq[i] = list_new ();
1447 assert(new->subq[i]);
1448 }
1449
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001450 return new;
1451}
1452
paul4d38fdb2005-04-28 17:35:14 +00001453/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001454static void
paul4d38fdb2005-04-28 17:35:14 +00001455rib_queue_init (struct zebra_t *zebra)
1456{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001457 assert (zebra);
1458
paul4d38fdb2005-04-28 17:35:14 +00001459 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001460 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001461 {
Paul Jakma6d691122006-07-27 21:49:00 +00001462 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001463 return;
1464 }
1465
1466 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001467 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001468 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001469 /* XXX: TODO: These should be runtime configurable via vty */
1470 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001471 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001472
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001473 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001474 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001475 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001476 return;
1477 }
1478 return;
paul718e3742002-12-13 20:15:29 +00001479}
1480
Paul Jakma6d691122006-07-27 21:49:00 +00001481/* RIB updates are processed via a queue of pointers to route_nodes.
1482 *
1483 * The queue length is bounded by the maximal size of the routing table,
1484 * as a route_node will not be requeued, if already queued.
1485 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001486 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1487 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1488 * and then submit route_node to queue for best-path selection later.
1489 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001490 *
1491 * Deleted RIBs are reaped during best-path selection.
1492 *
1493 * rib_addnode
1494 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001495 * |-------->| | best RIB, if required
1496 * | |
1497 * static_install->|->rib_addqueue...... -> rib_process
1498 * | |
1499 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001500 * |-> set RIB_ENTRY_REMOVE |
1501 * rib_delnode (RIB freed)
1502 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001503 * The 'info' pointer of a route_node points to a rib_dest_t
1504 * ('dest'). Queueing state for a route_node is kept on the dest. The
1505 * dest is created on-demand by rib_link() and is kept around at least
1506 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001507 *
1508 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1509 *
1510 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001511 * - dest attached to route_node:
1512 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001513 * - route_node processing queue
1514 * - managed by: rib_addqueue, rib_process.
1515 *
1516 */
1517
paul718e3742002-12-13 20:15:29 +00001518/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001519static void
Paul Jakma6d691122006-07-27 21:49:00 +00001520rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001521{
1522 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001523 rib_dest_t *dest;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001524 char buf[INET6_ADDRSTRLEN];
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001525
paul4d38fdb2005-04-28 17:35:14 +00001526 assert (rib && rn);
1527
Paul Jakma6d691122006-07-27 21:49:00 +00001528 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001529 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001530 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001531 zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
1532 buf, rn->p.prefixlen, rn, rib);
1533 }
Paul Jakma6d691122006-07-27 21:49:00 +00001534
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001535 dest = rib_dest_from_rnode (rn);
1536 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001537 {
1538 if (IS_ZEBRA_DEBUG_RIB)
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001539 {
1540 zlog_debug ("%s: %s/%d: adding dest to table", __func__,
1541 buf, rn->p.prefixlen);
1542 }
1543
1544 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1545 route_lock_node (rn); /* rn route table reference */
1546 rn->info = dest;
1547 dest->rnode = rn;
1548 }
1549
1550 head = dest->routes;
1551 if (head)
1552 {
Paul Jakma6d691122006-07-27 21:49:00 +00001553 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001554 }
paul718e3742002-12-13 20:15:29 +00001555 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001556 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001557 rib_queue_add (&zebrad, rn);
1558}
1559
1560static void
1561rib_addnode (struct route_node *rn, struct rib *rib)
1562{
1563 /* RIB node has been un-removed before route-node is processed.
1564 * route_node must hence already be on the queue for processing..
1565 */
1566 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1567 {
1568 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001569 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001570 char buf[INET6_ADDRSTRLEN];
1571 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001572 zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
1573 __func__, buf, rn->p.prefixlen, rn, rib);
1574 }
Paul Jakma6d691122006-07-27 21:49:00 +00001575 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1576 return;
1577 }
1578 rib_link (rn, rib);
1579}
1580
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001581/*
1582 * rib_unlink
1583 *
1584 * Detach a rib structure from a route_node.
1585 *
1586 * Note that a call to rib_unlink() should be followed by a call to
1587 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1588 * longer required to be deleted.
1589 */
Paul Jakma6d691122006-07-27 21:49:00 +00001590static void
1591rib_unlink (struct route_node *rn, struct rib *rib)
1592{
1593 struct nexthop *nexthop, *next;
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001594 char buf[INET6_ADDRSTRLEN];
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001595 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001596
1597 assert (rn && rib);
1598
1599 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001600 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001601 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001602 zlog_debug ("%s: %s/%d: rn %p, rib %p",
1603 __func__, buf, rn->p.prefixlen, rn, rib);
1604 }
Paul Jakma6d691122006-07-27 21:49:00 +00001605
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001606 dest = rib_dest_from_rnode (rn);
1607
Paul Jakma6d691122006-07-27 21:49:00 +00001608 if (rib->next)
1609 rib->next->prev = rib->prev;
1610
1611 if (rib->prev)
1612 rib->prev->next = rib->next;
1613 else
1614 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001615 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001616 }
1617
1618 /* free RIB and nexthops */
1619 for (nexthop = rib->nexthop; nexthop; nexthop = next)
1620 {
1621 next = nexthop->next;
1622 nexthop_free (nexthop);
1623 }
1624 XFREE (MTYPE_RIB, rib);
1625
paul718e3742002-12-13 20:15:29 +00001626}
1627
paula1ac18c2005-06-28 17:17:12 +00001628static void
paul718e3742002-12-13 20:15:29 +00001629rib_delnode (struct route_node *rn, struct rib *rib)
1630{
Paul Jakma6d691122006-07-27 21:49:00 +00001631 if (IS_ZEBRA_DEBUG_RIB)
Paul Jakma93bdada2007-08-06 19:25:11 +00001632 {
Denis Ovsienkof304cb42007-10-03 12:27:16 +00001633 char buf[INET6_ADDRSTRLEN];
1634 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Paul Jakma93bdada2007-08-06 19:25:11 +00001635 zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
1636 buf, rn->p.prefixlen, rn, rib);
1637 }
Paul Jakma6d691122006-07-27 21:49:00 +00001638 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1639 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001640}
1641
1642int
1643rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001644 struct in_addr *gate, struct in_addr *src,
1645 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001646 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001647{
1648 struct rib *rib;
1649 struct rib *same = NULL;
1650 struct route_table *table;
1651 struct route_node *rn;
1652 struct nexthop *nexthop;
1653
1654 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001655 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001656 if (! table)
1657 return 0;
1658
1659 /* Make it sure prefixlen is applied to the prefix. */
1660 apply_mask_ipv4 (p);
1661
1662 /* Set default distance by route type. */
1663 if (distance == 0)
1664 {
Balaji.G837d16c2012-09-26 14:09:10 +05301665 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001666 distance = 150;
1667 else
1668 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001669
1670 /* iBGP distance is 200. */
1671 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1672 distance = 200;
1673 }
1674
1675 /* Lookup route node.*/
1676 rn = route_node_get (table, (struct prefix *) p);
1677
1678 /* If same type of route are installed, treat it as a implicit
1679 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001680 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001681 {
Paul Jakma6d691122006-07-27 21:49:00 +00001682 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1683 continue;
1684
hassoebf1ead2005-09-21 14:58:20 +00001685 if (rib->type != type)
1686 continue;
1687 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001688 {
1689 same = rib;
1690 break;
1691 }
hassoebf1ead2005-09-21 14:58:20 +00001692 /* Duplicate connected route comes in. */
1693 else if ((nexthop = rib->nexthop) &&
1694 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001695 nexthop->ifindex == ifindex &&
1696 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001697 {
1698 rib->refcnt++;
1699 return 0 ;
1700 }
paul718e3742002-12-13 20:15:29 +00001701 }
1702
1703 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001704 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001705 rib->type = type;
1706 rib->distance = distance;
1707 rib->flags = flags;
1708 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001709 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001710 rib->nexthop_num = 0;
1711 rib->uptime = time (NULL);
1712
1713 /* Nexthop settings. */
1714 if (gate)
1715 {
1716 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001717 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001718 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001719 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001720 }
1721 else
1722 nexthop_ifindex_add (rib, ifindex);
1723
1724 /* If this route is kernel route, set FIB flag to the route. */
1725 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1726 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1727 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1728
1729 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001730 if (IS_ZEBRA_DEBUG_RIB)
1731 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001732 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001733
paul718e3742002-12-13 20:15:29 +00001734 /* Free implicit route.*/
1735 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001736 {
1737 if (IS_ZEBRA_DEBUG_RIB)
1738 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001739 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001740 }
paul4d38fdb2005-04-28 17:35:14 +00001741
1742 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001743 return 0;
1744}
1745
Denis Ovsienkodc958242007-08-13 16:03:06 +00001746/* This function dumps the contents of a given RIB entry into
1747 * standard debug log. Calling function name and IP prefix in
1748 * question are passed as 1st and 2nd arguments.
1749 */
1750
1751void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
1752{
1753 char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
1754 struct nexthop *nexthop;
1755
1756 inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
1757 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
1758 zlog_debug
1759 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001760 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001761 func,
1762 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001763 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001764 rib->type,
1765 rib->table
1766 );
1767 zlog_debug
1768 (
1769 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1770 func,
1771 rib->metric,
1772 rib->distance,
1773 rib->flags,
1774 rib->status
1775 );
1776 zlog_debug
1777 (
1778 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1779 func,
1780 rib->nexthop_num,
1781 rib->nexthop_active_num,
1782 rib->nexthop_fib_num
1783 );
1784 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1785 {
1786 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
1787 inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
1788 zlog_debug
1789 (
1790 "%s: NH %s (%s) with flags %s%s%s",
1791 func,
1792 straddr1,
1793 straddr2,
1794 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1795 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1796 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1797 );
1798 }
1799 zlog_debug ("%s: dump complete", func);
1800}
1801
1802/* This is an exported helper to rtm_read() to dump the strange
1803 * RIB entry found by rib_lookup_ipv4_route()
1804 */
1805
1806void rib_lookup_and_dump (struct prefix_ipv4 * p)
1807{
1808 struct route_table *table;
1809 struct route_node *rn;
1810 struct rib *rib;
1811 char prefix_buf[INET_ADDRSTRLEN];
1812
1813 /* Lookup table. */
1814 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1815 if (! table)
1816 {
1817 zlog_err ("%s: vrf_table() returned NULL", __func__);
1818 return;
1819 }
1820
1821 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
1822 /* Scan the RIB table for exactly matching RIB entry. */
1823 rn = route_node_lookup (table, (struct prefix *) p);
1824
1825 /* No route for this prefix. */
1826 if (! rn)
1827 {
1828 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
1829 return;
1830 }
1831
1832 /* Unlock node. */
1833 route_unlock_node (rn);
1834
1835 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001836 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001837 {
1838 zlog_debug
1839 (
1840 "%s: rn %p, rib %p: %s, %s",
1841 __func__,
1842 rn,
1843 rib,
1844 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1845 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1846 );
1847 rib_dump (__func__, p, rib);
1848 }
1849}
1850
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001851/* Check if requested address assignment will fail due to another
1852 * route being installed by zebra in FIB already. Take necessary
1853 * actions, if needed: remove such a route from FIB and deSELECT
1854 * corresponding RIB entry. Then put affected RN into RIBQ head.
1855 */
1856void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1857{
1858 struct route_table *table;
1859 struct route_node *rn;
1860 struct rib *rib;
1861 unsigned changed = 0;
1862
1863 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
1864 {
1865 zlog_err ("%s: vrf_table() returned NULL", __func__);
1866 return;
1867 }
1868
1869 /* No matches would be the simplest case. */
1870 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1871 return;
1872
1873 /* Unlock node. */
1874 route_unlock_node (rn);
1875
1876 /* Check all RIB entries. In case any changes have to be done, requeue
1877 * the RN into RIBQ head. If the routing message about the new connected
1878 * route (generated by the IP address we are going to assign very soon)
1879 * comes before the RIBQ is processed, the new RIB entry will join
1880 * RIBQ record already on head. This is necessary for proper revalidation
1881 * of the rest of the RIB.
1882 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001883 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001884 {
1885 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1886 ! RIB_SYSTEM_ROUTE (rib))
1887 {
1888 changed = 1;
1889 if (IS_ZEBRA_DEBUG_RIB)
1890 {
1891 char buf[INET_ADDRSTRLEN];
1892 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
1893 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
1894 rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
1895 }
1896 rib_uninstall (rn, rib);
1897 }
1898 }
1899 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001900 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001901}
1902
paul718e3742002-12-13 20:15:29 +00001903int
G.Balajicddf3912011-11-26 21:59:32 +04001904rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001905{
1906 struct route_table *table;
1907 struct route_node *rn;
1908 struct rib *same;
1909 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001910
paul718e3742002-12-13 20:15:29 +00001911 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001912 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001913 if (! table)
1914 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04001915
paul718e3742002-12-13 20:15:29 +00001916 /* Make it sure prefixlen is applied to the prefix. */
1917 apply_mask_ipv4 (p);
1918
1919 /* Set default distance by route type. */
1920 if (rib->distance == 0)
1921 {
1922 rib->distance = route_info[rib->type].distance;
1923
1924 /* iBGP distance is 200. */
1925 if (rib->type == ZEBRA_ROUTE_BGP
1926 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1927 rib->distance = 200;
1928 }
1929
1930 /* Lookup route node.*/
1931 rn = route_node_get (table, (struct prefix *) p);
1932
1933 /* If same type of route are installed, treat it as a implicit
1934 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001935 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00001936 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00001937 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00001938 continue;
1939
paul718e3742002-12-13 20:15:29 +00001940 if (same->type == rib->type && same->table == rib->table
1941 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001942 break;
paul718e3742002-12-13 20:15:29 +00001943 }
paul4d38fdb2005-04-28 17:35:14 +00001944
paul718e3742002-12-13 20:15:29 +00001945 /* If this route is kernel route, set FIB flag to the route. */
1946 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1947 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1948 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1949
1950 /* Link new rib to node.*/
1951 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001952 if (IS_ZEBRA_DEBUG_RIB)
1953 {
1954 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1955 __func__, rn, rib);
1956 rib_dump (__func__, p, rib);
1957 }
paul718e3742002-12-13 20:15:29 +00001958
paul718e3742002-12-13 20:15:29 +00001959 /* Free implicit route.*/
1960 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001961 {
1962 if (IS_ZEBRA_DEBUG_RIB)
1963 {
1964 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1965 __func__, rn, same);
1966 rib_dump (__func__, p, same);
1967 }
paul4d38fdb2005-04-28 17:35:14 +00001968 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001969 }
paul4d38fdb2005-04-28 17:35:14 +00001970
1971 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001972 return 0;
1973}
1974
hassoebf1ead2005-09-21 14:58:20 +00001975/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001976int
1977rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04001978 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001979{
1980 struct route_table *table;
1981 struct route_node *rn;
1982 struct rib *rib;
1983 struct rib *fib = NULL;
1984 struct rib *same = NULL;
1985 struct nexthop *nexthop;
Stephen Hemminger81cce012009-04-28 14:28:00 -07001986 char buf1[INET_ADDRSTRLEN];
1987 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00001988
1989 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001990 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001991 if (! table)
1992 return 0;
1993
1994 /* Apply mask. */
1995 apply_mask_ipv4 (p);
1996
paul5ec90d22003-06-19 01:41:37 +00001997 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001998 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001999 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul5ec90d22003-06-19 01:41:37 +00002000 p->prefixlen,
2001 inet_ntoa (*gate),
2002 ifindex);
2003
paul718e3742002-12-13 20:15:29 +00002004 /* Lookup route node. */
2005 rn = route_node_lookup (table, (struct prefix *) p);
2006 if (! rn)
2007 {
2008 if (IS_ZEBRA_DEBUG_KERNEL)
2009 {
2010 if (gate)
ajsb6178002004-12-07 21:12:56 +00002011 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002012 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002013 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002014 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002015 ifindex);
2016 else
ajsb6178002004-12-07 21:12:56 +00002017 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002018 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002019 p->prefixlen,
2020 ifindex);
2021 }
2022 return ZEBRA_ERR_RTNOEXIST;
2023 }
2024
2025 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002026 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002027 {
Paul Jakma6d691122006-07-27 21:49:00 +00002028 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2029 continue;
2030
paul718e3742002-12-13 20:15:29 +00002031 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2032 fib = rib;
2033
hassoebf1ead2005-09-21 14:58:20 +00002034 if (rib->type != type)
2035 continue;
2036 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002037 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002038 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002039 if (nexthop->ifindex != ifindex)
2040 continue;
hassoebf1ead2005-09-21 14:58:20 +00002041 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002042 {
hassoebf1ead2005-09-21 14:58:20 +00002043 rib->refcnt--;
2044 route_unlock_node (rn);
2045 route_unlock_node (rn);
2046 return 0;
paul718e3742002-12-13 20:15:29 +00002047 }
hassoebf1ead2005-09-21 14:58:20 +00002048 same = rib;
2049 break;
paul718e3742002-12-13 20:15:29 +00002050 }
hassoebf1ead2005-09-21 14:58:20 +00002051 /* Make sure that the route found has the same gateway. */
2052 else if (gate == NULL ||
2053 ((nexthop = rib->nexthop) &&
2054 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
2055 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00002056 {
hassoebf1ead2005-09-21 14:58:20 +00002057 same = rib;
2058 break;
paul718e3742002-12-13 20:15:29 +00002059 }
2060 }
2061
2062 /* If same type of route can't be found and this message is from
2063 kernel. */
2064 if (! same)
2065 {
2066 if (fib && type == ZEBRA_ROUTE_KERNEL)
2067 {
2068 /* Unset flags. */
2069 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2070 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2071
2072 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2073 }
2074 else
2075 {
2076 if (IS_ZEBRA_DEBUG_KERNEL)
2077 {
2078 if (gate)
ajsb6178002004-12-07 21:12:56 +00002079 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002080 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002081 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002082 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002083 ifindex,
2084 type);
2085 else
ajsb6178002004-12-07 21:12:56 +00002086 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002087 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002088 p->prefixlen,
2089 ifindex,
2090 type);
2091 }
2092 route_unlock_node (rn);
2093 return ZEBRA_ERR_RTNOEXIST;
2094 }
2095 }
paul4d38fdb2005-04-28 17:35:14 +00002096
paul718e3742002-12-13 20:15:29 +00002097 if (same)
2098 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002099
paul718e3742002-12-13 20:15:29 +00002100 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002101 return 0;
2102}
2103
2104/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002105static void
paul718e3742002-12-13 20:15:29 +00002106static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
2107{
2108 struct rib *rib;
2109 struct route_node *rn;
2110 struct route_table *table;
2111
2112 /* Lookup table. */
2113 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2114 if (! table)
2115 return;
2116
2117 /* Lookup existing route */
2118 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002119 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002120 {
2121 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2122 continue;
2123
2124 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2125 break;
2126 }
paul718e3742002-12-13 20:15:29 +00002127
2128 if (rib)
2129 {
2130 /* Same distance static route is there. Update it with new
2131 nexthop. */
paul718e3742002-12-13 20:15:29 +00002132 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002133 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;
paul4d38fdb2005-04-28 17:35:14 +00002144 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002145 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002146 }
2147 else
2148 {
2149 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002150 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2151
paul718e3742002-12-13 20:15:29 +00002152 rib->type = ZEBRA_ROUTE_STATIC;
2153 rib->distance = si->distance;
2154 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002155 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002156 rib->nexthop_num = 0;
2157
2158 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002159 {
2160 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002161 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002162 break;
2163 case STATIC_IPV4_IFNAME:
2164 nexthop_ifname_add (rib, si->gate.ifname);
2165 break;
2166 case STATIC_IPV4_BLACKHOLE:
2167 nexthop_blackhole_add (rib);
2168 break;
2169 }
paul718e3742002-12-13 20:15:29 +00002170
hasso81dfcaa2003-05-25 19:21:25 +00002171 /* Save the flags of this static routes (reject, blackhole) */
2172 rib->flags = si->flags;
2173
paul718e3742002-12-13 20:15:29 +00002174 /* Link this rib to the tree. */
2175 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002176 }
2177}
2178
paula1ac18c2005-06-28 17:17:12 +00002179static int
paul718e3742002-12-13 20:15:29 +00002180static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2181{
2182 if (nexthop->type == NEXTHOP_TYPE_IPV4
2183 && si->type == STATIC_IPV4_GATEWAY
2184 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2185 return 1;
2186 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2187 && si->type == STATIC_IPV4_IFNAME
2188 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2189 return 1;
paul595db7f2003-05-25 21:35:06 +00002190 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2191 && si->type == STATIC_IPV4_BLACKHOLE)
2192 return 1;
paule8e19462006-01-19 20:16:55 +00002193 return 0;
paul718e3742002-12-13 20:15:29 +00002194}
2195
2196/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002197static void
paul718e3742002-12-13 20:15:29 +00002198static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
2199{
2200 struct route_node *rn;
2201 struct rib *rib;
2202 struct nexthop *nexthop;
2203 struct route_table *table;
2204
2205 /* Lookup table. */
2206 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2207 if (! table)
2208 return;
paul4d38fdb2005-04-28 17:35:14 +00002209
paul718e3742002-12-13 20:15:29 +00002210 /* Lookup existing route with type and distance. */
2211 rn = route_node_lookup (table, p);
2212 if (! rn)
2213 return;
2214
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002215 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002216 {
2217 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2218 continue;
2219
2220 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2221 break;
2222 }
paul718e3742002-12-13 20:15:29 +00002223
2224 if (! rib)
2225 {
2226 route_unlock_node (rn);
2227 return;
2228 }
2229
2230 /* Lookup nexthop. */
2231 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2232 if (static_ipv4_nexthop_same (nexthop, si))
2233 break;
2234
2235 /* Can't find nexthop. */
2236 if (! nexthop)
2237 {
2238 route_unlock_node (rn);
2239 return;
2240 }
2241
2242 /* Check nexthop. */
2243 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002244 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002245 else
2246 {
paul6baeb982003-10-28 03:47:15 +00002247 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2248 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002249 nexthop_delete (rib, nexthop);
2250 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002251 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002252 }
paul718e3742002-12-13 20:15:29 +00002253 /* Unlock node. */
2254 route_unlock_node (rn);
2255}
2256
2257/* Add static route into static route configuration. */
2258int
hasso39db97e2004-10-12 20:50:58 +00002259static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00002260 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002261{
2262 u_char type = 0;
2263 struct route_node *rn;
2264 struct static_ipv4 *si;
2265 struct static_ipv4 *pp;
2266 struct static_ipv4 *cp;
2267 struct static_ipv4 *update = NULL;
2268 struct route_table *stable;
2269
2270 /* Lookup table. */
2271 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2272 if (! stable)
2273 return -1;
2274
2275 /* Lookup static route prefix. */
2276 rn = route_node_get (stable, p);
2277
2278 /* Make flags. */
2279 if (gate)
2280 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002281 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002282 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002283 else
2284 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002285
2286 /* Do nothing if there is a same static route. */
2287 for (si = rn->info; si; si = si->next)
2288 {
2289 if (type == si->type
2290 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2291 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2292 {
2293 if (distance == si->distance)
2294 {
2295 route_unlock_node (rn);
2296 return 0;
2297 }
2298 else
2299 update = si;
2300 }
2301 }
2302
Paul Jakma3c0755d2006-12-08 00:53:14 +00002303 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002304 if (update)
2305 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2306
2307 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002308 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002309
2310 si->type = type;
2311 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002312 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002313
2314 if (gate)
2315 si->gate.ipv4 = *gate;
2316 if (ifname)
2317 si->gate.ifname = XSTRDUP (0, ifname);
2318
2319 /* Add new static route information to the tree with sort by
2320 distance value and gateway address. */
2321 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2322 {
2323 if (si->distance < cp->distance)
2324 break;
2325 if (si->distance > cp->distance)
2326 continue;
2327 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2328 {
2329 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2330 break;
2331 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2332 continue;
2333 }
2334 }
2335
2336 /* Make linked list. */
2337 if (pp)
2338 pp->next = si;
2339 else
2340 rn->info = si;
2341 if (cp)
2342 cp->prev = si;
2343 si->prev = pp;
2344 si->next = cp;
2345
2346 /* Install into rib. */
2347 static_install_ipv4 (p, si);
2348
2349 return 1;
2350}
2351
2352/* Delete static route from static route configuration. */
2353int
hasso39db97e2004-10-12 20:50:58 +00002354static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002355 u_char distance, u_int32_t vrf_id)
2356{
2357 u_char type = 0;
2358 struct route_node *rn;
2359 struct static_ipv4 *si;
2360 struct route_table *stable;
2361
2362 /* Lookup table. */
2363 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2364 if (! stable)
2365 return -1;
2366
2367 /* Lookup static route prefix. */
2368 rn = route_node_lookup (stable, p);
2369 if (! rn)
2370 return 0;
2371
2372 /* Make flags. */
2373 if (gate)
2374 type = STATIC_IPV4_GATEWAY;
2375 else if (ifname)
2376 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002377 else
2378 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002379
2380 /* Find same static route is the tree */
2381 for (si = rn->info; si; si = si->next)
2382 if (type == si->type
2383 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2384 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2385 break;
2386
2387 /* Can't find static route. */
2388 if (! si)
2389 {
2390 route_unlock_node (rn);
2391 return 0;
2392 }
2393
2394 /* Install into rib. */
2395 static_uninstall_ipv4 (p, si);
2396
2397 /* Unlink static route from linked list. */
2398 if (si->prev)
2399 si->prev->next = si->next;
2400 else
2401 rn->info = si->next;
2402 if (si->next)
2403 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002404 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002405
2406 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002407 if (ifname)
2408 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002409 XFREE (MTYPE_STATIC_IPV4, si);
2410
paul143a3852003-09-29 20:06:13 +00002411 route_unlock_node (rn);
2412
paul718e3742002-12-13 20:15:29 +00002413 return 1;
2414}
2415
2416
2417#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002418static int
paul718e3742002-12-13 20:15:29 +00002419rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2420 struct in6_addr *gate, unsigned int ifindex, int table)
2421{
hasso726f9b22003-05-25 21:04:54 +00002422 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2423#if defined (MUSICA) || defined (LINUX)
2424 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2425 if (p->prefixlen == 96)
2426 return 0;
2427#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002428 return 1;
hasso726f9b22003-05-25 21:04:54 +00002429 }
paul718e3742002-12-13 20:15:29 +00002430 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2431 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2432 {
2433 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2434 return 1;
2435 }
2436 return 0;
2437}
2438
2439int
2440rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002441 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002442 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002443{
2444 struct rib *rib;
2445 struct rib *same = NULL;
2446 struct route_table *table;
2447 struct route_node *rn;
2448 struct nexthop *nexthop;
2449
paul718e3742002-12-13 20:15:29 +00002450 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002451 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002452 if (! table)
2453 return 0;
2454
2455 /* Make sure mask is applied. */
2456 apply_mask_ipv6 (p);
2457
2458 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002459 if (!distance)
2460 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002461
2462 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2463 distance = 200;
2464
2465 /* Filter bogus route. */
2466 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2467 return 0;
2468
2469 /* Lookup route node.*/
2470 rn = route_node_get (table, (struct prefix *) p);
2471
2472 /* If same type of route are installed, treat it as a implicit
2473 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002474 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002475 {
Paul Jakma6d691122006-07-27 21:49:00 +00002476 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2477 continue;
2478
hassoebf1ead2005-09-21 14:58:20 +00002479 if (rib->type != type)
2480 continue;
2481 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002482 {
2483 same = rib;
paul718e3742002-12-13 20:15:29 +00002484 break;
2485 }
hassoebf1ead2005-09-21 14:58:20 +00002486 else if ((nexthop = rib->nexthop) &&
2487 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2488 nexthop->ifindex == ifindex)
2489 {
2490 rib->refcnt++;
2491 return 0;
2492 }
paul718e3742002-12-13 20:15:29 +00002493 }
2494
2495 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002496 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2497
paul718e3742002-12-13 20:15:29 +00002498 rib->type = type;
2499 rib->distance = distance;
2500 rib->flags = flags;
2501 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002502 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002503 rib->nexthop_num = 0;
2504 rib->uptime = time (NULL);
2505
2506 /* Nexthop settings. */
2507 if (gate)
2508 {
2509 if (ifindex)
2510 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2511 else
2512 nexthop_ipv6_add (rib, gate);
2513 }
2514 else
2515 nexthop_ifindex_add (rib, ifindex);
2516
2517 /* If this route is kernel route, set FIB flag to the route. */
2518 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2519 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2520 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2521
2522 /* Link new rib to node.*/
2523 rib_addnode (rn, rib);
2524
paul718e3742002-12-13 20:15:29 +00002525 /* Free implicit route.*/
2526 if (same)
paul4d38fdb2005-04-28 17:35:14 +00002527 rib_delnode (rn, same);
2528
2529 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002530 return 0;
2531}
2532
hassoebf1ead2005-09-21 14:58:20 +00002533/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002534int
2535rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002536 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002537{
2538 struct route_table *table;
2539 struct route_node *rn;
2540 struct rib *rib;
2541 struct rib *fib = NULL;
2542 struct rib *same = NULL;
2543 struct nexthop *nexthop;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002544 char buf1[INET6_ADDRSTRLEN];
2545 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002546
2547 /* Apply mask. */
2548 apply_mask_ipv6 (p);
2549
2550 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002551 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002552 if (! table)
2553 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002554
paul718e3742002-12-13 20:15:29 +00002555 /* Lookup route node. */
2556 rn = route_node_lookup (table, (struct prefix *) p);
2557 if (! rn)
2558 {
2559 if (IS_ZEBRA_DEBUG_KERNEL)
2560 {
2561 if (gate)
ajsb6178002004-12-07 21:12:56 +00002562 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002563 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002564 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002565 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002566 ifindex);
2567 else
ajsb6178002004-12-07 21:12:56 +00002568 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002569 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002570 p->prefixlen,
2571 ifindex);
2572 }
2573 return ZEBRA_ERR_RTNOEXIST;
2574 }
2575
2576 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002577 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002578 {
Paul Jakma6d691122006-07-27 21:49:00 +00002579 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2580 continue;
2581
paul718e3742002-12-13 20:15:29 +00002582 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2583 fib = rib;
2584
hassoebf1ead2005-09-21 14:58:20 +00002585 if (rib->type != type)
2586 continue;
2587 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002588 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002589 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002590 if (nexthop->ifindex != ifindex)
2591 continue;
hassoebf1ead2005-09-21 14:58:20 +00002592 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002593 {
hassoebf1ead2005-09-21 14:58:20 +00002594 rib->refcnt--;
2595 route_unlock_node (rn);
2596 route_unlock_node (rn);
2597 return 0;
paul718e3742002-12-13 20:15:29 +00002598 }
hassoebf1ead2005-09-21 14:58:20 +00002599 same = rib;
2600 break;
paul718e3742002-12-13 20:15:29 +00002601 }
hassoebf1ead2005-09-21 14:58:20 +00002602 /* Make sure that the route found has the same gateway. */
2603 else if (gate == NULL ||
2604 ((nexthop = rib->nexthop) &&
2605 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
2606 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00002607 {
hassoebf1ead2005-09-21 14:58:20 +00002608 same = rib;
2609 break;
paul718e3742002-12-13 20:15:29 +00002610 }
2611 }
2612
2613 /* If same type of route can't be found and this message is from
2614 kernel. */
2615 if (! same)
2616 {
2617 if (fib && type == ZEBRA_ROUTE_KERNEL)
2618 {
2619 /* Unset flags. */
2620 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2621 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2622
2623 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2624 }
2625 else
2626 {
2627 if (IS_ZEBRA_DEBUG_KERNEL)
2628 {
2629 if (gate)
ajsb6178002004-12-07 21:12:56 +00002630 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002631 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002632 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002633 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002634 ifindex,
2635 type);
2636 else
ajsb6178002004-12-07 21:12:56 +00002637 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002638 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002639 p->prefixlen,
2640 ifindex,
2641 type);
2642 }
2643 route_unlock_node (rn);
2644 return ZEBRA_ERR_RTNOEXIST;
2645 }
2646 }
2647
2648 if (same)
2649 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002650
paul718e3742002-12-13 20:15:29 +00002651 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002652 return 0;
2653}
2654
2655/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002656static void
paul718e3742002-12-13 20:15:29 +00002657static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2658{
2659 struct rib *rib;
2660 struct route_table *table;
2661 struct route_node *rn;
2662
2663 /* Lookup table. */
2664 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2665 if (! table)
2666 return;
2667
2668 /* Lookup existing route */
2669 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002670 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002671 {
2672 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2673 continue;
2674
2675 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2676 break;
2677 }
paul718e3742002-12-13 20:15:29 +00002678
2679 if (rib)
2680 {
2681 /* Same distance static route is there. Update it with new
2682 nexthop. */
paul718e3742002-12-13 20:15:29 +00002683 route_unlock_node (rn);
2684
2685 switch (si->type)
2686 {
2687 case STATIC_IPV6_GATEWAY:
2688 nexthop_ipv6_add (rib, &si->ipv6);
2689 break;
2690 case STATIC_IPV6_IFNAME:
2691 nexthop_ifname_add (rib, si->ifname);
2692 break;
2693 case STATIC_IPV6_GATEWAY_IFNAME:
2694 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2695 break;
2696 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002697 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002698 }
2699 else
2700 {
2701 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002702 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2703
paul718e3742002-12-13 20:15:29 +00002704 rib->type = ZEBRA_ROUTE_STATIC;
2705 rib->distance = si->distance;
2706 rib->metric = 0;
2707 rib->nexthop_num = 0;
2708
2709 switch (si->type)
2710 {
2711 case STATIC_IPV6_GATEWAY:
2712 nexthop_ipv6_add (rib, &si->ipv6);
2713 break;
2714 case STATIC_IPV6_IFNAME:
2715 nexthop_ifname_add (rib, si->ifname);
2716 break;
2717 case STATIC_IPV6_GATEWAY_IFNAME:
2718 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2719 break;
2720 }
2721
hasso81dfcaa2003-05-25 19:21:25 +00002722 /* Save the flags of this static routes (reject, blackhole) */
2723 rib->flags = si->flags;
2724
paul718e3742002-12-13 20:15:29 +00002725 /* Link this rib to the tree. */
2726 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002727 }
2728}
2729
paula1ac18c2005-06-28 17:17:12 +00002730static int
paul718e3742002-12-13 20:15:29 +00002731static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2732{
2733 if (nexthop->type == NEXTHOP_TYPE_IPV6
2734 && si->type == STATIC_IPV6_GATEWAY
2735 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2736 return 1;
2737 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2738 && si->type == STATIC_IPV6_IFNAME
2739 && strcmp (nexthop->ifname, si->ifname) == 0)
2740 return 1;
2741 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2742 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2743 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2744 && strcmp (nexthop->ifname, si->ifname) == 0)
2745 return 1;
paule8e19462006-01-19 20:16:55 +00002746 return 0;
paul718e3742002-12-13 20:15:29 +00002747}
2748
paula1ac18c2005-06-28 17:17:12 +00002749static void
paul718e3742002-12-13 20:15:29 +00002750static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2751{
2752 struct route_table *table;
2753 struct route_node *rn;
2754 struct rib *rib;
2755 struct nexthop *nexthop;
2756
2757 /* Lookup table. */
2758 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2759 if (! table)
2760 return;
2761
2762 /* Lookup existing route with type and distance. */
2763 rn = route_node_lookup (table, (struct prefix *) p);
2764 if (! rn)
2765 return;
2766
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002767 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002768 {
2769 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2770 continue;
2771
2772 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2773 break;
2774 }
2775
paul718e3742002-12-13 20:15:29 +00002776 if (! rib)
2777 {
2778 route_unlock_node (rn);
2779 return;
2780 }
2781
2782 /* Lookup nexthop. */
2783 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2784 if (static_ipv6_nexthop_same (nexthop, si))
2785 break;
2786
2787 /* Can't find nexthop. */
2788 if (! nexthop)
2789 {
2790 route_unlock_node (rn);
2791 return;
2792 }
2793
2794 /* Check nexthop. */
2795 if (rib->nexthop_num == 1)
2796 {
2797 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002798 }
2799 else
2800 {
paul6baeb982003-10-28 03:47:15 +00002801 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2802 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002803 nexthop_delete (rib, nexthop);
2804 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002805 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002806 }
paul718e3742002-12-13 20:15:29 +00002807 /* Unlock node. */
2808 route_unlock_node (rn);
2809}
2810
2811/* Add static route into static route configuration. */
2812int
2813static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002814 const char *ifname, u_char flags, u_char distance,
2815 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002816{
2817 struct route_node *rn;
2818 struct static_ipv6 *si;
2819 struct static_ipv6 *pp;
2820 struct static_ipv6 *cp;
2821 struct route_table *stable;
2822
2823 /* Lookup table. */
2824 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2825 if (! stable)
2826 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002827
2828 if (!gate &&
2829 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2830 return -1;
2831
2832 if (!ifname &&
2833 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2834 return -1;
paul718e3742002-12-13 20:15:29 +00002835
2836 /* Lookup static route prefix. */
2837 rn = route_node_get (stable, p);
2838
2839 /* Do nothing if there is a same static route. */
2840 for (si = rn->info; si; si = si->next)
2841 {
2842 if (distance == si->distance
2843 && type == si->type
2844 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2845 && (! ifname || strcmp (ifname, si->ifname) == 0))
2846 {
2847 route_unlock_node (rn);
2848 return 0;
2849 }
2850 }
2851
2852 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002853 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00002854
2855 si->type = type;
2856 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002857 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002858
2859 switch (type)
2860 {
2861 case STATIC_IPV6_GATEWAY:
2862 si->ipv6 = *gate;
2863 break;
2864 case STATIC_IPV6_IFNAME:
2865 si->ifname = XSTRDUP (0, ifname);
2866 break;
2867 case STATIC_IPV6_GATEWAY_IFNAME:
2868 si->ipv6 = *gate;
2869 si->ifname = XSTRDUP (0, ifname);
2870 break;
2871 }
2872
2873 /* Add new static route information to the tree with sort by
2874 distance value and gateway address. */
2875 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2876 {
2877 if (si->distance < cp->distance)
2878 break;
2879 if (si->distance > cp->distance)
2880 continue;
2881 }
2882
2883 /* Make linked list. */
2884 if (pp)
2885 pp->next = si;
2886 else
2887 rn->info = si;
2888 if (cp)
2889 cp->prev = si;
2890 si->prev = pp;
2891 si->next = cp;
2892
2893 /* Install into rib. */
2894 static_install_ipv6 (p, si);
2895
2896 return 1;
2897}
2898
2899/* Delete static route from static route configuration. */
2900int
2901static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002902 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002903{
2904 struct route_node *rn;
2905 struct static_ipv6 *si;
2906 struct route_table *stable;
2907
2908 /* Lookup table. */
2909 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2910 if (! stable)
2911 return -1;
2912
2913 /* Lookup static route prefix. */
2914 rn = route_node_lookup (stable, p);
2915 if (! rn)
2916 return 0;
2917
2918 /* Find same static route is the tree */
2919 for (si = rn->info; si; si = si->next)
2920 if (distance == si->distance
2921 && type == si->type
2922 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2923 && (! ifname || strcmp (ifname, si->ifname) == 0))
2924 break;
2925
2926 /* Can't find static route. */
2927 if (! si)
2928 {
2929 route_unlock_node (rn);
2930 return 0;
2931 }
2932
2933 /* Install into rib. */
2934 static_uninstall_ipv6 (p, si);
2935
2936 /* Unlink static route from linked list. */
2937 if (si->prev)
2938 si->prev->next = si->next;
2939 else
2940 rn->info = si->next;
2941 if (si->next)
2942 si->next->prev = si->prev;
2943
2944 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002945 if (ifname)
2946 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002947 XFREE (MTYPE_STATIC_IPV6, si);
2948
2949 return 1;
2950}
2951#endif /* HAVE_IPV6 */
2952
2953/* RIB update function. */
2954void
paula1ac18c2005-06-28 17:17:12 +00002955rib_update (void)
paul718e3742002-12-13 20:15:29 +00002956{
2957 struct route_node *rn;
2958 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002959
paul718e3742002-12-13 20:15:29 +00002960 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2961 if (table)
2962 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002963 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002964 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002965
2966 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2967 if (table)
2968 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002969 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002970 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002971}
2972
paul718e3742002-12-13 20:15:29 +00002973
2974/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002975static void
paul718e3742002-12-13 20:15:29 +00002976rib_weed_table (struct route_table *table)
2977{
2978 struct route_node *rn;
2979 struct rib *rib;
2980 struct rib *next;
2981
2982 if (table)
2983 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002984 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002985 {
Paul Jakma6d691122006-07-27 21:49:00 +00002986 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2987 continue;
2988
paulb21b19c2003-06-15 01:28:29 +00002989 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002990 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002991 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002992 }
2993}
2994
2995/* Delete all routes from non main table. */
2996void
paula1ac18c2005-06-28 17:17:12 +00002997rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002998{
2999 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3000 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3001}
3002
3003/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003004static void
paul718e3742002-12-13 20:15:29 +00003005rib_sweep_table (struct route_table *table)
3006{
3007 struct route_node *rn;
3008 struct rib *rib;
3009 struct rib *next;
3010 int ret = 0;
3011
3012 if (table)
3013 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003014 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003015 {
Paul Jakma6d691122006-07-27 21:49:00 +00003016 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3017 continue;
3018
paul718e3742002-12-13 20:15:29 +00003019 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3020 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3021 {
3022 ret = rib_uninstall_kernel (rn, rib);
3023 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003024 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003025 }
3026 }
3027}
3028
3029/* Sweep all RIB tables. */
3030void
paula1ac18c2005-06-28 17:17:12 +00003031rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003032{
3033 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3034 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3035}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003036
3037/* Remove specific by protocol routes from 'table'. */
3038static unsigned long
3039rib_score_proto_table (u_char proto, struct route_table *table)
3040{
3041 struct route_node *rn;
3042 struct rib *rib;
3043 struct rib *next;
3044 unsigned long n = 0;
3045
3046 if (table)
3047 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003048 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003049 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003050 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3051 continue;
3052 if (rib->type == proto)
3053 {
3054 rib_delnode (rn, rib);
3055 n++;
3056 }
3057 }
3058
3059 return n;
3060}
3061
3062/* Remove specific by protocol routes. */
3063unsigned long
3064rib_score_proto (u_char proto)
3065{
3066 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3067 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3068}
3069
paul718e3742002-12-13 20:15:29 +00003070/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003071static void
paul718e3742002-12-13 20:15:29 +00003072rib_close_table (struct route_table *table)
3073{
3074 struct route_node *rn;
3075 struct rib *rib;
3076
3077 if (table)
3078 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003079 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003080 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003081 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3082 continue;
3083
3084 if (! RIB_SYSTEM_ROUTE (rib))
3085 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003086 }
paul718e3742002-12-13 20:15:29 +00003087}
3088
3089/* Close all RIB tables. */
3090void
paula1ac18c2005-06-28 17:17:12 +00003091rib_close (void)
paul718e3742002-12-13 20:15:29 +00003092{
3093 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3094 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3095}
3096
3097/* Routing information base initialize. */
3098void
paula1ac18c2005-06-28 17:17:12 +00003099rib_init (void)
paul718e3742002-12-13 20:15:29 +00003100{
paul4d38fdb2005-04-28 17:35:14 +00003101 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003102 /* VRF initialization. */
3103 vrf_init ();
3104}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003105
3106/*
3107 * vrf_id_get_next
3108 *
3109 * Get the first vrf id that is greater than the given vrf id if any.
3110 *
3111 * Returns TRUE if a vrf id was found, FALSE otherwise.
3112 */
3113static inline int
3114vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3115{
3116 while (++id < vector_active (vrf_vector))
3117 {
3118 if (vrf_lookup (id))
3119 {
3120 *next_id_p = id;
3121 return 1;
3122 }
3123 }
3124
3125 return 0;
3126}
3127
3128/*
3129 * rib_tables_iter_next
3130 *
3131 * Returns the next table in the iteration.
3132 */
3133struct route_table *
3134rib_tables_iter_next (rib_tables_iter_t *iter)
3135{
3136 struct route_table *table;
3137
3138 /*
3139 * Array that helps us go over all AFI/SAFI combinations via one
3140 * index.
3141 */
3142 static struct {
3143 afi_t afi;
3144 safi_t safi;
3145 } afi_safis[] = {
3146 { AFI_IP, SAFI_UNICAST },
3147 { AFI_IP, SAFI_MULTICAST },
3148 { AFI_IP6, SAFI_UNICAST },
3149 { AFI_IP6, SAFI_MULTICAST },
3150 };
3151
3152 table = NULL;
3153
3154 switch (iter->state)
3155 {
3156
3157 case RIB_TABLES_ITER_S_INIT:
3158 iter->vrf_id = 0;
3159 iter->afi_safi_ix = -1;
3160
3161 /* Fall through */
3162
3163 case RIB_TABLES_ITER_S_ITERATING:
3164 iter->afi_safi_ix++;
3165 while (1)
3166 {
3167
3168 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3169 {
3170 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3171 afi_safis[iter->afi_safi_ix].safi,
3172 iter->vrf_id);
3173 if (table)
3174 break;
3175
3176 iter->afi_safi_ix++;
3177 }
3178
3179 /*
3180 * Found another table in this vrf.
3181 */
3182 if (table)
3183 break;
3184
3185 /*
3186 * Done with all tables in the current vrf, go to the next
3187 * one.
3188 */
3189 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3190 break;
3191
3192 iter->afi_safi_ix = 0;
3193 }
3194
3195 break;
3196
3197 case RIB_TABLES_ITER_S_DONE:
3198 return NULL;
3199 }
3200
3201 if (table)
3202 iter->state = RIB_TABLES_ITER_S_ITERATING;
3203 else
3204 iter->state = RIB_TABLES_ITER_S_DONE;
3205
3206 return table;
3207}