blob: effe23384d5c4b31870649facb0705ae2ce42b0b [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 Lamparter240c56f2015-01-06 19:53:24 +010078/* RPF lookup behaviour */
79static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
80
David Lampartere0b0ac82014-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 Lamparterf7b3d1e2015-01-22 19:02:13 +010095 rib_table_info_t *info = rn->table->info;
96
David Lampartere0b0ac82014-04-24 20:22:53 +020097 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
98 bptr = buf + strlen(buf);
David Lamparterf7b3d1e2015-01-22 19:02:13 +010099 snprintf(bptr, buf + sizeof(buf) - bptr, "/%d%s", rn->p.prefixlen,
100 info->safi == SAFI_MULTICAST ? " (MRIB)" : "");
David Lampartere0b0ac82014-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 Lamparter29ce93e2015-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 Marques346a8b52014-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 Marques12150f02014-09-19 16:39:34 -0300756 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques346a8b52014-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 Lamparter29ce93e2015-01-22 19:09:36 +0100766 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques346a8b52014-09-22 19:35:51 -0300767 {
David Lamparter29ce93e2015-01-22 19:09:36 +0100768 int found = 0;
Everton Marques346a8b52014-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 Lamparter29ce93e2015-01-22 19:09:36 +0100771 {
772 found = 1;
773 break;
774 }
775 if (!found)
776 return NULL;
Everton Marques346a8b52014-09-22 19:35:51 -0300777 }
David Lamparter29ce93e2015-01-22 19:09:36 +0100778
779 if (rn_out)
780 *rn_out = rn;
781 return match;
Everton Marques346a8b52014-09-22 19:35:51 -0300782 }
783 }
784 return NULL;
785}
786
787struct rib *
David Lamparter240c56f2015-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 Lamparterc048dcc2015-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 Lamparterc048dcc2015-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 Lamparterc048dcc2015-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 Lamparterc048dcc2015-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 Lamparterc048dcc2015-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 Lamparterc048dcc2015-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lamparterc048dcc2015-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 Lampartere0b0ac82014-04-24 20:22:53 +02001514 rnode_debug (rn, "Removing existing route, fib %p", fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001515
David Lamparterc048dcc2015-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 Lampartere0b0ac82014-04-24 20:22:53 +02001535 rnode_debug (rn, "Adding route, select %p", select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001536
David Lamparterc048dcc2015-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Lampartere0b0ac82014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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 Marques96bb2662014-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
paula1ac18c2005-06-28 17:17:12 +00002690static int
paul718e3742002-12-13 20:15:29 +00002691rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2692 struct in6_addr *gate, unsigned int ifindex, int table)
2693{
hasso726f9b22003-05-25 21:04:54 +00002694 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2695#if defined (MUSICA) || defined (LINUX)
2696 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2697 if (p->prefixlen == 96)
2698 return 0;
2699#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002700 return 1;
hasso726f9b22003-05-25 21:04:54 +00002701 }
paul718e3742002-12-13 20:15:29 +00002702 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2703 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2704 {
2705 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2706 return 1;
2707 }
2708 return 0;
2709}
2710
2711int
2712rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002713 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002714 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002715{
2716 struct rib *rib;
2717 struct rib *same = NULL;
2718 struct route_table *table;
2719 struct route_node *rn;
2720 struct nexthop *nexthop;
2721
paul718e3742002-12-13 20:15:29 +00002722 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002723 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002724 if (! table)
2725 return 0;
2726
2727 /* Make sure mask is applied. */
2728 apply_mask_ipv6 (p);
2729
2730 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002731 if (!distance)
2732 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002733
2734 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2735 distance = 200;
2736
2737 /* Filter bogus route. */
2738 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2739 return 0;
2740
2741 /* Lookup route node.*/
2742 rn = route_node_get (table, (struct prefix *) p);
2743
2744 /* If same type of route are installed, treat it as a implicit
2745 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002746 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002747 {
Paul Jakma6d691122006-07-27 21:49:00 +00002748 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2749 continue;
2750
hassoebf1ead2005-09-21 14:58:20 +00002751 if (rib->type != type)
2752 continue;
2753 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002754 {
2755 same = rib;
paul718e3742002-12-13 20:15:29 +00002756 break;
2757 }
hassoebf1ead2005-09-21 14:58:20 +00002758 else if ((nexthop = rib->nexthop) &&
2759 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2760 nexthop->ifindex == ifindex)
2761 {
2762 rib->refcnt++;
2763 return 0;
2764 }
paul718e3742002-12-13 20:15:29 +00002765 }
2766
2767 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002768 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2769
paul718e3742002-12-13 20:15:29 +00002770 rib->type = type;
2771 rib->distance = distance;
2772 rib->flags = flags;
2773 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002774 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002775 rib->nexthop_num = 0;
2776 rib->uptime = time (NULL);
2777
2778 /* Nexthop settings. */
2779 if (gate)
2780 {
2781 if (ifindex)
2782 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2783 else
2784 nexthop_ipv6_add (rib, gate);
2785 }
2786 else
2787 nexthop_ifindex_add (rib, ifindex);
2788
2789 /* If this route is kernel route, set FIB flag to the route. */
2790 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2791 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2792 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2793
2794 /* Link new rib to node.*/
2795 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002796 if (IS_ZEBRA_DEBUG_RIB)
2797 {
2798 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2799 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002800 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002801 }
paul718e3742002-12-13 20:15:29 +00002802
paul718e3742002-12-13 20:15:29 +00002803 /* Free implicit route.*/
2804 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002805 {
2806 if (IS_ZEBRA_DEBUG_RIB)
2807 {
2808 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2809 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002810 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002811 }
paul4d38fdb2005-04-28 17:35:14 +00002812 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002813 }
paul4d38fdb2005-04-28 17:35:14 +00002814
2815 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002816 return 0;
2817}
2818
hassoebf1ead2005-09-21 14:58:20 +00002819/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002820int
2821rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002822 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002823{
2824 struct route_table *table;
2825 struct route_node *rn;
2826 struct rib *rib;
2827 struct rib *fib = NULL;
2828 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002829 struct nexthop *nexthop, *tnexthop;
2830 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002831 char buf1[INET6_ADDRSTRLEN];
2832 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002833
2834 /* Apply mask. */
2835 apply_mask_ipv6 (p);
2836
2837 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002838 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002839 if (! table)
2840 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002841
paul718e3742002-12-13 20:15:29 +00002842 /* Lookup route node. */
2843 rn = route_node_lookup (table, (struct prefix *) p);
2844 if (! rn)
2845 {
2846 if (IS_ZEBRA_DEBUG_KERNEL)
2847 {
2848 if (gate)
ajsb6178002004-12-07 21:12:56 +00002849 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002850 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002851 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002852 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002853 ifindex);
2854 else
ajsb6178002004-12-07 21:12:56 +00002855 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002856 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002857 p->prefixlen,
2858 ifindex);
2859 }
2860 return ZEBRA_ERR_RTNOEXIST;
2861 }
2862
2863 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002864 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002865 {
Paul Jakma6d691122006-07-27 21:49:00 +00002866 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2867 continue;
2868
paul718e3742002-12-13 20:15:29 +00002869 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2870 fib = rib;
2871
hassoebf1ead2005-09-21 14:58:20 +00002872 if (rib->type != type)
2873 continue;
2874 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002875 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002876 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002877 if (nexthop->ifindex != ifindex)
2878 continue;
hassoebf1ead2005-09-21 14:58:20 +00002879 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002880 {
hassoebf1ead2005-09-21 14:58:20 +00002881 rib->refcnt--;
2882 route_unlock_node (rn);
2883 route_unlock_node (rn);
2884 return 0;
paul718e3742002-12-13 20:15:29 +00002885 }
hassoebf1ead2005-09-21 14:58:20 +00002886 same = rib;
2887 break;
paul718e3742002-12-13 20:15:29 +00002888 }
hassoebf1ead2005-09-21 14:58:20 +00002889 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002890 else
2891 {
2892 if (gate == NULL)
2893 {
2894 same = rib;
2895 break;
2896 }
2897 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2898 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2899 {
2900 same = rib;
2901 break;
2902 }
2903 if (same)
2904 break;
2905 }
paul718e3742002-12-13 20:15:29 +00002906 }
2907
2908 /* If same type of route can't be found and this message is from
2909 kernel. */
2910 if (! same)
2911 {
2912 if (fib && type == ZEBRA_ROUTE_KERNEL)
2913 {
2914 /* Unset flags. */
2915 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2916 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2917
2918 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2919 }
2920 else
2921 {
2922 if (IS_ZEBRA_DEBUG_KERNEL)
2923 {
2924 if (gate)
ajsb6178002004-12-07 21:12:56 +00002925 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002926 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002927 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002928 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002929 ifindex,
2930 type);
2931 else
ajsb6178002004-12-07 21:12:56 +00002932 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002933 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002934 p->prefixlen,
2935 ifindex,
2936 type);
2937 }
2938 route_unlock_node (rn);
2939 return ZEBRA_ERR_RTNOEXIST;
2940 }
2941 }
2942
2943 if (same)
2944 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002945
paul718e3742002-12-13 20:15:29 +00002946 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002947 return 0;
2948}
David Lamparter6b0655a2014-06-04 06:53:35 +02002949
paul718e3742002-12-13 20:15:29 +00002950/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002951static void
paul718e3742002-12-13 20:15:29 +00002952static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2953{
2954 struct rib *rib;
2955 struct route_table *table;
2956 struct route_node *rn;
2957
2958 /* Lookup table. */
2959 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2960 if (! table)
2961 return;
2962
2963 /* Lookup existing route */
2964 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002965 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002966 {
2967 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2968 continue;
2969
2970 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2971 break;
2972 }
paul718e3742002-12-13 20:15:29 +00002973
2974 if (rib)
2975 {
2976 /* Same distance static route is there. Update it with new
2977 nexthop. */
paul718e3742002-12-13 20:15:29 +00002978 route_unlock_node (rn);
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 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002992 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002993 }
2994 else
2995 {
2996 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002997 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2998
paul718e3742002-12-13 20:15:29 +00002999 rib->type = ZEBRA_ROUTE_STATIC;
3000 rib->distance = si->distance;
3001 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07003002 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00003003 rib->nexthop_num = 0;
3004
3005 switch (si->type)
3006 {
3007 case STATIC_IPV6_GATEWAY:
3008 nexthop_ipv6_add (rib, &si->ipv6);
3009 break;
3010 case STATIC_IPV6_IFNAME:
3011 nexthop_ifname_add (rib, si->ifname);
3012 break;
3013 case STATIC_IPV6_GATEWAY_IFNAME:
3014 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
3015 break;
3016 }
3017
hasso81dfcaa2003-05-25 19:21:25 +00003018 /* Save the flags of this static routes (reject, blackhole) */
3019 rib->flags = si->flags;
3020
paul718e3742002-12-13 20:15:29 +00003021 /* Link this rib to the tree. */
3022 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003023 }
3024}
3025
paula1ac18c2005-06-28 17:17:12 +00003026static int
paul718e3742002-12-13 20:15:29 +00003027static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
3028{
3029 if (nexthop->type == NEXTHOP_TYPE_IPV6
3030 && si->type == STATIC_IPV6_GATEWAY
3031 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
3032 return 1;
3033 if (nexthop->type == NEXTHOP_TYPE_IFNAME
3034 && si->type == STATIC_IPV6_IFNAME
3035 && strcmp (nexthop->ifname, si->ifname) == 0)
3036 return 1;
3037 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3038 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3039 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3040 && strcmp (nexthop->ifname, si->ifname) == 0)
3041 return 1;
paule8e19462006-01-19 20:16:55 +00003042 return 0;
paul718e3742002-12-13 20:15:29 +00003043}
3044
paula1ac18c2005-06-28 17:17:12 +00003045static void
paul718e3742002-12-13 20:15:29 +00003046static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3047{
3048 struct route_table *table;
3049 struct route_node *rn;
3050 struct rib *rib;
3051 struct nexthop *nexthop;
3052
3053 /* Lookup table. */
3054 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3055 if (! table)
3056 return;
3057
3058 /* Lookup existing route with type and distance. */
3059 rn = route_node_lookup (table, (struct prefix *) p);
3060 if (! rn)
3061 return;
3062
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003063 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003064 {
3065 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3066 continue;
3067
3068 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3069 break;
3070 }
3071
paul718e3742002-12-13 20:15:29 +00003072 if (! rib)
3073 {
3074 route_unlock_node (rn);
3075 return;
3076 }
3077
3078 /* Lookup nexthop. */
3079 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3080 if (static_ipv6_nexthop_same (nexthop, si))
3081 break;
3082
3083 /* Can't find nexthop. */
3084 if (! nexthop)
3085 {
3086 route_unlock_node (rn);
3087 return;
3088 }
3089
3090 /* Check nexthop. */
3091 if (rib->nexthop_num == 1)
3092 {
3093 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003094 }
3095 else
3096 {
paul6baeb982003-10-28 03:47:15 +00003097 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3098 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003099 nexthop_delete (rib, nexthop);
3100 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003101 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003102 }
paul718e3742002-12-13 20:15:29 +00003103 /* Unlock node. */
3104 route_unlock_node (rn);
3105}
3106
3107/* Add static route into static route configuration. */
3108int
3109static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003110 const char *ifname, u_char flags, u_char distance,
3111 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003112{
3113 struct route_node *rn;
3114 struct static_ipv6 *si;
3115 struct static_ipv6 *pp;
3116 struct static_ipv6 *cp;
3117 struct route_table *stable;
3118
3119 /* Lookup table. */
3120 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3121 if (! stable)
3122 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003123
3124 if (!gate &&
3125 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3126 return -1;
3127
3128 if (!ifname &&
3129 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3130 return -1;
paul718e3742002-12-13 20:15:29 +00003131
3132 /* Lookup static route prefix. */
3133 rn = route_node_get (stable, p);
3134
3135 /* Do nothing if there is a same static route. */
3136 for (si = rn->info; si; si = si->next)
3137 {
3138 if (distance == si->distance
3139 && type == si->type
3140 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3141 && (! ifname || strcmp (ifname, si->ifname) == 0))
3142 {
3143 route_unlock_node (rn);
3144 return 0;
3145 }
3146 }
3147
3148 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003149 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003150
3151 si->type = type;
3152 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003153 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003154
3155 switch (type)
3156 {
3157 case STATIC_IPV6_GATEWAY:
3158 si->ipv6 = *gate;
3159 break;
3160 case STATIC_IPV6_IFNAME:
3161 si->ifname = XSTRDUP (0, ifname);
3162 break;
3163 case STATIC_IPV6_GATEWAY_IFNAME:
3164 si->ipv6 = *gate;
3165 si->ifname = XSTRDUP (0, ifname);
3166 break;
3167 }
3168
3169 /* Add new static route information to the tree with sort by
3170 distance value and gateway address. */
3171 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3172 {
3173 if (si->distance < cp->distance)
3174 break;
3175 if (si->distance > cp->distance)
3176 continue;
3177 }
3178
3179 /* Make linked list. */
3180 if (pp)
3181 pp->next = si;
3182 else
3183 rn->info = si;
3184 if (cp)
3185 cp->prev = si;
3186 si->prev = pp;
3187 si->next = cp;
3188
3189 /* Install into rib. */
3190 static_install_ipv6 (p, si);
3191
3192 return 1;
3193}
3194
3195/* Delete static route from static route configuration. */
3196int
3197static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003198 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003199{
3200 struct route_node *rn;
3201 struct static_ipv6 *si;
3202 struct route_table *stable;
3203
3204 /* Lookup table. */
3205 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3206 if (! stable)
3207 return -1;
3208
3209 /* Lookup static route prefix. */
3210 rn = route_node_lookup (stable, p);
3211 if (! rn)
3212 return 0;
3213
3214 /* Find same static route is the tree */
3215 for (si = rn->info; si; si = si->next)
3216 if (distance == si->distance
3217 && type == si->type
3218 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3219 && (! ifname || strcmp (ifname, si->ifname) == 0))
3220 break;
3221
3222 /* Can't find static route. */
3223 if (! si)
3224 {
3225 route_unlock_node (rn);
3226 return 0;
3227 }
3228
3229 /* Install into rib. */
3230 static_uninstall_ipv6 (p, si);
3231
3232 /* Unlink static route from linked list. */
3233 if (si->prev)
3234 si->prev->next = si->next;
3235 else
3236 rn->info = si->next;
3237 if (si->next)
3238 si->next->prev = si->prev;
3239
3240 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003241 if (ifname)
3242 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003243 XFREE (MTYPE_STATIC_IPV6, si);
3244
3245 return 1;
3246}
3247#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003248
paul718e3742002-12-13 20:15:29 +00003249/* RIB update function. */
3250void
paula1ac18c2005-06-28 17:17:12 +00003251rib_update (void)
paul718e3742002-12-13 20:15:29 +00003252{
3253 struct route_node *rn;
3254 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003255
paul718e3742002-12-13 20:15:29 +00003256 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3257 if (table)
3258 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003259 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003260 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003261
3262 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3263 if (table)
3264 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003265 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003266 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003267}
3268
David Lamparter6b0655a2014-06-04 06:53:35 +02003269
paul718e3742002-12-13 20:15:29 +00003270/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003271static void
paul718e3742002-12-13 20:15:29 +00003272rib_weed_table (struct route_table *table)
3273{
3274 struct route_node *rn;
3275 struct rib *rib;
3276 struct rib *next;
3277
3278 if (table)
3279 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003280 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003281 {
Paul Jakma6d691122006-07-27 21:49:00 +00003282 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3283 continue;
3284
paulb21b19c2003-06-15 01:28:29 +00003285 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003286 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003287 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003288 }
3289}
3290
3291/* Delete all routes from non main table. */
3292void
paula1ac18c2005-06-28 17:17:12 +00003293rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003294{
3295 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3296 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3297}
David Lamparter6b0655a2014-06-04 06:53:35 +02003298
paul718e3742002-12-13 20:15:29 +00003299/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003300static void
paul718e3742002-12-13 20:15:29 +00003301rib_sweep_table (struct route_table *table)
3302{
3303 struct route_node *rn;
3304 struct rib *rib;
3305 struct rib *next;
3306 int ret = 0;
3307
3308 if (table)
3309 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003310 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003311 {
Paul Jakma6d691122006-07-27 21:49:00 +00003312 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3313 continue;
3314
paul718e3742002-12-13 20:15:29 +00003315 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3316 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3317 {
3318 ret = rib_uninstall_kernel (rn, rib);
3319 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003320 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003321 }
3322 }
3323}
3324
3325/* Sweep all RIB tables. */
3326void
paula1ac18c2005-06-28 17:17:12 +00003327rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003328{
3329 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3330 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3331}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003332
3333/* Remove specific by protocol routes from 'table'. */
3334static unsigned long
3335rib_score_proto_table (u_char proto, struct route_table *table)
3336{
3337 struct route_node *rn;
3338 struct rib *rib;
3339 struct rib *next;
3340 unsigned long n = 0;
3341
3342 if (table)
3343 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003344 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003345 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003346 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3347 continue;
3348 if (rib->type == proto)
3349 {
3350 rib_delnode (rn, rib);
3351 n++;
3352 }
3353 }
3354
3355 return n;
3356}
3357
3358/* Remove specific by protocol routes. */
3359unsigned long
3360rib_score_proto (u_char proto)
3361{
3362 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3363 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3364}
3365
paul718e3742002-12-13 20:15:29 +00003366/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003367static void
paul718e3742002-12-13 20:15:29 +00003368rib_close_table (struct route_table *table)
3369{
3370 struct route_node *rn;
David Lamparterc048dcc2015-01-12 07:05:06 +01003371 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003372 struct rib *rib;
3373
3374 if (table)
3375 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003376 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003377 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003378 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3379 continue;
3380
David Lamparterc048dcc2015-01-12 07:05:06 +01003381 if (info->safi == SAFI_UNICAST)
3382 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003383
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003384 if (! RIB_SYSTEM_ROUTE (rib))
3385 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003386 }
paul718e3742002-12-13 20:15:29 +00003387}
3388
3389/* Close all RIB tables. */
3390void
paula1ac18c2005-06-28 17:17:12 +00003391rib_close (void)
paul718e3742002-12-13 20:15:29 +00003392{
3393 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3394 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3395}
David Lamparter6b0655a2014-06-04 06:53:35 +02003396
paul718e3742002-12-13 20:15:29 +00003397/* Routing information base initialize. */
3398void
paula1ac18c2005-06-28 17:17:12 +00003399rib_init (void)
paul718e3742002-12-13 20:15:29 +00003400{
paul4d38fdb2005-04-28 17:35:14 +00003401 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003402 /* VRF initialization. */
3403 vrf_init ();
3404}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003405
3406/*
3407 * vrf_id_get_next
3408 *
3409 * Get the first vrf id that is greater than the given vrf id if any.
3410 *
3411 * Returns TRUE if a vrf id was found, FALSE otherwise.
3412 */
3413static inline int
3414vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3415{
3416 while (++id < vector_active (vrf_vector))
3417 {
3418 if (vrf_lookup (id))
3419 {
3420 *next_id_p = id;
3421 return 1;
3422 }
3423 }
3424
3425 return 0;
3426}
3427
3428/*
3429 * rib_tables_iter_next
3430 *
3431 * Returns the next table in the iteration.
3432 */
3433struct route_table *
3434rib_tables_iter_next (rib_tables_iter_t *iter)
3435{
3436 struct route_table *table;
3437
3438 /*
3439 * Array that helps us go over all AFI/SAFI combinations via one
3440 * index.
3441 */
3442 static struct {
3443 afi_t afi;
3444 safi_t safi;
3445 } afi_safis[] = {
3446 { AFI_IP, SAFI_UNICAST },
3447 { AFI_IP, SAFI_MULTICAST },
3448 { AFI_IP6, SAFI_UNICAST },
3449 { AFI_IP6, SAFI_MULTICAST },
3450 };
3451
3452 table = NULL;
3453
3454 switch (iter->state)
3455 {
3456
3457 case RIB_TABLES_ITER_S_INIT:
3458 iter->vrf_id = 0;
3459 iter->afi_safi_ix = -1;
3460
3461 /* Fall through */
3462
3463 case RIB_TABLES_ITER_S_ITERATING:
3464 iter->afi_safi_ix++;
3465 while (1)
3466 {
3467
3468 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3469 {
3470 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3471 afi_safis[iter->afi_safi_ix].safi,
3472 iter->vrf_id);
3473 if (table)
3474 break;
3475
3476 iter->afi_safi_ix++;
3477 }
3478
3479 /*
3480 * Found another table in this vrf.
3481 */
3482 if (table)
3483 break;
3484
3485 /*
3486 * Done with all tables in the current vrf, go to the next
3487 * one.
3488 */
3489 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3490 break;
3491
3492 iter->afi_safi_ix = 0;
3493 }
3494
3495 break;
3496
3497 case RIB_TABLES_ITER_S_DONE:
3498 return NULL;
3499 }
3500
3501 if (table)
3502 iter->state = RIB_TABLES_ITER_S_ITERATING;
3503 else
3504 iter->state = RIB_TABLES_ITER_S_DONE;
3505
3506 return table;
3507}