blob: abef90fb913ff61f12eddefb84cc3c6b78b79ccd [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"
Avneesh Sachdev5adc2522012-11-13 22:48:59 +000043#include "zebra/zebra_fpm.h"
paul718e3742002-12-13 20:15:29 +000044
45/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000046extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000047
Paul Jakma457eb9a2006-07-27 19:59:58 +000048/* Hold time for RIB process, should be very minimal.
49 * it is useful to able to set it otherwise for testing, hence exported
50 * as global here for test-rig code.
51 */
52int rib_process_hold_time = 10;
53
paul718e3742002-12-13 20:15:29 +000054/* Each route type's string and default distance value. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010055static const struct
paul718e3742002-12-13 20:15:29 +000056{
57 int key;
58 int distance;
Paul Jakma57345092011-12-25 17:52:09 +010059} route_info[ZEBRA_ROUTE_MAX] =
paul718e3742002-12-13 20:15:29 +000060{
Paul Jakma57345092011-12-25 17:52:09 +010061 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
62 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
63 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
64 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
65 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
66 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
67 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
68 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
69 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
70 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
71 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
David Lamparter7052f222009-08-27 00:28:28 +020072 /* no entry/default: 150 */
paul718e3742002-12-13 20:15:29 +000073};
David Lamparter6b0655a2014-06-04 06:53:35 +020074
paul718e3742002-12-13 20:15:29 +000075/* Vector for routing table. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010076static vector vrf_vector;
paul718e3742002-12-13 20:15:29 +000077
David Lamparter94813742014-04-24 20:22:53 +020078static void
79_rnode_zlog(const char *_func, struct route_node *rn, int priority,
80 const char *msgfmt, ...)
81{
82 char buf[INET6_ADDRSTRLEN + 4], *bptr;
83 char msgbuf[512];
84 va_list ap;
85
86 va_start(ap, msgfmt);
87 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
88 va_end(ap);
89
90 if (rn)
91 {
David Lamparterab2ba612015-01-22 19:02:13 +010092 rib_table_info_t *info = rn->table->info;
93
David Lamparter94813742014-04-24 20:22:53 +020094 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
95 bptr = buf + strlen(buf);
David Lamparterab2ba612015-01-22 19:02:13 +010096 snprintf(bptr, buf + sizeof(buf) - bptr, "/%d%s", rn->p.prefixlen,
97 info->safi == SAFI_MULTICAST ? " (MRIB)" : "");
David Lamparter94813742014-04-24 20:22:53 +020098 }
99 else
100 {
101 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
102 }
103
104 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
105}
106
107#define rnode_debug(node, ...) \
108 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
109#define rnode_info(node, ...) \
110 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
111
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000112/*
113 * vrf_table_create
114 */
115static void
116vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
117{
118 rib_table_info_t *info;
119 struct route_table *table;
120
121 assert (!vrf->table[afi][safi]);
122
123 table = route_table_init ();
124 vrf->table[afi][safi] = table;
125
126 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
127 info->vrf = vrf;
128 info->afi = afi;
129 info->safi = safi;
130 table->info = info;
131}
132
paul718e3742002-12-13 20:15:29 +0000133/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +0000134static struct vrf *
hassofce954f2004-10-07 20:29:24 +0000135vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +0000136{
137 struct vrf *vrf;
138
139 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
140
141 /* Put name. */
142 if (name)
143 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
144
145 /* Allocate routing table and static table. */
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000146 vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
147 vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000148 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
149 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000150 vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
151 vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
G.Balajicddf3912011-11-26 21:59:32 +0400152 vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
153 vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
154
paul718e3742002-12-13 20:15:29 +0000155
156 return vrf;
157}
158
paul718e3742002-12-13 20:15:29 +0000159/* Lookup VRF by identifier. */
160struct vrf *
161vrf_lookup (u_int32_t id)
162{
163 return vector_lookup (vrf_vector, id);
164}
165
paul718e3742002-12-13 20:15:29 +0000166/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000167static void
168vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000169{
170 struct vrf *default_table;
171
172 /* Allocate VRF vector. */
173 vrf_vector = vector_init (1);
174
175 /* Allocate default main table. */
176 default_table = vrf_alloc ("Default-IP-Routing-Table");
177
178 /* Default table index must be 0. */
179 vector_set_index (vrf_vector, 0, default_table);
180}
181
182/* Lookup route table. */
183struct route_table *
184vrf_table (afi_t afi, safi_t safi, u_int32_t id)
185{
186 struct vrf *vrf;
187
188 vrf = vrf_lookup (id);
189 if (! vrf)
190 return NULL;
191
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000192 if( afi >= AFI_MAX || safi >= SAFI_MAX )
193 return NULL;
194
paul718e3742002-12-13 20:15:29 +0000195 return vrf->table[afi][safi];
196}
197
198/* Lookup static route table. */
199struct route_table *
200vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
201{
202 struct vrf *vrf;
203
204 vrf = vrf_lookup (id);
205 if (! vrf)
206 return NULL;
207
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000208 if( afi >= AFI_MAX || safi >= SAFI_MAX )
209 return NULL;
210
paul718e3742002-12-13 20:15:29 +0000211 return vrf->stable[afi][safi];
212}
David Lamparter6b0655a2014-06-04 06:53:35 +0200213
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000214/*
215 * nexthop_type_to_str
216 */
217const char *
218nexthop_type_to_str (enum nexthop_types_t nh_type)
219{
220 static const char *desc[] = {
221 "none",
222 "Directly connected",
223 "Interface route",
224 "IPv4 nexthop",
225 "IPv4 nexthop with ifindex",
226 "IPv4 nexthop with ifname",
227 "IPv6 nexthop",
228 "IPv6 nexthop with ifindex",
229 "IPv6 nexthop with ifname",
230 "Null0 nexthop",
231 };
232
233 if (nh_type >= ZEBRA_NUM_OF (desc))
234 return "<Invalid nh type>";
235
236 return desc[nh_type];
237}
238
Christian Frankefa713d92013-07-05 15:35:37 +0000239/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000240static void
Christian Frankefa713d92013-07-05 15:35:37 +0000241_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000242{
243 struct nexthop *last;
244
Christian Frankefa713d92013-07-05 15:35:37 +0000245 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000246 ;
247 if (last)
248 last->next = nexthop;
249 else
Christian Frankefa713d92013-07-05 15:35:37 +0000250 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000251 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000252}
paul718e3742002-12-13 20:15:29 +0000253
Christian Frankefa713d92013-07-05 15:35:37 +0000254/* Add nexthop to the end of a rib node's nexthop list */
255static void
256nexthop_add (struct rib *rib, struct nexthop *nexthop)
257{
258 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000259 rib->nexthop_num++;
260}
261
262/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000263static void
paul718e3742002-12-13 20:15:29 +0000264nexthop_delete (struct rib *rib, struct nexthop *nexthop)
265{
266 if (nexthop->next)
267 nexthop->next->prev = nexthop->prev;
268 if (nexthop->prev)
269 nexthop->prev->next = nexthop->next;
270 else
271 rib->nexthop = nexthop->next;
272 rib->nexthop_num--;
273}
274
Christian Frankefa713d92013-07-05 15:35:37 +0000275static void nexthops_free(struct nexthop *nexthop);
276
paul718e3742002-12-13 20:15:29 +0000277/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000278static void
paul718e3742002-12-13 20:15:29 +0000279nexthop_free (struct nexthop *nexthop)
280{
paula4b70762003-05-16 17:19:48 +0000281 if (nexthop->ifname)
282 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000283 if (nexthop->resolved)
284 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000285 XFREE (MTYPE_NEXTHOP, nexthop);
286}
287
Christian Frankefa713d92013-07-05 15:35:37 +0000288/* Frees a list of nexthops */
289static void
290nexthops_free (struct nexthop *nexthop)
291{
292 struct nexthop *nh, *next;
293
294 for (nh = nexthop; nh; nh = next)
295 {
296 next = nh->next;
297 nexthop_free (nh);
298 }
299}
300
paul718e3742002-12-13 20:15:29 +0000301struct nexthop *
302nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
303{
304 struct nexthop *nexthop;
305
Stephen Hemminger393deb92008-08-18 14:13:29 -0700306 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000307 nexthop->type = NEXTHOP_TYPE_IFINDEX;
308 nexthop->ifindex = ifindex;
309
310 nexthop_add (rib, nexthop);
311
312 return nexthop;
313}
314
315struct nexthop *
316nexthop_ifname_add (struct rib *rib, 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_IFNAME;
paula4b70762003-05-16 17:19:48 +0000322 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000323
324 nexthop_add (rib, nexthop);
325
326 return nexthop;
327}
328
329struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000330nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000331{
332 struct nexthop *nexthop;
333
Stephen Hemminger393deb92008-08-18 14:13:29 -0700334 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000335 nexthop->type = NEXTHOP_TYPE_IPV4;
336 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000337 if (src)
338 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000339
340 nexthop_add (rib, nexthop);
341
342 return nexthop;
343}
344
Josh Bailey26e2ae32012-03-22 01:09:21 -0700345struct nexthop *
paul718e3742002-12-13 20:15:29 +0000346nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000347 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000348{
349 struct nexthop *nexthop;
350
Stephen Hemminger393deb92008-08-18 14:13:29 -0700351 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000352 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
353 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000354 if (src)
355 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000356 nexthop->ifindex = ifindex;
357
358 nexthop_add (rib, nexthop);
359
360 return nexthop;
361}
362
363#ifdef HAVE_IPV6
364struct nexthop *
365nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
366{
367 struct nexthop *nexthop;
368
Stephen Hemminger393deb92008-08-18 14:13:29 -0700369 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000370 nexthop->type = NEXTHOP_TYPE_IPV6;
371 nexthop->gate.ipv6 = *ipv6;
372
373 nexthop_add (rib, nexthop);
374
375 return nexthop;
376}
377
paula1ac18c2005-06-28 17:17:12 +0000378static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000379nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
380 char *ifname)
381{
382 struct nexthop *nexthop;
383
Stephen Hemminger393deb92008-08-18 14:13:29 -0700384 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000385 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
386 nexthop->gate.ipv6 = *ipv6;
387 nexthop->ifname = XSTRDUP (0, ifname);
388
389 nexthop_add (rib, nexthop);
390
391 return nexthop;
392}
393
paula1ac18c2005-06-28 17:17:12 +0000394static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000395nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
396 unsigned int ifindex)
397{
398 struct nexthop *nexthop;
399
Stephen Hemminger393deb92008-08-18 14:13:29 -0700400 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000401 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
402 nexthop->gate.ipv6 = *ipv6;
403 nexthop->ifindex = ifindex;
404
405 nexthop_add (rib, nexthop);
406
407 return nexthop;
408}
409#endif /* HAVE_IPV6 */
410
paul595db7f2003-05-25 21:35:06 +0000411struct nexthop *
412nexthop_blackhole_add (struct rib *rib)
413{
414 struct nexthop *nexthop;
415
Stephen Hemminger393deb92008-08-18 14:13:29 -0700416 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000417 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
418 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
419
420 nexthop_add (rib, nexthop);
421
422 return nexthop;
423}
424
Christian Frankefa713d92013-07-05 15:35:37 +0000425/* This method checks whether a recursive nexthop has at
426 * least one resolved nexthop in the fib.
427 */
428int
429nexthop_has_fib_child(struct nexthop *nexthop)
430{
431 struct nexthop *nh;
432
433 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
434 return 0;
435
436 for (nh = nexthop->resolved; nh; nh = nh->next)
437 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
438 return 1;
439
440 return 0;
441}
442
paul718e3742002-12-13 20:15:29 +0000443/* If force flag is not set, do not modify falgs at all for uninstall
444 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000445static int
paul718e3742002-12-13 20:15:29 +0000446nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
447 struct route_node *top)
448{
449 struct prefix_ipv4 p;
450 struct route_table *table;
451 struct route_node *rn;
452 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000453 int resolved;
paul718e3742002-12-13 20:15:29 +0000454 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000455 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000456
457 if (nexthop->type == NEXTHOP_TYPE_IPV4)
458 nexthop->ifindex = 0;
459
460 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000461 {
462 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
463 nexthops_free(nexthop->resolved);
464 nexthop->resolved = NULL;
465 }
paul718e3742002-12-13 20:15:29 +0000466
467 /* Make lookup prefix. */
468 memset (&p, 0, sizeof (struct prefix_ipv4));
469 p.family = AF_INET;
470 p.prefixlen = IPV4_MAX_PREFIXLEN;
471 p.prefix = nexthop->gate.ipv4;
472
473 /* Lookup table. */
474 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
475 if (! table)
476 return 0;
477
478 rn = route_node_match (table, (struct prefix *) &p);
479 while (rn)
480 {
481 route_unlock_node (rn);
482
David Warda50c1072009-12-03 15:34:39 +0300483 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000484 if (rn == top)
485 return 0;
486
487 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000488 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100489 {
490 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
491 continue;
492 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
493 break;
494 }
paul718e3742002-12-13 20:15:29 +0000495
496 /* If there is no selected route or matched route is EGP, go up
497 tree. */
498 if (! match
499 || match->type == ZEBRA_ROUTE_BGP)
500 {
501 do {
502 rn = rn->parent;
503 } while (rn && rn->info == NULL);
504 if (rn)
505 route_lock_node (rn);
506 }
507 else
508 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000509 /* If the longest prefix match for the nexthop yields
510 * a blackhole, mark it as inactive. */
511 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
512 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
513 return 0;
514
paul718e3742002-12-13 20:15:29 +0000515 if (match->type == ZEBRA_ROUTE_CONNECT)
516 {
517 /* Directly point connected route. */
518 newhop = match->nexthop;
519 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
520 nexthop->ifindex = newhop->ifindex;
521
522 return 1;
523 }
524 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
525 {
Christian Frankefa713d92013-07-05 15:35:37 +0000526 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000527 for (newhop = match->nexthop; newhop; newhop = newhop->next)
528 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
529 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
530 {
531 if (set)
532 {
533 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000534
535 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
536 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000537 /* If the resolving route specifies a gateway, use it */
538 if (newhop->type == NEXTHOP_TYPE_IPV4
539 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
540 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
541 {
542 resolved_hop->type = newhop->type;
543 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000544
Christian Frankec3e6b592013-07-05 15:35:40 +0000545 if (newhop->ifindex)
546 {
547 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
548 resolved_hop->ifindex = newhop->ifindex;
549 }
550 }
Christian Frankefa713d92013-07-05 15:35:37 +0000551
Christian Frankec3e6b592013-07-05 15:35:40 +0000552 /* If the resolving route is an interface route,
553 * it means the gateway we are looking up is connected
554 * to that interface. (The actual network is _not_ onlink).
555 * Therefore, the resolved route should have the original
556 * gateway as nexthop as it is directly connected.
557 *
558 * On Linux, we have to set the onlink netlink flag because
559 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000560 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000561 || newhop->type == NEXTHOP_TYPE_IFNAME)
562 {
563 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
564 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
565 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
566 resolved_hop->ifindex = newhop->ifindex;
567 }
Christian Frankefa713d92013-07-05 15:35:37 +0000568
569 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000570 }
Christian Frankefa713d92013-07-05 15:35:37 +0000571 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000572 }
Christian Frankefa713d92013-07-05 15:35:37 +0000573 return resolved;
paul718e3742002-12-13 20:15:29 +0000574 }
575 else
576 {
577 return 0;
578 }
579 }
580 }
581 return 0;
582}
583
584#ifdef HAVE_IPV6
585/* If force flag is not set, do not modify falgs at all for uninstall
586 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000587static int
paul718e3742002-12-13 20:15:29 +0000588nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
589 struct route_node *top)
590{
591 struct prefix_ipv6 p;
592 struct route_table *table;
593 struct route_node *rn;
594 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000595 int resolved;
paul718e3742002-12-13 20:15:29 +0000596 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000597 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000598
599 if (nexthop->type == NEXTHOP_TYPE_IPV6)
600 nexthop->ifindex = 0;
601
602 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000603 {
604 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
605 nexthops_free(nexthop->resolved);
606 nexthop->resolved = NULL;
607 }
paul718e3742002-12-13 20:15:29 +0000608
609 /* Make lookup prefix. */
610 memset (&p, 0, sizeof (struct prefix_ipv6));
611 p.family = AF_INET6;
612 p.prefixlen = IPV6_MAX_PREFIXLEN;
613 p.prefix = nexthop->gate.ipv6;
614
615 /* Lookup table. */
616 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
617 if (! table)
618 return 0;
619
620 rn = route_node_match (table, (struct prefix *) &p);
621 while (rn)
622 {
623 route_unlock_node (rn);
624
David Warda50c1072009-12-03 15:34:39 +0300625 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000626 if (rn == top)
627 return 0;
628
629 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000630 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100631 {
632 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
633 continue;
634 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
635 break;
636 }
paul718e3742002-12-13 20:15:29 +0000637
638 /* If there is no selected route or matched route is EGP, go up
639 tree. */
640 if (! match
641 || match->type == ZEBRA_ROUTE_BGP)
642 {
643 do {
644 rn = rn->parent;
645 } while (rn && rn->info == NULL);
646 if (rn)
647 route_lock_node (rn);
648 }
649 else
650 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000651 /* If the longest prefix match for the nexthop yields
652 * a blackhole, mark it as inactive. */
653 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
654 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
655 return 0;
656
paul718e3742002-12-13 20:15:29 +0000657 if (match->type == ZEBRA_ROUTE_CONNECT)
658 {
659 /* Directly point connected route. */
660 newhop = match->nexthop;
661
662 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
663 nexthop->ifindex = newhop->ifindex;
664
665 return 1;
666 }
667 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
668 {
Christian Frankefa713d92013-07-05 15:35:37 +0000669 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000670 for (newhop = match->nexthop; newhop; newhop = newhop->next)
671 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
672 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
673 {
674 if (set)
675 {
676 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000677
678 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
679 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000680 /* See nexthop_active_ipv4 for a description how the
681 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000682 if (newhop->type == NEXTHOP_TYPE_IPV6
683 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
684 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000685 {
686 resolved_hop->type = newhop->type;
687 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
688
689 if (newhop->ifindex)
690 {
691 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
692 resolved_hop->ifindex = newhop->ifindex;
693 }
694 }
Christian Frankefa713d92013-07-05 15:35:37 +0000695
paul718e3742002-12-13 20:15:29 +0000696 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000697 || newhop->type == NEXTHOP_TYPE_IFNAME)
698 {
699 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
700 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
701 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
702 resolved_hop->ifindex = newhop->ifindex;
703 }
Christian Frankefa713d92013-07-05 15:35:37 +0000704
705 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000706 }
Christian Frankefa713d92013-07-05 15:35:37 +0000707 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000708 }
Christian Frankefa713d92013-07-05 15:35:37 +0000709 return resolved;
paul718e3742002-12-13 20:15:29 +0000710 }
711 else
712 {
713 return 0;
714 }
715 }
716 }
717 return 0;
718}
719#endif /* HAVE_IPV6 */
720
721struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100722rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
723 struct route_node **rn_out)
Everton Marques3dea1782014-09-22 19:35:51 -0300724{
725 struct route_table *table;
726 struct route_node *rn;
727 struct rib *match;
728 struct nexthop *newhop, *tnewhop;
729 int recursing;
730
731 /* Lookup table. */
732 table = vrf_table (AFI_IP, safi, 0);
733 if (! table)
734 return 0;
735
736 rn = route_node_match_ipv4 (table, &addr);
737
738 while (rn)
739 {
740 route_unlock_node (rn);
741
742 /* Pick up selected route. */
743 RNODE_FOREACH_RIB (rn, match)
744 {
745 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
746 continue;
747 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
748 break;
749 }
750
751 /* If there is no selected route or matched route is EGP, go up
752 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300753 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300754 {
755 do {
756 rn = rn->parent;
757 } while (rn && rn->info == NULL);
758 if (rn)
759 route_lock_node (rn);
760 }
761 else
762 {
David Lamparter24480d42015-01-22 19:09:36 +0100763 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300764 {
David Lamparter24480d42015-01-22 19:09:36 +0100765 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300766 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
767 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100768 {
769 found = 1;
770 break;
771 }
772 if (!found)
773 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300774 }
David Lamparter24480d42015-01-22 19:09:36 +0100775
776 if (rn_out)
777 *rn_out = rn;
778 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300779 }
780 }
781 return NULL;
782}
783
784struct rib *
paul718e3742002-12-13 20:15:29 +0000785rib_lookup_ipv4 (struct prefix_ipv4 *p)
786{
787 struct route_table *table;
788 struct route_node *rn;
789 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000790 struct nexthop *nexthop, *tnexthop;
791 int recursing;
paul718e3742002-12-13 20:15:29 +0000792
793 /* Lookup table. */
794 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
795 if (! table)
796 return 0;
797
798 rn = route_node_lookup (table, (struct prefix *) p);
799
800 /* No route for this prefix. */
801 if (! rn)
802 return NULL;
803
804 /* Unlock node. */
805 route_unlock_node (rn);
806
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000807 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100808 {
809 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
810 continue;
811 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
812 break;
813 }
paul718e3742002-12-13 20:15:29 +0000814
815 if (! match || match->type == ZEBRA_ROUTE_BGP)
816 return NULL;
817
818 if (match->type == ZEBRA_ROUTE_CONNECT)
819 return match;
820
Christian Frankefa713d92013-07-05 15:35:37 +0000821 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000822 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
823 return match;
824
825 return NULL;
826}
827
Denis Ovsienkodc958242007-08-13 16:03:06 +0000828/*
829 * This clone function, unlike its original rib_lookup_ipv4(), checks
830 * if specified IPv4 route record (prefix/mask -> gate) exists in
831 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
832 *
833 * Return values:
834 * -1: error
835 * 0: exact match found
836 * 1: a match was found with a different gate
837 * 2: connected route found
838 * 3: no matches found
839 */
840int
841rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
842{
843 struct route_table *table;
844 struct route_node *rn;
845 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000846 struct nexthop *nexthop, *tnexthop;
847 int recursing;
848 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000849
850 /* Lookup table. */
851 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
852 if (! table)
853 return ZEBRA_RIB_LOOKUP_ERROR;
854
855 /* Scan the RIB table for exactly matching RIB entry. */
856 rn = route_node_lookup (table, (struct prefix *) p);
857
858 /* No route for this prefix. */
859 if (! rn)
860 return ZEBRA_RIB_NOTFOUND;
861
862 /* Unlock node. */
863 route_unlock_node (rn);
864
865 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000866 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100867 {
868 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
869 continue;
870 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
871 break;
872 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000873
874 /* None such found :( */
875 if (!match)
876 return ZEBRA_RIB_NOTFOUND;
877
878 if (match->type == ZEBRA_ROUTE_CONNECT)
879 return ZEBRA_RIB_FOUND_CONNECTED;
880
881 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000882 nexthops_active = 0;
883 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000884 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000885 {
Christian Frankefa713d92013-07-05 15:35:37 +0000886 nexthops_active = 1;
887 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
888 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000889 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000890 {
891 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
892 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
893 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
894 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
895 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
896 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000897 }
Christian Frankefa713d92013-07-05 15:35:37 +0000898
899 if (nexthops_active)
900 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000901
902 return ZEBRA_RIB_NOTFOUND;
903}
904
paul718e3742002-12-13 20:15:29 +0000905#ifdef HAVE_IPV6
906struct rib *
907rib_match_ipv6 (struct in6_addr *addr)
908{
909 struct prefix_ipv6 p;
910 struct route_table *table;
911 struct route_node *rn;
912 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000913 struct nexthop *newhop, *tnewhop;
914 int recursing;
paul718e3742002-12-13 20:15:29 +0000915
916 /* Lookup table. */
917 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
918 if (! table)
919 return 0;
920
921 memset (&p, 0, sizeof (struct prefix_ipv6));
922 p.family = AF_INET6;
923 p.prefixlen = IPV6_MAX_PREFIXLEN;
924 IPV6_ADDR_COPY (&p.prefix, addr);
925
926 rn = route_node_match (table, (struct prefix *) &p);
927
928 while (rn)
929 {
930 route_unlock_node (rn);
931
932 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000933 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100934 {
935 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
936 continue;
937 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
938 break;
939 }
paul718e3742002-12-13 20:15:29 +0000940
941 /* If there is no selected route or matched route is EGP, go up
942 tree. */
943 if (! match
944 || match->type == ZEBRA_ROUTE_BGP)
945 {
946 do {
947 rn = rn->parent;
948 } while (rn && rn->info == NULL);
949 if (rn)
950 route_lock_node (rn);
951 }
952 else
953 {
954 if (match->type == ZEBRA_ROUTE_CONNECT)
955 /* Directly point connected route. */
956 return match;
957 else
958 {
Christian Frankefa713d92013-07-05 15:35:37 +0000959 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000960 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
961 return match;
962 return NULL;
963 }
964 }
965 }
966 return NULL;
967}
968#endif /* HAVE_IPV6 */
969
Paul Jakma7514fb72007-05-02 16:05:35 +0000970#define RIB_SYSTEM_ROUTE(R) \
971 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
972
Denis Ovsienkodc958242007-08-13 16:03:06 +0000973/* This function verifies reachability of one given nexthop, which can be
974 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
975 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
976 * nexthop->ifindex will be updated appropriately as well.
977 * An existing route map can turn (otherwise active) nexthop into inactive, but
978 * not vice versa.
979 *
980 * The return value is the final value of 'ACTIVE' flag.
981 */
982
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300983static unsigned
paul718e3742002-12-13 20:15:29 +0000984nexthop_active_check (struct route_node *rn, struct rib *rib,
985 struct nexthop *nexthop, int set)
986{
Christian Frankef3a17322013-07-05 15:35:41 +0000987 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +0000988 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000989 route_map_result_t ret = RMAP_MATCH;
990 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
991 struct route_map *rmap;
992 int family;
paul718e3742002-12-13 20:15:29 +0000993
Paul Jakma7514fb72007-05-02 16:05:35 +0000994 family = 0;
paul718e3742002-12-13 20:15:29 +0000995 switch (nexthop->type)
996 {
997 case NEXTHOP_TYPE_IFINDEX:
998 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000999 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001000 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1001 else
1002 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1003 break;
paul718e3742002-12-13 20:15:29 +00001004 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001005 family = AFI_IP6;
1006 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001007 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001008 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001009 {
1010 if (set)
1011 nexthop->ifindex = ifp->ifindex;
1012 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1013 }
1014 else
1015 {
1016 if (set)
1017 nexthop->ifindex = 0;
1018 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1019 }
1020 break;
1021 case NEXTHOP_TYPE_IPV4:
1022 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001023 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001024 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1025 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1026 else
1027 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1028 break;
1029#ifdef HAVE_IPV6
1030 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001031 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001032 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1033 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1034 else
1035 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1036 break;
1037 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001038 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001039 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1040 {
1041 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001042 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001043 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1044 else
1045 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1046 }
1047 else
1048 {
1049 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1050 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1051 else
1052 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1053 }
1054 break;
1055#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001056 case NEXTHOP_TYPE_BLACKHOLE:
1057 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1058 break;
paul718e3742002-12-13 20:15:29 +00001059 default:
1060 break;
1061 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001062 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1063 return 0;
1064
Christian Frankef3a17322013-07-05 15:35:41 +00001065 /* XXX: What exactly do those checks do? Do we support
1066 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001067 if (RIB_SYSTEM_ROUTE(rib) ||
1068 (family == AFI_IP && rn->p.family != AF_INET) ||
1069 (family == AFI_IP6 && rn->p.family != AF_INET6))
1070 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1071
Christian Frankef3a17322013-07-05 15:35:41 +00001072 /* The original code didn't determine the family correctly
1073 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1074 * from the rib_table_info in those cases.
1075 * Possibly it may be better to use only the rib_table_info
1076 * in every case.
1077 */
1078 if (!family)
1079 family = info->afi;
1080
Paul Jakma7514fb72007-05-02 16:05:35 +00001081 rmap = 0;
1082 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1083 proto_rm[family][rib->type])
1084 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1085 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1086 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1087 if (rmap) {
1088 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1089 }
1090
1091 if (ret == RMAP_DENYMATCH)
1092 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001093 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1094}
1095
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001096/* Iterate over all nexthops of the given RIB entry and refresh their
1097 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1098 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1099 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1100 * transparently passed to nexthop_active_check().
1101 *
1102 * Return value is the new number of active nexthops.
1103 */
1104
paula1ac18c2005-06-28 17:17:12 +00001105static int
paul718e3742002-12-13 20:15:29 +00001106nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1107{
1108 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001109 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001110
1111 rib->nexthop_active_num = 0;
1112 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1113
1114 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001115 {
1116 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001117 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001118 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1119 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001120 if (prev_active != new_active ||
1121 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001122 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1123 }
paul718e3742002-12-13 20:15:29 +00001124 return rib->nexthop_active_num;
1125}
paul6baeb982003-10-28 03:47:15 +00001126
David Lamparter6b0655a2014-06-04 06:53:35 +02001127
paul718e3742002-12-13 20:15:29 +00001128
paula1ac18c2005-06-28 17:17:12 +00001129static void
paul718e3742002-12-13 20:15:29 +00001130rib_install_kernel (struct route_node *rn, struct rib *rib)
1131{
1132 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001133 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001134 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001135 int recursing;
paul718e3742002-12-13 20:15:29 +00001136
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001137 if (info->safi != SAFI_UNICAST)
1138 {
1139 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1140 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1141 return;
1142 }
1143
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001144 /*
1145 * Make sure we update the FPM any time we send new information to
1146 * the kernel.
1147 */
1148 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001149 switch (PREFIX_FAMILY (&rn->p))
1150 {
1151 case AF_INET:
1152 ret = kernel_add_ipv4 (&rn->p, rib);
1153 break;
1154#ifdef HAVE_IPV6
1155 case AF_INET6:
1156 ret = kernel_add_ipv6 (&rn->p, rib);
1157 break;
1158#endif /* HAVE_IPV6 */
1159 }
1160
Denis Ovsienkodc958242007-08-13 16:03:06 +00001161 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001162 if (ret < 0)
1163 {
Christian Frankefa713d92013-07-05 15:35:37 +00001164 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001165 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1166 }
1167}
1168
1169/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001170static int
paul718e3742002-12-13 20:15:29 +00001171rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1172{
1173 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001174 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001175 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001176 int recursing;
paul718e3742002-12-13 20:15:29 +00001177
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001178 if (info->safi != SAFI_UNICAST)
1179 {
1180 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1181 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1182 return ret;
1183 }
1184
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001185 /*
1186 * Make sure we update the FPM any time we send new information to
1187 * the kernel.
1188 */
1189 zfpm_trigger_update (rn, "uninstalling from kernel");
1190
paul718e3742002-12-13 20:15:29 +00001191 switch (PREFIX_FAMILY (&rn->p))
1192 {
1193 case AF_INET:
1194 ret = kernel_delete_ipv4 (&rn->p, rib);
1195 break;
1196#ifdef HAVE_IPV6
1197 case AF_INET6:
1198 ret = kernel_delete_ipv6 (&rn->p, rib);
1199 break;
1200#endif /* HAVE_IPV6 */
1201 }
1202
Christian Frankefa713d92013-07-05 15:35:37 +00001203 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001204 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1205
1206 return ret;
1207}
1208
1209/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001210static void
paul718e3742002-12-13 20:15:29 +00001211rib_uninstall (struct route_node *rn, struct rib *rib)
1212{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001213 rib_table_info_t *info = rn->table->info;
1214
paul718e3742002-12-13 20:15:29 +00001215 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1216 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001217 if (info->safi == SAFI_UNICAST)
1218 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001219
paul718e3742002-12-13 20:15:29 +00001220 redistribute_delete (&rn->p, rib);
1221 if (! RIB_SYSTEM_ROUTE (rib))
1222 rib_uninstall_kernel (rn, rib);
1223 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1224 }
1225}
1226
Paul Jakma6d691122006-07-27 21:49:00 +00001227static void rib_unlink (struct route_node *, struct rib *);
1228
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001229/*
1230 * rib_can_delete_dest
1231 *
1232 * Returns TRUE if the given dest can be deleted from the table.
1233 */
1234static int
1235rib_can_delete_dest (rib_dest_t *dest)
1236{
1237 if (dest->routes)
1238 {
1239 return 0;
1240 }
1241
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001242 /*
1243 * Don't delete the dest if we have to update the FPM about this
1244 * prefix.
1245 */
1246 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1247 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1248 return 0;
1249
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001250 return 1;
1251}
1252
1253/*
1254 * rib_gc_dest
1255 *
1256 * Garbage collect the rib dest corresponding to the given route node
1257 * if appropriate.
1258 *
1259 * Returns TRUE if the dest was deleted, FALSE otherwise.
1260 */
1261int
1262rib_gc_dest (struct route_node *rn)
1263{
1264 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001265
1266 dest = rib_dest_from_rnode (rn);
1267 if (!dest)
1268 return 0;
1269
1270 if (!rib_can_delete_dest (dest))
1271 return 0;
1272
1273 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001274 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001275
1276 dest->rnode = NULL;
1277 XFREE (MTYPE_RIB_DEST, dest);
1278 rn->info = NULL;
1279
1280 /*
1281 * Release the one reference that we keep on the route node.
1282 */
1283 route_unlock_node (rn);
1284 return 1;
1285}
1286
paul718e3742002-12-13 20:15:29 +00001287/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001288static void
1289rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001290{
1291 struct rib *rib;
1292 struct rib *next;
1293 struct rib *fib = NULL;
1294 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001295 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001296 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001297 struct nexthop *nexthop = NULL, *tnexthop;
1298 int recursing;
Balaji95116332014-10-23 15:25:25 +00001299 rib_table_info_t *info;
1300
paul4d38fdb2005-04-28 17:35:14 +00001301 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001302
1303 info = rn->table->info;
1304
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001305 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001306 {
paul718e3742002-12-13 20:15:29 +00001307 /* Currently installed rib. */
1308 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001309 {
1310 assert (fib == NULL);
1311 fib = rib;
1312 }
1313
1314 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1315 * which we need to do do further work with below.
1316 */
1317 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1318 {
1319 if (rib != fib)
1320 {
1321 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001322 rnode_debug (rn, "rn %p, removing rib %p", rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001323 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001324 }
1325 else
1326 del = rib;
1327
1328 continue;
1329 }
paul4d38fdb2005-04-28 17:35:14 +00001330
paul718e3742002-12-13 20:15:29 +00001331 /* Skip unreachable nexthop. */
1332 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001333 continue;
paul718e3742002-12-13 20:15:29 +00001334
1335 /* Infinit distance. */
1336 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001337 continue;
paul718e3742002-12-13 20:15:29 +00001338
paulaf887b52006-01-18 14:52:52 +00001339 /* Newly selected rib, the common case. */
1340 if (!select)
1341 {
1342 select = rib;
1343 continue;
1344 }
1345
1346 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001347 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001348 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001349 * - lower metric beats higher for equal distance
1350 * - last, hence oldest, route wins tie break.
1351 */
paula1038a12006-01-30 14:08:51 +00001352
1353 /* Connected routes. Pick the last connected
1354 * route of the set of lowest metric connected routes.
1355 */
paula8d9c1f2006-01-25 06:31:04 +00001356 if (rib->type == ZEBRA_ROUTE_CONNECT)
1357 {
paula1038a12006-01-30 14:08:51 +00001358 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001359 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001360 select = rib;
1361 continue;
paula8d9c1f2006-01-25 06:31:04 +00001362 }
1363 else if (select->type == ZEBRA_ROUTE_CONNECT)
1364 continue;
1365
1366 /* higher distance loses */
1367 if (rib->distance > select->distance)
1368 continue;
1369
1370 /* lower wins */
1371 if (rib->distance < select->distance)
1372 {
paulaf887b52006-01-18 14:52:52 +00001373 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001374 continue;
1375 }
1376
1377 /* metric tie-breaks equal distance */
1378 if (rib->metric <= select->metric)
1379 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001380 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001381
1382 /* After the cycle is finished, the following pointers will be set:
1383 * select --- the winner RIB entry, if any was found, otherwise NULL
1384 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1385 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1386 * rib --- NULL
1387 */
1388
1389 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001390 if (select && select == fib)
1391 {
Paul Jakma6d691122006-07-27 21:49:00 +00001392 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001393 rnode_debug (rn, "Updating existing route, select %p, fib %p",
1394 select, fib);
paul718e3742002-12-13 20:15:29 +00001395 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001396 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001397 if (info->safi == SAFI_UNICAST)
1398 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001399
paul4d38fdb2005-04-28 17:35:14 +00001400 redistribute_delete (&rn->p, select);
1401 if (! RIB_SYSTEM_ROUTE (select))
1402 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001403
paul4d38fdb2005-04-28 17:35:14 +00001404 /* Set real nexthop. */
1405 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001406
paul4d38fdb2005-04-28 17:35:14 +00001407 if (! RIB_SYSTEM_ROUTE (select))
1408 rib_install_kernel (rn, select);
1409 redistribute_add (&rn->p, select);
1410 }
pauld753e9e2003-01-22 19:45:50 +00001411 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001412 {
1413 /* Housekeeping code to deal with
1414 race conditions in kernel with linux
1415 netlink reporting interface up before IPv4 or IPv6 protocol
1416 is ready to add routes.
1417 This makes sure the routes are IN the kernel.
1418 */
pauld753e9e2003-01-22 19:45:50 +00001419
Christian Frankefa713d92013-07-05 15:35:37 +00001420 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001421 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001422 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001423 installed = 1;
1424 break;
paul4d38fdb2005-04-28 17:35:14 +00001425 }
1426 if (! installed)
1427 rib_install_kernel (rn, select);
1428 }
Paul Jakma6d691122006-07-27 21:49:00 +00001429 goto end;
paul718e3742002-12-13 20:15:29 +00001430 }
1431
Denis Ovsienkodc958242007-08-13 16:03:06 +00001432 /* At this point we either haven't found the best RIB entry or it is
1433 * different from what we currently intend to flag with SELECTED. In both
1434 * cases, if a RIB block is present in FIB, it should be withdrawn.
1435 */
paul718e3742002-12-13 20:15:29 +00001436 if (fib)
1437 {
Paul Jakma6d691122006-07-27 21:49:00 +00001438 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001439 rnode_debug (rn, "Removing existing route, fib %p", fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001440
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001441 if (info->safi == SAFI_UNICAST)
1442 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001443
paul718e3742002-12-13 20:15:29 +00001444 redistribute_delete (&rn->p, fib);
1445 if (! RIB_SYSTEM_ROUTE (fib))
1446 rib_uninstall_kernel (rn, fib);
1447 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1448
1449 /* Set real nexthop. */
1450 nexthop_active_update (rn, fib, 1);
1451 }
1452
Denis Ovsienkodc958242007-08-13 16:03:06 +00001453 /* Regardless of some RIB entry being SELECTED or not before, now we can
1454 * tell, that if a new winner exists, FIB is still not updated with this
1455 * data, but ready to be.
1456 */
paul718e3742002-12-13 20:15:29 +00001457 if (select)
1458 {
Paul Jakma6d691122006-07-27 21:49:00 +00001459 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001460 rnode_debug (rn, "Adding route, select %p", select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001461
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001462 if (info->safi == SAFI_UNICAST)
1463 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001464
paul718e3742002-12-13 20:15:29 +00001465 /* Set real nexthop. */
1466 nexthop_active_update (rn, select, 1);
1467
1468 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001469 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001470 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1471 redistribute_add (&rn->p, select);
1472 }
paul4d38fdb2005-04-28 17:35:14 +00001473
Paul Jakma6d691122006-07-27 21:49:00 +00001474 /* FIB route was removed, should be deleted */
1475 if (del)
1476 {
1477 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001478 rnode_debug (rn, "Deleting fib %p, rn %p", del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001479 rib_unlink (rn, del);
1480 }
paul4d38fdb2005-04-28 17:35:14 +00001481
Paul Jakma6d691122006-07-27 21:49:00 +00001482end:
1483 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001484 rnode_debug (rn, "rn %p dequeued", rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001485
1486 /*
1487 * Check if the dest can be deleted now.
1488 */
1489 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001490}
1491
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001492/* Take a list of route_node structs and return 1, if there was a record
1493 * picked from it and processed by rib_process(). Don't process more,
1494 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001495 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001496static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001497process_subq (struct list * subq, u_char qindex)
1498{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001499 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001500 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001501
1502 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001503 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001504
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001505 rnode = listgetdata (lnode);
1506 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001507
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001508 if (rnode->info)
1509 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1510
Chris Caputo67b94672009-07-18 04:02:26 +00001511#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001512 else
1513 {
1514 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1515 __func__, rnode, rnode->lock);
1516 zlog_backtrace(LOG_DEBUG);
1517 }
Chris Caputo67b94672009-07-18 04:02:26 +00001518#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001519 route_unlock_node (rnode);
1520 list_delete_node (subq, lnode);
1521 return 1;
1522}
1523
1524/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1525 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1526 * is pointed to the meta queue structure.
1527 */
1528static wq_item_status
1529meta_queue_process (struct work_queue *dummy, void *data)
1530{
1531 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001532 unsigned i;
1533
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001534 for (i = 0; i < MQ_SIZE; i++)
1535 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001536 {
1537 mq->size--;
1538 break;
1539 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001540 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1541}
1542
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001543/*
1544 * Map from rib types to queue type (priority) in meta queue
1545 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001546static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1547 [ZEBRA_ROUTE_SYSTEM] = 4,
1548 [ZEBRA_ROUTE_KERNEL] = 0,
1549 [ZEBRA_ROUTE_CONNECT] = 0,
1550 [ZEBRA_ROUTE_STATIC] = 1,
1551 [ZEBRA_ROUTE_RIP] = 2,
1552 [ZEBRA_ROUTE_RIPNG] = 2,
1553 [ZEBRA_ROUTE_OSPF] = 2,
1554 [ZEBRA_ROUTE_OSPF6] = 2,
1555 [ZEBRA_ROUTE_ISIS] = 2,
1556 [ZEBRA_ROUTE_BGP] = 3,
1557 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001558 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001559};
1560
1561/* Look into the RN and queue it into one or more priority queues,
1562 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001563 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001564static void
1565rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001566{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001567 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001568
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001569 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001570 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001571 u_char qindex = meta_queue_map[rib->type];
1572
1573 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001574 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1575 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001576 {
1577 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001578 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
1579 rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001580 continue;
1581 }
1582
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001583 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001584 listnode_add (mq->subq[qindex], rn);
1585 route_lock_node (rn);
1586 mq->size++;
1587
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001588 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001589 rnode_debug (rn, "queued rn %p into sub-queue %u",
1590 rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001591 }
paul4d38fdb2005-04-28 17:35:14 +00001592}
1593
Paul Jakma6d691122006-07-27 21:49:00 +00001594/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001595static void
Paul Jakma6d691122006-07-27 21:49:00 +00001596rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001597{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001598 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001599
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001600 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001601 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001602 {
1603 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1604 __func__, rn, rn->lock);
1605 zlog_backtrace(LOG_DEBUG);
1606 return;
1607 }
1608
1609 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001610 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001611
1612 assert (zebra);
1613
1614 if (zebra->ribq == NULL)
1615 {
1616 zlog_err ("%s: work_queue does not exist!", __func__);
1617 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001618 }
paul4d38fdb2005-04-28 17:35:14 +00001619
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001620 /*
1621 * The RIB queue should normally be either empty or holding the only
1622 * work_queue_item element. In the latter case this element would
1623 * hold a pointer to the meta queue structure, which must be used to
1624 * actually queue the route nodes to process. So create the MQ
1625 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001626 * This semantics was introduced after 0.99.9 release.
1627 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001628 if (!zebra->ribq->items->count)
1629 work_queue_add (zebra->ribq, zebra->mq);
1630
1631 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001632
1633 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001634 rnode_debug (rn, "rn %p queued", rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001635
1636 return;
paul4d38fdb2005-04-28 17:35:14 +00001637}
1638
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001639/* Create new meta queue.
1640 A destructor function doesn't seem to be necessary here.
1641 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001642static struct meta_queue *
1643meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001644{
1645 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001646 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001647
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001648 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1649 assert(new);
1650
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001651 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001652 {
1653 new->subq[i] = list_new ();
1654 assert(new->subq[i]);
1655 }
1656
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001657 return new;
1658}
1659
paul4d38fdb2005-04-28 17:35:14 +00001660/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001661static void
paul4d38fdb2005-04-28 17:35:14 +00001662rib_queue_init (struct zebra_t *zebra)
1663{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001664 assert (zebra);
1665
paul4d38fdb2005-04-28 17:35:14 +00001666 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001667 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001668 {
Paul Jakma6d691122006-07-27 21:49:00 +00001669 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001670 return;
1671 }
1672
1673 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001674 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001675 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001676 /* XXX: TODO: These should be runtime configurable via vty */
1677 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001678 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001679
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001680 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001681 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001682 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001683 return;
1684 }
1685 return;
paul718e3742002-12-13 20:15:29 +00001686}
1687
Paul Jakma6d691122006-07-27 21:49:00 +00001688/* RIB updates are processed via a queue of pointers to route_nodes.
1689 *
1690 * The queue length is bounded by the maximal size of the routing table,
1691 * as a route_node will not be requeued, if already queued.
1692 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001693 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1694 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1695 * and then submit route_node to queue for best-path selection later.
1696 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001697 *
1698 * Deleted RIBs are reaped during best-path selection.
1699 *
1700 * rib_addnode
1701 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001702 * |-------->| | best RIB, if required
1703 * | |
1704 * static_install->|->rib_addqueue...... -> rib_process
1705 * | |
1706 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001707 * |-> set RIB_ENTRY_REMOVE |
1708 * rib_delnode (RIB freed)
1709 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001710 * The 'info' pointer of a route_node points to a rib_dest_t
1711 * ('dest'). Queueing state for a route_node is kept on the dest. The
1712 * dest is created on-demand by rib_link() and is kept around at least
1713 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001714 *
1715 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1716 *
1717 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001718 * - dest attached to route_node:
1719 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001720 * - route_node processing queue
1721 * - managed by: rib_addqueue, rib_process.
1722 *
1723 */
1724
paul718e3742002-12-13 20:15:29 +00001725/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001726static void
Paul Jakma6d691122006-07-27 21:49:00 +00001727rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001728{
1729 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001730 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001731
paul4d38fdb2005-04-28 17:35:14 +00001732 assert (rib && rn);
1733
Paul Jakma6d691122006-07-27 21:49:00 +00001734 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001735 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001736
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001737 dest = rib_dest_from_rnode (rn);
1738 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001739 {
1740 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001741 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001742
1743 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1744 route_lock_node (rn); /* rn route table reference */
1745 rn->info = dest;
1746 dest->rnode = rn;
1747 }
1748
1749 head = dest->routes;
1750 if (head)
1751 {
Paul Jakma6d691122006-07-27 21:49:00 +00001752 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001753 }
paul718e3742002-12-13 20:15:29 +00001754 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001755 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001756 rib_queue_add (&zebrad, rn);
1757}
1758
1759static void
1760rib_addnode (struct route_node *rn, struct rib *rib)
1761{
1762 /* RIB node has been un-removed before route-node is processed.
1763 * route_node must hence already be on the queue for processing..
1764 */
1765 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1766 {
1767 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001768 rnode_debug (rn, "rn %p, un-removed rib %p", rn, rib);
1769
Paul Jakma6d691122006-07-27 21:49:00 +00001770 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1771 return;
1772 }
1773 rib_link (rn, rib);
1774}
1775
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001776/*
1777 * rib_unlink
1778 *
1779 * Detach a rib structure from a route_node.
1780 *
1781 * Note that a call to rib_unlink() should be followed by a call to
1782 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1783 * longer required to be deleted.
1784 */
Paul Jakma6d691122006-07-27 21:49:00 +00001785static void
1786rib_unlink (struct route_node *rn, struct rib *rib)
1787{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001788 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001789
1790 assert (rn && rib);
1791
1792 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001793 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001794
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001795 dest = rib_dest_from_rnode (rn);
1796
Paul Jakma6d691122006-07-27 21:49:00 +00001797 if (rib->next)
1798 rib->next->prev = rib->prev;
1799
1800 if (rib->prev)
1801 rib->prev->next = rib->next;
1802 else
1803 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001804 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001805 }
1806
1807 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001808 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001809 XFREE (MTYPE_RIB, rib);
1810
paul718e3742002-12-13 20:15:29 +00001811}
1812
paula1ac18c2005-06-28 17:17:12 +00001813static void
paul718e3742002-12-13 20:15:29 +00001814rib_delnode (struct route_node *rn, struct rib *rib)
1815{
Paul Jakma6d691122006-07-27 21:49:00 +00001816 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001817 rnode_debug (rn, "rn %p, rib %p, removing", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001818 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1819 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001820}
1821
1822int
1823rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001824 struct in_addr *gate, struct in_addr *src,
1825 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001826 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001827{
1828 struct rib *rib;
1829 struct rib *same = NULL;
1830 struct route_table *table;
1831 struct route_node *rn;
1832 struct nexthop *nexthop;
1833
1834 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001835 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001836 if (! table)
1837 return 0;
1838
1839 /* Make it sure prefixlen is applied to the prefix. */
1840 apply_mask_ipv4 (p);
1841
1842 /* Set default distance by route type. */
1843 if (distance == 0)
1844 {
Balaji.G837d16c2012-09-26 14:09:10 +05301845 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001846 distance = 150;
1847 else
1848 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001849
1850 /* iBGP distance is 200. */
1851 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1852 distance = 200;
1853 }
1854
1855 /* Lookup route node.*/
1856 rn = route_node_get (table, (struct prefix *) p);
1857
1858 /* If same type of route are installed, treat it as a implicit
1859 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001860 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001861 {
Paul Jakma6d691122006-07-27 21:49:00 +00001862 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1863 continue;
1864
hassoebf1ead2005-09-21 14:58:20 +00001865 if (rib->type != type)
1866 continue;
1867 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001868 {
1869 same = rib;
1870 break;
1871 }
hassoebf1ead2005-09-21 14:58:20 +00001872 /* Duplicate connected route comes in. */
1873 else if ((nexthop = rib->nexthop) &&
1874 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001875 nexthop->ifindex == ifindex &&
1876 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001877 {
1878 rib->refcnt++;
1879 return 0 ;
1880 }
paul718e3742002-12-13 20:15:29 +00001881 }
1882
1883 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001884 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001885 rib->type = type;
1886 rib->distance = distance;
1887 rib->flags = flags;
1888 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001889 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001890 rib->nexthop_num = 0;
1891 rib->uptime = time (NULL);
1892
1893 /* Nexthop settings. */
1894 if (gate)
1895 {
1896 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001897 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001898 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001899 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001900 }
1901 else
1902 nexthop_ifindex_add (rib, ifindex);
1903
1904 /* If this route is kernel route, set FIB flag to the route. */
1905 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1906 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1907 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1908
1909 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001910 if (IS_ZEBRA_DEBUG_RIB)
1911 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001912 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001913
paul718e3742002-12-13 20:15:29 +00001914 /* Free implicit route.*/
1915 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001916 {
1917 if (IS_ZEBRA_DEBUG_RIB)
1918 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001919 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001920 }
paul4d38fdb2005-04-28 17:35:14 +00001921
1922 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001923 return 0;
1924}
1925
Denis Ovsienkodc958242007-08-13 16:03:06 +00001926/* This function dumps the contents of a given RIB entry into
1927 * standard debug log. Calling function name and IP prefix in
1928 * question are passed as 1st and 2nd arguments.
1929 */
1930
David Lamparterf7bf4152013-10-22 17:10:21 +00001931void _rib_dump (const char * func,
1932 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001933{
David Lamparterf7bf4152013-10-22 17:10:21 +00001934 const struct prefix *p = pp.p;
Vincent Bernatfed643f2012-10-23 16:00:42 +00001935 char straddr[INET6_ADDRSTRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001936 struct nexthop *nexthop, *tnexthop;
1937 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001938
Vincent Bernatfed643f2012-10-23 16:00:42 +00001939 inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001940 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001941 zlog_debug
1942 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001943 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001944 func,
1945 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001946 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001947 rib->type,
1948 rib->table
1949 );
1950 zlog_debug
1951 (
1952 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1953 func,
1954 rib->metric,
1955 rib->distance,
1956 rib->flags,
1957 rib->status
1958 );
1959 zlog_debug
1960 (
1961 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1962 func,
1963 rib->nexthop_num,
1964 rib->nexthop_active_num,
1965 rib->nexthop_fib_num
1966 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001967
Christian Frankefa713d92013-07-05 15:35:37 +00001968 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1969 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001970 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001971 zlog_debug
1972 (
1973 "%s: %s %s with flags %s%s%s",
1974 func,
1975 (recursing ? " NH" : "NH"),
1976 straddr,
1977 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1978 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1979 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1980 );
1981 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001982 zlog_debug ("%s: dump complete", func);
1983}
1984
1985/* This is an exported helper to rtm_read() to dump the strange
1986 * RIB entry found by rib_lookup_ipv4_route()
1987 */
1988
1989void rib_lookup_and_dump (struct prefix_ipv4 * p)
1990{
1991 struct route_table *table;
1992 struct route_node *rn;
1993 struct rib *rib;
1994 char prefix_buf[INET_ADDRSTRLEN];
1995
1996 /* Lookup table. */
1997 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1998 if (! table)
1999 {
2000 zlog_err ("%s: vrf_table() returned NULL", __func__);
2001 return;
2002 }
2003
2004 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
2005 /* Scan the RIB table for exactly matching RIB entry. */
2006 rn = route_node_lookup (table, (struct prefix *) p);
2007
2008 /* No route for this prefix. */
2009 if (! rn)
2010 {
2011 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
2012 return;
2013 }
2014
2015 /* Unlock node. */
2016 route_unlock_node (rn);
2017
2018 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002019 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002020 {
2021 zlog_debug
2022 (
2023 "%s: rn %p, rib %p: %s, %s",
2024 __func__,
2025 rn,
2026 rib,
2027 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2028 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2029 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002030 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002031 }
2032}
2033
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002034/* Check if requested address assignment will fail due to another
2035 * route being installed by zebra in FIB already. Take necessary
2036 * actions, if needed: remove such a route from FIB and deSELECT
2037 * corresponding RIB entry. Then put affected RN into RIBQ head.
2038 */
2039void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2040{
2041 struct route_table *table;
2042 struct route_node *rn;
2043 struct rib *rib;
2044 unsigned changed = 0;
2045
2046 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2047 {
2048 zlog_err ("%s: vrf_table() returned NULL", __func__);
2049 return;
2050 }
2051
2052 /* No matches would be the simplest case. */
2053 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2054 return;
2055
2056 /* Unlock node. */
2057 route_unlock_node (rn);
2058
2059 /* Check all RIB entries. In case any changes have to be done, requeue
2060 * the RN into RIBQ head. If the routing message about the new connected
2061 * route (generated by the IP address we are going to assign very soon)
2062 * comes before the RIBQ is processed, the new RIB entry will join
2063 * RIBQ record already on head. This is necessary for proper revalidation
2064 * of the rest of the RIB.
2065 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002066 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002067 {
2068 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2069 ! RIB_SYSTEM_ROUTE (rib))
2070 {
2071 changed = 1;
2072 if (IS_ZEBRA_DEBUG_RIB)
2073 {
2074 char buf[INET_ADDRSTRLEN];
2075 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
2076 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
David Lamparterf7bf4152013-10-22 17:10:21 +00002077 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002078 }
2079 rib_uninstall (rn, rib);
2080 }
2081 }
2082 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002083 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002084}
2085
paul718e3742002-12-13 20:15:29 +00002086int
G.Balajicddf3912011-11-26 21:59:32 +04002087rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002088{
2089 struct route_table *table;
2090 struct route_node *rn;
2091 struct rib *same;
2092 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002093
paul718e3742002-12-13 20:15:29 +00002094 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002095 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002096 if (! table)
2097 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002098
paul718e3742002-12-13 20:15:29 +00002099 /* Make it sure prefixlen is applied to the prefix. */
2100 apply_mask_ipv4 (p);
2101
2102 /* Set default distance by route type. */
2103 if (rib->distance == 0)
2104 {
2105 rib->distance = route_info[rib->type].distance;
2106
2107 /* iBGP distance is 200. */
2108 if (rib->type == ZEBRA_ROUTE_BGP
2109 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2110 rib->distance = 200;
2111 }
2112
2113 /* Lookup route node.*/
2114 rn = route_node_get (table, (struct prefix *) p);
2115
2116 /* If same type of route are installed, treat it as a implicit
2117 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002118 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002119 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002120 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002121 continue;
2122
paul718e3742002-12-13 20:15:29 +00002123 if (same->type == rib->type && same->table == rib->table
2124 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002125 break;
paul718e3742002-12-13 20:15:29 +00002126 }
paul4d38fdb2005-04-28 17:35:14 +00002127
paul718e3742002-12-13 20:15:29 +00002128 /* If this route is kernel route, set FIB flag to the route. */
2129 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2130 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2131 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2132
2133 /* Link new rib to node.*/
2134 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002135 if (IS_ZEBRA_DEBUG_RIB)
2136 {
2137 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2138 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002139 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002140 }
paul718e3742002-12-13 20:15:29 +00002141
paul718e3742002-12-13 20:15:29 +00002142 /* Free implicit route.*/
2143 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002144 {
2145 if (IS_ZEBRA_DEBUG_RIB)
2146 {
2147 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2148 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002149 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002150 }
paul4d38fdb2005-04-28 17:35:14 +00002151 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002152 }
paul4d38fdb2005-04-28 17:35:14 +00002153
2154 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002155 return 0;
2156}
2157
hassoebf1ead2005-09-21 14:58:20 +00002158/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002159int
2160rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002161 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002162{
2163 struct route_table *table;
2164 struct route_node *rn;
2165 struct rib *rib;
2166 struct rib *fib = NULL;
2167 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002168 struct nexthop *nexthop, *tnexthop;
2169 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002170 char buf1[INET_ADDRSTRLEN];
2171 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002172
2173 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002174 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002175 if (! table)
2176 return 0;
2177
2178 /* Apply mask. */
2179 apply_mask_ipv4 (p);
2180
Christian Frankeb52aef12013-11-27 17:06:15 +00002181 if (IS_ZEBRA_DEBUG_KERNEL)
2182 {
2183 if (gate)
2184 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
2185 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2186 p->prefixlen,
2187 inet_ntoa (*gate),
2188 ifindex);
2189 else
2190 zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d",
2191 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2192 p->prefixlen,
2193 ifindex);
2194 }
paul5ec90d22003-06-19 01:41:37 +00002195
paul718e3742002-12-13 20:15:29 +00002196 /* Lookup route node. */
2197 rn = route_node_lookup (table, (struct prefix *) p);
2198 if (! rn)
2199 {
2200 if (IS_ZEBRA_DEBUG_KERNEL)
2201 {
2202 if (gate)
ajsb6178002004-12-07 21:12:56 +00002203 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002204 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002205 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002206 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002207 ifindex);
2208 else
ajsb6178002004-12-07 21:12:56 +00002209 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002210 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002211 p->prefixlen,
2212 ifindex);
2213 }
2214 return ZEBRA_ERR_RTNOEXIST;
2215 }
2216
2217 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002218 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002219 {
Paul Jakma6d691122006-07-27 21:49:00 +00002220 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2221 continue;
2222
paul718e3742002-12-13 20:15:29 +00002223 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2224 fib = rib;
2225
hassoebf1ead2005-09-21 14:58:20 +00002226 if (rib->type != type)
2227 continue;
2228 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002229 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002230 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002231 if (nexthop->ifindex != ifindex)
2232 continue;
hassoebf1ead2005-09-21 14:58:20 +00002233 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002234 {
hassoebf1ead2005-09-21 14:58:20 +00002235 rib->refcnt--;
2236 route_unlock_node (rn);
2237 route_unlock_node (rn);
2238 return 0;
paul718e3742002-12-13 20:15:29 +00002239 }
hassoebf1ead2005-09-21 14:58:20 +00002240 same = rib;
2241 break;
paul718e3742002-12-13 20:15:29 +00002242 }
hassoebf1ead2005-09-21 14:58:20 +00002243 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002244 else
paul5ec90d22003-06-19 01:41:37 +00002245 {
Christian Frankefa713d92013-07-05 15:35:37 +00002246 if (gate == NULL)
2247 {
2248 same = rib;
2249 break;
2250 }
2251 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2252 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2253 {
2254 same = rib;
2255 break;
2256 }
2257 if (same)
2258 break;
2259 }
paul718e3742002-12-13 20:15:29 +00002260 }
paul718e3742002-12-13 20:15:29 +00002261 /* If same type of route can't be found and this message is from
2262 kernel. */
2263 if (! same)
2264 {
2265 if (fib && type == ZEBRA_ROUTE_KERNEL)
2266 {
2267 /* Unset flags. */
2268 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2269 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2270
2271 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2272 }
2273 else
2274 {
2275 if (IS_ZEBRA_DEBUG_KERNEL)
2276 {
2277 if (gate)
ajsb6178002004-12-07 21:12:56 +00002278 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002279 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002280 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002281 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002282 ifindex,
2283 type);
2284 else
ajsb6178002004-12-07 21:12:56 +00002285 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002286 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002287 p->prefixlen,
2288 ifindex,
2289 type);
2290 }
2291 route_unlock_node (rn);
2292 return ZEBRA_ERR_RTNOEXIST;
2293 }
2294 }
paul4d38fdb2005-04-28 17:35:14 +00002295
paul718e3742002-12-13 20:15:29 +00002296 if (same)
2297 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002298
paul718e3742002-12-13 20:15:29 +00002299 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002300 return 0;
2301}
David Lamparter6b0655a2014-06-04 06:53:35 +02002302
paul718e3742002-12-13 20:15:29 +00002303/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002304static void
Everton Marques33d86db2014-07-14 11:19:00 -03002305static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002306{
2307 struct rib *rib;
2308 struct route_node *rn;
2309 struct route_table *table;
2310
2311 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002312 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002313 if (! table)
2314 return;
2315
2316 /* Lookup existing route */
2317 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002318 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002319 {
2320 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2321 continue;
2322
2323 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2324 break;
2325 }
paul718e3742002-12-13 20:15:29 +00002326
2327 if (rib)
2328 {
2329 /* Same distance static route is there. Update it with new
2330 nexthop. */
paul718e3742002-12-13 20:15:29 +00002331 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002332 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002333 {
2334 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002335 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002336 break;
2337 case STATIC_IPV4_IFNAME:
2338 nexthop_ifname_add (rib, si->gate.ifname);
2339 break;
2340 case STATIC_IPV4_BLACKHOLE:
2341 nexthop_blackhole_add (rib);
2342 break;
paul4d38fdb2005-04-28 17:35:14 +00002343 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002344 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002345 }
2346 else
2347 {
2348 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002349 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2350
paul718e3742002-12-13 20:15:29 +00002351 rib->type = ZEBRA_ROUTE_STATIC;
2352 rib->distance = si->distance;
2353 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002354 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002355 rib->nexthop_num = 0;
2356
2357 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002358 {
2359 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002360 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002361 break;
2362 case STATIC_IPV4_IFNAME:
2363 nexthop_ifname_add (rib, si->gate.ifname);
2364 break;
2365 case STATIC_IPV4_BLACKHOLE:
2366 nexthop_blackhole_add (rib);
2367 break;
2368 }
paul718e3742002-12-13 20:15:29 +00002369
hasso81dfcaa2003-05-25 19:21:25 +00002370 /* Save the flags of this static routes (reject, blackhole) */
2371 rib->flags = si->flags;
2372
paul718e3742002-12-13 20:15:29 +00002373 /* Link this rib to the tree. */
2374 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002375 }
2376}
2377
paula1ac18c2005-06-28 17:17:12 +00002378static int
paul718e3742002-12-13 20:15:29 +00002379static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2380{
2381 if (nexthop->type == NEXTHOP_TYPE_IPV4
2382 && si->type == STATIC_IPV4_GATEWAY
2383 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2384 return 1;
2385 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2386 && si->type == STATIC_IPV4_IFNAME
2387 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2388 return 1;
paul595db7f2003-05-25 21:35:06 +00002389 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2390 && si->type == STATIC_IPV4_BLACKHOLE)
2391 return 1;
paule8e19462006-01-19 20:16:55 +00002392 return 0;
paul718e3742002-12-13 20:15:29 +00002393}
2394
2395/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002396static void
Everton Marques33d86db2014-07-14 11:19:00 -03002397static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002398{
2399 struct route_node *rn;
2400 struct rib *rib;
2401 struct nexthop *nexthop;
2402 struct route_table *table;
2403
2404 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002405 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002406 if (! table)
2407 return;
paul4d38fdb2005-04-28 17:35:14 +00002408
paul718e3742002-12-13 20:15:29 +00002409 /* Lookup existing route with type and distance. */
2410 rn = route_node_lookup (table, p);
2411 if (! rn)
2412 return;
2413
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002414 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002415 {
2416 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2417 continue;
2418
2419 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2420 break;
2421 }
paul718e3742002-12-13 20:15:29 +00002422
2423 if (! rib)
2424 {
2425 route_unlock_node (rn);
2426 return;
2427 }
2428
2429 /* Lookup nexthop. */
2430 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2431 if (static_ipv4_nexthop_same (nexthop, si))
2432 break;
2433
2434 /* Can't find nexthop. */
2435 if (! nexthop)
2436 {
2437 route_unlock_node (rn);
2438 return;
2439 }
2440
2441 /* Check nexthop. */
2442 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002443 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002444 else
2445 {
paul6baeb982003-10-28 03:47:15 +00002446 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2447 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002448 nexthop_delete (rib, nexthop);
2449 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002450 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002451 }
paul718e3742002-12-13 20:15:29 +00002452 /* Unlock node. */
2453 route_unlock_node (rn);
2454}
2455
paul718e3742002-12-13 20:15:29 +00002456int
Everton Marques33d86db2014-07-14 11:19:00 -03002457static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2458 const char *ifname, u_char flags, u_char distance,
2459 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002460{
2461 u_char type = 0;
2462 struct route_node *rn;
2463 struct static_ipv4 *si;
2464 struct static_ipv4 *pp;
2465 struct static_ipv4 *cp;
2466 struct static_ipv4 *update = NULL;
2467 struct route_table *stable;
2468
2469 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002470 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002471 if (! stable)
2472 return -1;
2473
2474 /* Lookup static route prefix. */
2475 rn = route_node_get (stable, p);
2476
2477 /* Make flags. */
2478 if (gate)
2479 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002480 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002481 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002482 else
2483 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002484
2485 /* Do nothing if there is a same static route. */
2486 for (si = rn->info; si; si = si->next)
2487 {
2488 if (type == si->type
2489 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2490 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2491 {
2492 if (distance == si->distance)
2493 {
2494 route_unlock_node (rn);
2495 return 0;
2496 }
2497 else
2498 update = si;
2499 }
2500 }
2501
Paul Jakma3c0755d2006-12-08 00:53:14 +00002502 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002503 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002504 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002505
2506 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002507 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002508
2509 si->type = type;
2510 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002511 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002512
2513 if (gate)
2514 si->gate.ipv4 = *gate;
2515 if (ifname)
2516 si->gate.ifname = XSTRDUP (0, ifname);
2517
2518 /* Add new static route information to the tree with sort by
2519 distance value and gateway address. */
2520 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2521 {
2522 if (si->distance < cp->distance)
2523 break;
2524 if (si->distance > cp->distance)
2525 continue;
2526 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2527 {
2528 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2529 break;
2530 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2531 continue;
2532 }
2533 }
2534
2535 /* Make linked list. */
2536 if (pp)
2537 pp->next = si;
2538 else
2539 rn->info = si;
2540 if (cp)
2541 cp->prev = si;
2542 si->prev = pp;
2543 si->next = cp;
2544
2545 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002546 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002547
2548 return 1;
2549}
2550
paul718e3742002-12-13 20:15:29 +00002551int
Everton Marques33d86db2014-07-14 11:19:00 -03002552static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2553 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002554{
2555 u_char type = 0;
2556 struct route_node *rn;
2557 struct static_ipv4 *si;
2558 struct route_table *stable;
2559
2560 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002561 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002562 if (! stable)
2563 return -1;
2564
2565 /* Lookup static route prefix. */
2566 rn = route_node_lookup (stable, p);
2567 if (! rn)
2568 return 0;
2569
2570 /* Make flags. */
2571 if (gate)
2572 type = STATIC_IPV4_GATEWAY;
2573 else if (ifname)
2574 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002575 else
2576 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002577
2578 /* Find same static route is the tree */
2579 for (si = rn->info; si; si = si->next)
2580 if (type == si->type
2581 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2582 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2583 break;
2584
2585 /* Can't find static route. */
2586 if (! si)
2587 {
2588 route_unlock_node (rn);
2589 return 0;
2590 }
2591
2592 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002593 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002594
2595 /* Unlink static route from linked list. */
2596 if (si->prev)
2597 si->prev->next = si->next;
2598 else
2599 rn->info = si->next;
2600 if (si->next)
2601 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002602 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002603
2604 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002605 if (ifname)
2606 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002607 XFREE (MTYPE_STATIC_IPV4, si);
2608
paul143a3852003-09-29 20:06:13 +00002609 route_unlock_node (rn);
2610
paul718e3742002-12-13 20:15:29 +00002611 return 1;
2612}
2613
paul718e3742002-12-13 20:15:29 +00002614#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002615static int
paul718e3742002-12-13 20:15:29 +00002616rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2617 struct in6_addr *gate, unsigned int ifindex, int table)
2618{
hasso726f9b22003-05-25 21:04:54 +00002619 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2620#if defined (MUSICA) || defined (LINUX)
2621 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2622 if (p->prefixlen == 96)
2623 return 0;
2624#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002625 return 1;
hasso726f9b22003-05-25 21:04:54 +00002626 }
paul718e3742002-12-13 20:15:29 +00002627 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2628 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2629 {
2630 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2631 return 1;
2632 }
2633 return 0;
2634}
2635
2636int
2637rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002638 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002639 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002640{
2641 struct rib *rib;
2642 struct rib *same = NULL;
2643 struct route_table *table;
2644 struct route_node *rn;
2645 struct nexthop *nexthop;
2646
paul718e3742002-12-13 20:15:29 +00002647 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002648 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002649 if (! table)
2650 return 0;
2651
2652 /* Make sure mask is applied. */
2653 apply_mask_ipv6 (p);
2654
2655 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002656 if (!distance)
2657 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002658
2659 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2660 distance = 200;
2661
2662 /* Filter bogus route. */
2663 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2664 return 0;
2665
2666 /* Lookup route node.*/
2667 rn = route_node_get (table, (struct prefix *) p);
2668
2669 /* If same type of route are installed, treat it as a implicit
2670 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002671 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002672 {
Paul Jakma6d691122006-07-27 21:49:00 +00002673 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2674 continue;
2675
hassoebf1ead2005-09-21 14:58:20 +00002676 if (rib->type != type)
2677 continue;
2678 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002679 {
2680 same = rib;
paul718e3742002-12-13 20:15:29 +00002681 break;
2682 }
hassoebf1ead2005-09-21 14:58:20 +00002683 else if ((nexthop = rib->nexthop) &&
2684 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2685 nexthop->ifindex == ifindex)
2686 {
2687 rib->refcnt++;
2688 return 0;
2689 }
paul718e3742002-12-13 20:15:29 +00002690 }
2691
2692 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002693 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2694
paul718e3742002-12-13 20:15:29 +00002695 rib->type = type;
2696 rib->distance = distance;
2697 rib->flags = flags;
2698 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002699 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002700 rib->nexthop_num = 0;
2701 rib->uptime = time (NULL);
2702
2703 /* Nexthop settings. */
2704 if (gate)
2705 {
2706 if (ifindex)
2707 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2708 else
2709 nexthop_ipv6_add (rib, gate);
2710 }
2711 else
2712 nexthop_ifindex_add (rib, ifindex);
2713
2714 /* If this route is kernel route, set FIB flag to the route. */
2715 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2716 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2717 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2718
2719 /* Link new rib to node.*/
2720 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002721 if (IS_ZEBRA_DEBUG_RIB)
2722 {
2723 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2724 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002725 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002726 }
paul718e3742002-12-13 20:15:29 +00002727
paul718e3742002-12-13 20:15:29 +00002728 /* Free implicit route.*/
2729 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002730 {
2731 if (IS_ZEBRA_DEBUG_RIB)
2732 {
2733 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2734 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002735 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002736 }
paul4d38fdb2005-04-28 17:35:14 +00002737 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002738 }
paul4d38fdb2005-04-28 17:35:14 +00002739
2740 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002741 return 0;
2742}
2743
hassoebf1ead2005-09-21 14:58:20 +00002744/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002745int
2746rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002747 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002748{
2749 struct route_table *table;
2750 struct route_node *rn;
2751 struct rib *rib;
2752 struct rib *fib = NULL;
2753 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002754 struct nexthop *nexthop, *tnexthop;
2755 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002756 char buf1[INET6_ADDRSTRLEN];
2757 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002758
2759 /* Apply mask. */
2760 apply_mask_ipv6 (p);
2761
2762 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002763 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002764 if (! table)
2765 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002766
paul718e3742002-12-13 20:15:29 +00002767 /* Lookup route node. */
2768 rn = route_node_lookup (table, (struct prefix *) p);
2769 if (! rn)
2770 {
2771 if (IS_ZEBRA_DEBUG_KERNEL)
2772 {
2773 if (gate)
ajsb6178002004-12-07 21:12:56 +00002774 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002775 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002776 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002777 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002778 ifindex);
2779 else
ajsb6178002004-12-07 21:12:56 +00002780 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002781 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002782 p->prefixlen,
2783 ifindex);
2784 }
2785 return ZEBRA_ERR_RTNOEXIST;
2786 }
2787
2788 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002789 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002790 {
Paul Jakma6d691122006-07-27 21:49:00 +00002791 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2792 continue;
2793
paul718e3742002-12-13 20:15:29 +00002794 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2795 fib = rib;
2796
hassoebf1ead2005-09-21 14:58:20 +00002797 if (rib->type != type)
2798 continue;
2799 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002800 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002801 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002802 if (nexthop->ifindex != ifindex)
2803 continue;
hassoebf1ead2005-09-21 14:58:20 +00002804 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002805 {
hassoebf1ead2005-09-21 14:58:20 +00002806 rib->refcnt--;
2807 route_unlock_node (rn);
2808 route_unlock_node (rn);
2809 return 0;
paul718e3742002-12-13 20:15:29 +00002810 }
hassoebf1ead2005-09-21 14:58:20 +00002811 same = rib;
2812 break;
paul718e3742002-12-13 20:15:29 +00002813 }
hassoebf1ead2005-09-21 14:58:20 +00002814 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002815 else
2816 {
2817 if (gate == NULL)
2818 {
2819 same = rib;
2820 break;
2821 }
2822 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2823 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2824 {
2825 same = rib;
2826 break;
2827 }
2828 if (same)
2829 break;
2830 }
paul718e3742002-12-13 20:15:29 +00002831 }
2832
2833 /* If same type of route can't be found and this message is from
2834 kernel. */
2835 if (! same)
2836 {
2837 if (fib && type == ZEBRA_ROUTE_KERNEL)
2838 {
2839 /* Unset flags. */
2840 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2841 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2842
2843 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2844 }
2845 else
2846 {
2847 if (IS_ZEBRA_DEBUG_KERNEL)
2848 {
2849 if (gate)
ajsb6178002004-12-07 21:12:56 +00002850 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002851 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002852 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002853 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002854 ifindex,
2855 type);
2856 else
ajsb6178002004-12-07 21:12:56 +00002857 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002858 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002859 p->prefixlen,
2860 ifindex,
2861 type);
2862 }
2863 route_unlock_node (rn);
2864 return ZEBRA_ERR_RTNOEXIST;
2865 }
2866 }
2867
2868 if (same)
2869 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002870
paul718e3742002-12-13 20:15:29 +00002871 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002872 return 0;
2873}
David Lamparter6b0655a2014-06-04 06:53:35 +02002874
paul718e3742002-12-13 20:15:29 +00002875/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002876static void
paul718e3742002-12-13 20:15:29 +00002877static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2878{
2879 struct rib *rib;
2880 struct route_table *table;
2881 struct route_node *rn;
2882
2883 /* Lookup table. */
2884 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2885 if (! table)
2886 return;
2887
2888 /* Lookup existing route */
2889 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002890 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002891 {
2892 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2893 continue;
2894
2895 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2896 break;
2897 }
paul718e3742002-12-13 20:15:29 +00002898
2899 if (rib)
2900 {
2901 /* Same distance static route is there. Update it with new
2902 nexthop. */
paul718e3742002-12-13 20:15:29 +00002903 route_unlock_node (rn);
2904
2905 switch (si->type)
2906 {
2907 case STATIC_IPV6_GATEWAY:
2908 nexthop_ipv6_add (rib, &si->ipv6);
2909 break;
2910 case STATIC_IPV6_IFNAME:
2911 nexthop_ifname_add (rib, si->ifname);
2912 break;
2913 case STATIC_IPV6_GATEWAY_IFNAME:
2914 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2915 break;
2916 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002917 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002918 }
2919 else
2920 {
2921 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002922 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2923
paul718e3742002-12-13 20:15:29 +00002924 rib->type = ZEBRA_ROUTE_STATIC;
2925 rib->distance = si->distance;
2926 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002927 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002928 rib->nexthop_num = 0;
2929
2930 switch (si->type)
2931 {
2932 case STATIC_IPV6_GATEWAY:
2933 nexthop_ipv6_add (rib, &si->ipv6);
2934 break;
2935 case STATIC_IPV6_IFNAME:
2936 nexthop_ifname_add (rib, si->ifname);
2937 break;
2938 case STATIC_IPV6_GATEWAY_IFNAME:
2939 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2940 break;
2941 }
2942
hasso81dfcaa2003-05-25 19:21:25 +00002943 /* Save the flags of this static routes (reject, blackhole) */
2944 rib->flags = si->flags;
2945
paul718e3742002-12-13 20:15:29 +00002946 /* Link this rib to the tree. */
2947 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002948 }
2949}
2950
paula1ac18c2005-06-28 17:17:12 +00002951static int
paul718e3742002-12-13 20:15:29 +00002952static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2953{
2954 if (nexthop->type == NEXTHOP_TYPE_IPV6
2955 && si->type == STATIC_IPV6_GATEWAY
2956 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2957 return 1;
2958 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2959 && si->type == STATIC_IPV6_IFNAME
2960 && strcmp (nexthop->ifname, si->ifname) == 0)
2961 return 1;
2962 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2963 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2964 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2965 && strcmp (nexthop->ifname, si->ifname) == 0)
2966 return 1;
paule8e19462006-01-19 20:16:55 +00002967 return 0;
paul718e3742002-12-13 20:15:29 +00002968}
2969
paula1ac18c2005-06-28 17:17:12 +00002970static void
paul718e3742002-12-13 20:15:29 +00002971static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2972{
2973 struct route_table *table;
2974 struct route_node *rn;
2975 struct rib *rib;
2976 struct nexthop *nexthop;
2977
2978 /* Lookup table. */
2979 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2980 if (! table)
2981 return;
2982
2983 /* Lookup existing route with type and distance. */
2984 rn = route_node_lookup (table, (struct prefix *) p);
2985 if (! rn)
2986 return;
2987
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002988 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002989 {
2990 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2991 continue;
2992
2993 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2994 break;
2995 }
2996
paul718e3742002-12-13 20:15:29 +00002997 if (! rib)
2998 {
2999 route_unlock_node (rn);
3000 return;
3001 }
3002
3003 /* Lookup nexthop. */
3004 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3005 if (static_ipv6_nexthop_same (nexthop, si))
3006 break;
3007
3008 /* Can't find nexthop. */
3009 if (! nexthop)
3010 {
3011 route_unlock_node (rn);
3012 return;
3013 }
3014
3015 /* Check nexthop. */
3016 if (rib->nexthop_num == 1)
3017 {
3018 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003019 }
3020 else
3021 {
paul6baeb982003-10-28 03:47:15 +00003022 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3023 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003024 nexthop_delete (rib, nexthop);
3025 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003026 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003027 }
paul718e3742002-12-13 20:15:29 +00003028 /* Unlock node. */
3029 route_unlock_node (rn);
3030}
3031
3032/* Add static route into static route configuration. */
3033int
3034static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003035 const char *ifname, u_char flags, u_char distance,
3036 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003037{
3038 struct route_node *rn;
3039 struct static_ipv6 *si;
3040 struct static_ipv6 *pp;
3041 struct static_ipv6 *cp;
3042 struct route_table *stable;
3043
3044 /* Lookup table. */
3045 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3046 if (! stable)
3047 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003048
3049 if (!gate &&
3050 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3051 return -1;
3052
3053 if (!ifname &&
3054 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3055 return -1;
paul718e3742002-12-13 20:15:29 +00003056
3057 /* Lookup static route prefix. */
3058 rn = route_node_get (stable, p);
3059
3060 /* Do nothing if there is a same static route. */
3061 for (si = rn->info; si; si = si->next)
3062 {
3063 if (distance == si->distance
3064 && type == si->type
3065 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3066 && (! ifname || strcmp (ifname, si->ifname) == 0))
3067 {
3068 route_unlock_node (rn);
3069 return 0;
3070 }
3071 }
3072
3073 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003074 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003075
3076 si->type = type;
3077 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003078 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003079
3080 switch (type)
3081 {
3082 case STATIC_IPV6_GATEWAY:
3083 si->ipv6 = *gate;
3084 break;
3085 case STATIC_IPV6_IFNAME:
3086 si->ifname = XSTRDUP (0, ifname);
3087 break;
3088 case STATIC_IPV6_GATEWAY_IFNAME:
3089 si->ipv6 = *gate;
3090 si->ifname = XSTRDUP (0, ifname);
3091 break;
3092 }
3093
3094 /* Add new static route information to the tree with sort by
3095 distance value and gateway address. */
3096 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3097 {
3098 if (si->distance < cp->distance)
3099 break;
3100 if (si->distance > cp->distance)
3101 continue;
3102 }
3103
3104 /* Make linked list. */
3105 if (pp)
3106 pp->next = si;
3107 else
3108 rn->info = si;
3109 if (cp)
3110 cp->prev = si;
3111 si->prev = pp;
3112 si->next = cp;
3113
3114 /* Install into rib. */
3115 static_install_ipv6 (p, si);
3116
3117 return 1;
3118}
3119
3120/* Delete static route from static route configuration. */
3121int
3122static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003123 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003124{
3125 struct route_node *rn;
3126 struct static_ipv6 *si;
3127 struct route_table *stable;
3128
3129 /* Lookup table. */
3130 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3131 if (! stable)
3132 return -1;
3133
3134 /* Lookup static route prefix. */
3135 rn = route_node_lookup (stable, p);
3136 if (! rn)
3137 return 0;
3138
3139 /* Find same static route is the tree */
3140 for (si = rn->info; si; si = si->next)
3141 if (distance == si->distance
3142 && type == si->type
3143 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3144 && (! ifname || strcmp (ifname, si->ifname) == 0))
3145 break;
3146
3147 /* Can't find static route. */
3148 if (! si)
3149 {
3150 route_unlock_node (rn);
3151 return 0;
3152 }
3153
3154 /* Install into rib. */
3155 static_uninstall_ipv6 (p, si);
3156
3157 /* Unlink static route from linked list. */
3158 if (si->prev)
3159 si->prev->next = si->next;
3160 else
3161 rn->info = si->next;
3162 if (si->next)
3163 si->next->prev = si->prev;
3164
3165 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003166 if (ifname)
3167 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003168 XFREE (MTYPE_STATIC_IPV6, si);
3169
3170 return 1;
3171}
3172#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003173
paul718e3742002-12-13 20:15:29 +00003174/* RIB update function. */
3175void
paula1ac18c2005-06-28 17:17:12 +00003176rib_update (void)
paul718e3742002-12-13 20:15:29 +00003177{
3178 struct route_node *rn;
3179 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003180
paul718e3742002-12-13 20:15:29 +00003181 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3182 if (table)
3183 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003184 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003185 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003186
3187 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3188 if (table)
3189 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003190 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003191 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003192}
3193
David Lamparter6b0655a2014-06-04 06:53:35 +02003194
paul718e3742002-12-13 20:15:29 +00003195/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003196static void
paul718e3742002-12-13 20:15:29 +00003197rib_weed_table (struct route_table *table)
3198{
3199 struct route_node *rn;
3200 struct rib *rib;
3201 struct rib *next;
3202
3203 if (table)
3204 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003205 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003206 {
Paul Jakma6d691122006-07-27 21:49:00 +00003207 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3208 continue;
3209
paulb21b19c2003-06-15 01:28:29 +00003210 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003211 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003212 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003213 }
3214}
3215
3216/* Delete all routes from non main table. */
3217void
paula1ac18c2005-06-28 17:17:12 +00003218rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003219{
3220 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3221 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3222}
David Lamparter6b0655a2014-06-04 06:53:35 +02003223
paul718e3742002-12-13 20:15:29 +00003224/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003225static void
paul718e3742002-12-13 20:15:29 +00003226rib_sweep_table (struct route_table *table)
3227{
3228 struct route_node *rn;
3229 struct rib *rib;
3230 struct rib *next;
3231 int ret = 0;
3232
3233 if (table)
3234 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003235 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003236 {
Paul Jakma6d691122006-07-27 21:49:00 +00003237 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3238 continue;
3239
paul718e3742002-12-13 20:15:29 +00003240 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3241 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3242 {
3243 ret = rib_uninstall_kernel (rn, rib);
3244 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003245 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003246 }
3247 }
3248}
3249
3250/* Sweep all RIB tables. */
3251void
paula1ac18c2005-06-28 17:17:12 +00003252rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003253{
3254 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3255 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3256}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003257
3258/* Remove specific by protocol routes from 'table'. */
3259static unsigned long
3260rib_score_proto_table (u_char proto, struct route_table *table)
3261{
3262 struct route_node *rn;
3263 struct rib *rib;
3264 struct rib *next;
3265 unsigned long n = 0;
3266
3267 if (table)
3268 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003269 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003270 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003271 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3272 continue;
3273 if (rib->type == proto)
3274 {
3275 rib_delnode (rn, rib);
3276 n++;
3277 }
3278 }
3279
3280 return n;
3281}
3282
3283/* Remove specific by protocol routes. */
3284unsigned long
3285rib_score_proto (u_char proto)
3286{
3287 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3288 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3289}
3290
paul718e3742002-12-13 20:15:29 +00003291/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003292static void
paul718e3742002-12-13 20:15:29 +00003293rib_close_table (struct route_table *table)
3294{
3295 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003296 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003297 struct rib *rib;
3298
3299 if (table)
3300 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003301 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003302 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003303 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3304 continue;
3305
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003306 if (info->safi == SAFI_UNICAST)
3307 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003308
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003309 if (! RIB_SYSTEM_ROUTE (rib))
3310 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003311 }
paul718e3742002-12-13 20:15:29 +00003312}
3313
3314/* Close all RIB tables. */
3315void
paula1ac18c2005-06-28 17:17:12 +00003316rib_close (void)
paul718e3742002-12-13 20:15:29 +00003317{
3318 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3319 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3320}
David Lamparter6b0655a2014-06-04 06:53:35 +02003321
paul718e3742002-12-13 20:15:29 +00003322/* Routing information base initialize. */
3323void
paula1ac18c2005-06-28 17:17:12 +00003324rib_init (void)
paul718e3742002-12-13 20:15:29 +00003325{
paul4d38fdb2005-04-28 17:35:14 +00003326 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003327 /* VRF initialization. */
3328 vrf_init ();
3329}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003330
3331/*
3332 * vrf_id_get_next
3333 *
3334 * Get the first vrf id that is greater than the given vrf id if any.
3335 *
3336 * Returns TRUE if a vrf id was found, FALSE otherwise.
3337 */
3338static inline int
3339vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3340{
3341 while (++id < vector_active (vrf_vector))
3342 {
3343 if (vrf_lookup (id))
3344 {
3345 *next_id_p = id;
3346 return 1;
3347 }
3348 }
3349
3350 return 0;
3351}
3352
3353/*
3354 * rib_tables_iter_next
3355 *
3356 * Returns the next table in the iteration.
3357 */
3358struct route_table *
3359rib_tables_iter_next (rib_tables_iter_t *iter)
3360{
3361 struct route_table *table;
3362
3363 /*
3364 * Array that helps us go over all AFI/SAFI combinations via one
3365 * index.
3366 */
3367 static struct {
3368 afi_t afi;
3369 safi_t safi;
3370 } afi_safis[] = {
3371 { AFI_IP, SAFI_UNICAST },
3372 { AFI_IP, SAFI_MULTICAST },
3373 { AFI_IP6, SAFI_UNICAST },
3374 { AFI_IP6, SAFI_MULTICAST },
3375 };
3376
3377 table = NULL;
3378
3379 switch (iter->state)
3380 {
3381
3382 case RIB_TABLES_ITER_S_INIT:
3383 iter->vrf_id = 0;
3384 iter->afi_safi_ix = -1;
3385
3386 /* Fall through */
3387
3388 case RIB_TABLES_ITER_S_ITERATING:
3389 iter->afi_safi_ix++;
3390 while (1)
3391 {
3392
3393 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3394 {
3395 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3396 afi_safis[iter->afi_safi_ix].safi,
3397 iter->vrf_id);
3398 if (table)
3399 break;
3400
3401 iter->afi_safi_ix++;
3402 }
3403
3404 /*
3405 * Found another table in this vrf.
3406 */
3407 if (table)
3408 break;
3409
3410 /*
3411 * Done with all tables in the current vrf, go to the next
3412 * one.
3413 */
3414 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3415 break;
3416
3417 iter->afi_safi_ix = 0;
3418 }
3419
3420 break;
3421
3422 case RIB_TABLES_ITER_S_DONE:
3423 return NULL;
3424 }
3425
3426 if (table)
3427 iter->state = RIB_TABLES_ITER_S_ITERATING;
3428 else
3429 iter->state = RIB_TABLES_ITER_S_DONE;
3430
3431 return table;
3432}