blob: 5b9b00ed673781e7c6b942a1c5b9890499774d64 [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 Lampartere0b0ac82014-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 Lamparterf7b3d1e2015-01-22 19:02:13 +010092 rib_table_info_t *info = rn->table->info;
93
David Lampartere0b0ac82014-04-24 20:22:53 +020094 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
95 bptr = buf + strlen(buf);
David Lamparterf7b3d1e2015-01-22 19:02:13 +010096 snprintf(bptr, buf + sizeof(buf) - bptr, "/%d%s", rn->p.prefixlen,
97 info->safi == SAFI_MULTICAST ? " (MRIB)" : "");
David Lampartere0b0ac82014-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 *
722rib_match_ipv4 (struct in_addr addr)
723{
724 struct prefix_ipv4 p;
725 struct route_table *table;
726 struct route_node *rn;
727 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000728 struct nexthop *newhop, *tnewhop;
729 int recursing;
paul718e3742002-12-13 20:15:29 +0000730
731 /* Lookup table. */
732 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
733 if (! table)
734 return 0;
735
736 memset (&p, 0, sizeof (struct prefix_ipv4));
737 p.family = AF_INET;
738 p.prefixlen = IPV4_MAX_PREFIXLEN;
739 p.prefix = addr;
740
741 rn = route_node_match (table, (struct prefix *) &p);
742
743 while (rn)
744 {
745 route_unlock_node (rn);
746
747 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000748 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100749 {
750 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
751 continue;
752 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
753 break;
754 }
paul718e3742002-12-13 20:15:29 +0000755
756 /* If there is no selected route or matched route is EGP, go up
757 tree. */
758 if (! match
759 || match->type == ZEBRA_ROUTE_BGP)
760 {
761 do {
762 rn = rn->parent;
763 } while (rn && rn->info == NULL);
764 if (rn)
765 route_lock_node (rn);
766 }
767 else
768 {
769 if (match->type == ZEBRA_ROUTE_CONNECT)
770 /* Directly point connected route. */
771 return match;
772 else
773 {
Christian Frankefa713d92013-07-05 15:35:37 +0000774 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000775 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
776 return match;
777 return NULL;
778 }
779 }
780 }
781 return NULL;
782}
783
784struct rib *
Everton Marques346a8b52014-09-22 19:35:51 -0300785rib_match_ipv4_safi (struct in_addr addr, safi_t safi)
786{
787 struct route_table *table;
788 struct route_node *rn;
789 struct rib *match;
790 struct nexthop *newhop, *tnewhop;
791 int recursing;
792
793 /* Lookup table. */
794 table = vrf_table (AFI_IP, safi, 0);
795 if (! table)
796 return 0;
797
798 rn = route_node_match_ipv4 (table, &addr);
799
800 while (rn)
801 {
802 route_unlock_node (rn);
803
804 /* Pick up selected route. */
805 RNODE_FOREACH_RIB (rn, match)
806 {
807 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
808 continue;
809 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
810 break;
811 }
812
813 /* If there is no selected route or matched route is EGP, go up
814 tree. */
815 if (! match
816 || match->type == ZEBRA_ROUTE_BGP)
817 {
818 do {
819 rn = rn->parent;
820 } while (rn && rn->info == NULL);
821 if (rn)
822 route_lock_node (rn);
823 }
824 else
825 {
826 if (match->type == ZEBRA_ROUTE_CONNECT)
827 /* Directly point connected route. */
828 return match;
829 else
830 {
831 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
832 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
833 return match;
834 return NULL;
835 }
836 }
837 }
838 return NULL;
839}
840
841struct rib *
paul718e3742002-12-13 20:15:29 +0000842rib_lookup_ipv4 (struct prefix_ipv4 *p)
843{
844 struct route_table *table;
845 struct route_node *rn;
846 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000847 struct nexthop *nexthop, *tnexthop;
848 int recursing;
paul718e3742002-12-13 20:15:29 +0000849
850 /* Lookup table. */
851 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
852 if (! table)
853 return 0;
854
855 rn = route_node_lookup (table, (struct prefix *) p);
856
857 /* No route for this prefix. */
858 if (! rn)
859 return NULL;
860
861 /* Unlock node. */
862 route_unlock_node (rn);
863
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000864 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100865 {
866 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
867 continue;
868 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
869 break;
870 }
paul718e3742002-12-13 20:15:29 +0000871
872 if (! match || match->type == ZEBRA_ROUTE_BGP)
873 return NULL;
874
875 if (match->type == ZEBRA_ROUTE_CONNECT)
876 return match;
877
Christian Frankefa713d92013-07-05 15:35:37 +0000878 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000879 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
880 return match;
881
882 return NULL;
883}
884
Denis Ovsienkodc958242007-08-13 16:03:06 +0000885/*
886 * This clone function, unlike its original rib_lookup_ipv4(), checks
887 * if specified IPv4 route record (prefix/mask -> gate) exists in
888 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
889 *
890 * Return values:
891 * -1: error
892 * 0: exact match found
893 * 1: a match was found with a different gate
894 * 2: connected route found
895 * 3: no matches found
896 */
897int
898rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
899{
900 struct route_table *table;
901 struct route_node *rn;
902 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000903 struct nexthop *nexthop, *tnexthop;
904 int recursing;
905 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000906
907 /* Lookup table. */
908 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
909 if (! table)
910 return ZEBRA_RIB_LOOKUP_ERROR;
911
912 /* Scan the RIB table for exactly matching RIB entry. */
913 rn = route_node_lookup (table, (struct prefix *) p);
914
915 /* No route for this prefix. */
916 if (! rn)
917 return ZEBRA_RIB_NOTFOUND;
918
919 /* Unlock node. */
920 route_unlock_node (rn);
921
922 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000923 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100924 {
925 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
926 continue;
927 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
928 break;
929 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000930
931 /* None such found :( */
932 if (!match)
933 return ZEBRA_RIB_NOTFOUND;
934
935 if (match->type == ZEBRA_ROUTE_CONNECT)
936 return ZEBRA_RIB_FOUND_CONNECTED;
937
938 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000939 nexthops_active = 0;
940 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000941 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000942 {
Christian Frankefa713d92013-07-05 15:35:37 +0000943 nexthops_active = 1;
944 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
945 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000946 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000947 {
948 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
949 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
950 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
951 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
952 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
953 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000954 }
Christian Frankefa713d92013-07-05 15:35:37 +0000955
956 if (nexthops_active)
957 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000958
959 return ZEBRA_RIB_NOTFOUND;
960}
961
paul718e3742002-12-13 20:15:29 +0000962#ifdef HAVE_IPV6
963struct rib *
964rib_match_ipv6 (struct in6_addr *addr)
965{
966 struct prefix_ipv6 p;
967 struct route_table *table;
968 struct route_node *rn;
969 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000970 struct nexthop *newhop, *tnewhop;
971 int recursing;
paul718e3742002-12-13 20:15:29 +0000972
973 /* Lookup table. */
974 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
975 if (! table)
976 return 0;
977
978 memset (&p, 0, sizeof (struct prefix_ipv6));
979 p.family = AF_INET6;
980 p.prefixlen = IPV6_MAX_PREFIXLEN;
981 IPV6_ADDR_COPY (&p.prefix, addr);
982
983 rn = route_node_match (table, (struct prefix *) &p);
984
985 while (rn)
986 {
987 route_unlock_node (rn);
988
989 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000990 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100991 {
992 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
993 continue;
994 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
995 break;
996 }
paul718e3742002-12-13 20:15:29 +0000997
998 /* If there is no selected route or matched route is EGP, go up
999 tree. */
1000 if (! match
1001 || match->type == ZEBRA_ROUTE_BGP)
1002 {
1003 do {
1004 rn = rn->parent;
1005 } while (rn && rn->info == NULL);
1006 if (rn)
1007 route_lock_node (rn);
1008 }
1009 else
1010 {
1011 if (match->type == ZEBRA_ROUTE_CONNECT)
1012 /* Directly point connected route. */
1013 return match;
1014 else
1015 {
Christian Frankefa713d92013-07-05 15:35:37 +00001016 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +00001017 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1018 return match;
1019 return NULL;
1020 }
1021 }
1022 }
1023 return NULL;
1024}
1025#endif /* HAVE_IPV6 */
1026
Paul Jakma7514fb72007-05-02 16:05:35 +00001027#define RIB_SYSTEM_ROUTE(R) \
1028 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
1029
Denis Ovsienkodc958242007-08-13 16:03:06 +00001030/* This function verifies reachability of one given nexthop, which can be
1031 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
1032 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
1033 * nexthop->ifindex will be updated appropriately as well.
1034 * An existing route map can turn (otherwise active) nexthop into inactive, but
1035 * not vice versa.
1036 *
1037 * The return value is the final value of 'ACTIVE' flag.
1038 */
1039
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001040static unsigned
paul718e3742002-12-13 20:15:29 +00001041nexthop_active_check (struct route_node *rn, struct rib *rib,
1042 struct nexthop *nexthop, int set)
1043{
Christian Frankef3a17322013-07-05 15:35:41 +00001044 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +00001045 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +00001046 route_map_result_t ret = RMAP_MATCH;
1047 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
1048 struct route_map *rmap;
1049 int family;
paul718e3742002-12-13 20:15:29 +00001050
Paul Jakma7514fb72007-05-02 16:05:35 +00001051 family = 0;
paul718e3742002-12-13 20:15:29 +00001052 switch (nexthop->type)
1053 {
1054 case NEXTHOP_TYPE_IFINDEX:
1055 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001056 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001057 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1058 else
1059 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1060 break;
paul718e3742002-12-13 20:15:29 +00001061 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001062 family = AFI_IP6;
1063 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001064 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001065 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001066 {
1067 if (set)
1068 nexthop->ifindex = ifp->ifindex;
1069 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1070 }
1071 else
1072 {
1073 if (set)
1074 nexthop->ifindex = 0;
1075 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1076 }
1077 break;
1078 case NEXTHOP_TYPE_IPV4:
1079 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001080 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001081 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1082 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1083 else
1084 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1085 break;
1086#ifdef HAVE_IPV6
1087 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001088 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001089 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1090 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1091 else
1092 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1093 break;
1094 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001095 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001096 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1097 {
1098 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001099 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001100 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1101 else
1102 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1103 }
1104 else
1105 {
1106 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1107 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1108 else
1109 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1110 }
1111 break;
1112#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001113 case NEXTHOP_TYPE_BLACKHOLE:
1114 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1115 break;
paul718e3742002-12-13 20:15:29 +00001116 default:
1117 break;
1118 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001119 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1120 return 0;
1121
Christian Frankef3a17322013-07-05 15:35:41 +00001122 /* XXX: What exactly do those checks do? Do we support
1123 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001124 if (RIB_SYSTEM_ROUTE(rib) ||
1125 (family == AFI_IP && rn->p.family != AF_INET) ||
1126 (family == AFI_IP6 && rn->p.family != AF_INET6))
1127 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1128
Christian Frankef3a17322013-07-05 15:35:41 +00001129 /* The original code didn't determine the family correctly
1130 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1131 * from the rib_table_info in those cases.
1132 * Possibly it may be better to use only the rib_table_info
1133 * in every case.
1134 */
1135 if (!family)
1136 family = info->afi;
1137
Paul Jakma7514fb72007-05-02 16:05:35 +00001138 rmap = 0;
1139 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1140 proto_rm[family][rib->type])
1141 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1142 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1143 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1144 if (rmap) {
1145 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1146 }
1147
1148 if (ret == RMAP_DENYMATCH)
1149 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001150 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1151}
1152
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001153/* Iterate over all nexthops of the given RIB entry and refresh their
1154 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1155 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1156 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1157 * transparently passed to nexthop_active_check().
1158 *
1159 * Return value is the new number of active nexthops.
1160 */
1161
paula1ac18c2005-06-28 17:17:12 +00001162static int
paul718e3742002-12-13 20:15:29 +00001163nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1164{
1165 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001166 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001167
1168 rib->nexthop_active_num = 0;
1169 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1170
1171 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001172 {
1173 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001174 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001175 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1176 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001177 if (prev_active != new_active ||
1178 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001179 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1180 }
paul718e3742002-12-13 20:15:29 +00001181 return rib->nexthop_active_num;
1182}
paul6baeb982003-10-28 03:47:15 +00001183
David Lamparter6b0655a2014-06-04 06:53:35 +02001184
paul718e3742002-12-13 20:15:29 +00001185
paula1ac18c2005-06-28 17:17:12 +00001186static void
paul718e3742002-12-13 20:15:29 +00001187rib_install_kernel (struct route_node *rn, struct rib *rib)
1188{
1189 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001190 struct nexthop *nexthop, *tnexthop;
1191 int recursing;
paul718e3742002-12-13 20:15:29 +00001192
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001193 /*
1194 * Make sure we update the FPM any time we send new information to
1195 * the kernel.
1196 */
1197 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001198 switch (PREFIX_FAMILY (&rn->p))
1199 {
1200 case AF_INET:
1201 ret = kernel_add_ipv4 (&rn->p, rib);
1202 break;
1203#ifdef HAVE_IPV6
1204 case AF_INET6:
1205 ret = kernel_add_ipv6 (&rn->p, rib);
1206 break;
1207#endif /* HAVE_IPV6 */
1208 }
1209
Denis Ovsienkodc958242007-08-13 16:03:06 +00001210 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001211 if (ret < 0)
1212 {
Christian Frankefa713d92013-07-05 15:35:37 +00001213 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001214 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1215 }
1216}
1217
1218/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001219static int
paul718e3742002-12-13 20:15:29 +00001220rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1221{
1222 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001223 struct nexthop *nexthop, *tnexthop;
1224 int recursing;
paul718e3742002-12-13 20:15:29 +00001225
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001226 /*
1227 * Make sure we update the FPM any time we send new information to
1228 * the kernel.
1229 */
1230 zfpm_trigger_update (rn, "uninstalling from kernel");
1231
paul718e3742002-12-13 20:15:29 +00001232 switch (PREFIX_FAMILY (&rn->p))
1233 {
1234 case AF_INET:
1235 ret = kernel_delete_ipv4 (&rn->p, rib);
1236 break;
1237#ifdef HAVE_IPV6
1238 case AF_INET6:
1239 ret = kernel_delete_ipv6 (&rn->p, rib);
1240 break;
1241#endif /* HAVE_IPV6 */
1242 }
1243
Christian Frankefa713d92013-07-05 15:35:37 +00001244 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001245 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1246
1247 return ret;
1248}
1249
1250/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001251static void
paul718e3742002-12-13 20:15:29 +00001252rib_uninstall (struct route_node *rn, struct rib *rib)
1253{
1254 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1255 {
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001256 zfpm_trigger_update (rn, "rib_uninstall");
1257
paul718e3742002-12-13 20:15:29 +00001258 redistribute_delete (&rn->p, rib);
1259 if (! RIB_SYSTEM_ROUTE (rib))
1260 rib_uninstall_kernel (rn, rib);
1261 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1262 }
1263}
1264
Paul Jakma6d691122006-07-27 21:49:00 +00001265static void rib_unlink (struct route_node *, struct rib *);
1266
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001267/*
1268 * rib_can_delete_dest
1269 *
1270 * Returns TRUE if the given dest can be deleted from the table.
1271 */
1272static int
1273rib_can_delete_dest (rib_dest_t *dest)
1274{
1275 if (dest->routes)
1276 {
1277 return 0;
1278 }
1279
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001280 /*
1281 * Don't delete the dest if we have to update the FPM about this
1282 * prefix.
1283 */
1284 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1285 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1286 return 0;
1287
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001288 return 1;
1289}
1290
1291/*
1292 * rib_gc_dest
1293 *
1294 * Garbage collect the rib dest corresponding to the given route node
1295 * if appropriate.
1296 *
1297 * Returns TRUE if the dest was deleted, FALSE otherwise.
1298 */
1299int
1300rib_gc_dest (struct route_node *rn)
1301{
1302 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001303
1304 dest = rib_dest_from_rnode (rn);
1305 if (!dest)
1306 return 0;
1307
1308 if (!rib_can_delete_dest (dest))
1309 return 0;
1310
1311 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001312 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001313
1314 dest->rnode = NULL;
1315 XFREE (MTYPE_RIB_DEST, dest);
1316 rn->info = NULL;
1317
1318 /*
1319 * Release the one reference that we keep on the route node.
1320 */
1321 route_unlock_node (rn);
1322 return 1;
1323}
1324
paul718e3742002-12-13 20:15:29 +00001325/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001326static void
1327rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001328{
1329 struct rib *rib;
1330 struct rib *next;
1331 struct rib *fib = NULL;
1332 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001333 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001334 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001335 struct nexthop *nexthop = NULL, *tnexthop;
1336 int recursing;
Balaji95116332014-10-23 15:25:25 +00001337 rib_table_info_t *info;
1338
paul4d38fdb2005-04-28 17:35:14 +00001339 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001340
1341 info = rn->table->info;
1342
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001343 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001344 {
paul718e3742002-12-13 20:15:29 +00001345 /* Currently installed rib. */
1346 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001347 {
1348 assert (fib == NULL);
1349 fib = rib;
1350 }
1351
1352 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1353 * which we need to do do further work with below.
1354 */
1355 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1356 {
1357 if (rib != fib)
1358 {
1359 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001360 rnode_debug (rn, "rn %p, removing rib %p", rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001361 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001362 }
1363 else
1364 del = rib;
1365
1366 continue;
1367 }
paul4d38fdb2005-04-28 17:35:14 +00001368
paul718e3742002-12-13 20:15:29 +00001369 /* Skip unreachable nexthop. */
1370 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001371 continue;
paul718e3742002-12-13 20:15:29 +00001372
Balaji95116332014-10-23 15:25:25 +00001373 if (info->safi == SAFI_MULTICAST)
1374 continue;
1375
paul718e3742002-12-13 20:15:29 +00001376 /* Infinit distance. */
1377 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001378 continue;
paul718e3742002-12-13 20:15:29 +00001379
paulaf887b52006-01-18 14:52:52 +00001380 /* Newly selected rib, the common case. */
1381 if (!select)
1382 {
1383 select = rib;
1384 continue;
1385 }
1386
1387 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001388 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001389 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001390 * - lower metric beats higher for equal distance
1391 * - last, hence oldest, route wins tie break.
1392 */
paula1038a12006-01-30 14:08:51 +00001393
1394 /* Connected routes. Pick the last connected
1395 * route of the set of lowest metric connected routes.
1396 */
paula8d9c1f2006-01-25 06:31:04 +00001397 if (rib->type == ZEBRA_ROUTE_CONNECT)
1398 {
paula1038a12006-01-30 14:08:51 +00001399 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001400 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001401 select = rib;
1402 continue;
paula8d9c1f2006-01-25 06:31:04 +00001403 }
1404 else if (select->type == ZEBRA_ROUTE_CONNECT)
1405 continue;
1406
1407 /* higher distance loses */
1408 if (rib->distance > select->distance)
1409 continue;
1410
1411 /* lower wins */
1412 if (rib->distance < select->distance)
1413 {
paulaf887b52006-01-18 14:52:52 +00001414 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001415 continue;
1416 }
1417
1418 /* metric tie-breaks equal distance */
1419 if (rib->metric <= select->metric)
1420 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001421 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001422
1423 /* After the cycle is finished, the following pointers will be set:
1424 * select --- the winner RIB entry, if any was found, otherwise NULL
1425 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1426 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1427 * rib --- NULL
1428 */
1429
1430 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001431 if (select && select == fib)
1432 {
Paul Jakma6d691122006-07-27 21:49:00 +00001433 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001434 rnode_debug (rn, "Updating existing route, select %p, fib %p",
1435 select, fib);
paul718e3742002-12-13 20:15:29 +00001436 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001437 {
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001438 zfpm_trigger_update (rn, "updating existing route");
1439
paul4d38fdb2005-04-28 17:35:14 +00001440 redistribute_delete (&rn->p, select);
1441 if (! RIB_SYSTEM_ROUTE (select))
1442 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001443
paul4d38fdb2005-04-28 17:35:14 +00001444 /* Set real nexthop. */
1445 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001446
paul4d38fdb2005-04-28 17:35:14 +00001447 if (! RIB_SYSTEM_ROUTE (select))
1448 rib_install_kernel (rn, select);
1449 redistribute_add (&rn->p, select);
1450 }
pauld753e9e2003-01-22 19:45:50 +00001451 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001452 {
1453 /* Housekeeping code to deal with
1454 race conditions in kernel with linux
1455 netlink reporting interface up before IPv4 or IPv6 protocol
1456 is ready to add routes.
1457 This makes sure the routes are IN the kernel.
1458 */
pauld753e9e2003-01-22 19:45:50 +00001459
Christian Frankefa713d92013-07-05 15:35:37 +00001460 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001461 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001462 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001463 installed = 1;
1464 break;
paul4d38fdb2005-04-28 17:35:14 +00001465 }
1466 if (! installed)
1467 rib_install_kernel (rn, select);
1468 }
Paul Jakma6d691122006-07-27 21:49:00 +00001469 goto end;
paul718e3742002-12-13 20:15:29 +00001470 }
1471
Denis Ovsienkodc958242007-08-13 16:03:06 +00001472 /* At this point we either haven't found the best RIB entry or it is
1473 * different from what we currently intend to flag with SELECTED. In both
1474 * cases, if a RIB block is present in FIB, it should be withdrawn.
1475 */
paul718e3742002-12-13 20:15:29 +00001476 if (fib)
1477 {
Paul Jakma6d691122006-07-27 21:49:00 +00001478 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001479 rnode_debug (rn, "Removing existing route, fib %p", fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001480
1481 zfpm_trigger_update (rn, "removing existing route");
1482
paul718e3742002-12-13 20:15:29 +00001483 redistribute_delete (&rn->p, fib);
1484 if (! RIB_SYSTEM_ROUTE (fib))
1485 rib_uninstall_kernel (rn, fib);
1486 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1487
1488 /* Set real nexthop. */
1489 nexthop_active_update (rn, fib, 1);
1490 }
1491
Denis Ovsienkodc958242007-08-13 16:03:06 +00001492 /* Regardless of some RIB entry being SELECTED or not before, now we can
1493 * tell, that if a new winner exists, FIB is still not updated with this
1494 * data, but ready to be.
1495 */
paul718e3742002-12-13 20:15:29 +00001496 if (select)
1497 {
Paul Jakma6d691122006-07-27 21:49:00 +00001498 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001499 rnode_debug (rn, "Adding route, select %p", select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001500
1501 zfpm_trigger_update (rn, "new route selected");
1502
paul718e3742002-12-13 20:15:29 +00001503 /* Set real nexthop. */
1504 nexthop_active_update (rn, select, 1);
1505
1506 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001507 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001508 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1509 redistribute_add (&rn->p, select);
1510 }
paul4d38fdb2005-04-28 17:35:14 +00001511
Paul Jakma6d691122006-07-27 21:49:00 +00001512 /* FIB route was removed, should be deleted */
1513 if (del)
1514 {
1515 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001516 rnode_debug (rn, "Deleting fib %p, rn %p", del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001517 rib_unlink (rn, del);
1518 }
paul4d38fdb2005-04-28 17:35:14 +00001519
Paul Jakma6d691122006-07-27 21:49:00 +00001520end:
1521 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001522 rnode_debug (rn, "rn %p dequeued", rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001523
1524 /*
1525 * Check if the dest can be deleted now.
1526 */
1527 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001528}
1529
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001530/* Take a list of route_node structs and return 1, if there was a record
1531 * picked from it and processed by rib_process(). Don't process more,
1532 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001533 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001534static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001535process_subq (struct list * subq, u_char qindex)
1536{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001537 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001538 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001539
1540 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001541 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001542
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001543 rnode = listgetdata (lnode);
1544 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001545
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001546 if (rnode->info)
1547 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1548
Chris Caputo67b94672009-07-18 04:02:26 +00001549#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001550 else
1551 {
1552 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1553 __func__, rnode, rnode->lock);
1554 zlog_backtrace(LOG_DEBUG);
1555 }
Chris Caputo67b94672009-07-18 04:02:26 +00001556#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001557 route_unlock_node (rnode);
1558 list_delete_node (subq, lnode);
1559 return 1;
1560}
1561
1562/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1563 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1564 * is pointed to the meta queue structure.
1565 */
1566static wq_item_status
1567meta_queue_process (struct work_queue *dummy, void *data)
1568{
1569 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001570 unsigned i;
1571
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001572 for (i = 0; i < MQ_SIZE; i++)
1573 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001574 {
1575 mq->size--;
1576 break;
1577 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001578 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1579}
1580
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001581/*
1582 * Map from rib types to queue type (priority) in meta queue
1583 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001584static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1585 [ZEBRA_ROUTE_SYSTEM] = 4,
1586 [ZEBRA_ROUTE_KERNEL] = 0,
1587 [ZEBRA_ROUTE_CONNECT] = 0,
1588 [ZEBRA_ROUTE_STATIC] = 1,
1589 [ZEBRA_ROUTE_RIP] = 2,
1590 [ZEBRA_ROUTE_RIPNG] = 2,
1591 [ZEBRA_ROUTE_OSPF] = 2,
1592 [ZEBRA_ROUTE_OSPF6] = 2,
1593 [ZEBRA_ROUTE_ISIS] = 2,
1594 [ZEBRA_ROUTE_BGP] = 3,
1595 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001596 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001597};
1598
1599/* Look into the RN and queue it into one or more priority queues,
1600 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001601 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001602static void
1603rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001604{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001605 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001606
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001607 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001608 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001609 u_char qindex = meta_queue_map[rib->type];
1610
1611 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001612 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1613 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001614 {
1615 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001616 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
1617 rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001618 continue;
1619 }
1620
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001621 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001622 listnode_add (mq->subq[qindex], rn);
1623 route_lock_node (rn);
1624 mq->size++;
1625
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001626 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001627 rnode_debug (rn, "queued rn %p into sub-queue %u",
1628 rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001629 }
paul4d38fdb2005-04-28 17:35:14 +00001630}
1631
Paul Jakma6d691122006-07-27 21:49:00 +00001632/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001633static void
Paul Jakma6d691122006-07-27 21:49:00 +00001634rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001635{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001636 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001637
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001638 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001639 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001640 {
1641 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1642 __func__, rn, rn->lock);
1643 zlog_backtrace(LOG_DEBUG);
1644 return;
1645 }
1646
1647 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001648 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001649
1650 assert (zebra);
1651
1652 if (zebra->ribq == NULL)
1653 {
1654 zlog_err ("%s: work_queue does not exist!", __func__);
1655 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001656 }
paul4d38fdb2005-04-28 17:35:14 +00001657
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001658 /*
1659 * The RIB queue should normally be either empty or holding the only
1660 * work_queue_item element. In the latter case this element would
1661 * hold a pointer to the meta queue structure, which must be used to
1662 * actually queue the route nodes to process. So create the MQ
1663 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001664 * This semantics was introduced after 0.99.9 release.
1665 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001666 if (!zebra->ribq->items->count)
1667 work_queue_add (zebra->ribq, zebra->mq);
1668
1669 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001670
1671 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001672 rnode_debug (rn, "rn %p queued", rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001673
1674 return;
paul4d38fdb2005-04-28 17:35:14 +00001675}
1676
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001677/* Create new meta queue.
1678 A destructor function doesn't seem to be necessary here.
1679 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001680static struct meta_queue *
1681meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001682{
1683 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001684 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001685
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001686 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1687 assert(new);
1688
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001689 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001690 {
1691 new->subq[i] = list_new ();
1692 assert(new->subq[i]);
1693 }
1694
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001695 return new;
1696}
1697
paul4d38fdb2005-04-28 17:35:14 +00001698/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001699static void
paul4d38fdb2005-04-28 17:35:14 +00001700rib_queue_init (struct zebra_t *zebra)
1701{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001702 assert (zebra);
1703
paul4d38fdb2005-04-28 17:35:14 +00001704 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001705 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001706 {
Paul Jakma6d691122006-07-27 21:49:00 +00001707 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001708 return;
1709 }
1710
1711 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001712 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001713 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001714 /* XXX: TODO: These should be runtime configurable via vty */
1715 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001716 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001717
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001718 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001719 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001720 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001721 return;
1722 }
1723 return;
paul718e3742002-12-13 20:15:29 +00001724}
1725
Paul Jakma6d691122006-07-27 21:49:00 +00001726/* RIB updates are processed via a queue of pointers to route_nodes.
1727 *
1728 * The queue length is bounded by the maximal size of the routing table,
1729 * as a route_node will not be requeued, if already queued.
1730 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001731 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1732 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1733 * and then submit route_node to queue for best-path selection later.
1734 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001735 *
1736 * Deleted RIBs are reaped during best-path selection.
1737 *
1738 * rib_addnode
1739 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001740 * |-------->| | best RIB, if required
1741 * | |
1742 * static_install->|->rib_addqueue...... -> rib_process
1743 * | |
1744 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001745 * |-> set RIB_ENTRY_REMOVE |
1746 * rib_delnode (RIB freed)
1747 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001748 * The 'info' pointer of a route_node points to a rib_dest_t
1749 * ('dest'). Queueing state for a route_node is kept on the dest. The
1750 * dest is created on-demand by rib_link() and is kept around at least
1751 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001752 *
1753 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1754 *
1755 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001756 * - dest attached to route_node:
1757 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001758 * - route_node processing queue
1759 * - managed by: rib_addqueue, rib_process.
1760 *
1761 */
1762
paul718e3742002-12-13 20:15:29 +00001763/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001764static void
Paul Jakma6d691122006-07-27 21:49:00 +00001765rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001766{
1767 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001768 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001769
paul4d38fdb2005-04-28 17:35:14 +00001770 assert (rib && rn);
1771
Paul Jakma6d691122006-07-27 21:49:00 +00001772 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001773 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001774
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001775 dest = rib_dest_from_rnode (rn);
1776 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001777 {
1778 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001779 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001780
1781 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1782 route_lock_node (rn); /* rn route table reference */
1783 rn->info = dest;
1784 dest->rnode = rn;
1785 }
1786
1787 head = dest->routes;
1788 if (head)
1789 {
Paul Jakma6d691122006-07-27 21:49:00 +00001790 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001791 }
paul718e3742002-12-13 20:15:29 +00001792 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001793 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001794 rib_queue_add (&zebrad, rn);
1795}
1796
1797static void
1798rib_addnode (struct route_node *rn, struct rib *rib)
1799{
1800 /* RIB node has been un-removed before route-node is processed.
1801 * route_node must hence already be on the queue for processing..
1802 */
1803 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1804 {
1805 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001806 rnode_debug (rn, "rn %p, un-removed rib %p", rn, rib);
1807
Paul Jakma6d691122006-07-27 21:49:00 +00001808 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1809 return;
1810 }
1811 rib_link (rn, rib);
1812}
1813
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001814/*
1815 * rib_unlink
1816 *
1817 * Detach a rib structure from a route_node.
1818 *
1819 * Note that a call to rib_unlink() should be followed by a call to
1820 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1821 * longer required to be deleted.
1822 */
Paul Jakma6d691122006-07-27 21:49:00 +00001823static void
1824rib_unlink (struct route_node *rn, struct rib *rib)
1825{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001826 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001827
1828 assert (rn && rib);
1829
1830 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001831 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001832
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001833 dest = rib_dest_from_rnode (rn);
1834
Paul Jakma6d691122006-07-27 21:49:00 +00001835 if (rib->next)
1836 rib->next->prev = rib->prev;
1837
1838 if (rib->prev)
1839 rib->prev->next = rib->next;
1840 else
1841 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001842 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001843 }
1844
1845 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001846 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001847 XFREE (MTYPE_RIB, rib);
1848
paul718e3742002-12-13 20:15:29 +00001849}
1850
paula1ac18c2005-06-28 17:17:12 +00001851static void
paul718e3742002-12-13 20:15:29 +00001852rib_delnode (struct route_node *rn, struct rib *rib)
1853{
Paul Jakma6d691122006-07-27 21:49:00 +00001854 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001855 rnode_debug (rn, "rn %p, rib %p, removing", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001856 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1857 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001858}
1859
1860int
1861rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001862 struct in_addr *gate, struct in_addr *src,
1863 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001864 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001865{
1866 struct rib *rib;
1867 struct rib *same = NULL;
1868 struct route_table *table;
1869 struct route_node *rn;
1870 struct nexthop *nexthop;
1871
1872 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001873 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001874 if (! table)
1875 return 0;
1876
1877 /* Make it sure prefixlen is applied to the prefix. */
1878 apply_mask_ipv4 (p);
1879
1880 /* Set default distance by route type. */
1881 if (distance == 0)
1882 {
Balaji.G837d16c2012-09-26 14:09:10 +05301883 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001884 distance = 150;
1885 else
1886 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001887
1888 /* iBGP distance is 200. */
1889 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1890 distance = 200;
1891 }
1892
1893 /* Lookup route node.*/
1894 rn = route_node_get (table, (struct prefix *) p);
1895
1896 /* If same type of route are installed, treat it as a implicit
1897 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001898 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001899 {
Paul Jakma6d691122006-07-27 21:49:00 +00001900 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1901 continue;
1902
hassoebf1ead2005-09-21 14:58:20 +00001903 if (rib->type != type)
1904 continue;
1905 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001906 {
1907 same = rib;
1908 break;
1909 }
hassoebf1ead2005-09-21 14:58:20 +00001910 /* Duplicate connected route comes in. */
1911 else if ((nexthop = rib->nexthop) &&
1912 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001913 nexthop->ifindex == ifindex &&
1914 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001915 {
1916 rib->refcnt++;
1917 return 0 ;
1918 }
paul718e3742002-12-13 20:15:29 +00001919 }
1920
1921 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001922 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001923 rib->type = type;
1924 rib->distance = distance;
1925 rib->flags = flags;
1926 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001927 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001928 rib->nexthop_num = 0;
1929 rib->uptime = time (NULL);
1930
1931 /* Nexthop settings. */
1932 if (gate)
1933 {
1934 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001935 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001936 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001937 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001938 }
1939 else
1940 nexthop_ifindex_add (rib, ifindex);
1941
1942 /* If this route is kernel route, set FIB flag to the route. */
1943 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1944 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1945 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1946
1947 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001948 if (IS_ZEBRA_DEBUG_RIB)
1949 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001950 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001951
paul718e3742002-12-13 20:15:29 +00001952 /* Free implicit route.*/
1953 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001954 {
1955 if (IS_ZEBRA_DEBUG_RIB)
1956 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001957 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001958 }
paul4d38fdb2005-04-28 17:35:14 +00001959
1960 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001961 return 0;
1962}
1963
Denis Ovsienkodc958242007-08-13 16:03:06 +00001964/* This function dumps the contents of a given RIB entry into
1965 * standard debug log. Calling function name and IP prefix in
1966 * question are passed as 1st and 2nd arguments.
1967 */
1968
David Lamparterf7bf4152013-10-22 17:10:21 +00001969void _rib_dump (const char * func,
1970 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001971{
David Lamparterf7bf4152013-10-22 17:10:21 +00001972 const struct prefix *p = pp.p;
Vincent Bernatfed643f2012-10-23 16:00:42 +00001973 char straddr[INET6_ADDRSTRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001974 struct nexthop *nexthop, *tnexthop;
1975 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001976
Vincent Bernatfed643f2012-10-23 16:00:42 +00001977 inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001978 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001979 zlog_debug
1980 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001981 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001982 func,
1983 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001984 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001985 rib->type,
1986 rib->table
1987 );
1988 zlog_debug
1989 (
1990 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1991 func,
1992 rib->metric,
1993 rib->distance,
1994 rib->flags,
1995 rib->status
1996 );
1997 zlog_debug
1998 (
1999 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
2000 func,
2001 rib->nexthop_num,
2002 rib->nexthop_active_num,
2003 rib->nexthop_fib_num
2004 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00002005
Christian Frankefa713d92013-07-05 15:35:37 +00002006 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2007 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00002008 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002009 zlog_debug
2010 (
2011 "%s: %s %s with flags %s%s%s",
2012 func,
2013 (recursing ? " NH" : "NH"),
2014 straddr,
2015 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
2016 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
2017 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
2018 );
2019 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00002020 zlog_debug ("%s: dump complete", func);
2021}
2022
2023/* This is an exported helper to rtm_read() to dump the strange
2024 * RIB entry found by rib_lookup_ipv4_route()
2025 */
2026
2027void rib_lookup_and_dump (struct prefix_ipv4 * p)
2028{
2029 struct route_table *table;
2030 struct route_node *rn;
2031 struct rib *rib;
2032 char prefix_buf[INET_ADDRSTRLEN];
2033
2034 /* Lookup table. */
2035 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2036 if (! table)
2037 {
2038 zlog_err ("%s: vrf_table() returned NULL", __func__);
2039 return;
2040 }
2041
2042 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
2043 /* Scan the RIB table for exactly matching RIB entry. */
2044 rn = route_node_lookup (table, (struct prefix *) p);
2045
2046 /* No route for this prefix. */
2047 if (! rn)
2048 {
2049 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
2050 return;
2051 }
2052
2053 /* Unlock node. */
2054 route_unlock_node (rn);
2055
2056 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002057 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002058 {
2059 zlog_debug
2060 (
2061 "%s: rn %p, rib %p: %s, %s",
2062 __func__,
2063 rn,
2064 rib,
2065 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2066 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2067 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002068 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002069 }
2070}
2071
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002072/* Check if requested address assignment will fail due to another
2073 * route being installed by zebra in FIB already. Take necessary
2074 * actions, if needed: remove such a route from FIB and deSELECT
2075 * corresponding RIB entry. Then put affected RN into RIBQ head.
2076 */
2077void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2078{
2079 struct route_table *table;
2080 struct route_node *rn;
2081 struct rib *rib;
2082 unsigned changed = 0;
2083
2084 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2085 {
2086 zlog_err ("%s: vrf_table() returned NULL", __func__);
2087 return;
2088 }
2089
2090 /* No matches would be the simplest case. */
2091 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2092 return;
2093
2094 /* Unlock node. */
2095 route_unlock_node (rn);
2096
2097 /* Check all RIB entries. In case any changes have to be done, requeue
2098 * the RN into RIBQ head. If the routing message about the new connected
2099 * route (generated by the IP address we are going to assign very soon)
2100 * comes before the RIBQ is processed, the new RIB entry will join
2101 * RIBQ record already on head. This is necessary for proper revalidation
2102 * of the rest of the RIB.
2103 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002104 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002105 {
2106 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2107 ! RIB_SYSTEM_ROUTE (rib))
2108 {
2109 changed = 1;
2110 if (IS_ZEBRA_DEBUG_RIB)
2111 {
2112 char buf[INET_ADDRSTRLEN];
2113 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
2114 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
David Lamparterf7bf4152013-10-22 17:10:21 +00002115 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002116 }
2117 rib_uninstall (rn, rib);
2118 }
2119 }
2120 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002121 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002122}
2123
paul718e3742002-12-13 20:15:29 +00002124int
G.Balajicddf3912011-11-26 21:59:32 +04002125rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002126{
2127 struct route_table *table;
2128 struct route_node *rn;
2129 struct rib *same;
2130 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002131
paul718e3742002-12-13 20:15:29 +00002132 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002133 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002134 if (! table)
2135 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002136
paul718e3742002-12-13 20:15:29 +00002137 /* Make it sure prefixlen is applied to the prefix. */
2138 apply_mask_ipv4 (p);
2139
2140 /* Set default distance by route type. */
2141 if (rib->distance == 0)
2142 {
2143 rib->distance = route_info[rib->type].distance;
2144
2145 /* iBGP distance is 200. */
2146 if (rib->type == ZEBRA_ROUTE_BGP
2147 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2148 rib->distance = 200;
2149 }
2150
2151 /* Lookup route node.*/
2152 rn = route_node_get (table, (struct prefix *) p);
2153
2154 /* If same type of route are installed, treat it as a implicit
2155 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002156 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002157 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002158 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002159 continue;
2160
paul718e3742002-12-13 20:15:29 +00002161 if (same->type == rib->type && same->table == rib->table
2162 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002163 break;
paul718e3742002-12-13 20:15:29 +00002164 }
paul4d38fdb2005-04-28 17:35:14 +00002165
paul718e3742002-12-13 20:15:29 +00002166 /* If this route is kernel route, set FIB flag to the route. */
2167 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2168 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2169 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2170
2171 /* Link new rib to node.*/
2172 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002173 if (IS_ZEBRA_DEBUG_RIB)
2174 {
2175 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2176 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002177 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002178 }
paul718e3742002-12-13 20:15:29 +00002179
paul718e3742002-12-13 20:15:29 +00002180 /* Free implicit route.*/
2181 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002182 {
2183 if (IS_ZEBRA_DEBUG_RIB)
2184 {
2185 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2186 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002187 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002188 }
paul4d38fdb2005-04-28 17:35:14 +00002189 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002190 }
paul4d38fdb2005-04-28 17:35:14 +00002191
2192 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002193 return 0;
2194}
2195
hassoebf1ead2005-09-21 14:58:20 +00002196/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002197int
2198rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002199 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002200{
2201 struct route_table *table;
2202 struct route_node *rn;
2203 struct rib *rib;
2204 struct rib *fib = NULL;
2205 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002206 struct nexthop *nexthop, *tnexthop;
2207 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002208 char buf1[INET_ADDRSTRLEN];
2209 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002210
2211 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002212 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002213 if (! table)
2214 return 0;
2215
2216 /* Apply mask. */
2217 apply_mask_ipv4 (p);
2218
Christian Frankeb52aef12013-11-27 17:06:15 +00002219 if (IS_ZEBRA_DEBUG_KERNEL)
2220 {
2221 if (gate)
2222 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
2223 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2224 p->prefixlen,
2225 inet_ntoa (*gate),
2226 ifindex);
2227 else
2228 zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d",
2229 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2230 p->prefixlen,
2231 ifindex);
2232 }
paul5ec90d22003-06-19 01:41:37 +00002233
paul718e3742002-12-13 20:15:29 +00002234 /* Lookup route node. */
2235 rn = route_node_lookup (table, (struct prefix *) p);
2236 if (! rn)
2237 {
2238 if (IS_ZEBRA_DEBUG_KERNEL)
2239 {
2240 if (gate)
ajsb6178002004-12-07 21:12:56 +00002241 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002242 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002243 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002244 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002245 ifindex);
2246 else
ajsb6178002004-12-07 21:12:56 +00002247 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002248 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002249 p->prefixlen,
2250 ifindex);
2251 }
2252 return ZEBRA_ERR_RTNOEXIST;
2253 }
2254
2255 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002256 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002257 {
Paul Jakma6d691122006-07-27 21:49:00 +00002258 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2259 continue;
2260
paul718e3742002-12-13 20:15:29 +00002261 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2262 fib = rib;
2263
hassoebf1ead2005-09-21 14:58:20 +00002264 if (rib->type != type)
2265 continue;
2266 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002267 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002268 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002269 if (nexthop->ifindex != ifindex)
2270 continue;
hassoebf1ead2005-09-21 14:58:20 +00002271 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002272 {
hassoebf1ead2005-09-21 14:58:20 +00002273 rib->refcnt--;
2274 route_unlock_node (rn);
2275 route_unlock_node (rn);
2276 return 0;
paul718e3742002-12-13 20:15:29 +00002277 }
hassoebf1ead2005-09-21 14:58:20 +00002278 same = rib;
2279 break;
paul718e3742002-12-13 20:15:29 +00002280 }
hassoebf1ead2005-09-21 14:58:20 +00002281 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002282 else
paul5ec90d22003-06-19 01:41:37 +00002283 {
Christian Frankefa713d92013-07-05 15:35:37 +00002284 if (gate == NULL)
2285 {
2286 same = rib;
2287 break;
2288 }
2289 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2290 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2291 {
2292 same = rib;
2293 break;
2294 }
2295 if (same)
2296 break;
2297 }
paul718e3742002-12-13 20:15:29 +00002298 }
paul718e3742002-12-13 20:15:29 +00002299 /* If same type of route can't be found and this message is from
2300 kernel. */
2301 if (! same)
2302 {
2303 if (fib && type == ZEBRA_ROUTE_KERNEL)
2304 {
2305 /* Unset flags. */
2306 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2307 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2308
2309 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2310 }
2311 else
2312 {
2313 if (IS_ZEBRA_DEBUG_KERNEL)
2314 {
2315 if (gate)
ajsb6178002004-12-07 21:12:56 +00002316 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002317 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002318 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002319 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002320 ifindex,
2321 type);
2322 else
ajsb6178002004-12-07 21:12:56 +00002323 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002324 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002325 p->prefixlen,
2326 ifindex,
2327 type);
2328 }
2329 route_unlock_node (rn);
2330 return ZEBRA_ERR_RTNOEXIST;
2331 }
2332 }
paul4d38fdb2005-04-28 17:35:14 +00002333
paul718e3742002-12-13 20:15:29 +00002334 if (same)
2335 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002336
paul718e3742002-12-13 20:15:29 +00002337 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002338 return 0;
2339}
David Lamparter6b0655a2014-06-04 06:53:35 +02002340
paul718e3742002-12-13 20:15:29 +00002341/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002342static void
paul718e3742002-12-13 20:15:29 +00002343static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
2344{
2345 struct rib *rib;
2346 struct route_node *rn;
2347 struct route_table *table;
2348
2349 /* Lookup table. */
2350 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2351 if (! table)
2352 return;
2353
2354 /* Lookup existing route */
2355 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002356 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002357 {
2358 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2359 continue;
2360
2361 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2362 break;
2363 }
paul718e3742002-12-13 20:15:29 +00002364
2365 if (rib)
2366 {
2367 /* Same distance static route is there. Update it with new
2368 nexthop. */
paul718e3742002-12-13 20:15:29 +00002369 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002370 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002371 {
2372 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002373 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002374 break;
2375 case STATIC_IPV4_IFNAME:
2376 nexthop_ifname_add (rib, si->gate.ifname);
2377 break;
2378 case STATIC_IPV4_BLACKHOLE:
2379 nexthop_blackhole_add (rib);
2380 break;
paul4d38fdb2005-04-28 17:35:14 +00002381 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002382 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002383 }
2384 else
2385 {
2386 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002387 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2388
paul718e3742002-12-13 20:15:29 +00002389 rib->type = ZEBRA_ROUTE_STATIC;
2390 rib->distance = si->distance;
2391 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002392 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002393 rib->nexthop_num = 0;
2394
2395 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002396 {
2397 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002398 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002399 break;
2400 case STATIC_IPV4_IFNAME:
2401 nexthop_ifname_add (rib, si->gate.ifname);
2402 break;
2403 case STATIC_IPV4_BLACKHOLE:
2404 nexthop_blackhole_add (rib);
2405 break;
2406 }
paul718e3742002-12-13 20:15:29 +00002407
hasso81dfcaa2003-05-25 19:21:25 +00002408 /* Save the flags of this static routes (reject, blackhole) */
2409 rib->flags = si->flags;
2410
paul718e3742002-12-13 20:15:29 +00002411 /* Link this rib to the tree. */
2412 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002413 }
2414}
2415
paula1ac18c2005-06-28 17:17:12 +00002416static int
paul718e3742002-12-13 20:15:29 +00002417static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2418{
2419 if (nexthop->type == NEXTHOP_TYPE_IPV4
2420 && si->type == STATIC_IPV4_GATEWAY
2421 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2422 return 1;
2423 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2424 && si->type == STATIC_IPV4_IFNAME
2425 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2426 return 1;
paul595db7f2003-05-25 21:35:06 +00002427 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2428 && si->type == STATIC_IPV4_BLACKHOLE)
2429 return 1;
paule8e19462006-01-19 20:16:55 +00002430 return 0;
paul718e3742002-12-13 20:15:29 +00002431}
2432
2433/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002434static void
paul718e3742002-12-13 20:15:29 +00002435static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
2436{
2437 struct route_node *rn;
2438 struct rib *rib;
2439 struct nexthop *nexthop;
2440 struct route_table *table;
2441
2442 /* Lookup table. */
2443 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2444 if (! table)
2445 return;
paul4d38fdb2005-04-28 17:35:14 +00002446
paul718e3742002-12-13 20:15:29 +00002447 /* Lookup existing route with type and distance. */
2448 rn = route_node_lookup (table, p);
2449 if (! rn)
2450 return;
2451
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002452 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002453 {
2454 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2455 continue;
2456
2457 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2458 break;
2459 }
paul718e3742002-12-13 20:15:29 +00002460
2461 if (! rib)
2462 {
2463 route_unlock_node (rn);
2464 return;
2465 }
2466
2467 /* Lookup nexthop. */
2468 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2469 if (static_ipv4_nexthop_same (nexthop, si))
2470 break;
2471
2472 /* Can't find nexthop. */
2473 if (! nexthop)
2474 {
2475 route_unlock_node (rn);
2476 return;
2477 }
2478
2479 /* Check nexthop. */
2480 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002481 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002482 else
2483 {
paul6baeb982003-10-28 03:47:15 +00002484 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2485 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002486 nexthop_delete (rib, nexthop);
2487 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002488 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002489 }
paul718e3742002-12-13 20:15:29 +00002490 /* Unlock node. */
2491 route_unlock_node (rn);
2492}
2493
2494/* Add static route into static route configuration. */
2495int
hasso39db97e2004-10-12 20:50:58 +00002496static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00002497 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002498{
2499 u_char type = 0;
2500 struct route_node *rn;
2501 struct static_ipv4 *si;
2502 struct static_ipv4 *pp;
2503 struct static_ipv4 *cp;
2504 struct static_ipv4 *update = NULL;
2505 struct route_table *stable;
2506
2507 /* Lookup table. */
2508 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2509 if (! stable)
2510 return -1;
2511
2512 /* Lookup static route prefix. */
2513 rn = route_node_get (stable, p);
2514
2515 /* Make flags. */
2516 if (gate)
2517 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002518 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002519 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002520 else
2521 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002522
2523 /* Do nothing if there is a same static route. */
2524 for (si = rn->info; si; si = si->next)
2525 {
2526 if (type == si->type
2527 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2528 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2529 {
2530 if (distance == si->distance)
2531 {
2532 route_unlock_node (rn);
2533 return 0;
2534 }
2535 else
2536 update = si;
2537 }
2538 }
2539
Paul Jakma3c0755d2006-12-08 00:53:14 +00002540 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002541 if (update)
2542 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
2543
2544 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002545 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002546
2547 si->type = type;
2548 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002549 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002550
2551 if (gate)
2552 si->gate.ipv4 = *gate;
2553 if (ifname)
2554 si->gate.ifname = XSTRDUP (0, ifname);
2555
2556 /* Add new static route information to the tree with sort by
2557 distance value and gateway address. */
2558 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2559 {
2560 if (si->distance < cp->distance)
2561 break;
2562 if (si->distance > cp->distance)
2563 continue;
2564 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2565 {
2566 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2567 break;
2568 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2569 continue;
2570 }
2571 }
2572
2573 /* Make linked list. */
2574 if (pp)
2575 pp->next = si;
2576 else
2577 rn->info = si;
2578 if (cp)
2579 cp->prev = si;
2580 si->prev = pp;
2581 si->next = cp;
2582
2583 /* Install into rib. */
2584 static_install_ipv4 (p, si);
2585
2586 return 1;
2587}
2588
2589/* Delete static route from static route configuration. */
2590int
hasso39db97e2004-10-12 20:50:58 +00002591static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00002592 u_char distance, u_int32_t vrf_id)
2593{
2594 u_char type = 0;
2595 struct route_node *rn;
2596 struct static_ipv4 *si;
2597 struct route_table *stable;
2598
2599 /* Lookup table. */
2600 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
2601 if (! stable)
2602 return -1;
2603
2604 /* Lookup static route prefix. */
2605 rn = route_node_lookup (stable, p);
2606 if (! rn)
2607 return 0;
2608
2609 /* Make flags. */
2610 if (gate)
2611 type = STATIC_IPV4_GATEWAY;
2612 else if (ifname)
2613 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002614 else
2615 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002616
2617 /* Find same static route is the tree */
2618 for (si = rn->info; si; si = si->next)
2619 if (type == si->type
2620 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2621 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2622 break;
2623
2624 /* Can't find static route. */
2625 if (! si)
2626 {
2627 route_unlock_node (rn);
2628 return 0;
2629 }
2630
2631 /* Install into rib. */
2632 static_uninstall_ipv4 (p, si);
2633
2634 /* Unlink static route from linked list. */
2635 if (si->prev)
2636 si->prev->next = si->next;
2637 else
2638 rn->info = si->next;
2639 if (si->next)
2640 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002641 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002642
2643 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002644 if (ifname)
2645 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002646 XFREE (MTYPE_STATIC_IPV4, si);
2647
paul143a3852003-09-29 20:06:13 +00002648 route_unlock_node (rn);
2649
paul718e3742002-12-13 20:15:29 +00002650 return 1;
2651}
2652
David Lamparter6b0655a2014-06-04 06:53:35 +02002653
paul718e3742002-12-13 20:15:29 +00002654#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002655static int
paul718e3742002-12-13 20:15:29 +00002656rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2657 struct in6_addr *gate, unsigned int ifindex, int table)
2658{
hasso726f9b22003-05-25 21:04:54 +00002659 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2660#if defined (MUSICA) || defined (LINUX)
2661 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2662 if (p->prefixlen == 96)
2663 return 0;
2664#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002665 return 1;
hasso726f9b22003-05-25 21:04:54 +00002666 }
paul718e3742002-12-13 20:15:29 +00002667 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2668 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2669 {
2670 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2671 return 1;
2672 }
2673 return 0;
2674}
2675
2676int
2677rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002678 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002679 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002680{
2681 struct rib *rib;
2682 struct rib *same = NULL;
2683 struct route_table *table;
2684 struct route_node *rn;
2685 struct nexthop *nexthop;
2686
paul718e3742002-12-13 20:15:29 +00002687 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002688 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002689 if (! table)
2690 return 0;
2691
2692 /* Make sure mask is applied. */
2693 apply_mask_ipv6 (p);
2694
2695 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002696 if (!distance)
2697 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002698
2699 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2700 distance = 200;
2701
2702 /* Filter bogus route. */
2703 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2704 return 0;
2705
2706 /* Lookup route node.*/
2707 rn = route_node_get (table, (struct prefix *) p);
2708
2709 /* If same type of route are installed, treat it as a implicit
2710 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002711 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002712 {
Paul Jakma6d691122006-07-27 21:49:00 +00002713 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2714 continue;
2715
hassoebf1ead2005-09-21 14:58:20 +00002716 if (rib->type != type)
2717 continue;
2718 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002719 {
2720 same = rib;
paul718e3742002-12-13 20:15:29 +00002721 break;
2722 }
hassoebf1ead2005-09-21 14:58:20 +00002723 else if ((nexthop = rib->nexthop) &&
2724 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2725 nexthop->ifindex == ifindex)
2726 {
2727 rib->refcnt++;
2728 return 0;
2729 }
paul718e3742002-12-13 20:15:29 +00002730 }
2731
2732 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002733 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2734
paul718e3742002-12-13 20:15:29 +00002735 rib->type = type;
2736 rib->distance = distance;
2737 rib->flags = flags;
2738 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002739 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002740 rib->nexthop_num = 0;
2741 rib->uptime = time (NULL);
2742
2743 /* Nexthop settings. */
2744 if (gate)
2745 {
2746 if (ifindex)
2747 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2748 else
2749 nexthop_ipv6_add (rib, gate);
2750 }
2751 else
2752 nexthop_ifindex_add (rib, ifindex);
2753
2754 /* If this route is kernel route, set FIB flag to the route. */
2755 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2756 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2757 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2758
2759 /* Link new rib to node.*/
2760 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002761 if (IS_ZEBRA_DEBUG_RIB)
2762 {
2763 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2764 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002765 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002766 }
paul718e3742002-12-13 20:15:29 +00002767
paul718e3742002-12-13 20:15:29 +00002768 /* Free implicit route.*/
2769 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002770 {
2771 if (IS_ZEBRA_DEBUG_RIB)
2772 {
2773 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2774 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002775 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002776 }
paul4d38fdb2005-04-28 17:35:14 +00002777 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002778 }
paul4d38fdb2005-04-28 17:35:14 +00002779
2780 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002781 return 0;
2782}
2783
hassoebf1ead2005-09-21 14:58:20 +00002784/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002785int
2786rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002787 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002788{
2789 struct route_table *table;
2790 struct route_node *rn;
2791 struct rib *rib;
2792 struct rib *fib = NULL;
2793 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002794 struct nexthop *nexthop, *tnexthop;
2795 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002796 char buf1[INET6_ADDRSTRLEN];
2797 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002798
2799 /* Apply mask. */
2800 apply_mask_ipv6 (p);
2801
2802 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002803 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002804 if (! table)
2805 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002806
paul718e3742002-12-13 20:15:29 +00002807 /* Lookup route node. */
2808 rn = route_node_lookup (table, (struct prefix *) p);
2809 if (! rn)
2810 {
2811 if (IS_ZEBRA_DEBUG_KERNEL)
2812 {
2813 if (gate)
ajsb6178002004-12-07 21:12:56 +00002814 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002815 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002816 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002817 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002818 ifindex);
2819 else
ajsb6178002004-12-07 21:12:56 +00002820 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002821 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002822 p->prefixlen,
2823 ifindex);
2824 }
2825 return ZEBRA_ERR_RTNOEXIST;
2826 }
2827
2828 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002829 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002830 {
Paul Jakma6d691122006-07-27 21:49:00 +00002831 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2832 continue;
2833
paul718e3742002-12-13 20:15:29 +00002834 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2835 fib = rib;
2836
hassoebf1ead2005-09-21 14:58:20 +00002837 if (rib->type != type)
2838 continue;
2839 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002840 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002841 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002842 if (nexthop->ifindex != ifindex)
2843 continue;
hassoebf1ead2005-09-21 14:58:20 +00002844 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002845 {
hassoebf1ead2005-09-21 14:58:20 +00002846 rib->refcnt--;
2847 route_unlock_node (rn);
2848 route_unlock_node (rn);
2849 return 0;
paul718e3742002-12-13 20:15:29 +00002850 }
hassoebf1ead2005-09-21 14:58:20 +00002851 same = rib;
2852 break;
paul718e3742002-12-13 20:15:29 +00002853 }
hassoebf1ead2005-09-21 14:58:20 +00002854 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002855 else
2856 {
2857 if (gate == NULL)
2858 {
2859 same = rib;
2860 break;
2861 }
2862 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2863 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2864 {
2865 same = rib;
2866 break;
2867 }
2868 if (same)
2869 break;
2870 }
paul718e3742002-12-13 20:15:29 +00002871 }
2872
2873 /* If same type of route can't be found and this message is from
2874 kernel. */
2875 if (! same)
2876 {
2877 if (fib && type == ZEBRA_ROUTE_KERNEL)
2878 {
2879 /* Unset flags. */
2880 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2881 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2882
2883 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2884 }
2885 else
2886 {
2887 if (IS_ZEBRA_DEBUG_KERNEL)
2888 {
2889 if (gate)
ajsb6178002004-12-07 21:12:56 +00002890 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002891 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002892 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002893 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002894 ifindex,
2895 type);
2896 else
ajsb6178002004-12-07 21:12:56 +00002897 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002898 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002899 p->prefixlen,
2900 ifindex,
2901 type);
2902 }
2903 route_unlock_node (rn);
2904 return ZEBRA_ERR_RTNOEXIST;
2905 }
2906 }
2907
2908 if (same)
2909 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002910
paul718e3742002-12-13 20:15:29 +00002911 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002912 return 0;
2913}
David Lamparter6b0655a2014-06-04 06:53:35 +02002914
paul718e3742002-12-13 20:15:29 +00002915/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002916static void
paul718e3742002-12-13 20:15:29 +00002917static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2918{
2919 struct rib *rib;
2920 struct route_table *table;
2921 struct route_node *rn;
2922
2923 /* Lookup table. */
2924 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2925 if (! table)
2926 return;
2927
2928 /* Lookup existing route */
2929 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002930 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002931 {
2932 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2933 continue;
2934
2935 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2936 break;
2937 }
paul718e3742002-12-13 20:15:29 +00002938
2939 if (rib)
2940 {
2941 /* Same distance static route is there. Update it with new
2942 nexthop. */
paul718e3742002-12-13 20:15:29 +00002943 route_unlock_node (rn);
2944
2945 switch (si->type)
2946 {
2947 case STATIC_IPV6_GATEWAY:
2948 nexthop_ipv6_add (rib, &si->ipv6);
2949 break;
2950 case STATIC_IPV6_IFNAME:
2951 nexthop_ifname_add (rib, si->ifname);
2952 break;
2953 case STATIC_IPV6_GATEWAY_IFNAME:
2954 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2955 break;
2956 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002957 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002958 }
2959 else
2960 {
2961 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002962 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2963
paul718e3742002-12-13 20:15:29 +00002964 rib->type = ZEBRA_ROUTE_STATIC;
2965 rib->distance = si->distance;
2966 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002967 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002968 rib->nexthop_num = 0;
2969
2970 switch (si->type)
2971 {
2972 case STATIC_IPV6_GATEWAY:
2973 nexthop_ipv6_add (rib, &si->ipv6);
2974 break;
2975 case STATIC_IPV6_IFNAME:
2976 nexthop_ifname_add (rib, si->ifname);
2977 break;
2978 case STATIC_IPV6_GATEWAY_IFNAME:
2979 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2980 break;
2981 }
2982
hasso81dfcaa2003-05-25 19:21:25 +00002983 /* Save the flags of this static routes (reject, blackhole) */
2984 rib->flags = si->flags;
2985
paul718e3742002-12-13 20:15:29 +00002986 /* Link this rib to the tree. */
2987 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002988 }
2989}
2990
paula1ac18c2005-06-28 17:17:12 +00002991static int
paul718e3742002-12-13 20:15:29 +00002992static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2993{
2994 if (nexthop->type == NEXTHOP_TYPE_IPV6
2995 && si->type == STATIC_IPV6_GATEWAY
2996 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2997 return 1;
2998 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2999 && si->type == STATIC_IPV6_IFNAME
3000 && strcmp (nexthop->ifname, si->ifname) == 0)
3001 return 1;
3002 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3003 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3004 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3005 && strcmp (nexthop->ifname, si->ifname) == 0)
3006 return 1;
paule8e19462006-01-19 20:16:55 +00003007 return 0;
paul718e3742002-12-13 20:15:29 +00003008}
3009
paula1ac18c2005-06-28 17:17:12 +00003010static void
paul718e3742002-12-13 20:15:29 +00003011static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3012{
3013 struct route_table *table;
3014 struct route_node *rn;
3015 struct rib *rib;
3016 struct nexthop *nexthop;
3017
3018 /* Lookup table. */
3019 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3020 if (! table)
3021 return;
3022
3023 /* Lookup existing route with type and distance. */
3024 rn = route_node_lookup (table, (struct prefix *) p);
3025 if (! rn)
3026 return;
3027
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003028 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003029 {
3030 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3031 continue;
3032
3033 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3034 break;
3035 }
3036
paul718e3742002-12-13 20:15:29 +00003037 if (! rib)
3038 {
3039 route_unlock_node (rn);
3040 return;
3041 }
3042
3043 /* Lookup nexthop. */
3044 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3045 if (static_ipv6_nexthop_same (nexthop, si))
3046 break;
3047
3048 /* Can't find nexthop. */
3049 if (! nexthop)
3050 {
3051 route_unlock_node (rn);
3052 return;
3053 }
3054
3055 /* Check nexthop. */
3056 if (rib->nexthop_num == 1)
3057 {
3058 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003059 }
3060 else
3061 {
paul6baeb982003-10-28 03:47:15 +00003062 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3063 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003064 nexthop_delete (rib, nexthop);
3065 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003066 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003067 }
paul718e3742002-12-13 20:15:29 +00003068 /* Unlock node. */
3069 route_unlock_node (rn);
3070}
3071
3072/* Add static route into static route configuration. */
3073int
3074static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003075 const char *ifname, u_char flags, u_char distance,
3076 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003077{
3078 struct route_node *rn;
3079 struct static_ipv6 *si;
3080 struct static_ipv6 *pp;
3081 struct static_ipv6 *cp;
3082 struct route_table *stable;
3083
3084 /* Lookup table. */
3085 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3086 if (! stable)
3087 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003088
3089 if (!gate &&
3090 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3091 return -1;
3092
3093 if (!ifname &&
3094 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3095 return -1;
paul718e3742002-12-13 20:15:29 +00003096
3097 /* Lookup static route prefix. */
3098 rn = route_node_get (stable, p);
3099
3100 /* Do nothing if there is a same static route. */
3101 for (si = rn->info; si; si = si->next)
3102 {
3103 if (distance == si->distance
3104 && type == si->type
3105 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3106 && (! ifname || strcmp (ifname, si->ifname) == 0))
3107 {
3108 route_unlock_node (rn);
3109 return 0;
3110 }
3111 }
3112
3113 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003114 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003115
3116 si->type = type;
3117 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003118 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003119
3120 switch (type)
3121 {
3122 case STATIC_IPV6_GATEWAY:
3123 si->ipv6 = *gate;
3124 break;
3125 case STATIC_IPV6_IFNAME:
3126 si->ifname = XSTRDUP (0, ifname);
3127 break;
3128 case STATIC_IPV6_GATEWAY_IFNAME:
3129 si->ipv6 = *gate;
3130 si->ifname = XSTRDUP (0, ifname);
3131 break;
3132 }
3133
3134 /* Add new static route information to the tree with sort by
3135 distance value and gateway address. */
3136 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3137 {
3138 if (si->distance < cp->distance)
3139 break;
3140 if (si->distance > cp->distance)
3141 continue;
3142 }
3143
3144 /* Make linked list. */
3145 if (pp)
3146 pp->next = si;
3147 else
3148 rn->info = si;
3149 if (cp)
3150 cp->prev = si;
3151 si->prev = pp;
3152 si->next = cp;
3153
3154 /* Install into rib. */
3155 static_install_ipv6 (p, si);
3156
3157 return 1;
3158}
3159
3160/* Delete static route from static route configuration. */
3161int
3162static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003163 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003164{
3165 struct route_node *rn;
3166 struct static_ipv6 *si;
3167 struct route_table *stable;
3168
3169 /* Lookup table. */
3170 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3171 if (! stable)
3172 return -1;
3173
3174 /* Lookup static route prefix. */
3175 rn = route_node_lookup (stable, p);
3176 if (! rn)
3177 return 0;
3178
3179 /* Find same static route is the tree */
3180 for (si = rn->info; si; si = si->next)
3181 if (distance == si->distance
3182 && type == si->type
3183 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3184 && (! ifname || strcmp (ifname, si->ifname) == 0))
3185 break;
3186
3187 /* Can't find static route. */
3188 if (! si)
3189 {
3190 route_unlock_node (rn);
3191 return 0;
3192 }
3193
3194 /* Install into rib. */
3195 static_uninstall_ipv6 (p, si);
3196
3197 /* Unlink static route from linked list. */
3198 if (si->prev)
3199 si->prev->next = si->next;
3200 else
3201 rn->info = si->next;
3202 if (si->next)
3203 si->next->prev = si->prev;
3204
3205 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003206 if (ifname)
3207 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003208 XFREE (MTYPE_STATIC_IPV6, si);
3209
3210 return 1;
3211}
3212#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003213
paul718e3742002-12-13 20:15:29 +00003214/* RIB update function. */
3215void
paula1ac18c2005-06-28 17:17:12 +00003216rib_update (void)
paul718e3742002-12-13 20:15:29 +00003217{
3218 struct route_node *rn;
3219 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003220
paul718e3742002-12-13 20:15:29 +00003221 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3222 if (table)
3223 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003224 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003225 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003226
3227 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3228 if (table)
3229 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003230 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003231 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003232}
3233
David Lamparter6b0655a2014-06-04 06:53:35 +02003234
paul718e3742002-12-13 20:15:29 +00003235/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003236static void
paul718e3742002-12-13 20:15:29 +00003237rib_weed_table (struct route_table *table)
3238{
3239 struct route_node *rn;
3240 struct rib *rib;
3241 struct rib *next;
3242
3243 if (table)
3244 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003245 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003246 {
Paul Jakma6d691122006-07-27 21:49:00 +00003247 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3248 continue;
3249
paulb21b19c2003-06-15 01:28:29 +00003250 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003251 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003252 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003253 }
3254}
3255
3256/* Delete all routes from non main table. */
3257void
paula1ac18c2005-06-28 17:17:12 +00003258rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003259{
3260 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3261 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3262}
David Lamparter6b0655a2014-06-04 06:53:35 +02003263
paul718e3742002-12-13 20:15:29 +00003264/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003265static void
paul718e3742002-12-13 20:15:29 +00003266rib_sweep_table (struct route_table *table)
3267{
3268 struct route_node *rn;
3269 struct rib *rib;
3270 struct rib *next;
3271 int ret = 0;
3272
3273 if (table)
3274 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003275 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003276 {
Paul Jakma6d691122006-07-27 21:49:00 +00003277 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3278 continue;
3279
paul718e3742002-12-13 20:15:29 +00003280 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3281 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3282 {
3283 ret = rib_uninstall_kernel (rn, rib);
3284 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003285 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003286 }
3287 }
3288}
3289
3290/* Sweep all RIB tables. */
3291void
paula1ac18c2005-06-28 17:17:12 +00003292rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003293{
3294 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3295 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3296}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003297
3298/* Remove specific by protocol routes from 'table'. */
3299static unsigned long
3300rib_score_proto_table (u_char proto, struct route_table *table)
3301{
3302 struct route_node *rn;
3303 struct rib *rib;
3304 struct rib *next;
3305 unsigned long n = 0;
3306
3307 if (table)
3308 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003309 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003310 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003311 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3312 continue;
3313 if (rib->type == proto)
3314 {
3315 rib_delnode (rn, rib);
3316 n++;
3317 }
3318 }
3319
3320 return n;
3321}
3322
3323/* Remove specific by protocol routes. */
3324unsigned long
3325rib_score_proto (u_char proto)
3326{
3327 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3328 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3329}
3330
paul718e3742002-12-13 20:15:29 +00003331/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003332static void
paul718e3742002-12-13 20:15:29 +00003333rib_close_table (struct route_table *table)
3334{
3335 struct route_node *rn;
3336 struct rib *rib;
3337
3338 if (table)
3339 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003340 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003341 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003342 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3343 continue;
3344
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003345 zfpm_trigger_update (rn, NULL);
3346
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003347 if (! RIB_SYSTEM_ROUTE (rib))
3348 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003349 }
paul718e3742002-12-13 20:15:29 +00003350}
3351
3352/* Close all RIB tables. */
3353void
paula1ac18c2005-06-28 17:17:12 +00003354rib_close (void)
paul718e3742002-12-13 20:15:29 +00003355{
3356 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3357 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3358}
David Lamparter6b0655a2014-06-04 06:53:35 +02003359
paul718e3742002-12-13 20:15:29 +00003360/* Routing information base initialize. */
3361void
paula1ac18c2005-06-28 17:17:12 +00003362rib_init (void)
paul718e3742002-12-13 20:15:29 +00003363{
paul4d38fdb2005-04-28 17:35:14 +00003364 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003365 /* VRF initialization. */
3366 vrf_init ();
3367}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003368
3369/*
3370 * vrf_id_get_next
3371 *
3372 * Get the first vrf id that is greater than the given vrf id if any.
3373 *
3374 * Returns TRUE if a vrf id was found, FALSE otherwise.
3375 */
3376static inline int
3377vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3378{
3379 while (++id < vector_active (vrf_vector))
3380 {
3381 if (vrf_lookup (id))
3382 {
3383 *next_id_p = id;
3384 return 1;
3385 }
3386 }
3387
3388 return 0;
3389}
3390
3391/*
3392 * rib_tables_iter_next
3393 *
3394 * Returns the next table in the iteration.
3395 */
3396struct route_table *
3397rib_tables_iter_next (rib_tables_iter_t *iter)
3398{
3399 struct route_table *table;
3400
3401 /*
3402 * Array that helps us go over all AFI/SAFI combinations via one
3403 * index.
3404 */
3405 static struct {
3406 afi_t afi;
3407 safi_t safi;
3408 } afi_safis[] = {
3409 { AFI_IP, SAFI_UNICAST },
3410 { AFI_IP, SAFI_MULTICAST },
3411 { AFI_IP6, SAFI_UNICAST },
3412 { AFI_IP6, SAFI_MULTICAST },
3413 };
3414
3415 table = NULL;
3416
3417 switch (iter->state)
3418 {
3419
3420 case RIB_TABLES_ITER_S_INIT:
3421 iter->vrf_id = 0;
3422 iter->afi_safi_ix = -1;
3423
3424 /* Fall through */
3425
3426 case RIB_TABLES_ITER_S_ITERATING:
3427 iter->afi_safi_ix++;
3428 while (1)
3429 {
3430
3431 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3432 {
3433 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3434 afi_safis[iter->afi_safi_ix].safi,
3435 iter->vrf_id);
3436 if (table)
3437 break;
3438
3439 iter->afi_safi_ix++;
3440 }
3441
3442 /*
3443 * Found another table in this vrf.
3444 */
3445 if (table)
3446 break;
3447
3448 /*
3449 * Done with all tables in the current vrf, go to the next
3450 * one.
3451 */
3452 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3453 break;
3454
3455 iter->afi_safi_ix = 0;
3456 }
3457
3458 break;
3459
3460 case RIB_TABLES_ITER_S_DONE:
3461 return NULL;
3462 }
3463
3464 if (table)
3465 iter->state = RIB_TABLES_ITER_S_ITERATING;
3466 else
3467 iter->state = RIB_TABLES_ITER_S_DONE;
3468
3469 return table;
3470}