blob: f247f1d29a2480878aebe951ffce4bd3b9ae8e8e [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 Lamparterbd078122015-01-06 19:53:24 +010078/* RPF lookup behaviour */
79static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
80
David Lampartereed3c482015-03-03 08:51:53 +010081static void __attribute__((format (printf, 4, 5)))
David Lamparter94813742014-04-24 20:22:53 +020082_rnode_zlog(const char *_func, struct route_node *rn, int priority,
83 const char *msgfmt, ...)
84{
Timo Teräsbe6335d2015-05-23 11:08:41 +030085 char buf[PREFIX_STRLEN + 8];
David Lamparter94813742014-04-24 20:22:53 +020086 char msgbuf[512];
87 va_list ap;
88
89 va_start(ap, msgfmt);
90 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
91 va_end(ap);
92
93 if (rn)
94 {
David Lamparterab2ba612015-01-22 19:02:13 +010095 rib_table_info_t *info = rn->table->info;
96
Timo Teräsbe6335d2015-05-23 11:08:41 +030097 prefix2str(&rn->p, buf, sizeof(buf));
98 if (info->safi == SAFI_MULTICAST)
99 strcat(buf, " (MRIB)");
David Lamparter94813742014-04-24 20:22:53 +0200100 }
101 else
102 {
103 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
104 }
105
106 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
107}
108
109#define rnode_debug(node, ...) \
110 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
111#define rnode_info(node, ...) \
112 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
113
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000114/*
115 * vrf_table_create
116 */
117static void
118vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
119{
120 rib_table_info_t *info;
121 struct route_table *table;
122
123 assert (!vrf->table[afi][safi]);
124
125 table = route_table_init ();
126 vrf->table[afi][safi] = table;
127
128 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
129 info->vrf = vrf;
130 info->afi = afi;
131 info->safi = safi;
132 table->info = info;
133}
134
paul718e3742002-12-13 20:15:29 +0000135/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +0000136static struct vrf *
hassofce954f2004-10-07 20:29:24 +0000137vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +0000138{
139 struct vrf *vrf;
140
141 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
142
143 /* Put name. */
144 if (name)
145 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
146
147 /* Allocate routing table and static table. */
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000148 vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
149 vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000150 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
151 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000152 vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
153 vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
G.Balajicddf3912011-11-26 21:59:32 +0400154 vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
155 vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
156
paul718e3742002-12-13 20:15:29 +0000157
158 return vrf;
159}
160
paul718e3742002-12-13 20:15:29 +0000161/* Lookup VRF by identifier. */
162struct vrf *
163vrf_lookup (u_int32_t id)
164{
165 return vector_lookup (vrf_vector, id);
166}
167
paul718e3742002-12-13 20:15:29 +0000168/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000169static void
170vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000171{
172 struct vrf *default_table;
173
174 /* Allocate VRF vector. */
175 vrf_vector = vector_init (1);
176
177 /* Allocate default main table. */
178 default_table = vrf_alloc ("Default-IP-Routing-Table");
179
180 /* Default table index must be 0. */
181 vector_set_index (vrf_vector, 0, default_table);
182}
183
184/* Lookup route table. */
185struct route_table *
186vrf_table (afi_t afi, safi_t safi, u_int32_t id)
187{
188 struct vrf *vrf;
189
190 vrf = vrf_lookup (id);
191 if (! vrf)
192 return NULL;
193
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000194 if( afi >= AFI_MAX || safi >= SAFI_MAX )
195 return NULL;
196
paul718e3742002-12-13 20:15:29 +0000197 return vrf->table[afi][safi];
198}
199
200/* Lookup static route table. */
201struct route_table *
202vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
203{
204 struct vrf *vrf;
205
206 vrf = vrf_lookup (id);
207 if (! vrf)
208 return NULL;
209
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000210 if( afi >= AFI_MAX || safi >= SAFI_MAX )
211 return NULL;
212
paul718e3742002-12-13 20:15:29 +0000213 return vrf->stable[afi][safi];
214}
David Lamparter6b0655a2014-06-04 06:53:35 +0200215
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000216/*
217 * nexthop_type_to_str
218 */
219const char *
220nexthop_type_to_str (enum nexthop_types_t nh_type)
221{
222 static const char *desc[] = {
223 "none",
224 "Directly connected",
225 "Interface route",
226 "IPv4 nexthop",
227 "IPv4 nexthop with ifindex",
228 "IPv4 nexthop with ifname",
229 "IPv6 nexthop",
230 "IPv6 nexthop with ifindex",
231 "IPv6 nexthop with ifname",
232 "Null0 nexthop",
233 };
234
235 if (nh_type >= ZEBRA_NUM_OF (desc))
236 return "<Invalid nh type>";
237
238 return desc[nh_type];
239}
240
Christian Frankefa713d92013-07-05 15:35:37 +0000241/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000242static void
Christian Frankefa713d92013-07-05 15:35:37 +0000243_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000244{
245 struct nexthop *last;
246
Christian Frankefa713d92013-07-05 15:35:37 +0000247 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000248 ;
249 if (last)
250 last->next = nexthop;
251 else
Christian Frankefa713d92013-07-05 15:35:37 +0000252 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000253 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000254}
paul718e3742002-12-13 20:15:29 +0000255
Christian Frankefa713d92013-07-05 15:35:37 +0000256/* Add nexthop to the end of a rib node's nexthop list */
257static void
258nexthop_add (struct rib *rib, struct nexthop *nexthop)
259{
260 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000261 rib->nexthop_num++;
262}
263
264/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000265static void
paul718e3742002-12-13 20:15:29 +0000266nexthop_delete (struct rib *rib, struct nexthop *nexthop)
267{
268 if (nexthop->next)
269 nexthop->next->prev = nexthop->prev;
270 if (nexthop->prev)
271 nexthop->prev->next = nexthop->next;
272 else
273 rib->nexthop = nexthop->next;
274 rib->nexthop_num--;
275}
276
Christian Frankefa713d92013-07-05 15:35:37 +0000277static void nexthops_free(struct nexthop *nexthop);
278
paul718e3742002-12-13 20:15:29 +0000279/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000280static void
paul718e3742002-12-13 20:15:29 +0000281nexthop_free (struct nexthop *nexthop)
282{
paula4b70762003-05-16 17:19:48 +0000283 if (nexthop->ifname)
284 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000285 if (nexthop->resolved)
286 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000287 XFREE (MTYPE_NEXTHOP, nexthop);
288}
289
Christian Frankefa713d92013-07-05 15:35:37 +0000290/* Frees a list of nexthops */
291static void
292nexthops_free (struct nexthop *nexthop)
293{
294 struct nexthop *nh, *next;
295
296 for (nh = nexthop; nh; nh = next)
297 {
298 next = nh->next;
299 nexthop_free (nh);
300 }
301}
302
paul718e3742002-12-13 20:15:29 +0000303struct nexthop *
304nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
305{
306 struct nexthop *nexthop;
307
Stephen Hemminger393deb92008-08-18 14:13:29 -0700308 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000309 nexthop->type = NEXTHOP_TYPE_IFINDEX;
310 nexthop->ifindex = ifindex;
311
312 nexthop_add (rib, nexthop);
313
314 return nexthop;
315}
316
317struct nexthop *
318nexthop_ifname_add (struct rib *rib, char *ifname)
319{
320 struct nexthop *nexthop;
321
Stephen Hemminger393deb92008-08-18 14:13:29 -0700322 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000323 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000324 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000325
326 nexthop_add (rib, nexthop);
327
328 return nexthop;
329}
330
331struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000332nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000333{
334 struct nexthop *nexthop;
335
Stephen Hemminger393deb92008-08-18 14:13:29 -0700336 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000337 nexthop->type = NEXTHOP_TYPE_IPV4;
338 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000339 if (src)
340 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000341
342 nexthop_add (rib, nexthop);
343
344 return nexthop;
345}
346
Josh Bailey26e2ae32012-03-22 01:09:21 -0700347struct nexthop *
paul718e3742002-12-13 20:15:29 +0000348nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000349 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000350{
351 struct nexthop *nexthop;
352
Stephen Hemminger393deb92008-08-18 14:13:29 -0700353 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000354 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
355 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000356 if (src)
357 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000358 nexthop->ifindex = ifindex;
359
360 nexthop_add (rib, nexthop);
361
362 return nexthop;
363}
364
365#ifdef HAVE_IPV6
366struct nexthop *
367nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
368{
369 struct nexthop *nexthop;
370
Stephen Hemminger393deb92008-08-18 14:13:29 -0700371 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000372 nexthop->type = NEXTHOP_TYPE_IPV6;
373 nexthop->gate.ipv6 = *ipv6;
374
375 nexthop_add (rib, nexthop);
376
377 return nexthop;
378}
379
paula1ac18c2005-06-28 17:17:12 +0000380static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000381nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
382 char *ifname)
383{
384 struct nexthop *nexthop;
385
Stephen Hemminger393deb92008-08-18 14:13:29 -0700386 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000387 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
388 nexthop->gate.ipv6 = *ipv6;
389 nexthop->ifname = XSTRDUP (0, ifname);
390
391 nexthop_add (rib, nexthop);
392
393 return nexthop;
394}
395
paula1ac18c2005-06-28 17:17:12 +0000396static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000397nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
398 unsigned int ifindex)
399{
400 struct nexthop *nexthop;
401
Stephen Hemminger393deb92008-08-18 14:13:29 -0700402 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000403 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
404 nexthop->gate.ipv6 = *ipv6;
405 nexthop->ifindex = ifindex;
406
407 nexthop_add (rib, nexthop);
408
409 return nexthop;
410}
411#endif /* HAVE_IPV6 */
412
paul595db7f2003-05-25 21:35:06 +0000413struct nexthop *
414nexthop_blackhole_add (struct rib *rib)
415{
416 struct nexthop *nexthop;
417
Stephen Hemminger393deb92008-08-18 14:13:29 -0700418 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000419 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
420 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
421
422 nexthop_add (rib, nexthop);
423
424 return nexthop;
425}
426
Christian Frankefa713d92013-07-05 15:35:37 +0000427/* This method checks whether a recursive nexthop has at
428 * least one resolved nexthop in the fib.
429 */
430int
431nexthop_has_fib_child(struct nexthop *nexthop)
432{
433 struct nexthop *nh;
434
435 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
436 return 0;
437
438 for (nh = nexthop->resolved; nh; nh = nh->next)
439 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
440 return 1;
441
442 return 0;
443}
444
paul718e3742002-12-13 20:15:29 +0000445/* If force flag is not set, do not modify falgs at all for uninstall
446 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000447static int
paul718e3742002-12-13 20:15:29 +0000448nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
449 struct route_node *top)
450{
451 struct prefix_ipv4 p;
452 struct route_table *table;
453 struct route_node *rn;
454 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000455 int resolved;
paul718e3742002-12-13 20:15:29 +0000456 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000457 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000458
459 if (nexthop->type == NEXTHOP_TYPE_IPV4)
460 nexthop->ifindex = 0;
461
462 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000463 {
464 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
465 nexthops_free(nexthop->resolved);
466 nexthop->resolved = NULL;
467 }
paul718e3742002-12-13 20:15:29 +0000468
469 /* Make lookup prefix. */
470 memset (&p, 0, sizeof (struct prefix_ipv4));
471 p.family = AF_INET;
472 p.prefixlen = IPV4_MAX_PREFIXLEN;
473 p.prefix = nexthop->gate.ipv4;
474
475 /* Lookup table. */
476 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
477 if (! table)
478 return 0;
479
480 rn = route_node_match (table, (struct prefix *) &p);
481 while (rn)
482 {
483 route_unlock_node (rn);
484
David Warda50c1072009-12-03 15:34:39 +0300485 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000486 if (rn == top)
487 return 0;
488
489 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000490 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100491 {
492 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
493 continue;
494 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
495 break;
496 }
paul718e3742002-12-13 20:15:29 +0000497
498 /* If there is no selected route or matched route is EGP, go up
499 tree. */
500 if (! match
501 || match->type == ZEBRA_ROUTE_BGP)
502 {
503 do {
504 rn = rn->parent;
505 } while (rn && rn->info == NULL);
506 if (rn)
507 route_lock_node (rn);
508 }
509 else
510 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000511 /* If the longest prefix match for the nexthop yields
512 * a blackhole, mark it as inactive. */
513 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
514 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
515 return 0;
516
paul718e3742002-12-13 20:15:29 +0000517 if (match->type == ZEBRA_ROUTE_CONNECT)
518 {
519 /* Directly point connected route. */
520 newhop = match->nexthop;
521 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
522 nexthop->ifindex = newhop->ifindex;
523
524 return 1;
525 }
526 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
527 {
Christian Frankefa713d92013-07-05 15:35:37 +0000528 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000529 for (newhop = match->nexthop; newhop; newhop = newhop->next)
530 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
531 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
532 {
533 if (set)
534 {
535 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000536
537 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
538 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000539 /* If the resolving route specifies a gateway, use it */
540 if (newhop->type == NEXTHOP_TYPE_IPV4
541 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
542 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
543 {
544 resolved_hop->type = newhop->type;
545 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000546
Christian Frankec3e6b592013-07-05 15:35:40 +0000547 if (newhop->ifindex)
548 {
549 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
550 resolved_hop->ifindex = newhop->ifindex;
551 }
552 }
Christian Frankefa713d92013-07-05 15:35:37 +0000553
Christian Frankec3e6b592013-07-05 15:35:40 +0000554 /* If the resolving route is an interface route,
555 * it means the gateway we are looking up is connected
556 * to that interface. (The actual network is _not_ onlink).
557 * Therefore, the resolved route should have the original
558 * gateway as nexthop as it is directly connected.
559 *
560 * On Linux, we have to set the onlink netlink flag because
561 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000562 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000563 || newhop->type == NEXTHOP_TYPE_IFNAME)
564 {
565 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
566 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
567 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
568 resolved_hop->ifindex = newhop->ifindex;
569 }
Christian Frankefa713d92013-07-05 15:35:37 +0000570
571 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000572 }
Christian Frankefa713d92013-07-05 15:35:37 +0000573 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000574 }
Christian Frankefa713d92013-07-05 15:35:37 +0000575 return resolved;
paul718e3742002-12-13 20:15:29 +0000576 }
577 else
578 {
579 return 0;
580 }
581 }
582 }
583 return 0;
584}
585
586#ifdef HAVE_IPV6
587/* If force flag is not set, do not modify falgs at all for uninstall
588 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000589static int
paul718e3742002-12-13 20:15:29 +0000590nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
591 struct route_node *top)
592{
593 struct prefix_ipv6 p;
594 struct route_table *table;
595 struct route_node *rn;
596 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000597 int resolved;
paul718e3742002-12-13 20:15:29 +0000598 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000599 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000600
601 if (nexthop->type == NEXTHOP_TYPE_IPV6)
602 nexthop->ifindex = 0;
603
604 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000605 {
606 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
607 nexthops_free(nexthop->resolved);
608 nexthop->resolved = NULL;
609 }
paul718e3742002-12-13 20:15:29 +0000610
611 /* Make lookup prefix. */
612 memset (&p, 0, sizeof (struct prefix_ipv6));
613 p.family = AF_INET6;
614 p.prefixlen = IPV6_MAX_PREFIXLEN;
615 p.prefix = nexthop->gate.ipv6;
616
617 /* Lookup table. */
618 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
619 if (! table)
620 return 0;
621
622 rn = route_node_match (table, (struct prefix *) &p);
623 while (rn)
624 {
625 route_unlock_node (rn);
626
David Warda50c1072009-12-03 15:34:39 +0300627 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000628 if (rn == top)
629 return 0;
630
631 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000632 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100633 {
634 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
635 continue;
636 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
637 break;
638 }
paul718e3742002-12-13 20:15:29 +0000639
640 /* If there is no selected route or matched route is EGP, go up
641 tree. */
642 if (! match
643 || match->type == ZEBRA_ROUTE_BGP)
644 {
645 do {
646 rn = rn->parent;
647 } while (rn && rn->info == NULL);
648 if (rn)
649 route_lock_node (rn);
650 }
651 else
652 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000653 /* If the longest prefix match for the nexthop yields
654 * a blackhole, mark it as inactive. */
655 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
656 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
657 return 0;
658
paul718e3742002-12-13 20:15:29 +0000659 if (match->type == ZEBRA_ROUTE_CONNECT)
660 {
661 /* Directly point connected route. */
662 newhop = match->nexthop;
663
664 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
665 nexthop->ifindex = newhop->ifindex;
666
667 return 1;
668 }
669 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
670 {
Christian Frankefa713d92013-07-05 15:35:37 +0000671 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000672 for (newhop = match->nexthop; newhop; newhop = newhop->next)
673 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
674 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
675 {
676 if (set)
677 {
678 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000679
680 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
681 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000682 /* See nexthop_active_ipv4 for a description how the
683 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000684 if (newhop->type == NEXTHOP_TYPE_IPV6
685 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
686 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000687 {
688 resolved_hop->type = newhop->type;
689 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
690
691 if (newhop->ifindex)
692 {
693 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
694 resolved_hop->ifindex = newhop->ifindex;
695 }
696 }
Christian Frankefa713d92013-07-05 15:35:37 +0000697
paul718e3742002-12-13 20:15:29 +0000698 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000699 || newhop->type == NEXTHOP_TYPE_IFNAME)
700 {
701 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
702 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
703 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
704 resolved_hop->ifindex = newhop->ifindex;
705 }
Christian Frankefa713d92013-07-05 15:35:37 +0000706
707 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000708 }
Christian Frankefa713d92013-07-05 15:35:37 +0000709 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000710 }
Christian Frankefa713d92013-07-05 15:35:37 +0000711 return resolved;
paul718e3742002-12-13 20:15:29 +0000712 }
713 else
714 {
715 return 0;
716 }
717 }
718 }
719 return 0;
720}
721#endif /* HAVE_IPV6 */
722
723struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100724rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
725 struct route_node **rn_out)
Everton Marques3dea1782014-09-22 19:35:51 -0300726{
727 struct route_table *table;
728 struct route_node *rn;
729 struct rib *match;
730 struct nexthop *newhop, *tnewhop;
731 int recursing;
732
733 /* Lookup table. */
734 table = vrf_table (AFI_IP, safi, 0);
735 if (! table)
736 return 0;
737
738 rn = route_node_match_ipv4 (table, &addr);
739
740 while (rn)
741 {
742 route_unlock_node (rn);
743
744 /* Pick up selected route. */
745 RNODE_FOREACH_RIB (rn, match)
746 {
747 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
748 continue;
749 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
750 break;
751 }
752
753 /* If there is no selected route or matched route is EGP, go up
754 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300755 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300756 {
757 do {
758 rn = rn->parent;
759 } while (rn && rn->info == NULL);
760 if (rn)
761 route_lock_node (rn);
762 }
763 else
764 {
David Lamparter24480d42015-01-22 19:09:36 +0100765 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300766 {
David Lamparter24480d42015-01-22 19:09:36 +0100767 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300768 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
769 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100770 {
771 found = 1;
772 break;
773 }
774 if (!found)
775 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300776 }
David Lamparter24480d42015-01-22 19:09:36 +0100777
778 if (rn_out)
779 *rn_out = rn;
780 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300781 }
782 }
783 return NULL;
784}
785
786struct rib *
David Lamparterbd078122015-01-06 19:53:24 +0100787rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
788{
789 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
790 struct route_node *m_rn = NULL, *u_rn = NULL;
791 int skip_bgp = 0; /* bool */
792
793 switch (ipv4_multicast_mode)
794 {
795 case MCAST_MRIB_ONLY:
796 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
797 case MCAST_URIB_ONLY:
798 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
799 case MCAST_NO_CONFIG:
800 case MCAST_MIX_MRIB_FIRST:
801 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
802 if (!mrib)
803 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
804 break;
805 case MCAST_MIX_DISTANCE:
806 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
807 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
808 if (mrib && urib)
809 rib = urib->distance < mrib->distance ? urib : mrib;
810 else if (mrib)
811 rib = mrib;
812 else if (urib)
813 rib = urib;
814 break;
815 case MCAST_MIX_PFXLEN:
816 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
817 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
818 if (mrib && urib)
819 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
820 else if (mrib)
821 rib = mrib;
822 else if (urib)
823 rib = urib;
824 break;
825 }
826
827 if (rn_out)
828 *rn_out = (rib == mrib) ? m_rn : u_rn;
829
830 if (IS_ZEBRA_DEBUG_RIB)
831 {
832 char buf[BUFSIZ];
833 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
834
835 zlog_debug("%s: %s: found %s, using %s",
836 __func__, buf,
837 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
838 urib ? "URIB" : "nothing",
839 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
840 }
841 return rib;
842}
843
844void
845multicast_mode_ipv4_set (enum multicast_mode mode)
846{
847 if (IS_ZEBRA_DEBUG_RIB)
848 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
849 ipv4_multicast_mode = mode;
850}
851
852enum multicast_mode
853multicast_mode_ipv4_get (void)
854{
855 return ipv4_multicast_mode;
856}
857
858struct rib *
paul718e3742002-12-13 20:15:29 +0000859rib_lookup_ipv4 (struct prefix_ipv4 *p)
860{
861 struct route_table *table;
862 struct route_node *rn;
863 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000864 struct nexthop *nexthop, *tnexthop;
865 int recursing;
paul718e3742002-12-13 20:15:29 +0000866
867 /* Lookup table. */
868 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
869 if (! table)
870 return 0;
871
872 rn = route_node_lookup (table, (struct prefix *) p);
873
874 /* No route for this prefix. */
875 if (! rn)
876 return NULL;
877
878 /* Unlock node. */
879 route_unlock_node (rn);
880
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000881 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100882 {
883 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
884 continue;
885 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
886 break;
887 }
paul718e3742002-12-13 20:15:29 +0000888
889 if (! match || match->type == ZEBRA_ROUTE_BGP)
890 return NULL;
891
892 if (match->type == ZEBRA_ROUTE_CONNECT)
893 return match;
894
Christian Frankefa713d92013-07-05 15:35:37 +0000895 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000896 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
897 return match;
898
899 return NULL;
900}
901
Denis Ovsienkodc958242007-08-13 16:03:06 +0000902/*
903 * This clone function, unlike its original rib_lookup_ipv4(), checks
904 * if specified IPv4 route record (prefix/mask -> gate) exists in
905 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
906 *
907 * Return values:
908 * -1: error
909 * 0: exact match found
910 * 1: a match was found with a different gate
911 * 2: connected route found
912 * 3: no matches found
913 */
914int
915rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
916{
917 struct route_table *table;
918 struct route_node *rn;
919 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000920 struct nexthop *nexthop, *tnexthop;
921 int recursing;
922 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000923
924 /* Lookup table. */
925 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
926 if (! table)
927 return ZEBRA_RIB_LOOKUP_ERROR;
928
929 /* Scan the RIB table for exactly matching RIB entry. */
930 rn = route_node_lookup (table, (struct prefix *) p);
931
932 /* No route for this prefix. */
933 if (! rn)
934 return ZEBRA_RIB_NOTFOUND;
935
936 /* Unlock node. */
937 route_unlock_node (rn);
938
939 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000940 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100941 {
942 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
943 continue;
944 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
945 break;
946 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000947
948 /* None such found :( */
949 if (!match)
950 return ZEBRA_RIB_NOTFOUND;
951
952 if (match->type == ZEBRA_ROUTE_CONNECT)
953 return ZEBRA_RIB_FOUND_CONNECTED;
954
955 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000956 nexthops_active = 0;
957 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000958 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000959 {
Christian Frankefa713d92013-07-05 15:35:37 +0000960 nexthops_active = 1;
961 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
962 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000963 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000964 {
965 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
966 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
967 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
968 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
969 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
970 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000971 }
Christian Frankefa713d92013-07-05 15:35:37 +0000972
973 if (nexthops_active)
974 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000975
976 return ZEBRA_RIB_NOTFOUND;
977}
978
paul718e3742002-12-13 20:15:29 +0000979#ifdef HAVE_IPV6
980struct rib *
981rib_match_ipv6 (struct in6_addr *addr)
982{
983 struct prefix_ipv6 p;
984 struct route_table *table;
985 struct route_node *rn;
986 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000987 struct nexthop *newhop, *tnewhop;
988 int recursing;
paul718e3742002-12-13 20:15:29 +0000989
990 /* Lookup table. */
991 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
992 if (! table)
993 return 0;
994
995 memset (&p, 0, sizeof (struct prefix_ipv6));
996 p.family = AF_INET6;
997 p.prefixlen = IPV6_MAX_PREFIXLEN;
998 IPV6_ADDR_COPY (&p.prefix, addr);
999
1000 rn = route_node_match (table, (struct prefix *) &p);
1001
1002 while (rn)
1003 {
1004 route_unlock_node (rn);
1005
1006 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001007 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +01001008 {
1009 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
1010 continue;
1011 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
1012 break;
1013 }
paul718e3742002-12-13 20:15:29 +00001014
1015 /* If there is no selected route or matched route is EGP, go up
1016 tree. */
1017 if (! match
1018 || match->type == ZEBRA_ROUTE_BGP)
1019 {
1020 do {
1021 rn = rn->parent;
1022 } while (rn && rn->info == NULL);
1023 if (rn)
1024 route_lock_node (rn);
1025 }
1026 else
1027 {
1028 if (match->type == ZEBRA_ROUTE_CONNECT)
1029 /* Directly point connected route. */
1030 return match;
1031 else
1032 {
Christian Frankefa713d92013-07-05 15:35:37 +00001033 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +00001034 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1035 return match;
1036 return NULL;
1037 }
1038 }
1039 }
1040 return NULL;
1041}
1042#endif /* HAVE_IPV6 */
1043
Paul Jakma7514fb72007-05-02 16:05:35 +00001044#define RIB_SYSTEM_ROUTE(R) \
1045 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
1046
Denis Ovsienkodc958242007-08-13 16:03:06 +00001047/* This function verifies reachability of one given nexthop, which can be
1048 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
1049 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
1050 * nexthop->ifindex will be updated appropriately as well.
1051 * An existing route map can turn (otherwise active) nexthop into inactive, but
1052 * not vice versa.
1053 *
1054 * The return value is the final value of 'ACTIVE' flag.
1055 */
1056
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001057static unsigned
paul718e3742002-12-13 20:15:29 +00001058nexthop_active_check (struct route_node *rn, struct rib *rib,
1059 struct nexthop *nexthop, int set)
1060{
Christian Frankef3a17322013-07-05 15:35:41 +00001061 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +00001062 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +00001063 route_map_result_t ret = RMAP_MATCH;
1064 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
1065 struct route_map *rmap;
1066 int family;
paul718e3742002-12-13 20:15:29 +00001067
Paul Jakma7514fb72007-05-02 16:05:35 +00001068 family = 0;
paul718e3742002-12-13 20:15:29 +00001069 switch (nexthop->type)
1070 {
1071 case NEXTHOP_TYPE_IFINDEX:
1072 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001073 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001074 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1075 else
1076 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1077 break;
paul718e3742002-12-13 20:15:29 +00001078 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001079 family = AFI_IP6;
1080 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001081 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001082 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001083 {
1084 if (set)
1085 nexthop->ifindex = ifp->ifindex;
1086 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1087 }
1088 else
1089 {
1090 if (set)
1091 nexthop->ifindex = 0;
1092 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1093 }
1094 break;
1095 case NEXTHOP_TYPE_IPV4:
1096 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001097 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001098 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1099 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1100 else
1101 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1102 break;
1103#ifdef HAVE_IPV6
1104 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001105 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001106 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 break;
1111 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001112 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001113 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1114 {
1115 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001116 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001117 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1118 else
1119 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1120 }
1121 else
1122 {
1123 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1124 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1125 else
1126 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1127 }
1128 break;
1129#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001130 case NEXTHOP_TYPE_BLACKHOLE:
1131 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1132 break;
paul718e3742002-12-13 20:15:29 +00001133 default:
1134 break;
1135 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001136 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1137 return 0;
1138
Christian Frankef3a17322013-07-05 15:35:41 +00001139 /* XXX: What exactly do those checks do? Do we support
1140 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001141 if (RIB_SYSTEM_ROUTE(rib) ||
1142 (family == AFI_IP && rn->p.family != AF_INET) ||
1143 (family == AFI_IP6 && rn->p.family != AF_INET6))
1144 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1145
Christian Frankef3a17322013-07-05 15:35:41 +00001146 /* The original code didn't determine the family correctly
1147 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1148 * from the rib_table_info in those cases.
1149 * Possibly it may be better to use only the rib_table_info
1150 * in every case.
1151 */
1152 if (!family)
1153 family = info->afi;
1154
Paul Jakma7514fb72007-05-02 16:05:35 +00001155 rmap = 0;
1156 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1157 proto_rm[family][rib->type])
1158 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1159 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1160 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1161 if (rmap) {
1162 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1163 }
1164
1165 if (ret == RMAP_DENYMATCH)
1166 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001167 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1168}
1169
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001170/* Iterate over all nexthops of the given RIB entry and refresh their
1171 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1172 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1173 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1174 * transparently passed to nexthop_active_check().
1175 *
1176 * Return value is the new number of active nexthops.
1177 */
1178
paula1ac18c2005-06-28 17:17:12 +00001179static int
paul718e3742002-12-13 20:15:29 +00001180nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1181{
1182 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001183 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001184
1185 rib->nexthop_active_num = 0;
1186 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1187
1188 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001189 {
1190 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001191 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001192 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1193 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001194 if (prev_active != new_active ||
1195 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001196 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1197 }
paul718e3742002-12-13 20:15:29 +00001198 return rib->nexthop_active_num;
1199}
paul6baeb982003-10-28 03:47:15 +00001200
David Lamparter6b0655a2014-06-04 06:53:35 +02001201
paul718e3742002-12-13 20:15:29 +00001202
paula1ac18c2005-06-28 17:17:12 +00001203static void
paul718e3742002-12-13 20:15:29 +00001204rib_install_kernel (struct route_node *rn, struct rib *rib)
1205{
1206 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001207 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001208 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001209 int recursing;
paul718e3742002-12-13 20:15:29 +00001210
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001211 if (info->safi != SAFI_UNICAST)
1212 {
1213 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1214 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1215 return;
1216 }
1217
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001218 /*
1219 * Make sure we update the FPM any time we send new information to
1220 * the kernel.
1221 */
1222 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001223 switch (PREFIX_FAMILY (&rn->p))
1224 {
1225 case AF_INET:
1226 ret = kernel_add_ipv4 (&rn->p, rib);
1227 break;
1228#ifdef HAVE_IPV6
1229 case AF_INET6:
1230 ret = kernel_add_ipv6 (&rn->p, rib);
1231 break;
1232#endif /* HAVE_IPV6 */
1233 }
1234
Denis Ovsienkodc958242007-08-13 16:03:06 +00001235 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001236 if (ret < 0)
1237 {
Christian Frankefa713d92013-07-05 15:35:37 +00001238 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001239 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1240 }
1241}
1242
1243/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001244static int
paul718e3742002-12-13 20:15:29 +00001245rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1246{
1247 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001248 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001249 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001250 int recursing;
paul718e3742002-12-13 20:15:29 +00001251
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001252 if (info->safi != SAFI_UNICAST)
1253 {
1254 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1255 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1256 return ret;
1257 }
1258
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001259 /*
1260 * Make sure we update the FPM any time we send new information to
1261 * the kernel.
1262 */
1263 zfpm_trigger_update (rn, "uninstalling from kernel");
1264
paul718e3742002-12-13 20:15:29 +00001265 switch (PREFIX_FAMILY (&rn->p))
1266 {
1267 case AF_INET:
1268 ret = kernel_delete_ipv4 (&rn->p, rib);
1269 break;
1270#ifdef HAVE_IPV6
1271 case AF_INET6:
1272 ret = kernel_delete_ipv6 (&rn->p, rib);
1273 break;
1274#endif /* HAVE_IPV6 */
1275 }
1276
Christian Frankefa713d92013-07-05 15:35:37 +00001277 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001278 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1279
1280 return ret;
1281}
1282
1283/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001284static void
paul718e3742002-12-13 20:15:29 +00001285rib_uninstall (struct route_node *rn, struct rib *rib)
1286{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001287 rib_table_info_t *info = rn->table->info;
1288
paul718e3742002-12-13 20:15:29 +00001289 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1290 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001291 if (info->safi == SAFI_UNICAST)
1292 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001293
paul718e3742002-12-13 20:15:29 +00001294 redistribute_delete (&rn->p, rib);
1295 if (! RIB_SYSTEM_ROUTE (rib))
1296 rib_uninstall_kernel (rn, rib);
1297 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1298 }
1299}
1300
Paul Jakma6d691122006-07-27 21:49:00 +00001301static void rib_unlink (struct route_node *, struct rib *);
1302
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001303/*
1304 * rib_can_delete_dest
1305 *
1306 * Returns TRUE if the given dest can be deleted from the table.
1307 */
1308static int
1309rib_can_delete_dest (rib_dest_t *dest)
1310{
1311 if (dest->routes)
1312 {
1313 return 0;
1314 }
1315
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001316 /*
1317 * Don't delete the dest if we have to update the FPM about this
1318 * prefix.
1319 */
1320 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1321 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1322 return 0;
1323
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001324 return 1;
1325}
1326
1327/*
1328 * rib_gc_dest
1329 *
1330 * Garbage collect the rib dest corresponding to the given route node
1331 * if appropriate.
1332 *
1333 * Returns TRUE if the dest was deleted, FALSE otherwise.
1334 */
1335int
1336rib_gc_dest (struct route_node *rn)
1337{
1338 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001339
1340 dest = rib_dest_from_rnode (rn);
1341 if (!dest)
1342 return 0;
1343
1344 if (!rib_can_delete_dest (dest))
1345 return 0;
1346
1347 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001348 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001349
1350 dest->rnode = NULL;
1351 XFREE (MTYPE_RIB_DEST, dest);
1352 rn->info = NULL;
1353
1354 /*
1355 * Release the one reference that we keep on the route node.
1356 */
1357 route_unlock_node (rn);
1358 return 1;
1359}
1360
paul718e3742002-12-13 20:15:29 +00001361/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001362static void
1363rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct rib *rib;
1366 struct rib *next;
1367 struct rib *fib = NULL;
1368 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001369 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001370 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001371 struct nexthop *nexthop = NULL, *tnexthop;
1372 int recursing;
Balaji95116332014-10-23 15:25:25 +00001373 rib_table_info_t *info;
1374
paul4d38fdb2005-04-28 17:35:14 +00001375 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001376
1377 info = rn->table->info;
1378
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001379 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001380 {
paul718e3742002-12-13 20:15:29 +00001381 /* Currently installed rib. */
1382 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001383 {
1384 assert (fib == NULL);
1385 fib = rib;
1386 }
1387
1388 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1389 * which we need to do do further work with below.
1390 */
1391 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1392 {
1393 if (rib != fib)
1394 {
1395 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001396 rnode_debug (rn, "rn %p, removing rib %p",
1397 (void *)rn, (void *)rib);
1398 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001399 }
1400 else
1401 del = rib;
1402
1403 continue;
1404 }
paul4d38fdb2005-04-28 17:35:14 +00001405
paul718e3742002-12-13 20:15:29 +00001406 /* Skip unreachable nexthop. */
1407 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001408 continue;
paul718e3742002-12-13 20:15:29 +00001409
1410 /* Infinit distance. */
1411 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001412 continue;
paul718e3742002-12-13 20:15:29 +00001413
paulaf887b52006-01-18 14:52:52 +00001414 /* Newly selected rib, the common case. */
1415 if (!select)
1416 {
1417 select = rib;
1418 continue;
1419 }
1420
1421 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001422 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001423 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001424 * - lower metric beats higher for equal distance
1425 * - last, hence oldest, route wins tie break.
1426 */
paula1038a12006-01-30 14:08:51 +00001427
1428 /* Connected routes. Pick the last connected
1429 * route of the set of lowest metric connected routes.
1430 */
paula8d9c1f2006-01-25 06:31:04 +00001431 if (rib->type == ZEBRA_ROUTE_CONNECT)
1432 {
paula1038a12006-01-30 14:08:51 +00001433 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001434 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001435 select = rib;
1436 continue;
paula8d9c1f2006-01-25 06:31:04 +00001437 }
1438 else if (select->type == ZEBRA_ROUTE_CONNECT)
1439 continue;
1440
1441 /* higher distance loses */
1442 if (rib->distance > select->distance)
1443 continue;
1444
1445 /* lower wins */
1446 if (rib->distance < select->distance)
1447 {
paulaf887b52006-01-18 14:52:52 +00001448 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001449 continue;
1450 }
1451
1452 /* metric tie-breaks equal distance */
1453 if (rib->metric <= select->metric)
1454 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001455 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001456
1457 /* After the cycle is finished, the following pointers will be set:
1458 * select --- the winner RIB entry, if any was found, otherwise NULL
1459 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1460 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1461 * rib --- NULL
1462 */
1463
1464 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001465 if (select && select == fib)
1466 {
Paul Jakma6d691122006-07-27 21:49:00 +00001467 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001468 rnode_debug (rn, "Updating existing route, select %p, fib %p",
David Lampartereed3c482015-03-03 08:51:53 +01001469 (void *)select, (void *)fib);
paul718e3742002-12-13 20:15:29 +00001470 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001471 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001472 if (info->safi == SAFI_UNICAST)
1473 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001474
paul4d38fdb2005-04-28 17:35:14 +00001475 redistribute_delete (&rn->p, select);
1476 if (! RIB_SYSTEM_ROUTE (select))
1477 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001478
paul4d38fdb2005-04-28 17:35:14 +00001479 /* Set real nexthop. */
1480 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001481
paul4d38fdb2005-04-28 17:35:14 +00001482 if (! RIB_SYSTEM_ROUTE (select))
1483 rib_install_kernel (rn, select);
1484 redistribute_add (&rn->p, select);
1485 }
pauld753e9e2003-01-22 19:45:50 +00001486 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001487 {
1488 /* Housekeeping code to deal with
1489 race conditions in kernel with linux
1490 netlink reporting interface up before IPv4 or IPv6 protocol
1491 is ready to add routes.
1492 This makes sure the routes are IN the kernel.
1493 */
pauld753e9e2003-01-22 19:45:50 +00001494
Christian Frankefa713d92013-07-05 15:35:37 +00001495 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001496 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001497 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001498 installed = 1;
1499 break;
paul4d38fdb2005-04-28 17:35:14 +00001500 }
1501 if (! installed)
1502 rib_install_kernel (rn, select);
1503 }
Paul Jakma6d691122006-07-27 21:49:00 +00001504 goto end;
paul718e3742002-12-13 20:15:29 +00001505 }
1506
Denis Ovsienkodc958242007-08-13 16:03:06 +00001507 /* At this point we either haven't found the best RIB entry or it is
1508 * different from what we currently intend to flag with SELECTED. In both
1509 * cases, if a RIB block is present in FIB, it should be withdrawn.
1510 */
paul718e3742002-12-13 20:15:29 +00001511 if (fib)
1512 {
Paul Jakma6d691122006-07-27 21:49:00 +00001513 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001514 rnode_debug (rn, "Removing existing route, fib %p", (void *)fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001515
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001516 if (info->safi == SAFI_UNICAST)
1517 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001518
paul718e3742002-12-13 20:15:29 +00001519 redistribute_delete (&rn->p, fib);
1520 if (! RIB_SYSTEM_ROUTE (fib))
1521 rib_uninstall_kernel (rn, fib);
1522 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1523
1524 /* Set real nexthop. */
1525 nexthop_active_update (rn, fib, 1);
1526 }
1527
Denis Ovsienkodc958242007-08-13 16:03:06 +00001528 /* Regardless of some RIB entry being SELECTED or not before, now we can
1529 * tell, that if a new winner exists, FIB is still not updated with this
1530 * data, but ready to be.
1531 */
paul718e3742002-12-13 20:15:29 +00001532 if (select)
1533 {
Paul Jakma6d691122006-07-27 21:49:00 +00001534 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001535 rnode_debug (rn, "Adding route, select %p", (void *)select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001536
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001537 if (info->safi == SAFI_UNICAST)
1538 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001539
paul718e3742002-12-13 20:15:29 +00001540 /* Set real nexthop. */
1541 nexthop_active_update (rn, select, 1);
1542
1543 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001544 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001545 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1546 redistribute_add (&rn->p, select);
1547 }
paul4d38fdb2005-04-28 17:35:14 +00001548
Paul Jakma6d691122006-07-27 21:49:00 +00001549 /* FIB route was removed, should be deleted */
1550 if (del)
1551 {
1552 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001553 rnode_debug (rn, "Deleting fib %p, rn %p", (void *)del, (void *)rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001554 rib_unlink (rn, del);
1555 }
paul4d38fdb2005-04-28 17:35:14 +00001556
Paul Jakma6d691122006-07-27 21:49:00 +00001557end:
1558 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001559 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001560
1561 /*
1562 * Check if the dest can be deleted now.
1563 */
1564 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001565}
1566
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001567/* Take a list of route_node structs and return 1, if there was a record
1568 * picked from it and processed by rib_process(). Don't process more,
1569 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001570 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001571static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001572process_subq (struct list * subq, u_char qindex)
1573{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001574 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001575 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001576
1577 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001578 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001579
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001580 rnode = listgetdata (lnode);
1581 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001582
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001583 if (rnode->info)
1584 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1585
Chris Caputo67b94672009-07-18 04:02:26 +00001586#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001587 else
1588 {
1589 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1590 __func__, rnode, rnode->lock);
1591 zlog_backtrace(LOG_DEBUG);
1592 }
Chris Caputo67b94672009-07-18 04:02:26 +00001593#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001594 route_unlock_node (rnode);
1595 list_delete_node (subq, lnode);
1596 return 1;
1597}
1598
1599/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1600 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1601 * is pointed to the meta queue structure.
1602 */
1603static wq_item_status
1604meta_queue_process (struct work_queue *dummy, void *data)
1605{
1606 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001607 unsigned i;
1608
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001609 for (i = 0; i < MQ_SIZE; i++)
1610 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001611 {
1612 mq->size--;
1613 break;
1614 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001615 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1616}
1617
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001618/*
1619 * Map from rib types to queue type (priority) in meta queue
1620 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001621static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1622 [ZEBRA_ROUTE_SYSTEM] = 4,
1623 [ZEBRA_ROUTE_KERNEL] = 0,
1624 [ZEBRA_ROUTE_CONNECT] = 0,
1625 [ZEBRA_ROUTE_STATIC] = 1,
1626 [ZEBRA_ROUTE_RIP] = 2,
1627 [ZEBRA_ROUTE_RIPNG] = 2,
1628 [ZEBRA_ROUTE_OSPF] = 2,
1629 [ZEBRA_ROUTE_OSPF6] = 2,
1630 [ZEBRA_ROUTE_ISIS] = 2,
1631 [ZEBRA_ROUTE_BGP] = 3,
1632 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001633 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001634};
1635
1636/* Look into the RN and queue it into one or more priority queues,
1637 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001638 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001639static void
1640rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001641{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001642 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001643
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001644 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001645 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001646 u_char qindex = meta_queue_map[rib->type];
1647
1648 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001649 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1650 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001651 {
1652 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001653 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001654 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001655 continue;
1656 }
1657
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001658 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001659 listnode_add (mq->subq[qindex], rn);
1660 route_lock_node (rn);
1661 mq->size++;
1662
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001663 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001664 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001665 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001666 }
paul4d38fdb2005-04-28 17:35:14 +00001667}
1668
Paul Jakma6d691122006-07-27 21:49:00 +00001669/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001670static void
Paul Jakma6d691122006-07-27 21:49:00 +00001671rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001672{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001673 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001674
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001675 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001676 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001677 {
1678 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001679 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001680 zlog_backtrace(LOG_DEBUG);
1681 return;
1682 }
1683
1684 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001685 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001686
1687 assert (zebra);
1688
1689 if (zebra->ribq == NULL)
1690 {
1691 zlog_err ("%s: work_queue does not exist!", __func__);
1692 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001693 }
paul4d38fdb2005-04-28 17:35:14 +00001694
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001695 /*
1696 * The RIB queue should normally be either empty or holding the only
1697 * work_queue_item element. In the latter case this element would
1698 * hold a pointer to the meta queue structure, which must be used to
1699 * actually queue the route nodes to process. So create the MQ
1700 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001701 * This semantics was introduced after 0.99.9 release.
1702 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001703 if (!zebra->ribq->items->count)
1704 work_queue_add (zebra->ribq, zebra->mq);
1705
1706 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001707
1708 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001709 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001710
1711 return;
paul4d38fdb2005-04-28 17:35:14 +00001712}
1713
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001714/* Create new meta queue.
1715 A destructor function doesn't seem to be necessary here.
1716 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001717static struct meta_queue *
1718meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001719{
1720 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001721 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001722
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001723 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1724 assert(new);
1725
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001726 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001727 {
1728 new->subq[i] = list_new ();
1729 assert(new->subq[i]);
1730 }
1731
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001732 return new;
1733}
1734
paul4d38fdb2005-04-28 17:35:14 +00001735/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001736static void
paul4d38fdb2005-04-28 17:35:14 +00001737rib_queue_init (struct zebra_t *zebra)
1738{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001739 assert (zebra);
1740
paul4d38fdb2005-04-28 17:35:14 +00001741 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001742 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001743 {
Paul Jakma6d691122006-07-27 21:49:00 +00001744 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001745 return;
1746 }
1747
1748 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001749 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001750 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001751 /* XXX: TODO: These should be runtime configurable via vty */
1752 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001753 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001754
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001755 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001756 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001757 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001758 return;
1759 }
1760 return;
paul718e3742002-12-13 20:15:29 +00001761}
1762
Paul Jakma6d691122006-07-27 21:49:00 +00001763/* RIB updates are processed via a queue of pointers to route_nodes.
1764 *
1765 * The queue length is bounded by the maximal size of the routing table,
1766 * as a route_node will not be requeued, if already queued.
1767 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001768 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1769 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1770 * and then submit route_node to queue for best-path selection later.
1771 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001772 *
1773 * Deleted RIBs are reaped during best-path selection.
1774 *
1775 * rib_addnode
1776 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001777 * |-------->| | best RIB, if required
1778 * | |
1779 * static_install->|->rib_addqueue...... -> rib_process
1780 * | |
1781 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001782 * |-> set RIB_ENTRY_REMOVE |
1783 * rib_delnode (RIB freed)
1784 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001785 * The 'info' pointer of a route_node points to a rib_dest_t
1786 * ('dest'). Queueing state for a route_node is kept on the dest. The
1787 * dest is created on-demand by rib_link() and is kept around at least
1788 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001789 *
1790 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1791 *
1792 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001793 * - dest attached to route_node:
1794 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001795 * - route_node processing queue
1796 * - managed by: rib_addqueue, rib_process.
1797 *
1798 */
1799
paul718e3742002-12-13 20:15:29 +00001800/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001801static void
Paul Jakma6d691122006-07-27 21:49:00 +00001802rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001803{
1804 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001805 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001806
paul4d38fdb2005-04-28 17:35:14 +00001807 assert (rib && rn);
1808
Paul Jakma6d691122006-07-27 21:49:00 +00001809 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001810 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001811
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001812 dest = rib_dest_from_rnode (rn);
1813 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001814 {
1815 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001816 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001817
1818 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1819 route_lock_node (rn); /* rn route table reference */
1820 rn->info = dest;
1821 dest->rnode = rn;
1822 }
1823
1824 head = dest->routes;
1825 if (head)
1826 {
Paul Jakma6d691122006-07-27 21:49:00 +00001827 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001828 }
paul718e3742002-12-13 20:15:29 +00001829 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001830 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001831 rib_queue_add (&zebrad, rn);
1832}
1833
1834static void
1835rib_addnode (struct route_node *rn, struct rib *rib)
1836{
1837 /* RIB node has been un-removed before route-node is processed.
1838 * route_node must hence already be on the queue for processing..
1839 */
1840 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1841 {
1842 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001843 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001844
Paul Jakma6d691122006-07-27 21:49:00 +00001845 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1846 return;
1847 }
1848 rib_link (rn, rib);
1849}
1850
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001851/*
1852 * rib_unlink
1853 *
1854 * Detach a rib structure from a route_node.
1855 *
1856 * Note that a call to rib_unlink() should be followed by a call to
1857 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1858 * longer required to be deleted.
1859 */
Paul Jakma6d691122006-07-27 21:49:00 +00001860static void
1861rib_unlink (struct route_node *rn, struct rib *rib)
1862{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001863 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001864
1865 assert (rn && rib);
1866
1867 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001868 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001869
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001870 dest = rib_dest_from_rnode (rn);
1871
Paul Jakma6d691122006-07-27 21:49:00 +00001872 if (rib->next)
1873 rib->next->prev = rib->prev;
1874
1875 if (rib->prev)
1876 rib->prev->next = rib->next;
1877 else
1878 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001879 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001880 }
1881
1882 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001883 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001884 XFREE (MTYPE_RIB, rib);
1885
paul718e3742002-12-13 20:15:29 +00001886}
1887
paula1ac18c2005-06-28 17:17:12 +00001888static void
paul718e3742002-12-13 20:15:29 +00001889rib_delnode (struct route_node *rn, struct rib *rib)
1890{
Paul Jakma6d691122006-07-27 21:49:00 +00001891 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001892 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001893 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1894 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001895}
1896
1897int
1898rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001899 struct in_addr *gate, struct in_addr *src,
1900 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001901 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001902{
1903 struct rib *rib;
1904 struct rib *same = NULL;
1905 struct route_table *table;
1906 struct route_node *rn;
1907 struct nexthop *nexthop;
1908
1909 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001910 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001911 if (! table)
1912 return 0;
1913
1914 /* Make it sure prefixlen is applied to the prefix. */
1915 apply_mask_ipv4 (p);
1916
1917 /* Set default distance by route type. */
1918 if (distance == 0)
1919 {
Balaji.G837d16c2012-09-26 14:09:10 +05301920 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001921 distance = 150;
1922 else
1923 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001924
1925 /* iBGP distance is 200. */
1926 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1927 distance = 200;
1928 }
1929
1930 /* Lookup route node.*/
1931 rn = route_node_get (table, (struct prefix *) p);
1932
1933 /* If same type of route are installed, treat it as a implicit
1934 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001935 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001936 {
Paul Jakma6d691122006-07-27 21:49:00 +00001937 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1938 continue;
1939
hassoebf1ead2005-09-21 14:58:20 +00001940 if (rib->type != type)
1941 continue;
1942 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001943 {
1944 same = rib;
1945 break;
1946 }
hassoebf1ead2005-09-21 14:58:20 +00001947 /* Duplicate connected route comes in. */
1948 else if ((nexthop = rib->nexthop) &&
1949 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001950 nexthop->ifindex == ifindex &&
1951 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001952 {
1953 rib->refcnt++;
1954 return 0 ;
1955 }
paul718e3742002-12-13 20:15:29 +00001956 }
1957
1958 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001959 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001960 rib->type = type;
1961 rib->distance = distance;
1962 rib->flags = flags;
1963 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001964 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001965 rib->nexthop_num = 0;
1966 rib->uptime = time (NULL);
1967
1968 /* Nexthop settings. */
1969 if (gate)
1970 {
1971 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001972 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001973 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001974 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001975 }
1976 else
1977 nexthop_ifindex_add (rib, ifindex);
1978
1979 /* If this route is kernel route, set FIB flag to the route. */
1980 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1981 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1982 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1983
1984 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001985 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001986 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1987 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001988 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001989
paul718e3742002-12-13 20:15:29 +00001990 /* Free implicit route.*/
1991 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001992 {
1993 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001994 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1995 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001996 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001997 }
paul4d38fdb2005-04-28 17:35:14 +00001998
1999 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002000 return 0;
2001}
2002
Denis Ovsienkodc958242007-08-13 16:03:06 +00002003/* This function dumps the contents of a given RIB entry into
2004 * standard debug log. Calling function name and IP prefix in
2005 * question are passed as 1st and 2nd arguments.
2006 */
2007
David Lamparterf7bf4152013-10-22 17:10:21 +00002008void _rib_dump (const char * func,
2009 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002010{
David Lamparterf7bf4152013-10-22 17:10:21 +00002011 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002012 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00002013 struct nexthop *nexthop, *tnexthop;
2014 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00002015
Timo Teräsbe6335d2015-05-23 11:08:41 +03002016 zlog_debug ("%s: dumping RIB entry %p for %s", func, (void *)rib,
2017 prefix2str(p, straddr, sizeof(straddr)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00002018 zlog_debug
2019 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002020 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00002021 func,
2022 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002023 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002024 rib->type,
2025 rib->table
2026 );
2027 zlog_debug
2028 (
2029 "%s: metric == %u, distance == %u, flags == %u, status == %u",
2030 func,
2031 rib->metric,
2032 rib->distance,
2033 rib->flags,
2034 rib->status
2035 );
2036 zlog_debug
2037 (
2038 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
2039 func,
2040 rib->nexthop_num,
2041 rib->nexthop_active_num,
2042 rib->nexthop_fib_num
2043 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00002044
Christian Frankefa713d92013-07-05 15:35:37 +00002045 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2046 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00002047 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002048 zlog_debug
2049 (
2050 "%s: %s %s with flags %s%s%s",
2051 func,
2052 (recursing ? " NH" : "NH"),
2053 straddr,
2054 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
2055 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
2056 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
2057 );
2058 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00002059 zlog_debug ("%s: dump complete", func);
2060}
2061
2062/* This is an exported helper to rtm_read() to dump the strange
2063 * RIB entry found by rib_lookup_ipv4_route()
2064 */
2065
2066void rib_lookup_and_dump (struct prefix_ipv4 * p)
2067{
2068 struct route_table *table;
2069 struct route_node *rn;
2070 struct rib *rib;
2071 char prefix_buf[INET_ADDRSTRLEN];
2072
2073 /* Lookup table. */
2074 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2075 if (! table)
2076 {
2077 zlog_err ("%s: vrf_table() returned NULL", __func__);
2078 return;
2079 }
2080
Denis Ovsienkodc958242007-08-13 16:03:06 +00002081 /* Scan the RIB table for exactly matching RIB entry. */
2082 rn = route_node_lookup (table, (struct prefix *) p);
2083
2084 /* No route for this prefix. */
2085 if (! rn)
2086 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03002087 zlog_debug ("%s: lookup failed for %s", __func__,
2088 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00002089 return;
2090 }
2091
2092 /* Unlock node. */
2093 route_unlock_node (rn);
2094
2095 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002096 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002097 {
2098 zlog_debug
2099 (
2100 "%s: rn %p, rib %p: %s, %s",
2101 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01002102 (void *)rn,
2103 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002104 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2105 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2106 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002107 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002108 }
2109}
2110
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002111/* Check if requested address assignment will fail due to another
2112 * route being installed by zebra in FIB already. Take necessary
2113 * actions, if needed: remove such a route from FIB and deSELECT
2114 * corresponding RIB entry. Then put affected RN into RIBQ head.
2115 */
2116void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2117{
2118 struct route_table *table;
2119 struct route_node *rn;
2120 struct rib *rib;
2121 unsigned changed = 0;
2122
2123 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2124 {
2125 zlog_err ("%s: vrf_table() returned NULL", __func__);
2126 return;
2127 }
2128
2129 /* No matches would be the simplest case. */
2130 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2131 return;
2132
2133 /* Unlock node. */
2134 route_unlock_node (rn);
2135
2136 /* Check all RIB entries. In case any changes have to be done, requeue
2137 * the RN into RIBQ head. If the routing message about the new connected
2138 * route (generated by the IP address we are going to assign very soon)
2139 * comes before the RIBQ is processed, the new RIB entry will join
2140 * RIBQ record already on head. This is necessary for proper revalidation
2141 * of the rest of the RIB.
2142 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002143 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002144 {
2145 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2146 ! RIB_SYSTEM_ROUTE (rib))
2147 {
2148 changed = 1;
2149 if (IS_ZEBRA_DEBUG_RIB)
2150 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03002151 char buf[PREFIX_STRLEN];
2152 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
2153 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00002154 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002155 }
2156 rib_uninstall (rn, rib);
2157 }
2158 }
2159 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002160 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002161}
2162
paul718e3742002-12-13 20:15:29 +00002163int
G.Balajicddf3912011-11-26 21:59:32 +04002164rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002165{
2166 struct route_table *table;
2167 struct route_node *rn;
2168 struct rib *same;
2169 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002170
paul718e3742002-12-13 20:15:29 +00002171 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002172 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002173 if (! table)
2174 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002175
paul718e3742002-12-13 20:15:29 +00002176 /* Make it sure prefixlen is applied to the prefix. */
2177 apply_mask_ipv4 (p);
2178
2179 /* Set default distance by route type. */
2180 if (rib->distance == 0)
2181 {
2182 rib->distance = route_info[rib->type].distance;
2183
2184 /* iBGP distance is 200. */
2185 if (rib->type == ZEBRA_ROUTE_BGP
2186 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2187 rib->distance = 200;
2188 }
2189
2190 /* Lookup route node.*/
2191 rn = route_node_get (table, (struct prefix *) p);
2192
2193 /* If same type of route are installed, treat it as a implicit
2194 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002195 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002196 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002197 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002198 continue;
2199
paul718e3742002-12-13 20:15:29 +00002200 if (same->type == rib->type && same->table == rib->table
2201 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002202 break;
paul718e3742002-12-13 20:15:29 +00002203 }
paul4d38fdb2005-04-28 17:35:14 +00002204
paul718e3742002-12-13 20:15:29 +00002205 /* If this route is kernel route, set FIB flag to the route. */
2206 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2207 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2208 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2209
2210 /* Link new rib to node.*/
2211 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002212 if (IS_ZEBRA_DEBUG_RIB)
2213 {
2214 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002215 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002216 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002217 }
paul718e3742002-12-13 20:15:29 +00002218
paul718e3742002-12-13 20:15:29 +00002219 /* Free implicit route.*/
2220 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002221 {
2222 if (IS_ZEBRA_DEBUG_RIB)
2223 {
2224 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002225 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002226 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002227 }
paul4d38fdb2005-04-28 17:35:14 +00002228 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002229 }
paul4d38fdb2005-04-28 17:35:14 +00002230
2231 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002232 return 0;
2233}
2234
hassoebf1ead2005-09-21 14:58:20 +00002235/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002236int
2237rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002238 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002239{
2240 struct route_table *table;
2241 struct route_node *rn;
2242 struct rib *rib;
2243 struct rib *fib = NULL;
2244 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002245 struct nexthop *nexthop, *tnexthop;
2246 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002247 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002248 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002249
2250 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002251 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002252 if (! table)
2253 return 0;
2254
2255 /* Apply mask. */
2256 apply_mask_ipv4 (p);
2257
Christian Frankeb52aef12013-11-27 17:06:15 +00002258 if (IS_ZEBRA_DEBUG_KERNEL)
2259 {
2260 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002261 zlog_debug ("rib_delete_ipv4(): route delete %s via %s ifindex %d",
2262 prefix2str (p, buf1, sizeof(buf1)),
Christian Frankeb52aef12013-11-27 17:06:15 +00002263 inet_ntoa (*gate),
2264 ifindex);
2265 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002266 zlog_debug ("rib_delete_ipv4(): route delete %s ifindex %d",
2267 prefix2str (p, buf1, sizeof(buf1)),
Christian Frankeb52aef12013-11-27 17:06:15 +00002268 ifindex);
2269 }
paul5ec90d22003-06-19 01:41:37 +00002270
paul718e3742002-12-13 20:15:29 +00002271 /* Lookup route node. */
2272 rn = route_node_lookup (table, (struct prefix *) p);
2273 if (! rn)
2274 {
2275 if (IS_ZEBRA_DEBUG_KERNEL)
2276 {
2277 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002278 zlog_debug ("route %s via %s ifindex %d doesn't exist in rib",
2279 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002280 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002281 ifindex);
2282 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002283 zlog_debug ("route %s ifindex %d doesn't exist in rib",
2284 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002285 ifindex);
2286 }
2287 return ZEBRA_ERR_RTNOEXIST;
2288 }
2289
2290 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002291 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002292 {
Paul Jakma6d691122006-07-27 21:49:00 +00002293 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2294 continue;
2295
paul718e3742002-12-13 20:15:29 +00002296 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2297 fib = rib;
2298
hassoebf1ead2005-09-21 14:58:20 +00002299 if (rib->type != type)
2300 continue;
2301 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002302 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002303 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002304 if (nexthop->ifindex != ifindex)
2305 continue;
hassoebf1ead2005-09-21 14:58:20 +00002306 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002307 {
hassoebf1ead2005-09-21 14:58:20 +00002308 rib->refcnt--;
2309 route_unlock_node (rn);
2310 route_unlock_node (rn);
2311 return 0;
paul718e3742002-12-13 20:15:29 +00002312 }
hassoebf1ead2005-09-21 14:58:20 +00002313 same = rib;
2314 break;
paul718e3742002-12-13 20:15:29 +00002315 }
hassoebf1ead2005-09-21 14:58:20 +00002316 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002317 else
paul5ec90d22003-06-19 01:41:37 +00002318 {
Christian Frankefa713d92013-07-05 15:35:37 +00002319 if (gate == NULL)
2320 {
2321 same = rib;
2322 break;
2323 }
2324 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2325 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2326 {
2327 same = rib;
2328 break;
2329 }
2330 if (same)
2331 break;
2332 }
paul718e3742002-12-13 20:15:29 +00002333 }
paul718e3742002-12-13 20:15:29 +00002334 /* If same type of route can't be found and this message is from
2335 kernel. */
2336 if (! same)
2337 {
2338 if (fib && type == ZEBRA_ROUTE_KERNEL)
2339 {
2340 /* Unset flags. */
2341 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2342 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2343
2344 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2345 }
2346 else
2347 {
2348 if (IS_ZEBRA_DEBUG_KERNEL)
2349 {
2350 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002351 zlog_debug ("route %s via %s ifindex %d type %d doesn't exist in rib",
2352 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002353 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002354 ifindex,
2355 type);
2356 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002357 zlog_debug ("route %s ifindex %d type %d doesn't exist in rib",
2358 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002359 ifindex,
2360 type);
2361 }
2362 route_unlock_node (rn);
2363 return ZEBRA_ERR_RTNOEXIST;
2364 }
2365 }
paul4d38fdb2005-04-28 17:35:14 +00002366
paul718e3742002-12-13 20:15:29 +00002367 if (same)
2368 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002369
paul718e3742002-12-13 20:15:29 +00002370 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002371 return 0;
2372}
David Lamparter6b0655a2014-06-04 06:53:35 +02002373
paul718e3742002-12-13 20:15:29 +00002374/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002375static void
Everton Marques33d86db2014-07-14 11:19:00 -03002376static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002377{
2378 struct rib *rib;
2379 struct route_node *rn;
2380 struct route_table *table;
2381
2382 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002383 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002384 if (! table)
2385 return;
2386
2387 /* Lookup existing route */
2388 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002389 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002390 {
2391 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2392 continue;
2393
2394 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2395 break;
2396 }
paul718e3742002-12-13 20:15:29 +00002397
2398 if (rib)
2399 {
2400 /* Same distance static route is there. Update it with new
2401 nexthop. */
paul718e3742002-12-13 20:15:29 +00002402 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002403 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002404 {
2405 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002406 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002407 break;
2408 case STATIC_IPV4_IFNAME:
2409 nexthop_ifname_add (rib, si->gate.ifname);
2410 break;
2411 case STATIC_IPV4_BLACKHOLE:
2412 nexthop_blackhole_add (rib);
2413 break;
paul4d38fdb2005-04-28 17:35:14 +00002414 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002415 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002416 }
2417 else
2418 {
2419 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002420 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2421
paul718e3742002-12-13 20:15:29 +00002422 rib->type = ZEBRA_ROUTE_STATIC;
2423 rib->distance = si->distance;
2424 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002425 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002426 rib->nexthop_num = 0;
2427
2428 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002429 {
2430 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002431 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002432 break;
2433 case STATIC_IPV4_IFNAME:
2434 nexthop_ifname_add (rib, si->gate.ifname);
2435 break;
2436 case STATIC_IPV4_BLACKHOLE:
2437 nexthop_blackhole_add (rib);
2438 break;
2439 }
paul718e3742002-12-13 20:15:29 +00002440
hasso81dfcaa2003-05-25 19:21:25 +00002441 /* Save the flags of this static routes (reject, blackhole) */
2442 rib->flags = si->flags;
2443
paul718e3742002-12-13 20:15:29 +00002444 /* Link this rib to the tree. */
2445 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002446 }
2447}
2448
paula1ac18c2005-06-28 17:17:12 +00002449static int
paul718e3742002-12-13 20:15:29 +00002450static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2451{
2452 if (nexthop->type == NEXTHOP_TYPE_IPV4
2453 && si->type == STATIC_IPV4_GATEWAY
2454 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2455 return 1;
2456 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2457 && si->type == STATIC_IPV4_IFNAME
2458 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2459 return 1;
paul595db7f2003-05-25 21:35:06 +00002460 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2461 && si->type == STATIC_IPV4_BLACKHOLE)
2462 return 1;
paule8e19462006-01-19 20:16:55 +00002463 return 0;
paul718e3742002-12-13 20:15:29 +00002464}
2465
2466/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002467static void
Everton Marques33d86db2014-07-14 11:19:00 -03002468static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002469{
2470 struct route_node *rn;
2471 struct rib *rib;
2472 struct nexthop *nexthop;
2473 struct route_table *table;
2474
2475 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002476 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002477 if (! table)
2478 return;
paul4d38fdb2005-04-28 17:35:14 +00002479
paul718e3742002-12-13 20:15:29 +00002480 /* Lookup existing route with type and distance. */
2481 rn = route_node_lookup (table, p);
2482 if (! rn)
2483 return;
2484
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002485 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002486 {
2487 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2488 continue;
2489
2490 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2491 break;
2492 }
paul718e3742002-12-13 20:15:29 +00002493
2494 if (! rib)
2495 {
2496 route_unlock_node (rn);
2497 return;
2498 }
2499
2500 /* Lookup nexthop. */
2501 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2502 if (static_ipv4_nexthop_same (nexthop, si))
2503 break;
2504
2505 /* Can't find nexthop. */
2506 if (! nexthop)
2507 {
2508 route_unlock_node (rn);
2509 return;
2510 }
2511
2512 /* Check nexthop. */
2513 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002514 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002515 else
2516 {
paul6baeb982003-10-28 03:47:15 +00002517 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2518 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002519 nexthop_delete (rib, nexthop);
2520 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002521 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002522 }
paul718e3742002-12-13 20:15:29 +00002523 /* Unlock node. */
2524 route_unlock_node (rn);
2525}
2526
paul718e3742002-12-13 20:15:29 +00002527int
Everton Marques33d86db2014-07-14 11:19:00 -03002528static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2529 const char *ifname, u_char flags, u_char distance,
2530 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002531{
2532 u_char type = 0;
2533 struct route_node *rn;
2534 struct static_ipv4 *si;
2535 struct static_ipv4 *pp;
2536 struct static_ipv4 *cp;
2537 struct static_ipv4 *update = NULL;
2538 struct route_table *stable;
2539
2540 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002541 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002542 if (! stable)
2543 return -1;
2544
2545 /* Lookup static route prefix. */
2546 rn = route_node_get (stable, p);
2547
2548 /* Make flags. */
2549 if (gate)
2550 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002551 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002552 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002553 else
2554 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002555
2556 /* Do nothing if there is a same static route. */
2557 for (si = rn->info; si; si = si->next)
2558 {
2559 if (type == si->type
2560 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2561 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2562 {
2563 if (distance == si->distance)
2564 {
2565 route_unlock_node (rn);
2566 return 0;
2567 }
2568 else
2569 update = si;
2570 }
2571 }
2572
Paul Jakma3c0755d2006-12-08 00:53:14 +00002573 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002574 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002575 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002576
2577 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002578 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002579
2580 si->type = type;
2581 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002582 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002583
2584 if (gate)
2585 si->gate.ipv4 = *gate;
2586 if (ifname)
2587 si->gate.ifname = XSTRDUP (0, ifname);
2588
2589 /* Add new static route information to the tree with sort by
2590 distance value and gateway address. */
2591 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2592 {
2593 if (si->distance < cp->distance)
2594 break;
2595 if (si->distance > cp->distance)
2596 continue;
2597 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2598 {
2599 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2600 break;
2601 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2602 continue;
2603 }
2604 }
2605
2606 /* Make linked list. */
2607 if (pp)
2608 pp->next = si;
2609 else
2610 rn->info = si;
2611 if (cp)
2612 cp->prev = si;
2613 si->prev = pp;
2614 si->next = cp;
2615
2616 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002617 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002618
2619 return 1;
2620}
2621
paul718e3742002-12-13 20:15:29 +00002622int
Everton Marques33d86db2014-07-14 11:19:00 -03002623static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2624 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002625{
2626 u_char type = 0;
2627 struct route_node *rn;
2628 struct static_ipv4 *si;
2629 struct route_table *stable;
2630
2631 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002632 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002633 if (! stable)
2634 return -1;
2635
2636 /* Lookup static route prefix. */
2637 rn = route_node_lookup (stable, p);
2638 if (! rn)
2639 return 0;
2640
2641 /* Make flags. */
2642 if (gate)
2643 type = STATIC_IPV4_GATEWAY;
2644 else if (ifname)
2645 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002646 else
2647 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002648
2649 /* Find same static route is the tree */
2650 for (si = rn->info; si; si = si->next)
2651 if (type == si->type
2652 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2653 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2654 break;
2655
2656 /* Can't find static route. */
2657 if (! si)
2658 {
2659 route_unlock_node (rn);
2660 return 0;
2661 }
2662
2663 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002664 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002665
2666 /* Unlink static route from linked list. */
2667 if (si->prev)
2668 si->prev->next = si->next;
2669 else
2670 rn->info = si->next;
2671 if (si->next)
2672 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002673 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002674
2675 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002676 if (ifname)
2677 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002678 XFREE (MTYPE_STATIC_IPV4, si);
2679
paul143a3852003-09-29 20:06:13 +00002680 route_unlock_node (rn);
2681
paul718e3742002-12-13 20:15:29 +00002682 return 1;
2683}
2684
paul718e3742002-12-13 20:15:29 +00002685#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00002686int
2687rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002688 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002689 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002690{
2691 struct rib *rib;
2692 struct rib *same = NULL;
2693 struct route_table *table;
2694 struct route_node *rn;
2695 struct nexthop *nexthop;
2696
paul718e3742002-12-13 20:15:29 +00002697 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002698 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002699 if (! table)
2700 return 0;
2701
2702 /* Make sure mask is applied. */
2703 apply_mask_ipv6 (p);
2704
2705 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002706 if (!distance)
2707 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002708
2709 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2710 distance = 200;
2711
paul718e3742002-12-13 20:15:29 +00002712 /* Lookup route node.*/
2713 rn = route_node_get (table, (struct prefix *) p);
2714
2715 /* If same type of route are installed, treat it as a implicit
2716 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002717 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002718 {
Paul Jakma6d691122006-07-27 21:49:00 +00002719 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2720 continue;
2721
hassoebf1ead2005-09-21 14:58:20 +00002722 if (rib->type != type)
2723 continue;
2724 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002725 {
2726 same = rib;
paul718e3742002-12-13 20:15:29 +00002727 break;
2728 }
hassoebf1ead2005-09-21 14:58:20 +00002729 else if ((nexthop = rib->nexthop) &&
2730 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2731 nexthop->ifindex == ifindex)
2732 {
2733 rib->refcnt++;
2734 return 0;
2735 }
paul718e3742002-12-13 20:15:29 +00002736 }
2737
2738 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002739 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2740
paul718e3742002-12-13 20:15:29 +00002741 rib->type = type;
2742 rib->distance = distance;
2743 rib->flags = flags;
2744 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002745 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002746 rib->nexthop_num = 0;
2747 rib->uptime = time (NULL);
2748
2749 /* Nexthop settings. */
2750 if (gate)
2751 {
2752 if (ifindex)
2753 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2754 else
2755 nexthop_ipv6_add (rib, gate);
2756 }
2757 else
2758 nexthop_ifindex_add (rib, ifindex);
2759
2760 /* If this route is kernel route, set FIB flag to the route. */
2761 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2762 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2763 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2764
2765 /* Link new rib to node.*/
2766 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002767 if (IS_ZEBRA_DEBUG_RIB)
2768 {
2769 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002770 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002771 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002772 }
paul718e3742002-12-13 20:15:29 +00002773
paul718e3742002-12-13 20:15:29 +00002774 /* Free implicit route.*/
2775 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002776 {
2777 if (IS_ZEBRA_DEBUG_RIB)
2778 {
2779 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002780 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002781 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002782 }
paul4d38fdb2005-04-28 17:35:14 +00002783 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002784 }
paul4d38fdb2005-04-28 17:35:14 +00002785
2786 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002787 return 0;
2788}
2789
hassoebf1ead2005-09-21 14:58:20 +00002790/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002791int
2792rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002793 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002794{
2795 struct route_table *table;
2796 struct route_node *rn;
2797 struct rib *rib;
2798 struct rib *fib = NULL;
2799 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002800 struct nexthop *nexthop, *tnexthop;
2801 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002802 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002803 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002804
2805 /* Apply mask. */
2806 apply_mask_ipv6 (p);
2807
2808 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002809 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002810 if (! table)
2811 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002812
paul718e3742002-12-13 20:15:29 +00002813 /* Lookup route node. */
2814 rn = route_node_lookup (table, (struct prefix *) p);
2815 if (! rn)
2816 {
2817 if (IS_ZEBRA_DEBUG_KERNEL)
2818 {
2819 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002820 zlog_debug ("route %s via %s ifindex %d doesn't exist in rib",
2821 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002822 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002823 ifindex);
2824 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002825 zlog_debug ("route %s ifindex %d doesn't exist in rib",
2826 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002827 ifindex);
2828 }
2829 return ZEBRA_ERR_RTNOEXIST;
2830 }
2831
2832 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002833 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002834 {
Paul Jakma6d691122006-07-27 21:49:00 +00002835 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2836 continue;
2837
paul718e3742002-12-13 20:15:29 +00002838 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2839 fib = rib;
2840
hassoebf1ead2005-09-21 14:58:20 +00002841 if (rib->type != type)
2842 continue;
2843 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002844 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002845 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002846 if (nexthop->ifindex != ifindex)
2847 continue;
hassoebf1ead2005-09-21 14:58:20 +00002848 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002849 {
hassoebf1ead2005-09-21 14:58:20 +00002850 rib->refcnt--;
2851 route_unlock_node (rn);
2852 route_unlock_node (rn);
2853 return 0;
paul718e3742002-12-13 20:15:29 +00002854 }
hassoebf1ead2005-09-21 14:58:20 +00002855 same = rib;
2856 break;
paul718e3742002-12-13 20:15:29 +00002857 }
hassoebf1ead2005-09-21 14:58:20 +00002858 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002859 else
2860 {
2861 if (gate == NULL)
2862 {
2863 same = rib;
2864 break;
2865 }
2866 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2867 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2868 {
2869 same = rib;
2870 break;
2871 }
2872 if (same)
2873 break;
2874 }
paul718e3742002-12-13 20:15:29 +00002875 }
2876
2877 /* If same type of route can't be found and this message is from
2878 kernel. */
2879 if (! same)
2880 {
2881 if (fib && type == ZEBRA_ROUTE_KERNEL)
2882 {
2883 /* Unset flags. */
2884 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2885 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2886
2887 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2888 }
2889 else
2890 {
2891 if (IS_ZEBRA_DEBUG_KERNEL)
2892 {
2893 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002894 zlog_debug ("route %s via %s ifindex %d type %d doesn't exist in rib",
2895 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002896 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002897 ifindex,
2898 type);
2899 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002900 zlog_debug ("route %s ifindex %d type %d doesn't exist in rib",
2901 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002902 ifindex,
2903 type);
2904 }
2905 route_unlock_node (rn);
2906 return ZEBRA_ERR_RTNOEXIST;
2907 }
2908 }
2909
2910 if (same)
2911 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002912
paul718e3742002-12-13 20:15:29 +00002913 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002914 return 0;
2915}
David Lamparter6b0655a2014-06-04 06:53:35 +02002916
paul718e3742002-12-13 20:15:29 +00002917/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002918static void
paul718e3742002-12-13 20:15:29 +00002919static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2920{
2921 struct rib *rib;
2922 struct route_table *table;
2923 struct route_node *rn;
2924
2925 /* Lookup table. */
2926 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2927 if (! table)
2928 return;
2929
2930 /* Lookup existing route */
2931 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002932 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002933 {
2934 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2935 continue;
2936
2937 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2938 break;
2939 }
paul718e3742002-12-13 20:15:29 +00002940
2941 if (rib)
2942 {
2943 /* Same distance static route is there. Update it with new
2944 nexthop. */
paul718e3742002-12-13 20:15:29 +00002945 route_unlock_node (rn);
2946
2947 switch (si->type)
2948 {
2949 case STATIC_IPV6_GATEWAY:
2950 nexthop_ipv6_add (rib, &si->ipv6);
2951 break;
2952 case STATIC_IPV6_IFNAME:
2953 nexthop_ifname_add (rib, si->ifname);
2954 break;
2955 case STATIC_IPV6_GATEWAY_IFNAME:
2956 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2957 break;
2958 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002959 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002960 }
2961 else
2962 {
2963 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002964 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2965
paul718e3742002-12-13 20:15:29 +00002966 rib->type = ZEBRA_ROUTE_STATIC;
2967 rib->distance = si->distance;
2968 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002969 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002970 rib->nexthop_num = 0;
2971
2972 switch (si->type)
2973 {
2974 case STATIC_IPV6_GATEWAY:
2975 nexthop_ipv6_add (rib, &si->ipv6);
2976 break;
2977 case STATIC_IPV6_IFNAME:
2978 nexthop_ifname_add (rib, si->ifname);
2979 break;
2980 case STATIC_IPV6_GATEWAY_IFNAME:
2981 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2982 break;
2983 }
2984
hasso81dfcaa2003-05-25 19:21:25 +00002985 /* Save the flags of this static routes (reject, blackhole) */
2986 rib->flags = si->flags;
2987
paul718e3742002-12-13 20:15:29 +00002988 /* Link this rib to the tree. */
2989 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002990 }
2991}
2992
paula1ac18c2005-06-28 17:17:12 +00002993static int
paul718e3742002-12-13 20:15:29 +00002994static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2995{
2996 if (nexthop->type == NEXTHOP_TYPE_IPV6
2997 && si->type == STATIC_IPV6_GATEWAY
2998 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2999 return 1;
3000 if (nexthop->type == NEXTHOP_TYPE_IFNAME
3001 && si->type == STATIC_IPV6_IFNAME
3002 && strcmp (nexthop->ifname, si->ifname) == 0)
3003 return 1;
3004 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3005 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3006 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3007 && strcmp (nexthop->ifname, si->ifname) == 0)
3008 return 1;
paule8e19462006-01-19 20:16:55 +00003009 return 0;
paul718e3742002-12-13 20:15:29 +00003010}
3011
paula1ac18c2005-06-28 17:17:12 +00003012static void
paul718e3742002-12-13 20:15:29 +00003013static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3014{
3015 struct route_table *table;
3016 struct route_node *rn;
3017 struct rib *rib;
3018 struct nexthop *nexthop;
3019
3020 /* Lookup table. */
3021 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3022 if (! table)
3023 return;
3024
3025 /* Lookup existing route with type and distance. */
3026 rn = route_node_lookup (table, (struct prefix *) p);
3027 if (! rn)
3028 return;
3029
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003030 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003031 {
3032 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3033 continue;
3034
3035 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3036 break;
3037 }
3038
paul718e3742002-12-13 20:15:29 +00003039 if (! rib)
3040 {
3041 route_unlock_node (rn);
3042 return;
3043 }
3044
3045 /* Lookup nexthop. */
3046 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3047 if (static_ipv6_nexthop_same (nexthop, si))
3048 break;
3049
3050 /* Can't find nexthop. */
3051 if (! nexthop)
3052 {
3053 route_unlock_node (rn);
3054 return;
3055 }
3056
3057 /* Check nexthop. */
3058 if (rib->nexthop_num == 1)
3059 {
3060 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003061 }
3062 else
3063 {
paul6baeb982003-10-28 03:47:15 +00003064 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3065 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003066 nexthop_delete (rib, nexthop);
3067 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003068 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003069 }
paul718e3742002-12-13 20:15:29 +00003070 /* Unlock node. */
3071 route_unlock_node (rn);
3072}
3073
3074/* Add static route into static route configuration. */
3075int
3076static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003077 const char *ifname, u_char flags, u_char distance,
3078 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003079{
3080 struct route_node *rn;
3081 struct static_ipv6 *si;
3082 struct static_ipv6 *pp;
3083 struct static_ipv6 *cp;
3084 struct route_table *stable;
3085
3086 /* Lookup table. */
3087 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3088 if (! stable)
3089 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003090
3091 if (!gate &&
3092 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3093 return -1;
3094
3095 if (!ifname &&
3096 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3097 return -1;
paul718e3742002-12-13 20:15:29 +00003098
3099 /* Lookup static route prefix. */
3100 rn = route_node_get (stable, p);
3101
3102 /* Do nothing if there is a same static route. */
3103 for (si = rn->info; si; si = si->next)
3104 {
3105 if (distance == si->distance
3106 && type == si->type
3107 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3108 && (! ifname || strcmp (ifname, si->ifname) == 0))
3109 {
3110 route_unlock_node (rn);
3111 return 0;
3112 }
3113 }
3114
3115 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003116 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003117
3118 si->type = type;
3119 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003120 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003121
3122 switch (type)
3123 {
3124 case STATIC_IPV6_GATEWAY:
3125 si->ipv6 = *gate;
3126 break;
3127 case STATIC_IPV6_IFNAME:
3128 si->ifname = XSTRDUP (0, ifname);
3129 break;
3130 case STATIC_IPV6_GATEWAY_IFNAME:
3131 si->ipv6 = *gate;
3132 si->ifname = XSTRDUP (0, ifname);
3133 break;
3134 }
3135
3136 /* Add new static route information to the tree with sort by
3137 distance value and gateway address. */
3138 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3139 {
3140 if (si->distance < cp->distance)
3141 break;
3142 if (si->distance > cp->distance)
3143 continue;
3144 }
3145
3146 /* Make linked list. */
3147 if (pp)
3148 pp->next = si;
3149 else
3150 rn->info = si;
3151 if (cp)
3152 cp->prev = si;
3153 si->prev = pp;
3154 si->next = cp;
3155
3156 /* Install into rib. */
3157 static_install_ipv6 (p, si);
3158
3159 return 1;
3160}
3161
3162/* Delete static route from static route configuration. */
3163int
3164static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003165 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003166{
3167 struct route_node *rn;
3168 struct static_ipv6 *si;
3169 struct route_table *stable;
3170
3171 /* Lookup table. */
3172 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3173 if (! stable)
3174 return -1;
3175
3176 /* Lookup static route prefix. */
3177 rn = route_node_lookup (stable, p);
3178 if (! rn)
3179 return 0;
3180
3181 /* Find same static route is the tree */
3182 for (si = rn->info; si; si = si->next)
3183 if (distance == si->distance
3184 && type == si->type
3185 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3186 && (! ifname || strcmp (ifname, si->ifname) == 0))
3187 break;
3188
3189 /* Can't find static route. */
3190 if (! si)
3191 {
3192 route_unlock_node (rn);
3193 return 0;
3194 }
3195
3196 /* Install into rib. */
3197 static_uninstall_ipv6 (p, si);
3198
3199 /* Unlink static route from linked list. */
3200 if (si->prev)
3201 si->prev->next = si->next;
3202 else
3203 rn->info = si->next;
3204 if (si->next)
3205 si->next->prev = si->prev;
3206
3207 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003208 if (ifname)
3209 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003210 XFREE (MTYPE_STATIC_IPV6, si);
3211
3212 return 1;
3213}
3214#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003215
paul718e3742002-12-13 20:15:29 +00003216/* RIB update function. */
3217void
paula1ac18c2005-06-28 17:17:12 +00003218rib_update (void)
paul718e3742002-12-13 20:15:29 +00003219{
3220 struct route_node *rn;
3221 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003222
paul718e3742002-12-13 20:15:29 +00003223 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3224 if (table)
3225 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003226 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003227 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003228
3229 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3230 if (table)
3231 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003232 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003233 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003234}
3235
David Lamparter6b0655a2014-06-04 06:53:35 +02003236
paul718e3742002-12-13 20:15:29 +00003237/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003238static void
paul718e3742002-12-13 20:15:29 +00003239rib_weed_table (struct route_table *table)
3240{
3241 struct route_node *rn;
3242 struct rib *rib;
3243 struct rib *next;
3244
3245 if (table)
3246 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003247 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003248 {
Paul Jakma6d691122006-07-27 21:49:00 +00003249 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3250 continue;
3251
paulb21b19c2003-06-15 01:28:29 +00003252 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003253 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003254 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003255 }
3256}
3257
3258/* Delete all routes from non main table. */
3259void
paula1ac18c2005-06-28 17:17:12 +00003260rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003261{
3262 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3263 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3264}
David Lamparter6b0655a2014-06-04 06:53:35 +02003265
paul718e3742002-12-13 20:15:29 +00003266/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003267static void
paul718e3742002-12-13 20:15:29 +00003268rib_sweep_table (struct route_table *table)
3269{
3270 struct route_node *rn;
3271 struct rib *rib;
3272 struct rib *next;
3273 int ret = 0;
3274
3275 if (table)
3276 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003277 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003278 {
Paul Jakma6d691122006-07-27 21:49:00 +00003279 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3280 continue;
3281
paul718e3742002-12-13 20:15:29 +00003282 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3283 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3284 {
3285 ret = rib_uninstall_kernel (rn, rib);
3286 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003287 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003288 }
3289 }
3290}
3291
3292/* Sweep all RIB tables. */
3293void
paula1ac18c2005-06-28 17:17:12 +00003294rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003295{
3296 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3297 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3298}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003299
3300/* Remove specific by protocol routes from 'table'. */
3301static unsigned long
3302rib_score_proto_table (u_char proto, struct route_table *table)
3303{
3304 struct route_node *rn;
3305 struct rib *rib;
3306 struct rib *next;
3307 unsigned long n = 0;
3308
3309 if (table)
3310 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003311 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003312 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003313 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3314 continue;
3315 if (rib->type == proto)
3316 {
3317 rib_delnode (rn, rib);
3318 n++;
3319 }
3320 }
3321
3322 return n;
3323}
3324
3325/* Remove specific by protocol routes. */
3326unsigned long
3327rib_score_proto (u_char proto)
3328{
3329 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3330 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3331}
3332
paul718e3742002-12-13 20:15:29 +00003333/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003334static void
paul718e3742002-12-13 20:15:29 +00003335rib_close_table (struct route_table *table)
3336{
3337 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003338 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003339 struct rib *rib;
3340
3341 if (table)
3342 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003343 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003344 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003345 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3346 continue;
3347
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003348 if (info->safi == SAFI_UNICAST)
3349 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003350
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003351 if (! RIB_SYSTEM_ROUTE (rib))
3352 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003353 }
paul718e3742002-12-13 20:15:29 +00003354}
3355
3356/* Close all RIB tables. */
3357void
paula1ac18c2005-06-28 17:17:12 +00003358rib_close (void)
paul718e3742002-12-13 20:15:29 +00003359{
3360 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3361 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3362}
David Lamparter6b0655a2014-06-04 06:53:35 +02003363
paul718e3742002-12-13 20:15:29 +00003364/* Routing information base initialize. */
3365void
paula1ac18c2005-06-28 17:17:12 +00003366rib_init (void)
paul718e3742002-12-13 20:15:29 +00003367{
paul4d38fdb2005-04-28 17:35:14 +00003368 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003369 /* VRF initialization. */
3370 vrf_init ();
3371}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003372
3373/*
3374 * vrf_id_get_next
3375 *
3376 * Get the first vrf id that is greater than the given vrf id if any.
3377 *
3378 * Returns TRUE if a vrf id was found, FALSE otherwise.
3379 */
3380static inline int
3381vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3382{
3383 while (++id < vector_active (vrf_vector))
3384 {
3385 if (vrf_lookup (id))
3386 {
3387 *next_id_p = id;
3388 return 1;
3389 }
3390 }
3391
3392 return 0;
3393}
3394
3395/*
3396 * rib_tables_iter_next
3397 *
3398 * Returns the next table in the iteration.
3399 */
3400struct route_table *
3401rib_tables_iter_next (rib_tables_iter_t *iter)
3402{
3403 struct route_table *table;
3404
3405 /*
3406 * Array that helps us go over all AFI/SAFI combinations via one
3407 * index.
3408 */
3409 static struct {
3410 afi_t afi;
3411 safi_t safi;
3412 } afi_safis[] = {
3413 { AFI_IP, SAFI_UNICAST },
3414 { AFI_IP, SAFI_MULTICAST },
3415 { AFI_IP6, SAFI_UNICAST },
3416 { AFI_IP6, SAFI_MULTICAST },
3417 };
3418
3419 table = NULL;
3420
3421 switch (iter->state)
3422 {
3423
3424 case RIB_TABLES_ITER_S_INIT:
3425 iter->vrf_id = 0;
3426 iter->afi_safi_ix = -1;
3427
3428 /* Fall through */
3429
3430 case RIB_TABLES_ITER_S_ITERATING:
3431 iter->afi_safi_ix++;
3432 while (1)
3433 {
3434
3435 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3436 {
3437 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3438 afi_safis[iter->afi_safi_ix].safi,
3439 iter->vrf_id);
3440 if (table)
3441 break;
3442
3443 iter->afi_safi_ix++;
3444 }
3445
3446 /*
3447 * Found another table in this vrf.
3448 */
3449 if (table)
3450 break;
3451
3452 /*
3453 * Done with all tables in the current vrf, go to the next
3454 * one.
3455 */
3456 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3457 break;
3458
3459 iter->afi_safi_ix = 0;
3460 }
3461
3462 break;
3463
3464 case RIB_TABLES_ITER_S_DONE:
3465 return NULL;
3466 }
3467
3468 if (table)
3469 iter->state = RIB_TABLES_ITER_S_ITERATING;
3470 else
3471 iter->state = RIB_TABLES_ITER_S_DONE;
3472
3473 return table;
3474}