blob: 0750e6eb6df1ee0846bd7b5d41294962d8010638 [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 Lamparter94813742014-04-24 20:22:53 +020081static void
82_rnode_zlog(const char *_func, struct route_node *rn, int priority,
83 const char *msgfmt, ...)
84{
85 char buf[INET6_ADDRSTRLEN + 4], *bptr;
86 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
David Lamparter94813742014-04-24 20:22:53 +020097 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
98 bptr = buf + strlen(buf);
David Lamparterab2ba612015-01-22 19:02:13 +010099 snprintf(bptr, buf + sizeof(buf) - bptr, "/%d%s", rn->p.prefixlen,
100 info->safi == SAFI_MULTICAST ? " (MRIB)" : "");
David Lamparter94813742014-04-24 20:22:53 +0200101 }
102 else
103 {
104 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
105 }
106
107 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
108}
109
110#define rnode_debug(node, ...) \
111 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
112#define rnode_info(node, ...) \
113 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
114
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000115/*
116 * vrf_table_create
117 */
118static void
119vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
120{
121 rib_table_info_t *info;
122 struct route_table *table;
123
124 assert (!vrf->table[afi][safi]);
125
126 table = route_table_init ();
127 vrf->table[afi][safi] = table;
128
129 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
130 info->vrf = vrf;
131 info->afi = afi;
132 info->safi = safi;
133 table->info = info;
134}
135
paul718e3742002-12-13 20:15:29 +0000136/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +0000137static struct vrf *
hassofce954f2004-10-07 20:29:24 +0000138vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +0000139{
140 struct vrf *vrf;
141
142 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
143
144 /* Put name. */
145 if (name)
146 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
147
148 /* Allocate routing table and static table. */
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000149 vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
150 vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000151 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
152 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000153 vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
154 vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
G.Balajicddf3912011-11-26 21:59:32 +0400155 vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
156 vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
157
paul718e3742002-12-13 20:15:29 +0000158
159 return vrf;
160}
161
paul718e3742002-12-13 20:15:29 +0000162/* Lookup VRF by identifier. */
163struct vrf *
164vrf_lookup (u_int32_t id)
165{
166 return vector_lookup (vrf_vector, id);
167}
168
paul718e3742002-12-13 20:15:29 +0000169/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000170static void
171vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000172{
173 struct vrf *default_table;
174
175 /* Allocate VRF vector. */
176 vrf_vector = vector_init (1);
177
178 /* Allocate default main table. */
179 default_table = vrf_alloc ("Default-IP-Routing-Table");
180
181 /* Default table index must be 0. */
182 vector_set_index (vrf_vector, 0, default_table);
183}
184
185/* Lookup route table. */
186struct route_table *
187vrf_table (afi_t afi, safi_t safi, u_int32_t id)
188{
189 struct vrf *vrf;
190
191 vrf = vrf_lookup (id);
192 if (! vrf)
193 return NULL;
194
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000195 if( afi >= AFI_MAX || safi >= SAFI_MAX )
196 return NULL;
197
paul718e3742002-12-13 20:15:29 +0000198 return vrf->table[afi][safi];
199}
200
201/* Lookup static route table. */
202struct route_table *
203vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
204{
205 struct vrf *vrf;
206
207 vrf = vrf_lookup (id);
208 if (! vrf)
209 return NULL;
210
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000211 if( afi >= AFI_MAX || safi >= SAFI_MAX )
212 return NULL;
213
paul718e3742002-12-13 20:15:29 +0000214 return vrf->stable[afi][safi];
215}
David Lamparter6b0655a2014-06-04 06:53:35 +0200216
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000217/*
218 * nexthop_type_to_str
219 */
220const char *
221nexthop_type_to_str (enum nexthop_types_t nh_type)
222{
223 static const char *desc[] = {
224 "none",
225 "Directly connected",
226 "Interface route",
227 "IPv4 nexthop",
228 "IPv4 nexthop with ifindex",
229 "IPv4 nexthop with ifname",
230 "IPv6 nexthop",
231 "IPv6 nexthop with ifindex",
232 "IPv6 nexthop with ifname",
233 "Null0 nexthop",
234 };
235
236 if (nh_type >= ZEBRA_NUM_OF (desc))
237 return "<Invalid nh type>";
238
239 return desc[nh_type];
240}
241
Christian Frankefa713d92013-07-05 15:35:37 +0000242/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000243static void
Christian Frankefa713d92013-07-05 15:35:37 +0000244_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000245{
246 struct nexthop *last;
247
Christian Frankefa713d92013-07-05 15:35:37 +0000248 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000249 ;
250 if (last)
251 last->next = nexthop;
252 else
Christian Frankefa713d92013-07-05 15:35:37 +0000253 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000254 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000255}
paul718e3742002-12-13 20:15:29 +0000256
Christian Frankefa713d92013-07-05 15:35:37 +0000257/* Add nexthop to the end of a rib node's nexthop list */
258static void
259nexthop_add (struct rib *rib, struct nexthop *nexthop)
260{
261 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000262 rib->nexthop_num++;
263}
264
265/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000266static void
paul718e3742002-12-13 20:15:29 +0000267nexthop_delete (struct rib *rib, struct nexthop *nexthop)
268{
269 if (nexthop->next)
270 nexthop->next->prev = nexthop->prev;
271 if (nexthop->prev)
272 nexthop->prev->next = nexthop->next;
273 else
274 rib->nexthop = nexthop->next;
275 rib->nexthop_num--;
276}
277
Christian Frankefa713d92013-07-05 15:35:37 +0000278static void nexthops_free(struct nexthop *nexthop);
279
paul718e3742002-12-13 20:15:29 +0000280/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000281static void
paul718e3742002-12-13 20:15:29 +0000282nexthop_free (struct nexthop *nexthop)
283{
paula4b70762003-05-16 17:19:48 +0000284 if (nexthop->ifname)
285 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000286 if (nexthop->resolved)
287 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000288 XFREE (MTYPE_NEXTHOP, nexthop);
289}
290
Christian Frankefa713d92013-07-05 15:35:37 +0000291/* Frees a list of nexthops */
292static void
293nexthops_free (struct nexthop *nexthop)
294{
295 struct nexthop *nh, *next;
296
297 for (nh = nexthop; nh; nh = next)
298 {
299 next = nh->next;
300 nexthop_free (nh);
301 }
302}
303
paul718e3742002-12-13 20:15:29 +0000304struct nexthop *
305nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
306{
307 struct nexthop *nexthop;
308
Stephen Hemminger393deb92008-08-18 14:13:29 -0700309 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000310 nexthop->type = NEXTHOP_TYPE_IFINDEX;
311 nexthop->ifindex = ifindex;
312
313 nexthop_add (rib, nexthop);
314
315 return nexthop;
316}
317
318struct nexthop *
319nexthop_ifname_add (struct rib *rib, char *ifname)
320{
321 struct nexthop *nexthop;
322
Stephen Hemminger393deb92008-08-18 14:13:29 -0700323 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000324 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000325 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000326
327 nexthop_add (rib, nexthop);
328
329 return nexthop;
330}
331
332struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000333nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000334{
335 struct nexthop *nexthop;
336
Stephen Hemminger393deb92008-08-18 14:13:29 -0700337 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000338 nexthop->type = NEXTHOP_TYPE_IPV4;
339 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000340 if (src)
341 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000342
343 nexthop_add (rib, nexthop);
344
345 return nexthop;
346}
347
Josh Bailey26e2ae32012-03-22 01:09:21 -0700348struct nexthop *
paul718e3742002-12-13 20:15:29 +0000349nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000350 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000351{
352 struct nexthop *nexthop;
353
Stephen Hemminger393deb92008-08-18 14:13:29 -0700354 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000355 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
356 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000357 if (src)
358 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000359 nexthop->ifindex = ifindex;
360
361 nexthop_add (rib, nexthop);
362
363 return nexthop;
364}
365
366#ifdef HAVE_IPV6
367struct nexthop *
368nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
369{
370 struct nexthop *nexthop;
371
Stephen Hemminger393deb92008-08-18 14:13:29 -0700372 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000373 nexthop->type = NEXTHOP_TYPE_IPV6;
374 nexthop->gate.ipv6 = *ipv6;
375
376 nexthop_add (rib, nexthop);
377
378 return nexthop;
379}
380
paula1ac18c2005-06-28 17:17:12 +0000381static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000382nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
383 char *ifname)
384{
385 struct nexthop *nexthop;
386
Stephen Hemminger393deb92008-08-18 14:13:29 -0700387 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000388 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
389 nexthop->gate.ipv6 = *ipv6;
390 nexthop->ifname = XSTRDUP (0, ifname);
391
392 nexthop_add (rib, nexthop);
393
394 return nexthop;
395}
396
paula1ac18c2005-06-28 17:17:12 +0000397static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000398nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
399 unsigned int ifindex)
400{
401 struct nexthop *nexthop;
402
Stephen Hemminger393deb92008-08-18 14:13:29 -0700403 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000404 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
405 nexthop->gate.ipv6 = *ipv6;
406 nexthop->ifindex = ifindex;
407
408 nexthop_add (rib, nexthop);
409
410 return nexthop;
411}
412#endif /* HAVE_IPV6 */
413
paul595db7f2003-05-25 21:35:06 +0000414struct nexthop *
415nexthop_blackhole_add (struct rib *rib)
416{
417 struct nexthop *nexthop;
418
Stephen Hemminger393deb92008-08-18 14:13:29 -0700419 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000420 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
421 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
422
423 nexthop_add (rib, nexthop);
424
425 return nexthop;
426}
427
Christian Frankefa713d92013-07-05 15:35:37 +0000428/* This method checks whether a recursive nexthop has at
429 * least one resolved nexthop in the fib.
430 */
431int
432nexthop_has_fib_child(struct nexthop *nexthop)
433{
434 struct nexthop *nh;
435
436 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
437 return 0;
438
439 for (nh = nexthop->resolved; nh; nh = nh->next)
440 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
441 return 1;
442
443 return 0;
444}
445
paul718e3742002-12-13 20:15:29 +0000446/* If force flag is not set, do not modify falgs at all for uninstall
447 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000448static int
paul718e3742002-12-13 20:15:29 +0000449nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
450 struct route_node *top)
451{
452 struct prefix_ipv4 p;
453 struct route_table *table;
454 struct route_node *rn;
455 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000456 int resolved;
paul718e3742002-12-13 20:15:29 +0000457 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000458 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000459
460 if (nexthop->type == NEXTHOP_TYPE_IPV4)
461 nexthop->ifindex = 0;
462
463 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000464 {
465 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
466 nexthops_free(nexthop->resolved);
467 nexthop->resolved = NULL;
468 }
paul718e3742002-12-13 20:15:29 +0000469
470 /* Make lookup prefix. */
471 memset (&p, 0, sizeof (struct prefix_ipv4));
472 p.family = AF_INET;
473 p.prefixlen = IPV4_MAX_PREFIXLEN;
474 p.prefix = nexthop->gate.ipv4;
475
476 /* Lookup table. */
477 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
478 if (! table)
479 return 0;
480
481 rn = route_node_match (table, (struct prefix *) &p);
482 while (rn)
483 {
484 route_unlock_node (rn);
485
David Warda50c1072009-12-03 15:34:39 +0300486 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000487 if (rn == top)
488 return 0;
489
490 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000491 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100492 {
493 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
494 continue;
495 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
496 break;
497 }
paul718e3742002-12-13 20:15:29 +0000498
499 /* If there is no selected route or matched route is EGP, go up
500 tree. */
501 if (! match
502 || match->type == ZEBRA_ROUTE_BGP)
503 {
504 do {
505 rn = rn->parent;
506 } while (rn && rn->info == NULL);
507 if (rn)
508 route_lock_node (rn);
509 }
510 else
511 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000512 /* If the longest prefix match for the nexthop yields
513 * a blackhole, mark it as inactive. */
514 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
515 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
516 return 0;
517
paul718e3742002-12-13 20:15:29 +0000518 if (match->type == ZEBRA_ROUTE_CONNECT)
519 {
520 /* Directly point connected route. */
521 newhop = match->nexthop;
522 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
523 nexthop->ifindex = newhop->ifindex;
524
525 return 1;
526 }
527 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
528 {
Christian Frankefa713d92013-07-05 15:35:37 +0000529 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000530 for (newhop = match->nexthop; newhop; newhop = newhop->next)
531 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
532 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
533 {
534 if (set)
535 {
536 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000537
538 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
539 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000540 /* If the resolving route specifies a gateway, use it */
541 if (newhop->type == NEXTHOP_TYPE_IPV4
542 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
543 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
544 {
545 resolved_hop->type = newhop->type;
546 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000547
Christian Frankec3e6b592013-07-05 15:35:40 +0000548 if (newhop->ifindex)
549 {
550 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
551 resolved_hop->ifindex = newhop->ifindex;
552 }
553 }
Christian Frankefa713d92013-07-05 15:35:37 +0000554
Christian Frankec3e6b592013-07-05 15:35:40 +0000555 /* If the resolving route is an interface route,
556 * it means the gateway we are looking up is connected
557 * to that interface. (The actual network is _not_ onlink).
558 * Therefore, the resolved route should have the original
559 * gateway as nexthop as it is directly connected.
560 *
561 * On Linux, we have to set the onlink netlink flag because
562 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000563 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000564 || newhop->type == NEXTHOP_TYPE_IFNAME)
565 {
566 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
567 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
568 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
569 resolved_hop->ifindex = newhop->ifindex;
570 }
Christian Frankefa713d92013-07-05 15:35:37 +0000571
572 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000573 }
Christian Frankefa713d92013-07-05 15:35:37 +0000574 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000575 }
Christian Frankefa713d92013-07-05 15:35:37 +0000576 return resolved;
paul718e3742002-12-13 20:15:29 +0000577 }
578 else
579 {
580 return 0;
581 }
582 }
583 }
584 return 0;
585}
586
587#ifdef HAVE_IPV6
588/* If force flag is not set, do not modify falgs at all for uninstall
589 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000590static int
paul718e3742002-12-13 20:15:29 +0000591nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
592 struct route_node *top)
593{
594 struct prefix_ipv6 p;
595 struct route_table *table;
596 struct route_node *rn;
597 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000598 int resolved;
paul718e3742002-12-13 20:15:29 +0000599 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000600 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000601
602 if (nexthop->type == NEXTHOP_TYPE_IPV6)
603 nexthop->ifindex = 0;
604
605 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000606 {
607 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
608 nexthops_free(nexthop->resolved);
609 nexthop->resolved = NULL;
610 }
paul718e3742002-12-13 20:15:29 +0000611
612 /* Make lookup prefix. */
613 memset (&p, 0, sizeof (struct prefix_ipv6));
614 p.family = AF_INET6;
615 p.prefixlen = IPV6_MAX_PREFIXLEN;
616 p.prefix = nexthop->gate.ipv6;
617
618 /* Lookup table. */
619 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
620 if (! table)
621 return 0;
622
623 rn = route_node_match (table, (struct prefix *) &p);
624 while (rn)
625 {
626 route_unlock_node (rn);
627
David Warda50c1072009-12-03 15:34:39 +0300628 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000629 if (rn == top)
630 return 0;
631
632 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000633 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100634 {
635 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
636 continue;
637 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
638 break;
639 }
paul718e3742002-12-13 20:15:29 +0000640
641 /* If there is no selected route or matched route is EGP, go up
642 tree. */
643 if (! match
644 || match->type == ZEBRA_ROUTE_BGP)
645 {
646 do {
647 rn = rn->parent;
648 } while (rn && rn->info == NULL);
649 if (rn)
650 route_lock_node (rn);
651 }
652 else
653 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000654 /* If the longest prefix match for the nexthop yields
655 * a blackhole, mark it as inactive. */
656 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
657 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
658 return 0;
659
paul718e3742002-12-13 20:15:29 +0000660 if (match->type == ZEBRA_ROUTE_CONNECT)
661 {
662 /* Directly point connected route. */
663 newhop = match->nexthop;
664
665 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
666 nexthop->ifindex = newhop->ifindex;
667
668 return 1;
669 }
670 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
671 {
Christian Frankefa713d92013-07-05 15:35:37 +0000672 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000673 for (newhop = match->nexthop; newhop; newhop = newhop->next)
674 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
675 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
676 {
677 if (set)
678 {
679 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000680
681 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
682 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000683 /* See nexthop_active_ipv4 for a description how the
684 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000685 if (newhop->type == NEXTHOP_TYPE_IPV6
686 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
687 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000688 {
689 resolved_hop->type = newhop->type;
690 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
691
692 if (newhop->ifindex)
693 {
694 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
695 resolved_hop->ifindex = newhop->ifindex;
696 }
697 }
Christian Frankefa713d92013-07-05 15:35:37 +0000698
paul718e3742002-12-13 20:15:29 +0000699 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000700 || newhop->type == NEXTHOP_TYPE_IFNAME)
701 {
702 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
703 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
704 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
705 resolved_hop->ifindex = newhop->ifindex;
706 }
Christian Frankefa713d92013-07-05 15:35:37 +0000707
708 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000709 }
Christian Frankefa713d92013-07-05 15:35:37 +0000710 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000711 }
Christian Frankefa713d92013-07-05 15:35:37 +0000712 return resolved;
paul718e3742002-12-13 20:15:29 +0000713 }
714 else
715 {
716 return 0;
717 }
718 }
719 }
720 return 0;
721}
722#endif /* HAVE_IPV6 */
723
724struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100725rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
726 struct route_node **rn_out)
Everton Marques3dea1782014-09-22 19:35:51 -0300727{
728 struct route_table *table;
729 struct route_node *rn;
730 struct rib *match;
731 struct nexthop *newhop, *tnewhop;
732 int recursing;
733
734 /* Lookup table. */
735 table = vrf_table (AFI_IP, safi, 0);
736 if (! table)
737 return 0;
738
739 rn = route_node_match_ipv4 (table, &addr);
740
741 while (rn)
742 {
743 route_unlock_node (rn);
744
745 /* Pick up selected route. */
746 RNODE_FOREACH_RIB (rn, match)
747 {
748 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
749 continue;
750 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
751 break;
752 }
753
754 /* If there is no selected route or matched route is EGP, go up
755 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300756 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300757 {
758 do {
759 rn = rn->parent;
760 } while (rn && rn->info == NULL);
761 if (rn)
762 route_lock_node (rn);
763 }
764 else
765 {
David Lamparter24480d42015-01-22 19:09:36 +0100766 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300767 {
David Lamparter24480d42015-01-22 19:09:36 +0100768 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300769 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
770 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100771 {
772 found = 1;
773 break;
774 }
775 if (!found)
776 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300777 }
David Lamparter24480d42015-01-22 19:09:36 +0100778
779 if (rn_out)
780 *rn_out = rn;
781 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300782 }
783 }
784 return NULL;
785}
786
787struct rib *
David Lamparterbd078122015-01-06 19:53:24 +0100788rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
789{
790 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
791 struct route_node *m_rn = NULL, *u_rn = NULL;
792 int skip_bgp = 0; /* bool */
793
794 switch (ipv4_multicast_mode)
795 {
796 case MCAST_MRIB_ONLY:
797 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
798 case MCAST_URIB_ONLY:
799 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
800 case MCAST_NO_CONFIG:
801 case MCAST_MIX_MRIB_FIRST:
802 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
803 if (!mrib)
804 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
805 break;
806 case MCAST_MIX_DISTANCE:
807 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
808 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
809 if (mrib && urib)
810 rib = urib->distance < mrib->distance ? urib : mrib;
811 else if (mrib)
812 rib = mrib;
813 else if (urib)
814 rib = urib;
815 break;
816 case MCAST_MIX_PFXLEN:
817 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
818 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
819 if (mrib && urib)
820 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
821 else if (mrib)
822 rib = mrib;
823 else if (urib)
824 rib = urib;
825 break;
826 }
827
828 if (rn_out)
829 *rn_out = (rib == mrib) ? m_rn : u_rn;
830
831 if (IS_ZEBRA_DEBUG_RIB)
832 {
833 char buf[BUFSIZ];
834 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
835
836 zlog_debug("%s: %s: found %s, using %s",
837 __func__, buf,
838 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
839 urib ? "URIB" : "nothing",
840 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
841 }
842 return rib;
843}
844
845void
846multicast_mode_ipv4_set (enum multicast_mode mode)
847{
848 if (IS_ZEBRA_DEBUG_RIB)
849 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
850 ipv4_multicast_mode = mode;
851}
852
853enum multicast_mode
854multicast_mode_ipv4_get (void)
855{
856 return ipv4_multicast_mode;
857}
858
859struct rib *
paul718e3742002-12-13 20:15:29 +0000860rib_lookup_ipv4 (struct prefix_ipv4 *p)
861{
862 struct route_table *table;
863 struct route_node *rn;
864 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000865 struct nexthop *nexthop, *tnexthop;
866 int recursing;
paul718e3742002-12-13 20:15:29 +0000867
868 /* Lookup table. */
869 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
870 if (! table)
871 return 0;
872
873 rn = route_node_lookup (table, (struct prefix *) p);
874
875 /* No route for this prefix. */
876 if (! rn)
877 return NULL;
878
879 /* Unlock node. */
880 route_unlock_node (rn);
881
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000882 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100883 {
884 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
885 continue;
886 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
887 break;
888 }
paul718e3742002-12-13 20:15:29 +0000889
890 if (! match || match->type == ZEBRA_ROUTE_BGP)
891 return NULL;
892
893 if (match->type == ZEBRA_ROUTE_CONNECT)
894 return match;
895
Christian Frankefa713d92013-07-05 15:35:37 +0000896 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000897 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
898 return match;
899
900 return NULL;
901}
902
Denis Ovsienkodc958242007-08-13 16:03:06 +0000903/*
904 * This clone function, unlike its original rib_lookup_ipv4(), checks
905 * if specified IPv4 route record (prefix/mask -> gate) exists in
906 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
907 *
908 * Return values:
909 * -1: error
910 * 0: exact match found
911 * 1: a match was found with a different gate
912 * 2: connected route found
913 * 3: no matches found
914 */
915int
916rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
917{
918 struct route_table *table;
919 struct route_node *rn;
920 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000921 struct nexthop *nexthop, *tnexthop;
922 int recursing;
923 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000924
925 /* Lookup table. */
926 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
927 if (! table)
928 return ZEBRA_RIB_LOOKUP_ERROR;
929
930 /* Scan the RIB table for exactly matching RIB entry. */
931 rn = route_node_lookup (table, (struct prefix *) p);
932
933 /* No route for this prefix. */
934 if (! rn)
935 return ZEBRA_RIB_NOTFOUND;
936
937 /* Unlock node. */
938 route_unlock_node (rn);
939
940 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000941 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100942 {
943 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
944 continue;
945 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
946 break;
947 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000948
949 /* None such found :( */
950 if (!match)
951 return ZEBRA_RIB_NOTFOUND;
952
953 if (match->type == ZEBRA_ROUTE_CONNECT)
954 return ZEBRA_RIB_FOUND_CONNECTED;
955
956 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000957 nexthops_active = 0;
958 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000959 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000960 {
Christian Frankefa713d92013-07-05 15:35:37 +0000961 nexthops_active = 1;
962 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
963 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000964 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000965 {
966 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
967 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
968 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
969 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
970 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
971 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000972 }
Christian Frankefa713d92013-07-05 15:35:37 +0000973
974 if (nexthops_active)
975 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000976
977 return ZEBRA_RIB_NOTFOUND;
978}
979
paul718e3742002-12-13 20:15:29 +0000980#ifdef HAVE_IPV6
981struct rib *
982rib_match_ipv6 (struct in6_addr *addr)
983{
984 struct prefix_ipv6 p;
985 struct route_table *table;
986 struct route_node *rn;
987 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000988 struct nexthop *newhop, *tnewhop;
989 int recursing;
paul718e3742002-12-13 20:15:29 +0000990
991 /* Lookup table. */
992 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
993 if (! table)
994 return 0;
995
996 memset (&p, 0, sizeof (struct prefix_ipv6));
997 p.family = AF_INET6;
998 p.prefixlen = IPV6_MAX_PREFIXLEN;
999 IPV6_ADDR_COPY (&p.prefix, addr);
1000
1001 rn = route_node_match (table, (struct prefix *) &p);
1002
1003 while (rn)
1004 {
1005 route_unlock_node (rn);
1006
1007 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001008 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +01001009 {
1010 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
1011 continue;
1012 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
1013 break;
1014 }
paul718e3742002-12-13 20:15:29 +00001015
1016 /* If there is no selected route or matched route is EGP, go up
1017 tree. */
1018 if (! match
1019 || match->type == ZEBRA_ROUTE_BGP)
1020 {
1021 do {
1022 rn = rn->parent;
1023 } while (rn && rn->info == NULL);
1024 if (rn)
1025 route_lock_node (rn);
1026 }
1027 else
1028 {
1029 if (match->type == ZEBRA_ROUTE_CONNECT)
1030 /* Directly point connected route. */
1031 return match;
1032 else
1033 {
Christian Frankefa713d92013-07-05 15:35:37 +00001034 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +00001035 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1036 return match;
1037 return NULL;
1038 }
1039 }
1040 }
1041 return NULL;
1042}
1043#endif /* HAVE_IPV6 */
1044
Paul Jakma7514fb72007-05-02 16:05:35 +00001045#define RIB_SYSTEM_ROUTE(R) \
1046 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
1047
Denis Ovsienkodc958242007-08-13 16:03:06 +00001048/* This function verifies reachability of one given nexthop, which can be
1049 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
1050 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
1051 * nexthop->ifindex will be updated appropriately as well.
1052 * An existing route map can turn (otherwise active) nexthop into inactive, but
1053 * not vice versa.
1054 *
1055 * The return value is the final value of 'ACTIVE' flag.
1056 */
1057
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001058static unsigned
paul718e3742002-12-13 20:15:29 +00001059nexthop_active_check (struct route_node *rn, struct rib *rib,
1060 struct nexthop *nexthop, int set)
1061{
Christian Frankef3a17322013-07-05 15:35:41 +00001062 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +00001063 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +00001064 route_map_result_t ret = RMAP_MATCH;
1065 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
1066 struct route_map *rmap;
1067 int family;
paul718e3742002-12-13 20:15:29 +00001068
Paul Jakma7514fb72007-05-02 16:05:35 +00001069 family = 0;
paul718e3742002-12-13 20:15:29 +00001070 switch (nexthop->type)
1071 {
1072 case NEXTHOP_TYPE_IFINDEX:
1073 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001074 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001075 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1076 else
1077 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1078 break;
paul718e3742002-12-13 20:15:29 +00001079 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001080 family = AFI_IP6;
1081 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001082 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001083 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001084 {
1085 if (set)
1086 nexthop->ifindex = ifp->ifindex;
1087 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1088 }
1089 else
1090 {
1091 if (set)
1092 nexthop->ifindex = 0;
1093 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1094 }
1095 break;
1096 case NEXTHOP_TYPE_IPV4:
1097 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001098 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001099 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1100 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1101 else
1102 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1103 break;
1104#ifdef HAVE_IPV6
1105 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001106 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001107 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1108 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1109 else
1110 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1111 break;
1112 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001113 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001114 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1115 {
1116 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001117 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001118 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1119 else
1120 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1121 }
1122 else
1123 {
1124 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1125 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1126 else
1127 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1128 }
1129 break;
1130#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001131 case NEXTHOP_TYPE_BLACKHOLE:
1132 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1133 break;
paul718e3742002-12-13 20:15:29 +00001134 default:
1135 break;
1136 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001137 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1138 return 0;
1139
Christian Frankef3a17322013-07-05 15:35:41 +00001140 /* XXX: What exactly do those checks do? Do we support
1141 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001142 if (RIB_SYSTEM_ROUTE(rib) ||
1143 (family == AFI_IP && rn->p.family != AF_INET) ||
1144 (family == AFI_IP6 && rn->p.family != AF_INET6))
1145 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1146
Christian Frankef3a17322013-07-05 15:35:41 +00001147 /* The original code didn't determine the family correctly
1148 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1149 * from the rib_table_info in those cases.
1150 * Possibly it may be better to use only the rib_table_info
1151 * in every case.
1152 */
1153 if (!family)
1154 family = info->afi;
1155
Paul Jakma7514fb72007-05-02 16:05:35 +00001156 rmap = 0;
1157 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1158 proto_rm[family][rib->type])
1159 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1160 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1161 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1162 if (rmap) {
1163 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1164 }
1165
1166 if (ret == RMAP_DENYMATCH)
1167 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001168 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1169}
1170
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001171/* Iterate over all nexthops of the given RIB entry and refresh their
1172 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1173 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1174 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1175 * transparently passed to nexthop_active_check().
1176 *
1177 * Return value is the new number of active nexthops.
1178 */
1179
paula1ac18c2005-06-28 17:17:12 +00001180static int
paul718e3742002-12-13 20:15:29 +00001181nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1182{
1183 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001184 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001185
1186 rib->nexthop_active_num = 0;
1187 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1188
1189 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001190 {
1191 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001192 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001193 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1194 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001195 if (prev_active != new_active ||
1196 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001197 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1198 }
paul718e3742002-12-13 20:15:29 +00001199 return rib->nexthop_active_num;
1200}
paul6baeb982003-10-28 03:47:15 +00001201
David Lamparter6b0655a2014-06-04 06:53:35 +02001202
paul718e3742002-12-13 20:15:29 +00001203
paula1ac18c2005-06-28 17:17:12 +00001204static void
paul718e3742002-12-13 20:15:29 +00001205rib_install_kernel (struct route_node *rn, struct rib *rib)
1206{
1207 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001208 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001209 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001210 int recursing;
paul718e3742002-12-13 20:15:29 +00001211
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001212 if (info->safi != SAFI_UNICAST)
1213 {
1214 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1215 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1216 return;
1217 }
1218
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001219 /*
1220 * Make sure we update the FPM any time we send new information to
1221 * the kernel.
1222 */
1223 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001224 switch (PREFIX_FAMILY (&rn->p))
1225 {
1226 case AF_INET:
1227 ret = kernel_add_ipv4 (&rn->p, rib);
1228 break;
1229#ifdef HAVE_IPV6
1230 case AF_INET6:
1231 ret = kernel_add_ipv6 (&rn->p, rib);
1232 break;
1233#endif /* HAVE_IPV6 */
1234 }
1235
Denis Ovsienkodc958242007-08-13 16:03:06 +00001236 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001237 if (ret < 0)
1238 {
Christian Frankefa713d92013-07-05 15:35:37 +00001239 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001240 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1241 }
1242}
1243
1244/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001245static int
paul718e3742002-12-13 20:15:29 +00001246rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1247{
1248 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001249 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001250 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001251 int recursing;
paul718e3742002-12-13 20:15:29 +00001252
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001253 if (info->safi != SAFI_UNICAST)
1254 {
1255 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1256 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1257 return ret;
1258 }
1259
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001260 /*
1261 * Make sure we update the FPM any time we send new information to
1262 * the kernel.
1263 */
1264 zfpm_trigger_update (rn, "uninstalling from kernel");
1265
paul718e3742002-12-13 20:15:29 +00001266 switch (PREFIX_FAMILY (&rn->p))
1267 {
1268 case AF_INET:
1269 ret = kernel_delete_ipv4 (&rn->p, rib);
1270 break;
1271#ifdef HAVE_IPV6
1272 case AF_INET6:
1273 ret = kernel_delete_ipv6 (&rn->p, rib);
1274 break;
1275#endif /* HAVE_IPV6 */
1276 }
1277
Christian Frankefa713d92013-07-05 15:35:37 +00001278 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001279 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1280
1281 return ret;
1282}
1283
1284/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001285static void
paul718e3742002-12-13 20:15:29 +00001286rib_uninstall (struct route_node *rn, struct rib *rib)
1287{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001288 rib_table_info_t *info = rn->table->info;
1289
paul718e3742002-12-13 20:15:29 +00001290 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1291 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001292 if (info->safi == SAFI_UNICAST)
1293 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001294
paul718e3742002-12-13 20:15:29 +00001295 redistribute_delete (&rn->p, rib);
1296 if (! RIB_SYSTEM_ROUTE (rib))
1297 rib_uninstall_kernel (rn, rib);
1298 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1299 }
1300}
1301
Paul Jakma6d691122006-07-27 21:49:00 +00001302static void rib_unlink (struct route_node *, struct rib *);
1303
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001304/*
1305 * rib_can_delete_dest
1306 *
1307 * Returns TRUE if the given dest can be deleted from the table.
1308 */
1309static int
1310rib_can_delete_dest (rib_dest_t *dest)
1311{
1312 if (dest->routes)
1313 {
1314 return 0;
1315 }
1316
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001317 /*
1318 * Don't delete the dest if we have to update the FPM about this
1319 * prefix.
1320 */
1321 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1322 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1323 return 0;
1324
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001325 return 1;
1326}
1327
1328/*
1329 * rib_gc_dest
1330 *
1331 * Garbage collect the rib dest corresponding to the given route node
1332 * if appropriate.
1333 *
1334 * Returns TRUE if the dest was deleted, FALSE otherwise.
1335 */
1336int
1337rib_gc_dest (struct route_node *rn)
1338{
1339 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001340
1341 dest = rib_dest_from_rnode (rn);
1342 if (!dest)
1343 return 0;
1344
1345 if (!rib_can_delete_dest (dest))
1346 return 0;
1347
1348 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001349 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001350
1351 dest->rnode = NULL;
1352 XFREE (MTYPE_RIB_DEST, dest);
1353 rn->info = NULL;
1354
1355 /*
1356 * Release the one reference that we keep on the route node.
1357 */
1358 route_unlock_node (rn);
1359 return 1;
1360}
1361
paul718e3742002-12-13 20:15:29 +00001362/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001363static void
1364rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001365{
1366 struct rib *rib;
1367 struct rib *next;
1368 struct rib *fib = NULL;
1369 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001370 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001371 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001372 struct nexthop *nexthop = NULL, *tnexthop;
1373 int recursing;
Balaji95116332014-10-23 15:25:25 +00001374 rib_table_info_t *info;
1375
paul4d38fdb2005-04-28 17:35:14 +00001376 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001377
1378 info = rn->table->info;
1379
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001380 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001381 {
paul718e3742002-12-13 20:15:29 +00001382 /* Currently installed rib. */
1383 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001384 {
1385 assert (fib == NULL);
1386 fib = rib;
1387 }
1388
1389 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1390 * which we need to do do further work with below.
1391 */
1392 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1393 {
1394 if (rib != fib)
1395 {
1396 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001397 rnode_debug (rn, "rn %p, removing rib %p", rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001398 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",
1469 select, 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 Lamparter94813742014-04-24 20:22:53 +02001514 rnode_debug (rn, "Removing existing route, fib %p", 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 Lamparter94813742014-04-24 20:22:53 +02001535 rnode_debug (rn, "Adding route, select %p", 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 Lamparter94813742014-04-24 20:22:53 +02001553 rnode_debug (rn, "Deleting fib %p, rn %p", del, 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 Lamparter94813742014-04-24 20:22:53 +02001559 rnode_debug (rn, "rn %p dequeued", 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",
1654 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",
1665 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",
1679 __func__, rn, rn->lock);
1680 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 Lamparter94813742014-04-24 20:22:53 +02001709 rnode_debug (rn, "rn %p queued", 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 Lamparter94813742014-04-24 20:22:53 +02001810 rnode_debug (rn, "rn %p, rib %p", rn, 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 Lamparter94813742014-04-24 20:22:53 +02001843 rnode_debug (rn, "rn %p, un-removed rib %p", rn, rib);
1844
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 Lamparter94813742014-04-24 20:22:53 +02001868 rnode_debug (rn, "rn %p, rib %p", rn, 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 Lamparter94813742014-04-24 20:22:53 +02001892 rnode_debug (rn, "rn %p, rib %p, removing", rn, 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)
1986 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001987 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001988
paul718e3742002-12-13 20:15:29 +00001989 /* Free implicit route.*/
1990 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001991 {
1992 if (IS_ZEBRA_DEBUG_RIB)
1993 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001994 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001995 }
paul4d38fdb2005-04-28 17:35:14 +00001996
1997 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001998 return 0;
1999}
2000
Denis Ovsienkodc958242007-08-13 16:03:06 +00002001/* This function dumps the contents of a given RIB entry into
2002 * standard debug log. Calling function name and IP prefix in
2003 * question are passed as 1st and 2nd arguments.
2004 */
2005
David Lamparterf7bf4152013-10-22 17:10:21 +00002006void _rib_dump (const char * func,
2007 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002008{
David Lamparterf7bf4152013-10-22 17:10:21 +00002009 const struct prefix *p = pp.p;
Vincent Bernatfed643f2012-10-23 16:00:42 +00002010 char straddr[INET6_ADDRSTRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00002011 struct nexthop *nexthop, *tnexthop;
2012 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00002013
Vincent Bernatfed643f2012-10-23 16:00:42 +00002014 inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002015 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002016 zlog_debug
2017 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002018 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00002019 func,
2020 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002021 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002022 rib->type,
2023 rib->table
2024 );
2025 zlog_debug
2026 (
2027 "%s: metric == %u, distance == %u, flags == %u, status == %u",
2028 func,
2029 rib->metric,
2030 rib->distance,
2031 rib->flags,
2032 rib->status
2033 );
2034 zlog_debug
2035 (
2036 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
2037 func,
2038 rib->nexthop_num,
2039 rib->nexthop_active_num,
2040 rib->nexthop_fib_num
2041 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00002042
Christian Frankefa713d92013-07-05 15:35:37 +00002043 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2044 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00002045 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002046 zlog_debug
2047 (
2048 "%s: %s %s with flags %s%s%s",
2049 func,
2050 (recursing ? " NH" : "NH"),
2051 straddr,
2052 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
2053 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
2054 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
2055 );
2056 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00002057 zlog_debug ("%s: dump complete", func);
2058}
2059
2060/* This is an exported helper to rtm_read() to dump the strange
2061 * RIB entry found by rib_lookup_ipv4_route()
2062 */
2063
2064void rib_lookup_and_dump (struct prefix_ipv4 * p)
2065{
2066 struct route_table *table;
2067 struct route_node *rn;
2068 struct rib *rib;
2069 char prefix_buf[INET_ADDRSTRLEN];
2070
2071 /* Lookup table. */
2072 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2073 if (! table)
2074 {
2075 zlog_err ("%s: vrf_table() returned NULL", __func__);
2076 return;
2077 }
2078
2079 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
2080 /* Scan the RIB table for exactly matching RIB entry. */
2081 rn = route_node_lookup (table, (struct prefix *) p);
2082
2083 /* No route for this prefix. */
2084 if (! rn)
2085 {
2086 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
2087 return;
2088 }
2089
2090 /* Unlock node. */
2091 route_unlock_node (rn);
2092
2093 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002094 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002095 {
2096 zlog_debug
2097 (
2098 "%s: rn %p, rib %p: %s, %s",
2099 __func__,
2100 rn,
2101 rib,
2102 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2103 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2104 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002105 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002106 }
2107}
2108
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002109/* Check if requested address assignment will fail due to another
2110 * route being installed by zebra in FIB already. Take necessary
2111 * actions, if needed: remove such a route from FIB and deSELECT
2112 * corresponding RIB entry. Then put affected RN into RIBQ head.
2113 */
2114void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2115{
2116 struct route_table *table;
2117 struct route_node *rn;
2118 struct rib *rib;
2119 unsigned changed = 0;
2120
2121 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2122 {
2123 zlog_err ("%s: vrf_table() returned NULL", __func__);
2124 return;
2125 }
2126
2127 /* No matches would be the simplest case. */
2128 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2129 return;
2130
2131 /* Unlock node. */
2132 route_unlock_node (rn);
2133
2134 /* Check all RIB entries. In case any changes have to be done, requeue
2135 * the RN into RIBQ head. If the routing message about the new connected
2136 * route (generated by the IP address we are going to assign very soon)
2137 * comes before the RIBQ is processed, the new RIB entry will join
2138 * RIBQ record already on head. This is necessary for proper revalidation
2139 * of the rest of the RIB.
2140 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002141 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002142 {
2143 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2144 ! RIB_SYSTEM_ROUTE (rib))
2145 {
2146 changed = 1;
2147 if (IS_ZEBRA_DEBUG_RIB)
2148 {
2149 char buf[INET_ADDRSTRLEN];
2150 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
2151 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
David Lamparterf7bf4152013-10-22 17:10:21 +00002152 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002153 }
2154 rib_uninstall (rn, rib);
2155 }
2156 }
2157 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002158 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002159}
2160
paul718e3742002-12-13 20:15:29 +00002161int
G.Balajicddf3912011-11-26 21:59:32 +04002162rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002163{
2164 struct route_table *table;
2165 struct route_node *rn;
2166 struct rib *same;
2167 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002168
paul718e3742002-12-13 20:15:29 +00002169 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002170 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002171 if (! table)
2172 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002173
paul718e3742002-12-13 20:15:29 +00002174 /* Make it sure prefixlen is applied to the prefix. */
2175 apply_mask_ipv4 (p);
2176
2177 /* Set default distance by route type. */
2178 if (rib->distance == 0)
2179 {
2180 rib->distance = route_info[rib->type].distance;
2181
2182 /* iBGP distance is 200. */
2183 if (rib->type == ZEBRA_ROUTE_BGP
2184 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2185 rib->distance = 200;
2186 }
2187
2188 /* Lookup route node.*/
2189 rn = route_node_get (table, (struct prefix *) p);
2190
2191 /* If same type of route are installed, treat it as a implicit
2192 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002193 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002194 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002195 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002196 continue;
2197
paul718e3742002-12-13 20:15:29 +00002198 if (same->type == rib->type && same->table == rib->table
2199 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002200 break;
paul718e3742002-12-13 20:15:29 +00002201 }
paul4d38fdb2005-04-28 17:35:14 +00002202
paul718e3742002-12-13 20:15:29 +00002203 /* If this route is kernel route, set FIB flag to the route. */
2204 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2205 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2206 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2207
2208 /* Link new rib to node.*/
2209 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002210 if (IS_ZEBRA_DEBUG_RIB)
2211 {
2212 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2213 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002214 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002215 }
paul718e3742002-12-13 20:15:29 +00002216
paul718e3742002-12-13 20:15:29 +00002217 /* Free implicit route.*/
2218 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002219 {
2220 if (IS_ZEBRA_DEBUG_RIB)
2221 {
2222 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2223 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002224 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002225 }
paul4d38fdb2005-04-28 17:35:14 +00002226 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002227 }
paul4d38fdb2005-04-28 17:35:14 +00002228
2229 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002230 return 0;
2231}
2232
hassoebf1ead2005-09-21 14:58:20 +00002233/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002234int
2235rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002236 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002237{
2238 struct route_table *table;
2239 struct route_node *rn;
2240 struct rib *rib;
2241 struct rib *fib = NULL;
2242 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002243 struct nexthop *nexthop, *tnexthop;
2244 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002245 char buf1[INET_ADDRSTRLEN];
2246 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002247
2248 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002249 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002250 if (! table)
2251 return 0;
2252
2253 /* Apply mask. */
2254 apply_mask_ipv4 (p);
2255
Christian Frankeb52aef12013-11-27 17:06:15 +00002256 if (IS_ZEBRA_DEBUG_KERNEL)
2257 {
2258 if (gate)
2259 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
2260 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2261 p->prefixlen,
2262 inet_ntoa (*gate),
2263 ifindex);
2264 else
2265 zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d",
2266 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2267 p->prefixlen,
2268 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)
ajsb6178002004-12-07 21:12:56 +00002278 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002279 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002280 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002281 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002282 ifindex);
2283 else
ajsb6178002004-12-07 21:12:56 +00002284 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002285 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002286 p->prefixlen,
2287 ifindex);
2288 }
2289 return ZEBRA_ERR_RTNOEXIST;
2290 }
2291
2292 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002293 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002294 {
Paul Jakma6d691122006-07-27 21:49:00 +00002295 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2296 continue;
2297
paul718e3742002-12-13 20:15:29 +00002298 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2299 fib = rib;
2300
hassoebf1ead2005-09-21 14:58:20 +00002301 if (rib->type != type)
2302 continue;
2303 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002304 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002305 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002306 if (nexthop->ifindex != ifindex)
2307 continue;
hassoebf1ead2005-09-21 14:58:20 +00002308 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002309 {
hassoebf1ead2005-09-21 14:58:20 +00002310 rib->refcnt--;
2311 route_unlock_node (rn);
2312 route_unlock_node (rn);
2313 return 0;
paul718e3742002-12-13 20:15:29 +00002314 }
hassoebf1ead2005-09-21 14:58:20 +00002315 same = rib;
2316 break;
paul718e3742002-12-13 20:15:29 +00002317 }
hassoebf1ead2005-09-21 14:58:20 +00002318 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002319 else
paul5ec90d22003-06-19 01:41:37 +00002320 {
Christian Frankefa713d92013-07-05 15:35:37 +00002321 if (gate == NULL)
2322 {
2323 same = rib;
2324 break;
2325 }
2326 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2327 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2328 {
2329 same = rib;
2330 break;
2331 }
2332 if (same)
2333 break;
2334 }
paul718e3742002-12-13 20:15:29 +00002335 }
paul718e3742002-12-13 20:15:29 +00002336 /* If same type of route can't be found and this message is from
2337 kernel. */
2338 if (! same)
2339 {
2340 if (fib && type == ZEBRA_ROUTE_KERNEL)
2341 {
2342 /* Unset flags. */
2343 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2344 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2345
2346 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2347 }
2348 else
2349 {
2350 if (IS_ZEBRA_DEBUG_KERNEL)
2351 {
2352 if (gate)
ajsb6178002004-12-07 21:12:56 +00002353 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002354 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002355 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002356 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002357 ifindex,
2358 type);
2359 else
ajsb6178002004-12-07 21:12:56 +00002360 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002361 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002362 p->prefixlen,
2363 ifindex,
2364 type);
2365 }
2366 route_unlock_node (rn);
2367 return ZEBRA_ERR_RTNOEXIST;
2368 }
2369 }
paul4d38fdb2005-04-28 17:35:14 +00002370
paul718e3742002-12-13 20:15:29 +00002371 if (same)
2372 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002373
paul718e3742002-12-13 20:15:29 +00002374 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002375 return 0;
2376}
David Lamparter6b0655a2014-06-04 06:53:35 +02002377
paul718e3742002-12-13 20:15:29 +00002378/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002379static void
Everton Marques33d86db2014-07-14 11:19:00 -03002380static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002381{
2382 struct rib *rib;
2383 struct route_node *rn;
2384 struct route_table *table;
2385
2386 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002387 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002388 if (! table)
2389 return;
2390
2391 /* Lookup existing route */
2392 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002393 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002394 {
2395 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2396 continue;
2397
2398 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2399 break;
2400 }
paul718e3742002-12-13 20:15:29 +00002401
2402 if (rib)
2403 {
2404 /* Same distance static route is there. Update it with new
2405 nexthop. */
paul718e3742002-12-13 20:15:29 +00002406 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002407 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002408 {
2409 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002410 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002411 break;
2412 case STATIC_IPV4_IFNAME:
2413 nexthop_ifname_add (rib, si->gate.ifname);
2414 break;
2415 case STATIC_IPV4_BLACKHOLE:
2416 nexthop_blackhole_add (rib);
2417 break;
paul4d38fdb2005-04-28 17:35:14 +00002418 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002419 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002420 }
2421 else
2422 {
2423 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002424 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2425
paul718e3742002-12-13 20:15:29 +00002426 rib->type = ZEBRA_ROUTE_STATIC;
2427 rib->distance = si->distance;
2428 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002429 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002430 rib->nexthop_num = 0;
2431
2432 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002433 {
2434 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002435 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002436 break;
2437 case STATIC_IPV4_IFNAME:
2438 nexthop_ifname_add (rib, si->gate.ifname);
2439 break;
2440 case STATIC_IPV4_BLACKHOLE:
2441 nexthop_blackhole_add (rib);
2442 break;
2443 }
paul718e3742002-12-13 20:15:29 +00002444
hasso81dfcaa2003-05-25 19:21:25 +00002445 /* Save the flags of this static routes (reject, blackhole) */
2446 rib->flags = si->flags;
2447
paul718e3742002-12-13 20:15:29 +00002448 /* Link this rib to the tree. */
2449 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002450 }
2451}
2452
paula1ac18c2005-06-28 17:17:12 +00002453static int
paul718e3742002-12-13 20:15:29 +00002454static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2455{
2456 if (nexthop->type == NEXTHOP_TYPE_IPV4
2457 && si->type == STATIC_IPV4_GATEWAY
2458 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2459 return 1;
2460 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2461 && si->type == STATIC_IPV4_IFNAME
2462 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2463 return 1;
paul595db7f2003-05-25 21:35:06 +00002464 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2465 && si->type == STATIC_IPV4_BLACKHOLE)
2466 return 1;
paule8e19462006-01-19 20:16:55 +00002467 return 0;
paul718e3742002-12-13 20:15:29 +00002468}
2469
2470/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002471static void
Everton Marques33d86db2014-07-14 11:19:00 -03002472static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002473{
2474 struct route_node *rn;
2475 struct rib *rib;
2476 struct nexthop *nexthop;
2477 struct route_table *table;
2478
2479 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002480 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002481 if (! table)
2482 return;
paul4d38fdb2005-04-28 17:35:14 +00002483
paul718e3742002-12-13 20:15:29 +00002484 /* Lookup existing route with type and distance. */
2485 rn = route_node_lookup (table, p);
2486 if (! rn)
2487 return;
2488
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002489 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002490 {
2491 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2492 continue;
2493
2494 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2495 break;
2496 }
paul718e3742002-12-13 20:15:29 +00002497
2498 if (! rib)
2499 {
2500 route_unlock_node (rn);
2501 return;
2502 }
2503
2504 /* Lookup nexthop. */
2505 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2506 if (static_ipv4_nexthop_same (nexthop, si))
2507 break;
2508
2509 /* Can't find nexthop. */
2510 if (! nexthop)
2511 {
2512 route_unlock_node (rn);
2513 return;
2514 }
2515
2516 /* Check nexthop. */
2517 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002518 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002519 else
2520 {
paul6baeb982003-10-28 03:47:15 +00002521 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2522 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002523 nexthop_delete (rib, nexthop);
2524 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002525 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002526 }
paul718e3742002-12-13 20:15:29 +00002527 /* Unlock node. */
2528 route_unlock_node (rn);
2529}
2530
paul718e3742002-12-13 20:15:29 +00002531int
Everton Marques33d86db2014-07-14 11:19:00 -03002532static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2533 const char *ifname, u_char flags, u_char distance,
2534 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002535{
2536 u_char type = 0;
2537 struct route_node *rn;
2538 struct static_ipv4 *si;
2539 struct static_ipv4 *pp;
2540 struct static_ipv4 *cp;
2541 struct static_ipv4 *update = NULL;
2542 struct route_table *stable;
2543
2544 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002545 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002546 if (! stable)
2547 return -1;
2548
2549 /* Lookup static route prefix. */
2550 rn = route_node_get (stable, p);
2551
2552 /* Make flags. */
2553 if (gate)
2554 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002555 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002556 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002557 else
2558 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002559
2560 /* Do nothing if there is a same static route. */
2561 for (si = rn->info; si; si = si->next)
2562 {
2563 if (type == si->type
2564 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2565 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2566 {
2567 if (distance == si->distance)
2568 {
2569 route_unlock_node (rn);
2570 return 0;
2571 }
2572 else
2573 update = si;
2574 }
2575 }
2576
Paul Jakma3c0755d2006-12-08 00:53:14 +00002577 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002578 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002579 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002580
2581 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002582 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002583
2584 si->type = type;
2585 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002586 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002587
2588 if (gate)
2589 si->gate.ipv4 = *gate;
2590 if (ifname)
2591 si->gate.ifname = XSTRDUP (0, ifname);
2592
2593 /* Add new static route information to the tree with sort by
2594 distance value and gateway address. */
2595 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2596 {
2597 if (si->distance < cp->distance)
2598 break;
2599 if (si->distance > cp->distance)
2600 continue;
2601 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2602 {
2603 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2604 break;
2605 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2606 continue;
2607 }
2608 }
2609
2610 /* Make linked list. */
2611 if (pp)
2612 pp->next = si;
2613 else
2614 rn->info = si;
2615 if (cp)
2616 cp->prev = si;
2617 si->prev = pp;
2618 si->next = cp;
2619
2620 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002621 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002622
2623 return 1;
2624}
2625
paul718e3742002-12-13 20:15:29 +00002626int
Everton Marques33d86db2014-07-14 11:19:00 -03002627static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2628 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002629{
2630 u_char type = 0;
2631 struct route_node *rn;
2632 struct static_ipv4 *si;
2633 struct route_table *stable;
2634
2635 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002636 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002637 if (! stable)
2638 return -1;
2639
2640 /* Lookup static route prefix. */
2641 rn = route_node_lookup (stable, p);
2642 if (! rn)
2643 return 0;
2644
2645 /* Make flags. */
2646 if (gate)
2647 type = STATIC_IPV4_GATEWAY;
2648 else if (ifname)
2649 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002650 else
2651 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002652
2653 /* Find same static route is the tree */
2654 for (si = rn->info; si; si = si->next)
2655 if (type == si->type
2656 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2657 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2658 break;
2659
2660 /* Can't find static route. */
2661 if (! si)
2662 {
2663 route_unlock_node (rn);
2664 return 0;
2665 }
2666
2667 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002668 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002669
2670 /* Unlink static route from linked list. */
2671 if (si->prev)
2672 si->prev->next = si->next;
2673 else
2674 rn->info = si->next;
2675 if (si->next)
2676 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002677 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002678
2679 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002680 if (ifname)
2681 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002682 XFREE (MTYPE_STATIC_IPV4, si);
2683
paul143a3852003-09-29 20:06:13 +00002684 route_unlock_node (rn);
2685
paul718e3742002-12-13 20:15:29 +00002686 return 1;
2687}
2688
paul718e3742002-12-13 20:15:29 +00002689#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00002690int
2691rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002692 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002693 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002694{
2695 struct rib *rib;
2696 struct rib *same = NULL;
2697 struct route_table *table;
2698 struct route_node *rn;
2699 struct nexthop *nexthop;
2700
paul718e3742002-12-13 20:15:29 +00002701 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002702 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002703 if (! table)
2704 return 0;
2705
2706 /* Make sure mask is applied. */
2707 apply_mask_ipv6 (p);
2708
2709 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002710 if (!distance)
2711 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002712
2713 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2714 distance = 200;
2715
paul718e3742002-12-13 20:15:29 +00002716 /* Lookup route node.*/
2717 rn = route_node_get (table, (struct prefix *) p);
2718
2719 /* If same type of route are installed, treat it as a implicit
2720 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002721 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002722 {
Paul Jakma6d691122006-07-27 21:49:00 +00002723 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2724 continue;
2725
hassoebf1ead2005-09-21 14:58:20 +00002726 if (rib->type != type)
2727 continue;
2728 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002729 {
2730 same = rib;
paul718e3742002-12-13 20:15:29 +00002731 break;
2732 }
hassoebf1ead2005-09-21 14:58:20 +00002733 else if ((nexthop = rib->nexthop) &&
2734 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2735 nexthop->ifindex == ifindex)
2736 {
2737 rib->refcnt++;
2738 return 0;
2739 }
paul718e3742002-12-13 20:15:29 +00002740 }
2741
2742 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002743 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2744
paul718e3742002-12-13 20:15:29 +00002745 rib->type = type;
2746 rib->distance = distance;
2747 rib->flags = flags;
2748 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002749 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002750 rib->nexthop_num = 0;
2751 rib->uptime = time (NULL);
2752
2753 /* Nexthop settings. */
2754 if (gate)
2755 {
2756 if (ifindex)
2757 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2758 else
2759 nexthop_ipv6_add (rib, gate);
2760 }
2761 else
2762 nexthop_ifindex_add (rib, ifindex);
2763
2764 /* If this route is kernel route, set FIB flag to the route. */
2765 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2766 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2767 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2768
2769 /* Link new rib to node.*/
2770 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002771 if (IS_ZEBRA_DEBUG_RIB)
2772 {
2773 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2774 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002775 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002776 }
paul718e3742002-12-13 20:15:29 +00002777
paul718e3742002-12-13 20:15:29 +00002778 /* Free implicit route.*/
2779 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002780 {
2781 if (IS_ZEBRA_DEBUG_RIB)
2782 {
2783 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2784 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002785 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002786 }
paul4d38fdb2005-04-28 17:35:14 +00002787 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002788 }
paul4d38fdb2005-04-28 17:35:14 +00002789
2790 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002791 return 0;
2792}
2793
hassoebf1ead2005-09-21 14:58:20 +00002794/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002795int
2796rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002797 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002798{
2799 struct route_table *table;
2800 struct route_node *rn;
2801 struct rib *rib;
2802 struct rib *fib = NULL;
2803 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002804 struct nexthop *nexthop, *tnexthop;
2805 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002806 char buf1[INET6_ADDRSTRLEN];
2807 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002808
2809 /* Apply mask. */
2810 apply_mask_ipv6 (p);
2811
2812 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002813 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002814 if (! table)
2815 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002816
paul718e3742002-12-13 20:15:29 +00002817 /* Lookup route node. */
2818 rn = route_node_lookup (table, (struct prefix *) p);
2819 if (! rn)
2820 {
2821 if (IS_ZEBRA_DEBUG_KERNEL)
2822 {
2823 if (gate)
ajsb6178002004-12-07 21:12:56 +00002824 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002825 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002826 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002827 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002828 ifindex);
2829 else
ajsb6178002004-12-07 21:12:56 +00002830 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002831 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002832 p->prefixlen,
2833 ifindex);
2834 }
2835 return ZEBRA_ERR_RTNOEXIST;
2836 }
2837
2838 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002839 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002840 {
Paul Jakma6d691122006-07-27 21:49:00 +00002841 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2842 continue;
2843
paul718e3742002-12-13 20:15:29 +00002844 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2845 fib = rib;
2846
hassoebf1ead2005-09-21 14:58:20 +00002847 if (rib->type != type)
2848 continue;
2849 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002850 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002851 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002852 if (nexthop->ifindex != ifindex)
2853 continue;
hassoebf1ead2005-09-21 14:58:20 +00002854 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002855 {
hassoebf1ead2005-09-21 14:58:20 +00002856 rib->refcnt--;
2857 route_unlock_node (rn);
2858 route_unlock_node (rn);
2859 return 0;
paul718e3742002-12-13 20:15:29 +00002860 }
hassoebf1ead2005-09-21 14:58:20 +00002861 same = rib;
2862 break;
paul718e3742002-12-13 20:15:29 +00002863 }
hassoebf1ead2005-09-21 14:58:20 +00002864 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002865 else
2866 {
2867 if (gate == NULL)
2868 {
2869 same = rib;
2870 break;
2871 }
2872 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2873 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2874 {
2875 same = rib;
2876 break;
2877 }
2878 if (same)
2879 break;
2880 }
paul718e3742002-12-13 20:15:29 +00002881 }
2882
2883 /* If same type of route can't be found and this message is from
2884 kernel. */
2885 if (! same)
2886 {
2887 if (fib && type == ZEBRA_ROUTE_KERNEL)
2888 {
2889 /* Unset flags. */
2890 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2891 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2892
2893 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2894 }
2895 else
2896 {
2897 if (IS_ZEBRA_DEBUG_KERNEL)
2898 {
2899 if (gate)
ajsb6178002004-12-07 21:12:56 +00002900 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002901 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002902 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002903 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002904 ifindex,
2905 type);
2906 else
ajsb6178002004-12-07 21:12:56 +00002907 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002908 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002909 p->prefixlen,
2910 ifindex,
2911 type);
2912 }
2913 route_unlock_node (rn);
2914 return ZEBRA_ERR_RTNOEXIST;
2915 }
2916 }
2917
2918 if (same)
2919 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002920
paul718e3742002-12-13 20:15:29 +00002921 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002922 return 0;
2923}
David Lamparter6b0655a2014-06-04 06:53:35 +02002924
paul718e3742002-12-13 20:15:29 +00002925/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002926static void
paul718e3742002-12-13 20:15:29 +00002927static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2928{
2929 struct rib *rib;
2930 struct route_table *table;
2931 struct route_node *rn;
2932
2933 /* Lookup table. */
2934 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2935 if (! table)
2936 return;
2937
2938 /* Lookup existing route */
2939 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002940 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002941 {
2942 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2943 continue;
2944
2945 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2946 break;
2947 }
paul718e3742002-12-13 20:15:29 +00002948
2949 if (rib)
2950 {
2951 /* Same distance static route is there. Update it with new
2952 nexthop. */
paul718e3742002-12-13 20:15:29 +00002953 route_unlock_node (rn);
2954
2955 switch (si->type)
2956 {
2957 case STATIC_IPV6_GATEWAY:
2958 nexthop_ipv6_add (rib, &si->ipv6);
2959 break;
2960 case STATIC_IPV6_IFNAME:
2961 nexthop_ifname_add (rib, si->ifname);
2962 break;
2963 case STATIC_IPV6_GATEWAY_IFNAME:
2964 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2965 break;
2966 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002967 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002968 }
2969 else
2970 {
2971 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002972 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2973
paul718e3742002-12-13 20:15:29 +00002974 rib->type = ZEBRA_ROUTE_STATIC;
2975 rib->distance = si->distance;
2976 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002977 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002978 rib->nexthop_num = 0;
2979
2980 switch (si->type)
2981 {
2982 case STATIC_IPV6_GATEWAY:
2983 nexthop_ipv6_add (rib, &si->ipv6);
2984 break;
2985 case STATIC_IPV6_IFNAME:
2986 nexthop_ifname_add (rib, si->ifname);
2987 break;
2988 case STATIC_IPV6_GATEWAY_IFNAME:
2989 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2990 break;
2991 }
2992
hasso81dfcaa2003-05-25 19:21:25 +00002993 /* Save the flags of this static routes (reject, blackhole) */
2994 rib->flags = si->flags;
2995
paul718e3742002-12-13 20:15:29 +00002996 /* Link this rib to the tree. */
2997 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002998 }
2999}
3000
paula1ac18c2005-06-28 17:17:12 +00003001static int
paul718e3742002-12-13 20:15:29 +00003002static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
3003{
3004 if (nexthop->type == NEXTHOP_TYPE_IPV6
3005 && si->type == STATIC_IPV6_GATEWAY
3006 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
3007 return 1;
3008 if (nexthop->type == NEXTHOP_TYPE_IFNAME
3009 && si->type == STATIC_IPV6_IFNAME
3010 && strcmp (nexthop->ifname, si->ifname) == 0)
3011 return 1;
3012 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3013 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3014 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3015 && strcmp (nexthop->ifname, si->ifname) == 0)
3016 return 1;
paule8e19462006-01-19 20:16:55 +00003017 return 0;
paul718e3742002-12-13 20:15:29 +00003018}
3019
paula1ac18c2005-06-28 17:17:12 +00003020static void
paul718e3742002-12-13 20:15:29 +00003021static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3022{
3023 struct route_table *table;
3024 struct route_node *rn;
3025 struct rib *rib;
3026 struct nexthop *nexthop;
3027
3028 /* Lookup table. */
3029 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3030 if (! table)
3031 return;
3032
3033 /* Lookup existing route with type and distance. */
3034 rn = route_node_lookup (table, (struct prefix *) p);
3035 if (! rn)
3036 return;
3037
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003038 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003039 {
3040 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3041 continue;
3042
3043 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3044 break;
3045 }
3046
paul718e3742002-12-13 20:15:29 +00003047 if (! rib)
3048 {
3049 route_unlock_node (rn);
3050 return;
3051 }
3052
3053 /* Lookup nexthop. */
3054 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3055 if (static_ipv6_nexthop_same (nexthop, si))
3056 break;
3057
3058 /* Can't find nexthop. */
3059 if (! nexthop)
3060 {
3061 route_unlock_node (rn);
3062 return;
3063 }
3064
3065 /* Check nexthop. */
3066 if (rib->nexthop_num == 1)
3067 {
3068 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003069 }
3070 else
3071 {
paul6baeb982003-10-28 03:47:15 +00003072 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3073 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003074 nexthop_delete (rib, nexthop);
3075 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003076 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003077 }
paul718e3742002-12-13 20:15:29 +00003078 /* Unlock node. */
3079 route_unlock_node (rn);
3080}
3081
3082/* Add static route into static route configuration. */
3083int
3084static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003085 const char *ifname, u_char flags, u_char distance,
3086 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003087{
3088 struct route_node *rn;
3089 struct static_ipv6 *si;
3090 struct static_ipv6 *pp;
3091 struct static_ipv6 *cp;
3092 struct route_table *stable;
3093
3094 /* Lookup table. */
3095 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3096 if (! stable)
3097 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003098
3099 if (!gate &&
3100 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3101 return -1;
3102
3103 if (!ifname &&
3104 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3105 return -1;
paul718e3742002-12-13 20:15:29 +00003106
3107 /* Lookup static route prefix. */
3108 rn = route_node_get (stable, p);
3109
3110 /* Do nothing if there is a same static route. */
3111 for (si = rn->info; si; si = si->next)
3112 {
3113 if (distance == si->distance
3114 && type == si->type
3115 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3116 && (! ifname || strcmp (ifname, si->ifname) == 0))
3117 {
3118 route_unlock_node (rn);
3119 return 0;
3120 }
3121 }
3122
3123 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003124 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003125
3126 si->type = type;
3127 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003128 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003129
3130 switch (type)
3131 {
3132 case STATIC_IPV6_GATEWAY:
3133 si->ipv6 = *gate;
3134 break;
3135 case STATIC_IPV6_IFNAME:
3136 si->ifname = XSTRDUP (0, ifname);
3137 break;
3138 case STATIC_IPV6_GATEWAY_IFNAME:
3139 si->ipv6 = *gate;
3140 si->ifname = XSTRDUP (0, ifname);
3141 break;
3142 }
3143
3144 /* Add new static route information to the tree with sort by
3145 distance value and gateway address. */
3146 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3147 {
3148 if (si->distance < cp->distance)
3149 break;
3150 if (si->distance > cp->distance)
3151 continue;
3152 }
3153
3154 /* Make linked list. */
3155 if (pp)
3156 pp->next = si;
3157 else
3158 rn->info = si;
3159 if (cp)
3160 cp->prev = si;
3161 si->prev = pp;
3162 si->next = cp;
3163
3164 /* Install into rib. */
3165 static_install_ipv6 (p, si);
3166
3167 return 1;
3168}
3169
3170/* Delete static route from static route configuration. */
3171int
3172static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003173 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003174{
3175 struct route_node *rn;
3176 struct static_ipv6 *si;
3177 struct route_table *stable;
3178
3179 /* Lookup table. */
3180 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3181 if (! stable)
3182 return -1;
3183
3184 /* Lookup static route prefix. */
3185 rn = route_node_lookup (stable, p);
3186 if (! rn)
3187 return 0;
3188
3189 /* Find same static route is the tree */
3190 for (si = rn->info; si; si = si->next)
3191 if (distance == si->distance
3192 && type == si->type
3193 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3194 && (! ifname || strcmp (ifname, si->ifname) == 0))
3195 break;
3196
3197 /* Can't find static route. */
3198 if (! si)
3199 {
3200 route_unlock_node (rn);
3201 return 0;
3202 }
3203
3204 /* Install into rib. */
3205 static_uninstall_ipv6 (p, si);
3206
3207 /* Unlink static route from linked list. */
3208 if (si->prev)
3209 si->prev->next = si->next;
3210 else
3211 rn->info = si->next;
3212 if (si->next)
3213 si->next->prev = si->prev;
3214
3215 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003216 if (ifname)
3217 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003218 XFREE (MTYPE_STATIC_IPV6, si);
3219
3220 return 1;
3221}
3222#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003223
paul718e3742002-12-13 20:15:29 +00003224/* RIB update function. */
3225void
paula1ac18c2005-06-28 17:17:12 +00003226rib_update (void)
paul718e3742002-12-13 20:15:29 +00003227{
3228 struct route_node *rn;
3229 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003230
paul718e3742002-12-13 20:15:29 +00003231 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3232 if (table)
3233 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003234 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003235 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003236
3237 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3238 if (table)
3239 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003240 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003241 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003242}
3243
David Lamparter6b0655a2014-06-04 06:53:35 +02003244
paul718e3742002-12-13 20:15:29 +00003245/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003246static void
paul718e3742002-12-13 20:15:29 +00003247rib_weed_table (struct route_table *table)
3248{
3249 struct route_node *rn;
3250 struct rib *rib;
3251 struct rib *next;
3252
3253 if (table)
3254 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003255 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003256 {
Paul Jakma6d691122006-07-27 21:49:00 +00003257 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3258 continue;
3259
paulb21b19c2003-06-15 01:28:29 +00003260 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003261 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003262 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003263 }
3264}
3265
3266/* Delete all routes from non main table. */
3267void
paula1ac18c2005-06-28 17:17:12 +00003268rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003269{
3270 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3271 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3272}
David Lamparter6b0655a2014-06-04 06:53:35 +02003273
paul718e3742002-12-13 20:15:29 +00003274/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003275static void
paul718e3742002-12-13 20:15:29 +00003276rib_sweep_table (struct route_table *table)
3277{
3278 struct route_node *rn;
3279 struct rib *rib;
3280 struct rib *next;
3281 int ret = 0;
3282
3283 if (table)
3284 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003285 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003286 {
Paul Jakma6d691122006-07-27 21:49:00 +00003287 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3288 continue;
3289
paul718e3742002-12-13 20:15:29 +00003290 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3291 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3292 {
3293 ret = rib_uninstall_kernel (rn, rib);
3294 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003295 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003296 }
3297 }
3298}
3299
3300/* Sweep all RIB tables. */
3301void
paula1ac18c2005-06-28 17:17:12 +00003302rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003303{
3304 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3305 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3306}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003307
3308/* Remove specific by protocol routes from 'table'. */
3309static unsigned long
3310rib_score_proto_table (u_char proto, struct route_table *table)
3311{
3312 struct route_node *rn;
3313 struct rib *rib;
3314 struct rib *next;
3315 unsigned long n = 0;
3316
3317 if (table)
3318 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003319 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003320 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003321 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3322 continue;
3323 if (rib->type == proto)
3324 {
3325 rib_delnode (rn, rib);
3326 n++;
3327 }
3328 }
3329
3330 return n;
3331}
3332
3333/* Remove specific by protocol routes. */
3334unsigned long
3335rib_score_proto (u_char proto)
3336{
3337 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3338 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3339}
3340
paul718e3742002-12-13 20:15:29 +00003341/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003342static void
paul718e3742002-12-13 20:15:29 +00003343rib_close_table (struct route_table *table)
3344{
3345 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003346 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003347 struct rib *rib;
3348
3349 if (table)
3350 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003351 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003352 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003353 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3354 continue;
3355
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003356 if (info->safi == SAFI_UNICAST)
3357 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003358
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003359 if (! RIB_SYSTEM_ROUTE (rib))
3360 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003361 }
paul718e3742002-12-13 20:15:29 +00003362}
3363
3364/* Close all RIB tables. */
3365void
paula1ac18c2005-06-28 17:17:12 +00003366rib_close (void)
paul718e3742002-12-13 20:15:29 +00003367{
3368 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3369 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3370}
David Lamparter6b0655a2014-06-04 06:53:35 +02003371
paul718e3742002-12-13 20:15:29 +00003372/* Routing information base initialize. */
3373void
paula1ac18c2005-06-28 17:17:12 +00003374rib_init (void)
paul718e3742002-12-13 20:15:29 +00003375{
paul4d38fdb2005-04-28 17:35:14 +00003376 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003377 /* VRF initialization. */
3378 vrf_init ();
3379}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003380
3381/*
3382 * vrf_id_get_next
3383 *
3384 * Get the first vrf id that is greater than the given vrf id if any.
3385 *
3386 * Returns TRUE if a vrf id was found, FALSE otherwise.
3387 */
3388static inline int
3389vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3390{
3391 while (++id < vector_active (vrf_vector))
3392 {
3393 if (vrf_lookup (id))
3394 {
3395 *next_id_p = id;
3396 return 1;
3397 }
3398 }
3399
3400 return 0;
3401}
3402
3403/*
3404 * rib_tables_iter_next
3405 *
3406 * Returns the next table in the iteration.
3407 */
3408struct route_table *
3409rib_tables_iter_next (rib_tables_iter_t *iter)
3410{
3411 struct route_table *table;
3412
3413 /*
3414 * Array that helps us go over all AFI/SAFI combinations via one
3415 * index.
3416 */
3417 static struct {
3418 afi_t afi;
3419 safi_t safi;
3420 } afi_safis[] = {
3421 { AFI_IP, SAFI_UNICAST },
3422 { AFI_IP, SAFI_MULTICAST },
3423 { AFI_IP6, SAFI_UNICAST },
3424 { AFI_IP6, SAFI_MULTICAST },
3425 };
3426
3427 table = NULL;
3428
3429 switch (iter->state)
3430 {
3431
3432 case RIB_TABLES_ITER_S_INIT:
3433 iter->vrf_id = 0;
3434 iter->afi_safi_ix = -1;
3435
3436 /* Fall through */
3437
3438 case RIB_TABLES_ITER_S_ITERATING:
3439 iter->afi_safi_ix++;
3440 while (1)
3441 {
3442
3443 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3444 {
3445 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3446 afi_safis[iter->afi_safi_ix].safi,
3447 iter->vrf_id);
3448 if (table)
3449 break;
3450
3451 iter->afi_safi_ix++;
3452 }
3453
3454 /*
3455 * Found another table in this vrf.
3456 */
3457 if (table)
3458 break;
3459
3460 /*
3461 * Done with all tables in the current vrf, go to the next
3462 * one.
3463 */
3464 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3465 break;
3466
3467 iter->afi_safi_ix = 0;
3468 }
3469
3470 break;
3471
3472 case RIB_TABLES_ITER_S_DONE:
3473 return NULL;
3474 }
3475
3476 if (table)
3477 iter->state = RIB_TABLES_ITER_S_ITERATING;
3478 else
3479 iter->state = RIB_TABLES_ITER_S_DONE;
3480
3481 return table;
3482}