blob: d6ec9147bcb804355c26b26eb88b282a4737342d [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
Everton Marques871dbcf2009-08-11 15:43:05 -0300499 if (IS_ZEBRA_DEBUG_RIB) {
500 char buf[INET6_ADDRSTRLEN];
501 inet_ntop(rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
502 zlog_debug("%s: %s/%d: nexthop match %p: %s type=%d sel=%d int=%d",
503 __func__, buf, rn->p.prefixlen, match,
504 match ? zebra_route_string(match->type) : "<?>",
505 match ? match->type : -1,
506 match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED) : -1,
507 match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_INTERNAL) : -1);
508 }
509
paul718e3742002-12-13 20:15:29 +0000510 /* If there is no selected route or matched route is EGP, go up
511 tree. */
512 if (! match
513 || match->type == ZEBRA_ROUTE_BGP)
514 {
515 do {
516 rn = rn->parent;
517 } while (rn && rn->info == NULL);
518 if (rn)
519 route_lock_node (rn);
520 }
521 else
522 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000523 /* If the longest prefix match for the nexthop yields
524 * a blackhole, mark it as inactive. */
525 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
526 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
527 return 0;
528
paul718e3742002-12-13 20:15:29 +0000529 if (match->type == ZEBRA_ROUTE_CONNECT)
530 {
531 /* Directly point connected route. */
532 newhop = match->nexthop;
533 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
534 nexthop->ifindex = newhop->ifindex;
535
536 return 1;
537 }
Everton Marques871dbcf2009-08-11 15:43:05 -0300538 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) ||
539 match->type == ZEBRA_ROUTE_KERNEL)
paul718e3742002-12-13 20:15:29 +0000540 {
Christian Frankefa713d92013-07-05 15:35:37 +0000541 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000542 for (newhop = match->nexthop; newhop; newhop = newhop->next)
543 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
544 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
545 {
546 if (set)
547 {
548 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000549
550 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
551 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000552 /* If the resolving route specifies a gateway, use it */
553 if (newhop->type == NEXTHOP_TYPE_IPV4
554 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
555 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
556 {
557 resolved_hop->type = newhop->type;
558 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000559
Christian Frankec3e6b592013-07-05 15:35:40 +0000560 if (newhop->ifindex)
561 {
562 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
563 resolved_hop->ifindex = newhop->ifindex;
564 }
565 }
Christian Frankefa713d92013-07-05 15:35:37 +0000566
Christian Frankec3e6b592013-07-05 15:35:40 +0000567 /* If the resolving route is an interface route,
568 * it means the gateway we are looking up is connected
569 * to that interface. (The actual network is _not_ onlink).
570 * Therefore, the resolved route should have the original
571 * gateway as nexthop as it is directly connected.
572 *
573 * On Linux, we have to set the onlink netlink flag because
574 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000575 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000576 || newhop->type == NEXTHOP_TYPE_IFNAME)
577 {
578 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
579 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
580 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
581 resolved_hop->ifindex = newhop->ifindex;
582 }
Christian Frankefa713d92013-07-05 15:35:37 +0000583
584 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000585 }
Christian Frankefa713d92013-07-05 15:35:37 +0000586 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000587 }
Christian Frankefa713d92013-07-05 15:35:37 +0000588 return resolved;
paul718e3742002-12-13 20:15:29 +0000589 }
590 else
591 {
592 return 0;
593 }
594 }
595 }
596 return 0;
597}
598
599#ifdef HAVE_IPV6
600/* If force flag is not set, do not modify falgs at all for uninstall
601 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000602static int
paul718e3742002-12-13 20:15:29 +0000603nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
604 struct route_node *top)
605{
606 struct prefix_ipv6 p;
607 struct route_table *table;
608 struct route_node *rn;
609 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000610 int resolved;
paul718e3742002-12-13 20:15:29 +0000611 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000612 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000613
614 if (nexthop->type == NEXTHOP_TYPE_IPV6)
615 nexthop->ifindex = 0;
616
617 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000618 {
619 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
620 nexthops_free(nexthop->resolved);
621 nexthop->resolved = NULL;
622 }
paul718e3742002-12-13 20:15:29 +0000623
624 /* Make lookup prefix. */
625 memset (&p, 0, sizeof (struct prefix_ipv6));
626 p.family = AF_INET6;
627 p.prefixlen = IPV6_MAX_PREFIXLEN;
628 p.prefix = nexthop->gate.ipv6;
629
630 /* Lookup table. */
631 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
632 if (! table)
633 return 0;
634
635 rn = route_node_match (table, (struct prefix *) &p);
636 while (rn)
637 {
638 route_unlock_node (rn);
639
David Warda50c1072009-12-03 15:34:39 +0300640 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000641 if (rn == top)
642 return 0;
643
644 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000645 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100646 {
647 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
648 continue;
649 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
650 break;
651 }
paul718e3742002-12-13 20:15:29 +0000652
653 /* If there is no selected route or matched route is EGP, go up
654 tree. */
655 if (! match
656 || match->type == ZEBRA_ROUTE_BGP)
657 {
658 do {
659 rn = rn->parent;
660 } while (rn && rn->info == NULL);
661 if (rn)
662 route_lock_node (rn);
663 }
664 else
665 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000666 /* If the longest prefix match for the nexthop yields
667 * a blackhole, mark it as inactive. */
668 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
669 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
670 return 0;
671
paul718e3742002-12-13 20:15:29 +0000672 if (match->type == ZEBRA_ROUTE_CONNECT)
673 {
674 /* Directly point connected route. */
675 newhop = match->nexthop;
676
677 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
678 nexthop->ifindex = newhop->ifindex;
679
680 return 1;
681 }
682 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
683 {
Christian Frankefa713d92013-07-05 15:35:37 +0000684 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000685 for (newhop = match->nexthop; newhop; newhop = newhop->next)
686 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
687 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
688 {
689 if (set)
690 {
691 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000692
693 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
694 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000695 /* See nexthop_active_ipv4 for a description how the
696 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000697 if (newhop->type == NEXTHOP_TYPE_IPV6
698 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
699 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000700 {
701 resolved_hop->type = newhop->type;
702 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
703
704 if (newhop->ifindex)
705 {
706 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
707 resolved_hop->ifindex = newhop->ifindex;
708 }
709 }
Christian Frankefa713d92013-07-05 15:35:37 +0000710
paul718e3742002-12-13 20:15:29 +0000711 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000712 || newhop->type == NEXTHOP_TYPE_IFNAME)
713 {
714 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
715 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
716 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
717 resolved_hop->ifindex = newhop->ifindex;
718 }
Christian Frankefa713d92013-07-05 15:35:37 +0000719
720 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000721 }
Christian Frankefa713d92013-07-05 15:35:37 +0000722 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000723 }
Christian Frankefa713d92013-07-05 15:35:37 +0000724 return resolved;
paul718e3742002-12-13 20:15:29 +0000725 }
726 else
727 {
728 return 0;
729 }
730 }
731 }
732 return 0;
733}
734#endif /* HAVE_IPV6 */
735
736struct rib *
David Lamparter29ce93e2015-01-22 19:09:36 +0100737rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
738 struct route_node **rn_out)
Everton Marques346a8b52014-09-22 19:35:51 -0300739{
740 struct route_table *table;
741 struct route_node *rn;
742 struct rib *match;
743 struct nexthop *newhop, *tnewhop;
744 int recursing;
745
746 /* Lookup table. */
747 table = vrf_table (AFI_IP, safi, 0);
748 if (! table)
749 return 0;
750
751 rn = route_node_match_ipv4 (table, &addr);
752
753 while (rn)
754 {
755 route_unlock_node (rn);
756
757 /* Pick up selected route. */
758 RNODE_FOREACH_RIB (rn, match)
759 {
760 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
761 continue;
762 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
763 break;
764 }
765
766 /* If there is no selected route or matched route is EGP, go up
767 tree. */
Everton Marques12150f02014-09-19 16:39:34 -0300768 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques346a8b52014-09-22 19:35:51 -0300769 {
770 do {
771 rn = rn->parent;
772 } while (rn && rn->info == NULL);
773 if (rn)
774 route_lock_node (rn);
775 }
776 else
777 {
David Lamparter29ce93e2015-01-22 19:09:36 +0100778 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques346a8b52014-09-22 19:35:51 -0300779 {
David Lamparter29ce93e2015-01-22 19:09:36 +0100780 int found = 0;
Everton Marques346a8b52014-09-22 19:35:51 -0300781 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
782 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter29ce93e2015-01-22 19:09:36 +0100783 {
784 found = 1;
785 break;
786 }
787 if (!found)
788 return NULL;
Everton Marques346a8b52014-09-22 19:35:51 -0300789 }
David Lamparter29ce93e2015-01-22 19:09:36 +0100790
791 if (rn_out)
792 *rn_out = rn;
793 return match;
Everton Marques346a8b52014-09-22 19:35:51 -0300794 }
795 }
796 return NULL;
797}
798
799struct rib *
David Lamparter240c56f2015-01-06 19:53:24 +0100800rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
801{
802 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
803 struct route_node *m_rn = NULL, *u_rn = NULL;
804 int skip_bgp = 0; /* bool */
805
806 switch (ipv4_multicast_mode)
807 {
808 case MCAST_MRIB_ONLY:
809 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
810 case MCAST_URIB_ONLY:
811 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
812 case MCAST_NO_CONFIG:
813 case MCAST_MIX_MRIB_FIRST:
814 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
815 if (!mrib)
816 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
817 break;
818 case MCAST_MIX_DISTANCE:
819 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
820 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
821 if (mrib && urib)
822 rib = urib->distance < mrib->distance ? urib : mrib;
823 else if (mrib)
824 rib = mrib;
825 else if (urib)
826 rib = urib;
827 break;
828 case MCAST_MIX_PFXLEN:
829 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
830 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
831 if (mrib && urib)
832 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
833 else if (mrib)
834 rib = mrib;
835 else if (urib)
836 rib = urib;
837 break;
838 }
839
840 if (rn_out)
841 *rn_out = (rib == mrib) ? m_rn : u_rn;
842
843 if (IS_ZEBRA_DEBUG_RIB)
844 {
845 char buf[BUFSIZ];
846 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
847
848 zlog_debug("%s: %s: found %s, using %s",
849 __func__, buf,
850 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
851 urib ? "URIB" : "nothing",
852 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
853 }
854 return rib;
855}
856
857void
858multicast_mode_ipv4_set (enum multicast_mode mode)
859{
860 if (IS_ZEBRA_DEBUG_RIB)
861 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
862 ipv4_multicast_mode = mode;
863}
864
865enum multicast_mode
866multicast_mode_ipv4_get (void)
867{
868 return ipv4_multicast_mode;
869}
870
871struct rib *
paul718e3742002-12-13 20:15:29 +0000872rib_lookup_ipv4 (struct prefix_ipv4 *p)
873{
874 struct route_table *table;
875 struct route_node *rn;
876 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000877 struct nexthop *nexthop, *tnexthop;
878 int recursing;
paul718e3742002-12-13 20:15:29 +0000879
880 /* Lookup table. */
881 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
882 if (! table)
883 return 0;
884
885 rn = route_node_lookup (table, (struct prefix *) p);
886
887 /* No route for this prefix. */
888 if (! rn)
889 return NULL;
890
891 /* Unlock node. */
892 route_unlock_node (rn);
893
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000894 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100895 {
896 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
897 continue;
898 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
899 break;
900 }
paul718e3742002-12-13 20:15:29 +0000901
902 if (! match || match->type == ZEBRA_ROUTE_BGP)
903 return NULL;
904
905 if (match->type == ZEBRA_ROUTE_CONNECT)
906 return match;
907
Christian Frankefa713d92013-07-05 15:35:37 +0000908 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000909 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
910 return match;
911
912 return NULL;
913}
914
Denis Ovsienkodc958242007-08-13 16:03:06 +0000915/*
916 * This clone function, unlike its original rib_lookup_ipv4(), checks
917 * if specified IPv4 route record (prefix/mask -> gate) exists in
918 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
919 *
920 * Return values:
921 * -1: error
922 * 0: exact match found
923 * 1: a match was found with a different gate
924 * 2: connected route found
925 * 3: no matches found
926 */
927int
928rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
929{
930 struct route_table *table;
931 struct route_node *rn;
932 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000933 struct nexthop *nexthop, *tnexthop;
934 int recursing;
935 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000936
937 /* Lookup table. */
938 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
939 if (! table)
940 return ZEBRA_RIB_LOOKUP_ERROR;
941
942 /* Scan the RIB table for exactly matching RIB entry. */
943 rn = route_node_lookup (table, (struct prefix *) p);
944
945 /* No route for this prefix. */
946 if (! rn)
947 return ZEBRA_RIB_NOTFOUND;
948
949 /* Unlock node. */
950 route_unlock_node (rn);
951
952 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000953 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100954 {
955 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
956 continue;
957 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
958 break;
959 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000960
961 /* None such found :( */
962 if (!match)
963 return ZEBRA_RIB_NOTFOUND;
964
965 if (match->type == ZEBRA_ROUTE_CONNECT)
966 return ZEBRA_RIB_FOUND_CONNECTED;
967
968 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000969 nexthops_active = 0;
970 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000971 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000972 {
Christian Frankefa713d92013-07-05 15:35:37 +0000973 nexthops_active = 1;
974 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
975 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000976 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000977 {
978 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
979 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
980 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
981 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
982 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
983 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000984 }
Christian Frankefa713d92013-07-05 15:35:37 +0000985
986 if (nexthops_active)
987 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000988
989 return ZEBRA_RIB_NOTFOUND;
990}
991
paul718e3742002-12-13 20:15:29 +0000992#ifdef HAVE_IPV6
993struct rib *
994rib_match_ipv6 (struct in6_addr *addr)
995{
996 struct prefix_ipv6 p;
997 struct route_table *table;
998 struct route_node *rn;
999 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +00001000 struct nexthop *newhop, *tnewhop;
1001 int recursing;
paul718e3742002-12-13 20:15:29 +00001002
1003 /* Lookup table. */
1004 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1005 if (! table)
1006 return 0;
1007
1008 memset (&p, 0, sizeof (struct prefix_ipv6));
1009 p.family = AF_INET6;
1010 p.prefixlen = IPV6_MAX_PREFIXLEN;
1011 IPV6_ADDR_COPY (&p.prefix, addr);
1012
1013 rn = route_node_match (table, (struct prefix *) &p);
1014
1015 while (rn)
1016 {
1017 route_unlock_node (rn);
1018
1019 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001020 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +01001021 {
1022 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
1023 continue;
1024 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
1025 break;
1026 }
paul718e3742002-12-13 20:15:29 +00001027
1028 /* If there is no selected route or matched route is EGP, go up
1029 tree. */
1030 if (! match
1031 || match->type == ZEBRA_ROUTE_BGP)
1032 {
1033 do {
1034 rn = rn->parent;
1035 } while (rn && rn->info == NULL);
1036 if (rn)
1037 route_lock_node (rn);
1038 }
1039 else
1040 {
1041 if (match->type == ZEBRA_ROUTE_CONNECT)
1042 /* Directly point connected route. */
1043 return match;
1044 else
1045 {
Christian Frankefa713d92013-07-05 15:35:37 +00001046 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +00001047 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1048 return match;
1049 return NULL;
1050 }
1051 }
1052 }
1053 return NULL;
1054}
1055#endif /* HAVE_IPV6 */
1056
Everton Marques871dbcf2009-08-11 15:43:05 -03001057static void nexthop_dump(struct nexthop *nexthop,
1058 char *type_str_buf,
1059 int type_str_buf_size,
1060 char *addr_str_buf,
1061 int addr_str_buf_size,
1062 char *via_str_buf,
1063 int via_str_buf_size)
1064{
1065 switch (nexthop->type) {
1066 case NEXTHOP_TYPE_IPV4:
1067 case NEXTHOP_TYPE_IPV4_IFINDEX:
1068 snprintf(type_str_buf, type_str_buf_size, "ipv4");
1069 snprintf(addr_str_buf, addr_str_buf_size, "%s", inet_ntoa(nexthop->gate.ipv4));
1070 snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifindex ? ifindex2ifname(nexthop->ifindex) : "<?>");
1071 break;
1072 case NEXTHOP_TYPE_IFINDEX:
1073 snprintf(type_str_buf, type_str_buf_size, "connected");
1074 snprintf(addr_str_buf, addr_str_buf_size, "<connected>");
1075 snprintf(via_str_buf, via_str_buf_size, "%s", ifindex2ifname(nexthop->ifindex));
1076 break;
1077 case NEXTHOP_TYPE_IFNAME:
1078 snprintf(type_str_buf, type_str_buf_size, "connected");
1079 snprintf(addr_str_buf, addr_str_buf_size, "<connected>");
1080 snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifname);
1081 break;
1082 case NEXTHOP_TYPE_BLACKHOLE:
1083 snprintf(type_str_buf, type_str_buf_size, "blackhole");
1084 snprintf(addr_str_buf, addr_str_buf_size, "<blackhole>");
1085 snprintf(via_str_buf, via_str_buf_size, "Null0");
1086 break;
1087 default:
1088 snprintf(type_str_buf, type_str_buf_size, "unknown");
1089 snprintf(addr_str_buf, addr_str_buf_size, "<unknown>");
1090 snprintf(via_str_buf, via_str_buf_size, "<?>");
1091 }
1092}
1093
Paul Jakma7514fb72007-05-02 16:05:35 +00001094#define RIB_SYSTEM_ROUTE(R) \
1095 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
1096
Denis Ovsienkodc958242007-08-13 16:03:06 +00001097/* This function verifies reachability of one given nexthop, which can be
1098 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
1099 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
1100 * nexthop->ifindex will be updated appropriately as well.
1101 * An existing route map can turn (otherwise active) nexthop into inactive, but
1102 * not vice versa.
1103 *
1104 * The return value is the final value of 'ACTIVE' flag.
1105 */
1106
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001107static unsigned
paul718e3742002-12-13 20:15:29 +00001108nexthop_active_check (struct route_node *rn, struct rib *rib,
1109 struct nexthop *nexthop, int set)
1110{
Christian Frankef3a17322013-07-05 15:35:41 +00001111 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +00001112 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +00001113 route_map_result_t ret = RMAP_MATCH;
1114 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
1115 struct route_map *rmap;
1116 int family;
paul718e3742002-12-13 20:15:29 +00001117
Paul Jakma7514fb72007-05-02 16:05:35 +00001118 family = 0;
paul718e3742002-12-13 20:15:29 +00001119 switch (nexthop->type)
1120 {
1121 case NEXTHOP_TYPE_IFINDEX:
1122 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001123 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001124 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1125 else
1126 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1127 break;
paul718e3742002-12-13 20:15:29 +00001128 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001129 family = AFI_IP6;
1130 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001131 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001132 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001133 {
1134 if (set)
1135 nexthop->ifindex = ifp->ifindex;
1136 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1137 }
1138 else
1139 {
1140 if (set)
1141 nexthop->ifindex = 0;
1142 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1143 }
1144 break;
1145 case NEXTHOP_TYPE_IPV4:
1146 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001147 family = AFI_IP;
Everton Marques871dbcf2009-08-11 15:43:05 -03001148 {
1149 int nh_active = nexthop_active_ipv4 (rib, nexthop, set, rn);
1150 if (IS_ZEBRA_DEBUG_RIB) {
1151 char type_str_buf[100];
1152 char addr_str_buf[100];
1153 char via_str_buf[100];
1154 nexthop_dump(nexthop,
1155 type_str_buf, sizeof(type_str_buf),
1156 addr_str_buf, sizeof(addr_str_buf),
1157 via_str_buf, sizeof(via_str_buf));
1158 zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d nexthop_active_ipv4=%d",
1159 __func__, rib, nexthop,
1160 nexthop->type, type_str_buf,
1161 addr_str_buf, via_str_buf, nexthop->ifindex,
1162 nh_active);
1163 }
1164 if (nh_active)
1165 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1166 else
1167 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1168 }
paul718e3742002-12-13 20:15:29 +00001169 break;
1170#ifdef HAVE_IPV6
1171 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001172 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001173 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1174 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1175 else
1176 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1177 break;
1178 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001179 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001180 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1181 {
1182 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001183 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001184 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1185 else
1186 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1187 }
1188 else
1189 {
1190 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1191 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1192 else
1193 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1194 }
1195 break;
1196#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001197 case NEXTHOP_TYPE_BLACKHOLE:
1198 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1199 break;
paul718e3742002-12-13 20:15:29 +00001200 default:
1201 break;
1202 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001203 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1204 return 0;
1205
Christian Frankef3a17322013-07-05 15:35:41 +00001206 /* XXX: What exactly do those checks do? Do we support
1207 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001208 if (RIB_SYSTEM_ROUTE(rib) ||
1209 (family == AFI_IP && rn->p.family != AF_INET) ||
1210 (family == AFI_IP6 && rn->p.family != AF_INET6))
1211 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1212
Christian Frankef3a17322013-07-05 15:35:41 +00001213 /* The original code didn't determine the family correctly
1214 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1215 * from the rib_table_info in those cases.
1216 * Possibly it may be better to use only the rib_table_info
1217 * in every case.
1218 */
1219 if (!family)
1220 family = info->afi;
1221
Paul Jakma7514fb72007-05-02 16:05:35 +00001222 rmap = 0;
1223 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1224 proto_rm[family][rib->type])
1225 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1226 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1227 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1228 if (rmap) {
1229 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1230 }
1231
1232 if (ret == RMAP_DENYMATCH)
1233 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001234 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1235}
1236
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001237/* Iterate over all nexthops of the given RIB entry and refresh their
1238 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1239 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1240 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1241 * transparently passed to nexthop_active_check().
1242 *
1243 * Return value is the new number of active nexthops.
1244 */
1245
paula1ac18c2005-06-28 17:17:12 +00001246static int
paul718e3742002-12-13 20:15:29 +00001247nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1248{
1249 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001250 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001251
1252 rib->nexthop_active_num = 0;
1253 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1254
1255 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001256 {
1257 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001258 prev_index = nexthop->ifindex;
Everton Marques871dbcf2009-08-11 15:43:05 -03001259 new_active = nexthop_active_check (rn, rib, nexthop, set);
1260 if (new_active)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001261 rib->nexthop_active_num++;
Everton Marques871dbcf2009-08-11 15:43:05 -03001262 if (IS_ZEBRA_DEBUG_RIB) {
1263 char type_str_buf[100];
1264 char addr_str_buf[100];
1265 char via_str_buf[100];
1266 nexthop_dump(nexthop,
1267 type_str_buf, sizeof(type_str_buf),
1268 addr_str_buf, sizeof(addr_str_buf),
1269 via_str_buf, sizeof(via_str_buf));
1270 zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d act=%d total_act=%d",
1271 __func__, rib, nexthop,
1272 nexthop->type, type_str_buf,
1273 addr_str_buf, via_str_buf, nexthop->ifindex,
1274 new_active, rib->nexthop_active_num);
1275 }
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001276 if (prev_active != new_active ||
1277 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001278 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1279 }
paul718e3742002-12-13 20:15:29 +00001280 return rib->nexthop_active_num;
1281}
paul6baeb982003-10-28 03:47:15 +00001282
David Lamparter6b0655a2014-06-04 06:53:35 +02001283
paul718e3742002-12-13 20:15:29 +00001284
paula1ac18c2005-06-28 17:17:12 +00001285static void
paul718e3742002-12-13 20:15:29 +00001286rib_install_kernel (struct route_node *rn, struct rib *rib)
1287{
1288 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001289 struct nexthop *nexthop, *tnexthop;
David Lamparterc048dcc2015-01-12 07:05:06 +01001290 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001291 int recursing;
paul718e3742002-12-13 20:15:29 +00001292
David Lamparterc048dcc2015-01-12 07:05:06 +01001293 if (info->safi != SAFI_UNICAST)
1294 {
1295 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1296 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1297 return;
1298 }
1299
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001300 /*
1301 * Make sure we update the FPM any time we send new information to
1302 * the kernel.
1303 */
1304 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001305 switch (PREFIX_FAMILY (&rn->p))
1306 {
1307 case AF_INET:
1308 ret = kernel_add_ipv4 (&rn->p, rib);
1309 break;
1310#ifdef HAVE_IPV6
1311 case AF_INET6:
1312 ret = kernel_add_ipv6 (&rn->p, rib);
1313 break;
1314#endif /* HAVE_IPV6 */
1315 }
1316
Denis Ovsienkodc958242007-08-13 16:03:06 +00001317 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001318 if (ret < 0)
1319 {
Christian Frankefa713d92013-07-05 15:35:37 +00001320 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001321 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1322 }
1323}
1324
1325/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001326static int
paul718e3742002-12-13 20:15:29 +00001327rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1328{
1329 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001330 struct nexthop *nexthop, *tnexthop;
David Lamparterc048dcc2015-01-12 07:05:06 +01001331 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001332 int recursing;
paul718e3742002-12-13 20:15:29 +00001333
David Lamparterc048dcc2015-01-12 07:05:06 +01001334 if (info->safi != SAFI_UNICAST)
1335 {
1336 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1337 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1338 return ret;
1339 }
1340
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001341 /*
1342 * Make sure we update the FPM any time we send new information to
1343 * the kernel.
1344 */
1345 zfpm_trigger_update (rn, "uninstalling from kernel");
1346
paul718e3742002-12-13 20:15:29 +00001347 switch (PREFIX_FAMILY (&rn->p))
1348 {
1349 case AF_INET:
1350 ret = kernel_delete_ipv4 (&rn->p, rib);
1351 break;
1352#ifdef HAVE_IPV6
1353 case AF_INET6:
1354 ret = kernel_delete_ipv6 (&rn->p, rib);
1355 break;
1356#endif /* HAVE_IPV6 */
1357 }
1358
Christian Frankefa713d92013-07-05 15:35:37 +00001359 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001360 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1361
1362 return ret;
1363}
1364
1365/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001366static void
paul718e3742002-12-13 20:15:29 +00001367rib_uninstall (struct route_node *rn, struct rib *rib)
1368{
David Lamparterc048dcc2015-01-12 07:05:06 +01001369 rib_table_info_t *info = rn->table->info;
1370
paul718e3742002-12-13 20:15:29 +00001371 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1372 {
David Lamparterc048dcc2015-01-12 07:05:06 +01001373 if (info->safi == SAFI_UNICAST)
1374 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001375
paul718e3742002-12-13 20:15:29 +00001376 redistribute_delete (&rn->p, rib);
1377 if (! RIB_SYSTEM_ROUTE (rib))
1378 rib_uninstall_kernel (rn, rib);
1379 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1380 }
1381}
1382
Paul Jakma6d691122006-07-27 21:49:00 +00001383static void rib_unlink (struct route_node *, struct rib *);
1384
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001385/*
1386 * rib_can_delete_dest
1387 *
1388 * Returns TRUE if the given dest can be deleted from the table.
1389 */
1390static int
1391rib_can_delete_dest (rib_dest_t *dest)
1392{
1393 if (dest->routes)
1394 {
1395 return 0;
1396 }
1397
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001398 /*
1399 * Don't delete the dest if we have to update the FPM about this
1400 * prefix.
1401 */
1402 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1403 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1404 return 0;
1405
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001406 return 1;
1407}
1408
1409/*
1410 * rib_gc_dest
1411 *
1412 * Garbage collect the rib dest corresponding to the given route node
1413 * if appropriate.
1414 *
1415 * Returns TRUE if the dest was deleted, FALSE otherwise.
1416 */
1417int
1418rib_gc_dest (struct route_node *rn)
1419{
1420 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001421
1422 dest = rib_dest_from_rnode (rn);
1423 if (!dest)
1424 return 0;
1425
1426 if (!rib_can_delete_dest (dest))
1427 return 0;
1428
1429 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001430 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001431
1432 dest->rnode = NULL;
1433 XFREE (MTYPE_RIB_DEST, dest);
1434 rn->info = NULL;
1435
1436 /*
1437 * Release the one reference that we keep on the route node.
1438 */
1439 route_unlock_node (rn);
1440 return 1;
1441}
1442
paul718e3742002-12-13 20:15:29 +00001443/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001444static void
1445rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001446{
1447 struct rib *rib;
1448 struct rib *next;
1449 struct rib *fib = NULL;
1450 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001451 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001452 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001453 struct nexthop *nexthop = NULL, *tnexthop;
1454 int recursing;
Balaji95116332014-10-23 15:25:25 +00001455 rib_table_info_t *info;
1456
paul4d38fdb2005-04-28 17:35:14 +00001457 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001458
1459 info = rn->table->info;
1460
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001461 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001462 {
paul718e3742002-12-13 20:15:29 +00001463 /* Currently installed rib. */
1464 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001465 {
1466 assert (fib == NULL);
1467 fib = rib;
1468 }
1469
1470 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1471 * which we need to do do further work with below.
1472 */
1473 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1474 {
1475 if (rib != fib)
1476 {
1477 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001478 rnode_debug (rn, "rn %p, removing rib %p", rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001479 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001480 }
1481 else
1482 del = rib;
1483
1484 continue;
1485 }
paul4d38fdb2005-04-28 17:35:14 +00001486
paul718e3742002-12-13 20:15:29 +00001487 /* Skip unreachable nexthop. */
1488 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001489 continue;
paul718e3742002-12-13 20:15:29 +00001490
1491 /* Infinit distance. */
1492 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001493 continue;
paul718e3742002-12-13 20:15:29 +00001494
paulaf887b52006-01-18 14:52:52 +00001495 /* Newly selected rib, the common case. */
1496 if (!select)
1497 {
1498 select = rib;
1499 continue;
1500 }
1501
1502 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001503 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001504 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001505 * - lower metric beats higher for equal distance
1506 * - last, hence oldest, route wins tie break.
1507 */
paula1038a12006-01-30 14:08:51 +00001508
1509 /* Connected routes. Pick the last connected
1510 * route of the set of lowest metric connected routes.
1511 */
paula8d9c1f2006-01-25 06:31:04 +00001512 if (rib->type == ZEBRA_ROUTE_CONNECT)
1513 {
paula1038a12006-01-30 14:08:51 +00001514 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001515 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001516 select = rib;
1517 continue;
paula8d9c1f2006-01-25 06:31:04 +00001518 }
1519 else if (select->type == ZEBRA_ROUTE_CONNECT)
1520 continue;
1521
1522 /* higher distance loses */
1523 if (rib->distance > select->distance)
1524 continue;
1525
1526 /* lower wins */
1527 if (rib->distance < select->distance)
1528 {
paulaf887b52006-01-18 14:52:52 +00001529 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001530 continue;
1531 }
1532
1533 /* metric tie-breaks equal distance */
1534 if (rib->metric <= select->metric)
1535 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001536 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001537
1538 /* After the cycle is finished, the following pointers will be set:
1539 * select --- the winner RIB entry, if any was found, otherwise NULL
1540 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1541 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1542 * rib --- NULL
1543 */
1544
1545 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001546 if (select && select == fib)
1547 {
Paul Jakma6d691122006-07-27 21:49:00 +00001548 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001549 rnode_debug (rn, "Updating existing route, select %p, fib %p",
1550 select, fib);
paul718e3742002-12-13 20:15:29 +00001551 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001552 {
David Lamparterc048dcc2015-01-12 07:05:06 +01001553 if (info->safi == SAFI_UNICAST)
1554 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001555
paul4d38fdb2005-04-28 17:35:14 +00001556 redistribute_delete (&rn->p, select);
1557 if (! RIB_SYSTEM_ROUTE (select))
1558 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001559
paul4d38fdb2005-04-28 17:35:14 +00001560 /* Set real nexthop. */
1561 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001562
paul4d38fdb2005-04-28 17:35:14 +00001563 if (! RIB_SYSTEM_ROUTE (select))
1564 rib_install_kernel (rn, select);
1565 redistribute_add (&rn->p, select);
1566 }
pauld753e9e2003-01-22 19:45:50 +00001567 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001568 {
1569 /* Housekeeping code to deal with
1570 race conditions in kernel with linux
1571 netlink reporting interface up before IPv4 or IPv6 protocol
1572 is ready to add routes.
1573 This makes sure the routes are IN the kernel.
1574 */
pauld753e9e2003-01-22 19:45:50 +00001575
Christian Frankefa713d92013-07-05 15:35:37 +00001576 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001577 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001578 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001579 installed = 1;
1580 break;
paul4d38fdb2005-04-28 17:35:14 +00001581 }
1582 if (! installed)
1583 rib_install_kernel (rn, select);
1584 }
Paul Jakma6d691122006-07-27 21:49:00 +00001585 goto end;
paul718e3742002-12-13 20:15:29 +00001586 }
1587
Denis Ovsienkodc958242007-08-13 16:03:06 +00001588 /* At this point we either haven't found the best RIB entry or it is
1589 * different from what we currently intend to flag with SELECTED. In both
1590 * cases, if a RIB block is present in FIB, it should be withdrawn.
1591 */
paul718e3742002-12-13 20:15:29 +00001592 if (fib)
1593 {
Paul Jakma6d691122006-07-27 21:49:00 +00001594 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001595 rnode_debug (rn, "Removing existing route, fib %p", fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001596
David Lamparterc048dcc2015-01-12 07:05:06 +01001597 if (info->safi == SAFI_UNICAST)
1598 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001599
paul718e3742002-12-13 20:15:29 +00001600 redistribute_delete (&rn->p, fib);
1601 if (! RIB_SYSTEM_ROUTE (fib))
1602 rib_uninstall_kernel (rn, fib);
1603 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1604
1605 /* Set real nexthop. */
1606 nexthop_active_update (rn, fib, 1);
1607 }
1608
Denis Ovsienkodc958242007-08-13 16:03:06 +00001609 /* Regardless of some RIB entry being SELECTED or not before, now we can
1610 * tell, that if a new winner exists, FIB is still not updated with this
1611 * data, but ready to be.
1612 */
paul718e3742002-12-13 20:15:29 +00001613 if (select)
1614 {
Paul Jakma6d691122006-07-27 21:49:00 +00001615 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001616 rnode_debug (rn, "Adding route, select %p", select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001617
David Lamparterc048dcc2015-01-12 07:05:06 +01001618 if (info->safi == SAFI_UNICAST)
1619 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001620
paul718e3742002-12-13 20:15:29 +00001621 /* Set real nexthop. */
1622 nexthop_active_update (rn, select, 1);
1623
1624 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001625 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001626 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1627 redistribute_add (&rn->p, select);
1628 }
paul4d38fdb2005-04-28 17:35:14 +00001629
Paul Jakma6d691122006-07-27 21:49:00 +00001630 /* FIB route was removed, should be deleted */
1631 if (del)
1632 {
1633 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001634 rnode_debug (rn, "Deleting fib %p, rn %p", del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001635 rib_unlink (rn, del);
1636 }
paul4d38fdb2005-04-28 17:35:14 +00001637
Paul Jakma6d691122006-07-27 21:49:00 +00001638end:
1639 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001640 rnode_debug (rn, "rn %p dequeued", rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001641
1642 /*
1643 * Check if the dest can be deleted now.
1644 */
1645 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001646}
1647
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001648/* Take a list of route_node structs and return 1, if there was a record
1649 * picked from it and processed by rib_process(). Don't process more,
1650 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001651 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001652static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001653process_subq (struct list * subq, u_char qindex)
1654{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001655 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001656 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001657
1658 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001659 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001660
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001661 rnode = listgetdata (lnode);
1662 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001663
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001664 if (rnode->info)
1665 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1666
Chris Caputo67b94672009-07-18 04:02:26 +00001667#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001668 else
1669 {
1670 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1671 __func__, rnode, rnode->lock);
1672 zlog_backtrace(LOG_DEBUG);
1673 }
Chris Caputo67b94672009-07-18 04:02:26 +00001674#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001675 route_unlock_node (rnode);
1676 list_delete_node (subq, lnode);
1677 return 1;
1678}
1679
1680/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1681 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1682 * is pointed to the meta queue structure.
1683 */
1684static wq_item_status
1685meta_queue_process (struct work_queue *dummy, void *data)
1686{
1687 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001688 unsigned i;
1689
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001690 for (i = 0; i < MQ_SIZE; i++)
1691 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001692 {
1693 mq->size--;
1694 break;
1695 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001696 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1697}
1698
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001699/*
1700 * Map from rib types to queue type (priority) in meta queue
1701 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001702static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1703 [ZEBRA_ROUTE_SYSTEM] = 4,
1704 [ZEBRA_ROUTE_KERNEL] = 0,
1705 [ZEBRA_ROUTE_CONNECT] = 0,
1706 [ZEBRA_ROUTE_STATIC] = 1,
1707 [ZEBRA_ROUTE_RIP] = 2,
1708 [ZEBRA_ROUTE_RIPNG] = 2,
1709 [ZEBRA_ROUTE_OSPF] = 2,
1710 [ZEBRA_ROUTE_OSPF6] = 2,
1711 [ZEBRA_ROUTE_ISIS] = 2,
1712 [ZEBRA_ROUTE_BGP] = 3,
1713 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001714 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001715};
1716
1717/* Look into the RN and queue it into one or more priority queues,
1718 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001719 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001720static void
1721rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001722{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001723 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001724
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001725 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001726 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001727 u_char qindex = meta_queue_map[rib->type];
1728
1729 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001730 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1731 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001732 {
1733 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001734 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
1735 rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001736 continue;
1737 }
1738
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001739 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001740 listnode_add (mq->subq[qindex], rn);
1741 route_lock_node (rn);
1742 mq->size++;
1743
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001744 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001745 rnode_debug (rn, "queued rn %p into sub-queue %u",
1746 rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001747 }
paul4d38fdb2005-04-28 17:35:14 +00001748}
1749
Paul Jakma6d691122006-07-27 21:49:00 +00001750/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001751static void
Paul Jakma6d691122006-07-27 21:49:00 +00001752rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001753{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001754 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001755
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001756 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001757 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001758 {
1759 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1760 __func__, rn, rn->lock);
1761 zlog_backtrace(LOG_DEBUG);
1762 return;
1763 }
1764
1765 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001766 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001767
1768 assert (zebra);
1769
1770 if (zebra->ribq == NULL)
1771 {
1772 zlog_err ("%s: work_queue does not exist!", __func__);
1773 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001774 }
paul4d38fdb2005-04-28 17:35:14 +00001775
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001776 /*
1777 * The RIB queue should normally be either empty or holding the only
1778 * work_queue_item element. In the latter case this element would
1779 * hold a pointer to the meta queue structure, which must be used to
1780 * actually queue the route nodes to process. So create the MQ
1781 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001782 * This semantics was introduced after 0.99.9 release.
1783 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001784 if (!zebra->ribq->items->count)
1785 work_queue_add (zebra->ribq, zebra->mq);
1786
1787 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001788
1789 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001790 rnode_debug (rn, "rn %p queued", rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001791
1792 return;
paul4d38fdb2005-04-28 17:35:14 +00001793}
1794
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001795/* Create new meta queue.
1796 A destructor function doesn't seem to be necessary here.
1797 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001798static struct meta_queue *
1799meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001800{
1801 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001802 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001803
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001804 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1805 assert(new);
1806
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001807 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001808 {
1809 new->subq[i] = list_new ();
1810 assert(new->subq[i]);
1811 }
1812
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001813 return new;
1814}
1815
paul4d38fdb2005-04-28 17:35:14 +00001816/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001817static void
paul4d38fdb2005-04-28 17:35:14 +00001818rib_queue_init (struct zebra_t *zebra)
1819{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001820 assert (zebra);
1821
paul4d38fdb2005-04-28 17:35:14 +00001822 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001823 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001824 {
Paul Jakma6d691122006-07-27 21:49:00 +00001825 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001826 return;
1827 }
1828
1829 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001830 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001831 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001832 /* XXX: TODO: These should be runtime configurable via vty */
1833 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001834 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001835
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001836 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001837 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001838 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001839 return;
1840 }
1841 return;
paul718e3742002-12-13 20:15:29 +00001842}
1843
Paul Jakma6d691122006-07-27 21:49:00 +00001844/* RIB updates are processed via a queue of pointers to route_nodes.
1845 *
1846 * The queue length is bounded by the maximal size of the routing table,
1847 * as a route_node will not be requeued, if already queued.
1848 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001849 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1850 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1851 * and then submit route_node to queue for best-path selection later.
1852 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001853 *
1854 * Deleted RIBs are reaped during best-path selection.
1855 *
1856 * rib_addnode
1857 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001858 * |-------->| | best RIB, if required
1859 * | |
1860 * static_install->|->rib_addqueue...... -> rib_process
1861 * | |
1862 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001863 * |-> set RIB_ENTRY_REMOVE |
1864 * rib_delnode (RIB freed)
1865 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001866 * The 'info' pointer of a route_node points to a rib_dest_t
1867 * ('dest'). Queueing state for a route_node is kept on the dest. The
1868 * dest is created on-demand by rib_link() and is kept around at least
1869 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001870 *
1871 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1872 *
1873 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001874 * - dest attached to route_node:
1875 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001876 * - route_node processing queue
1877 * - managed by: rib_addqueue, rib_process.
1878 *
1879 */
1880
paul718e3742002-12-13 20:15:29 +00001881/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001882static void
Paul Jakma6d691122006-07-27 21:49:00 +00001883rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001884{
1885 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001886 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001887
paul4d38fdb2005-04-28 17:35:14 +00001888 assert (rib && rn);
1889
Paul Jakma6d691122006-07-27 21:49:00 +00001890 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001891 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001892
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001893 dest = rib_dest_from_rnode (rn);
1894 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001895 {
1896 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001897 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001898
1899 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1900 route_lock_node (rn); /* rn route table reference */
1901 rn->info = dest;
1902 dest->rnode = rn;
1903 }
1904
1905 head = dest->routes;
1906 if (head)
1907 {
Paul Jakma6d691122006-07-27 21:49:00 +00001908 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001909 }
paul718e3742002-12-13 20:15:29 +00001910 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001911 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001912 rib_queue_add (&zebrad, rn);
1913}
1914
1915static void
1916rib_addnode (struct route_node *rn, struct rib *rib)
1917{
1918 /* RIB node has been un-removed before route-node is processed.
1919 * route_node must hence already be on the queue for processing..
1920 */
1921 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1922 {
1923 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001924 rnode_debug (rn, "rn %p, un-removed rib %p", rn, rib);
1925
Paul Jakma6d691122006-07-27 21:49:00 +00001926 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1927 return;
1928 }
1929 rib_link (rn, rib);
1930}
1931
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001932/*
1933 * rib_unlink
1934 *
1935 * Detach a rib structure from a route_node.
1936 *
1937 * Note that a call to rib_unlink() should be followed by a call to
1938 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1939 * longer required to be deleted.
1940 */
Paul Jakma6d691122006-07-27 21:49:00 +00001941static void
1942rib_unlink (struct route_node *rn, struct rib *rib)
1943{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001944 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001945
1946 assert (rn && rib);
1947
1948 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001949 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001950
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001951 dest = rib_dest_from_rnode (rn);
1952
Paul Jakma6d691122006-07-27 21:49:00 +00001953 if (rib->next)
1954 rib->next->prev = rib->prev;
1955
1956 if (rib->prev)
1957 rib->prev->next = rib->next;
1958 else
1959 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001960 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001961 }
1962
1963 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001964 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001965 XFREE (MTYPE_RIB, rib);
1966
paul718e3742002-12-13 20:15:29 +00001967}
1968
paula1ac18c2005-06-28 17:17:12 +00001969static void
paul718e3742002-12-13 20:15:29 +00001970rib_delnode (struct route_node *rn, struct rib *rib)
1971{
Paul Jakma6d691122006-07-27 21:49:00 +00001972 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001973 rnode_debug (rn, "rn %p, rib %p, removing", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001974 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1975 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001976}
1977
1978int
1979rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001980 struct in_addr *gate, struct in_addr *src,
1981 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001982 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001983{
1984 struct rib *rib;
1985 struct rib *same = NULL;
1986 struct route_table *table;
1987 struct route_node *rn;
1988 struct nexthop *nexthop;
1989
1990 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001991 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001992 if (! table)
1993 return 0;
1994
1995 /* Make it sure prefixlen is applied to the prefix. */
1996 apply_mask_ipv4 (p);
1997
1998 /* Set default distance by route type. */
1999 if (distance == 0)
2000 {
Balaji.G837d16c2012-09-26 14:09:10 +05302001 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02002002 distance = 150;
2003 else
2004 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002005
2006 /* iBGP distance is 200. */
2007 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2008 distance = 200;
2009 }
2010
2011 /* Lookup route node.*/
2012 rn = route_node_get (table, (struct prefix *) p);
2013
2014 /* If same type of route are installed, treat it as a implicit
2015 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002016 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002017 {
Paul Jakma6d691122006-07-27 21:49:00 +00002018 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2019 continue;
2020
hassoebf1ead2005-09-21 14:58:20 +00002021 if (rib->type != type)
2022 continue;
2023 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002024 {
2025 same = rib;
2026 break;
2027 }
hassoebf1ead2005-09-21 14:58:20 +00002028 /* Duplicate connected route comes in. */
2029 else if ((nexthop = rib->nexthop) &&
2030 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00002031 nexthop->ifindex == ifindex &&
2032 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00002033 {
2034 rib->refcnt++;
2035 return 0 ;
2036 }
paul718e3742002-12-13 20:15:29 +00002037 }
2038
2039 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002040 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00002041 rib->type = type;
2042 rib->distance = distance;
2043 rib->flags = flags;
2044 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002045 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002046 rib->nexthop_num = 0;
2047 rib->uptime = time (NULL);
2048
2049 /* Nexthop settings. */
2050 if (gate)
2051 {
2052 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00002053 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00002054 else
Paul Jakma7514fb72007-05-02 16:05:35 +00002055 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00002056 }
2057 else
2058 nexthop_ifindex_add (rib, ifindex);
2059
2060 /* If this route is kernel route, set FIB flag to the route. */
2061 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2062 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2063 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2064
2065 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00002066 if (IS_ZEBRA_DEBUG_RIB)
2067 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00002068 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002069
paul718e3742002-12-13 20:15:29 +00002070 /* Free implicit route.*/
2071 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002072 {
2073 if (IS_ZEBRA_DEBUG_RIB)
2074 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002075 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002076 }
paul4d38fdb2005-04-28 17:35:14 +00002077
2078 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002079 return 0;
2080}
2081
Denis Ovsienkodc958242007-08-13 16:03:06 +00002082/* This function dumps the contents of a given RIB entry into
2083 * standard debug log. Calling function name and IP prefix in
2084 * question are passed as 1st and 2nd arguments.
2085 */
2086
David Lamparterf7bf4152013-10-22 17:10:21 +00002087void _rib_dump (const char * func,
2088 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002089{
David Lamparterf7bf4152013-10-22 17:10:21 +00002090 const struct prefix *p = pp.p;
Vincent Bernatfed643f2012-10-23 16:00:42 +00002091 char straddr[INET6_ADDRSTRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00002092 struct nexthop *nexthop, *tnexthop;
2093 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00002094
Vincent Bernatfed643f2012-10-23 16:00:42 +00002095 inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002096 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002097 zlog_debug
2098 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002099 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00002100 func,
2101 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002102 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002103 rib->type,
2104 rib->table
2105 );
2106 zlog_debug
2107 (
2108 "%s: metric == %u, distance == %u, flags == %u, status == %u",
2109 func,
2110 rib->metric,
2111 rib->distance,
2112 rib->flags,
2113 rib->status
2114 );
2115 zlog_debug
2116 (
2117 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
2118 func,
2119 rib->nexthop_num,
2120 rib->nexthop_active_num,
2121 rib->nexthop_fib_num
2122 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00002123
Christian Frankefa713d92013-07-05 15:35:37 +00002124 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2125 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00002126 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002127 zlog_debug
2128 (
2129 "%s: %s %s with flags %s%s%s",
2130 func,
2131 (recursing ? " NH" : "NH"),
2132 straddr,
2133 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
2134 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
2135 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
2136 );
2137 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00002138 zlog_debug ("%s: dump complete", func);
2139}
2140
2141/* This is an exported helper to rtm_read() to dump the strange
2142 * RIB entry found by rib_lookup_ipv4_route()
2143 */
2144
2145void rib_lookup_and_dump (struct prefix_ipv4 * p)
2146{
2147 struct route_table *table;
2148 struct route_node *rn;
2149 struct rib *rib;
2150 char prefix_buf[INET_ADDRSTRLEN];
2151
2152 /* Lookup table. */
2153 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2154 if (! table)
2155 {
2156 zlog_err ("%s: vrf_table() returned NULL", __func__);
2157 return;
2158 }
2159
2160 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
2161 /* Scan the RIB table for exactly matching RIB entry. */
2162 rn = route_node_lookup (table, (struct prefix *) p);
2163
2164 /* No route for this prefix. */
2165 if (! rn)
2166 {
2167 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
2168 return;
2169 }
2170
2171 /* Unlock node. */
2172 route_unlock_node (rn);
2173
2174 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002175 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002176 {
2177 zlog_debug
2178 (
2179 "%s: rn %p, rib %p: %s, %s",
2180 __func__,
2181 rn,
2182 rib,
2183 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2184 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2185 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002186 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002187 }
2188}
2189
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002190/* Check if requested address assignment will fail due to another
2191 * route being installed by zebra in FIB already. Take necessary
2192 * actions, if needed: remove such a route from FIB and deSELECT
2193 * corresponding RIB entry. Then put affected RN into RIBQ head.
2194 */
2195void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2196{
2197 struct route_table *table;
2198 struct route_node *rn;
2199 struct rib *rib;
2200 unsigned changed = 0;
2201
2202 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2203 {
2204 zlog_err ("%s: vrf_table() returned NULL", __func__);
2205 return;
2206 }
2207
2208 /* No matches would be the simplest case. */
2209 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2210 return;
2211
2212 /* Unlock node. */
2213 route_unlock_node (rn);
2214
2215 /* Check all RIB entries. In case any changes have to be done, requeue
2216 * the RN into RIBQ head. If the routing message about the new connected
2217 * route (generated by the IP address we are going to assign very soon)
2218 * comes before the RIBQ is processed, the new RIB entry will join
2219 * RIBQ record already on head. This is necessary for proper revalidation
2220 * of the rest of the RIB.
2221 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002222 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002223 {
2224 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2225 ! RIB_SYSTEM_ROUTE (rib))
2226 {
2227 changed = 1;
2228 if (IS_ZEBRA_DEBUG_RIB)
2229 {
2230 char buf[INET_ADDRSTRLEN];
2231 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
2232 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
David Lamparterf7bf4152013-10-22 17:10:21 +00002233 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002234 }
2235 rib_uninstall (rn, rib);
2236 }
2237 }
2238 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002239 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002240}
2241
paul718e3742002-12-13 20:15:29 +00002242int
G.Balajicddf3912011-11-26 21:59:32 +04002243rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002244{
2245 struct route_table *table;
2246 struct route_node *rn;
2247 struct rib *same;
2248 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002249
paul718e3742002-12-13 20:15:29 +00002250 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002251 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002252 if (! table)
2253 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002254
paul718e3742002-12-13 20:15:29 +00002255 /* Make it sure prefixlen is applied to the prefix. */
2256 apply_mask_ipv4 (p);
2257
2258 /* Set default distance by route type. */
2259 if (rib->distance == 0)
2260 {
2261 rib->distance = route_info[rib->type].distance;
2262
2263 /* iBGP distance is 200. */
2264 if (rib->type == ZEBRA_ROUTE_BGP
2265 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2266 rib->distance = 200;
2267 }
2268
2269 /* Lookup route node.*/
2270 rn = route_node_get (table, (struct prefix *) p);
2271
2272 /* If same type of route are installed, treat it as a implicit
2273 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002274 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002275 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002276 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002277 continue;
2278
paul718e3742002-12-13 20:15:29 +00002279 if (same->type == rib->type && same->table == rib->table
2280 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002281 break;
paul718e3742002-12-13 20:15:29 +00002282 }
paul4d38fdb2005-04-28 17:35:14 +00002283
paul718e3742002-12-13 20:15:29 +00002284 /* If this route is kernel route, set FIB flag to the route. */
2285 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2286 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2287 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2288
2289 /* Link new rib to node.*/
2290 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002291 if (IS_ZEBRA_DEBUG_RIB)
2292 {
2293 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2294 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002295 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002296 }
paul718e3742002-12-13 20:15:29 +00002297
paul718e3742002-12-13 20:15:29 +00002298 /* Free implicit route.*/
2299 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002300 {
2301 if (IS_ZEBRA_DEBUG_RIB)
2302 {
2303 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2304 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002305 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002306 }
paul4d38fdb2005-04-28 17:35:14 +00002307 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002308 }
paul4d38fdb2005-04-28 17:35:14 +00002309
2310 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002311 return 0;
2312}
2313
hassoebf1ead2005-09-21 14:58:20 +00002314/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002315int
2316rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002317 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002318{
2319 struct route_table *table;
2320 struct route_node *rn;
2321 struct rib *rib;
2322 struct rib *fib = NULL;
2323 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002324 struct nexthop *nexthop, *tnexthop;
2325 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002326 char buf1[INET_ADDRSTRLEN];
2327 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002328
2329 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002330 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002331 if (! table)
2332 return 0;
2333
2334 /* Apply mask. */
2335 apply_mask_ipv4 (p);
2336
Christian Frankeb52aef12013-11-27 17:06:15 +00002337 if (IS_ZEBRA_DEBUG_KERNEL)
2338 {
2339 if (gate)
2340 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
2341 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2342 p->prefixlen,
2343 inet_ntoa (*gate),
2344 ifindex);
2345 else
2346 zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d",
2347 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2348 p->prefixlen,
2349 ifindex);
2350 }
paul5ec90d22003-06-19 01:41:37 +00002351
paul718e3742002-12-13 20:15:29 +00002352 /* Lookup route node. */
2353 rn = route_node_lookup (table, (struct prefix *) p);
2354 if (! rn)
2355 {
2356 if (IS_ZEBRA_DEBUG_KERNEL)
2357 {
2358 if (gate)
ajsb6178002004-12-07 21:12:56 +00002359 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002360 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002361 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002362 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002363 ifindex);
2364 else
ajsb6178002004-12-07 21:12:56 +00002365 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002366 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002367 p->prefixlen,
2368 ifindex);
2369 }
2370 return ZEBRA_ERR_RTNOEXIST;
2371 }
2372
2373 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002374 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002375 {
Paul Jakma6d691122006-07-27 21:49:00 +00002376 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2377 continue;
2378
paul718e3742002-12-13 20:15:29 +00002379 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2380 fib = rib;
2381
hassoebf1ead2005-09-21 14:58:20 +00002382 if (rib->type != type)
2383 continue;
2384 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002385 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002386 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002387 if (nexthop->ifindex != ifindex)
2388 continue;
hassoebf1ead2005-09-21 14:58:20 +00002389 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002390 {
hassoebf1ead2005-09-21 14:58:20 +00002391 rib->refcnt--;
2392 route_unlock_node (rn);
2393 route_unlock_node (rn);
2394 return 0;
paul718e3742002-12-13 20:15:29 +00002395 }
hassoebf1ead2005-09-21 14:58:20 +00002396 same = rib;
2397 break;
paul718e3742002-12-13 20:15:29 +00002398 }
hassoebf1ead2005-09-21 14:58:20 +00002399 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002400 else
paul5ec90d22003-06-19 01:41:37 +00002401 {
Christian Frankefa713d92013-07-05 15:35:37 +00002402 if (gate == NULL)
2403 {
2404 same = rib;
2405 break;
2406 }
2407 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2408 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2409 {
2410 same = rib;
2411 break;
2412 }
2413 if (same)
2414 break;
2415 }
paul718e3742002-12-13 20:15:29 +00002416 }
paul718e3742002-12-13 20:15:29 +00002417 /* If same type of route can't be found and this message is from
2418 kernel. */
2419 if (! same)
2420 {
2421 if (fib && type == ZEBRA_ROUTE_KERNEL)
2422 {
2423 /* Unset flags. */
2424 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2425 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2426
2427 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2428 }
2429 else
2430 {
2431 if (IS_ZEBRA_DEBUG_KERNEL)
2432 {
2433 if (gate)
ajsb6178002004-12-07 21:12:56 +00002434 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002435 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002436 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002437 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002438 ifindex,
2439 type);
2440 else
ajsb6178002004-12-07 21:12:56 +00002441 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002442 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002443 p->prefixlen,
2444 ifindex,
2445 type);
2446 }
2447 route_unlock_node (rn);
2448 return ZEBRA_ERR_RTNOEXIST;
2449 }
2450 }
paul4d38fdb2005-04-28 17:35:14 +00002451
paul718e3742002-12-13 20:15:29 +00002452 if (same)
2453 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002454
paul718e3742002-12-13 20:15:29 +00002455 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002456 return 0;
2457}
David Lamparter6b0655a2014-06-04 06:53:35 +02002458
paul718e3742002-12-13 20:15:29 +00002459/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002460static void
Everton Marques96bb2662014-07-14 11:19:00 -03002461static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002462{
2463 struct rib *rib;
2464 struct route_node *rn;
2465 struct route_table *table;
2466
2467 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002468 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002469 if (! table)
2470 return;
2471
2472 /* Lookup existing route */
2473 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002474 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002475 {
2476 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2477 continue;
2478
2479 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2480 break;
2481 }
paul718e3742002-12-13 20:15:29 +00002482
2483 if (rib)
2484 {
2485 /* Same distance static route is there. Update it with new
2486 nexthop. */
paul718e3742002-12-13 20:15:29 +00002487 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002488 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002489 {
2490 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002491 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002492 break;
2493 case STATIC_IPV4_IFNAME:
2494 nexthop_ifname_add (rib, si->gate.ifname);
2495 break;
2496 case STATIC_IPV4_BLACKHOLE:
2497 nexthop_blackhole_add (rib);
2498 break;
paul4d38fdb2005-04-28 17:35:14 +00002499 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002500 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002501 }
2502 else
2503 {
2504 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002505 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2506
paul718e3742002-12-13 20:15:29 +00002507 rib->type = ZEBRA_ROUTE_STATIC;
2508 rib->distance = si->distance;
2509 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002510 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002511 rib->nexthop_num = 0;
2512
2513 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002514 {
2515 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002516 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002517 break;
2518 case STATIC_IPV4_IFNAME:
2519 nexthop_ifname_add (rib, si->gate.ifname);
2520 break;
2521 case STATIC_IPV4_BLACKHOLE:
2522 nexthop_blackhole_add (rib);
2523 break;
2524 }
paul718e3742002-12-13 20:15:29 +00002525
hasso81dfcaa2003-05-25 19:21:25 +00002526 /* Save the flags of this static routes (reject, blackhole) */
2527 rib->flags = si->flags;
2528
paul718e3742002-12-13 20:15:29 +00002529 /* Link this rib to the tree. */
2530 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002531 }
2532}
2533
paula1ac18c2005-06-28 17:17:12 +00002534static int
paul718e3742002-12-13 20:15:29 +00002535static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2536{
2537 if (nexthop->type == NEXTHOP_TYPE_IPV4
2538 && si->type == STATIC_IPV4_GATEWAY
2539 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2540 return 1;
2541 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2542 && si->type == STATIC_IPV4_IFNAME
2543 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2544 return 1;
paul595db7f2003-05-25 21:35:06 +00002545 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2546 && si->type == STATIC_IPV4_BLACKHOLE)
2547 return 1;
paule8e19462006-01-19 20:16:55 +00002548 return 0;
paul718e3742002-12-13 20:15:29 +00002549}
2550
2551/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002552static void
Everton Marques96bb2662014-07-14 11:19:00 -03002553static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002554{
2555 struct route_node *rn;
2556 struct rib *rib;
2557 struct nexthop *nexthop;
2558 struct route_table *table;
2559
2560 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002561 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002562 if (! table)
2563 return;
paul4d38fdb2005-04-28 17:35:14 +00002564
paul718e3742002-12-13 20:15:29 +00002565 /* Lookup existing route with type and distance. */
2566 rn = route_node_lookup (table, p);
2567 if (! rn)
2568 return;
2569
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002570 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002571 {
2572 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2573 continue;
2574
2575 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2576 break;
2577 }
paul718e3742002-12-13 20:15:29 +00002578
2579 if (! rib)
2580 {
2581 route_unlock_node (rn);
2582 return;
2583 }
2584
2585 /* Lookup nexthop. */
2586 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2587 if (static_ipv4_nexthop_same (nexthop, si))
2588 break;
2589
2590 /* Can't find nexthop. */
2591 if (! nexthop)
2592 {
2593 route_unlock_node (rn);
2594 return;
2595 }
2596
2597 /* Check nexthop. */
2598 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002599 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002600 else
2601 {
paul6baeb982003-10-28 03:47:15 +00002602 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2603 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002604 nexthop_delete (rib, nexthop);
2605 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002606 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002607 }
paul718e3742002-12-13 20:15:29 +00002608 /* Unlock node. */
2609 route_unlock_node (rn);
2610}
2611
paul718e3742002-12-13 20:15:29 +00002612int
Everton Marques96bb2662014-07-14 11:19:00 -03002613static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2614 const char *ifname, u_char flags, u_char distance,
2615 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002616{
2617 u_char type = 0;
2618 struct route_node *rn;
2619 struct static_ipv4 *si;
2620 struct static_ipv4 *pp;
2621 struct static_ipv4 *cp;
2622 struct static_ipv4 *update = NULL;
2623 struct route_table *stable;
2624
2625 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002626 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002627 if (! stable)
2628 return -1;
2629
2630 /* Lookup static route prefix. */
2631 rn = route_node_get (stable, p);
2632
2633 /* Make flags. */
2634 if (gate)
2635 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002636 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002637 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002638 else
2639 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002640
2641 /* Do nothing if there is a same static route. */
2642 for (si = rn->info; si; si = si->next)
2643 {
2644 if (type == si->type
2645 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2646 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2647 {
2648 if (distance == si->distance)
2649 {
2650 route_unlock_node (rn);
2651 return 0;
2652 }
2653 else
2654 update = si;
2655 }
2656 }
2657
Paul Jakma3c0755d2006-12-08 00:53:14 +00002658 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002659 if (update)
Everton Marques96bb2662014-07-14 11:19:00 -03002660 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002661
2662 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002663 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002664
2665 si->type = type;
2666 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002667 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002668
2669 if (gate)
2670 si->gate.ipv4 = *gate;
2671 if (ifname)
2672 si->gate.ifname = XSTRDUP (0, ifname);
2673
2674 /* Add new static route information to the tree with sort by
2675 distance value and gateway address. */
2676 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2677 {
2678 if (si->distance < cp->distance)
2679 break;
2680 if (si->distance > cp->distance)
2681 continue;
2682 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2683 {
2684 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2685 break;
2686 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2687 continue;
2688 }
2689 }
2690
2691 /* Make linked list. */
2692 if (pp)
2693 pp->next = si;
2694 else
2695 rn->info = si;
2696 if (cp)
2697 cp->prev = si;
2698 si->prev = pp;
2699 si->next = cp;
2700
2701 /* Install into rib. */
Everton Marques96bb2662014-07-14 11:19:00 -03002702 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002703
2704 return 1;
2705}
2706
paul718e3742002-12-13 20:15:29 +00002707int
Everton Marques96bb2662014-07-14 11:19:00 -03002708static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2709 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002710{
2711 u_char type = 0;
2712 struct route_node *rn;
2713 struct static_ipv4 *si;
2714 struct route_table *stable;
2715
2716 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002717 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002718 if (! stable)
2719 return -1;
2720
2721 /* Lookup static route prefix. */
2722 rn = route_node_lookup (stable, p);
2723 if (! rn)
2724 return 0;
2725
2726 /* Make flags. */
2727 if (gate)
2728 type = STATIC_IPV4_GATEWAY;
2729 else if (ifname)
2730 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002731 else
2732 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002733
2734 /* Find same static route is the tree */
2735 for (si = rn->info; si; si = si->next)
2736 if (type == si->type
2737 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2738 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2739 break;
2740
2741 /* Can't find static route. */
2742 if (! si)
2743 {
2744 route_unlock_node (rn);
2745 return 0;
2746 }
2747
2748 /* Install into rib. */
Everton Marques96bb2662014-07-14 11:19:00 -03002749 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002750
2751 /* Unlink static route from linked list. */
2752 if (si->prev)
2753 si->prev->next = si->next;
2754 else
2755 rn->info = si->next;
2756 if (si->next)
2757 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002758 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002759
2760 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002761 if (ifname)
2762 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002763 XFREE (MTYPE_STATIC_IPV4, si);
2764
paul143a3852003-09-29 20:06:13 +00002765 route_unlock_node (rn);
2766
paul718e3742002-12-13 20:15:29 +00002767 return 1;
2768}
2769
paul718e3742002-12-13 20:15:29 +00002770#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002771static int
paul718e3742002-12-13 20:15:29 +00002772rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2773 struct in6_addr *gate, unsigned int ifindex, int table)
2774{
hasso726f9b22003-05-25 21:04:54 +00002775 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2776#if defined (MUSICA) || defined (LINUX)
2777 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2778 if (p->prefixlen == 96)
2779 return 0;
2780#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002781 return 1;
hasso726f9b22003-05-25 21:04:54 +00002782 }
paul718e3742002-12-13 20:15:29 +00002783 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2784 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2785 {
2786 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2787 return 1;
2788 }
2789 return 0;
2790}
2791
2792int
2793rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002794 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002795 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002796{
2797 struct rib *rib;
2798 struct rib *same = NULL;
2799 struct route_table *table;
2800 struct route_node *rn;
2801 struct nexthop *nexthop;
2802
paul718e3742002-12-13 20:15:29 +00002803 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002804 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002805 if (! table)
2806 return 0;
2807
2808 /* Make sure mask is applied. */
2809 apply_mask_ipv6 (p);
2810
2811 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002812 if (!distance)
2813 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002814
2815 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2816 distance = 200;
2817
2818 /* Filter bogus route. */
2819 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2820 return 0;
2821
2822 /* Lookup route node.*/
2823 rn = route_node_get (table, (struct prefix *) p);
2824
2825 /* If same type of route are installed, treat it as a implicit
2826 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002827 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002828 {
Paul Jakma6d691122006-07-27 21:49:00 +00002829 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2830 continue;
2831
hassoebf1ead2005-09-21 14:58:20 +00002832 if (rib->type != type)
2833 continue;
2834 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002835 {
2836 same = rib;
paul718e3742002-12-13 20:15:29 +00002837 break;
2838 }
hassoebf1ead2005-09-21 14:58:20 +00002839 else if ((nexthop = rib->nexthop) &&
2840 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2841 nexthop->ifindex == ifindex)
2842 {
2843 rib->refcnt++;
2844 return 0;
2845 }
paul718e3742002-12-13 20:15:29 +00002846 }
2847
2848 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002849 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2850
paul718e3742002-12-13 20:15:29 +00002851 rib->type = type;
2852 rib->distance = distance;
2853 rib->flags = flags;
2854 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002855 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002856 rib->nexthop_num = 0;
2857 rib->uptime = time (NULL);
2858
2859 /* Nexthop settings. */
2860 if (gate)
2861 {
2862 if (ifindex)
2863 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2864 else
2865 nexthop_ipv6_add (rib, gate);
2866 }
2867 else
2868 nexthop_ifindex_add (rib, ifindex);
2869
2870 /* If this route is kernel route, set FIB flag to the route. */
2871 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2872 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2873 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2874
2875 /* Link new rib to node.*/
2876 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002877 if (IS_ZEBRA_DEBUG_RIB)
2878 {
2879 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2880 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002881 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002882 }
paul718e3742002-12-13 20:15:29 +00002883
paul718e3742002-12-13 20:15:29 +00002884 /* Free implicit route.*/
2885 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002886 {
2887 if (IS_ZEBRA_DEBUG_RIB)
2888 {
2889 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2890 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002891 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002892 }
paul4d38fdb2005-04-28 17:35:14 +00002893 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002894 }
paul4d38fdb2005-04-28 17:35:14 +00002895
2896 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002897 return 0;
2898}
2899
hassoebf1ead2005-09-21 14:58:20 +00002900/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002901int
2902rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002903 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002904{
2905 struct route_table *table;
2906 struct route_node *rn;
2907 struct rib *rib;
2908 struct rib *fib = NULL;
2909 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002910 struct nexthop *nexthop, *tnexthop;
2911 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002912 char buf1[INET6_ADDRSTRLEN];
2913 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002914
2915 /* Apply mask. */
2916 apply_mask_ipv6 (p);
2917
2918 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002919 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002920 if (! table)
2921 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002922
paul718e3742002-12-13 20:15:29 +00002923 /* Lookup route node. */
2924 rn = route_node_lookup (table, (struct prefix *) p);
2925 if (! rn)
2926 {
2927 if (IS_ZEBRA_DEBUG_KERNEL)
2928 {
2929 if (gate)
ajsb6178002004-12-07 21:12:56 +00002930 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002931 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002932 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002933 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002934 ifindex);
2935 else
ajsb6178002004-12-07 21:12:56 +00002936 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002937 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002938 p->prefixlen,
2939 ifindex);
2940 }
2941 return ZEBRA_ERR_RTNOEXIST;
2942 }
2943
2944 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002945 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002946 {
Paul Jakma6d691122006-07-27 21:49:00 +00002947 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2948 continue;
2949
paul718e3742002-12-13 20:15:29 +00002950 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2951 fib = rib;
2952
hassoebf1ead2005-09-21 14:58:20 +00002953 if (rib->type != type)
2954 continue;
2955 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002956 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002957 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002958 if (nexthop->ifindex != ifindex)
2959 continue;
hassoebf1ead2005-09-21 14:58:20 +00002960 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002961 {
hassoebf1ead2005-09-21 14:58:20 +00002962 rib->refcnt--;
2963 route_unlock_node (rn);
2964 route_unlock_node (rn);
2965 return 0;
paul718e3742002-12-13 20:15:29 +00002966 }
hassoebf1ead2005-09-21 14:58:20 +00002967 same = rib;
2968 break;
paul718e3742002-12-13 20:15:29 +00002969 }
hassoebf1ead2005-09-21 14:58:20 +00002970 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002971 else
2972 {
2973 if (gate == NULL)
2974 {
2975 same = rib;
2976 break;
2977 }
2978 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2979 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2980 {
2981 same = rib;
2982 break;
2983 }
2984 if (same)
2985 break;
2986 }
paul718e3742002-12-13 20:15:29 +00002987 }
2988
2989 /* If same type of route can't be found and this message is from
2990 kernel. */
2991 if (! same)
2992 {
2993 if (fib && type == ZEBRA_ROUTE_KERNEL)
2994 {
2995 /* Unset flags. */
2996 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2997 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2998
2999 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
3000 }
3001 else
3002 {
3003 if (IS_ZEBRA_DEBUG_KERNEL)
3004 {
3005 if (gate)
ajsb6178002004-12-07 21:12:56 +00003006 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07003007 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00003008 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07003009 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00003010 ifindex,
3011 type);
3012 else
ajsb6178002004-12-07 21:12:56 +00003013 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07003014 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00003015 p->prefixlen,
3016 ifindex,
3017 type);
3018 }
3019 route_unlock_node (rn);
3020 return ZEBRA_ERR_RTNOEXIST;
3021 }
3022 }
3023
3024 if (same)
3025 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00003026
paul718e3742002-12-13 20:15:29 +00003027 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00003028 return 0;
3029}
David Lamparter6b0655a2014-06-04 06:53:35 +02003030
paul718e3742002-12-13 20:15:29 +00003031/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00003032static void
paul718e3742002-12-13 20:15:29 +00003033static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
3034{
3035 struct rib *rib;
3036 struct route_table *table;
3037 struct route_node *rn;
3038
3039 /* Lookup table. */
3040 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3041 if (! table)
3042 return;
3043
3044 /* Lookup existing route */
3045 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003046 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003047 {
3048 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
3049 continue;
3050
3051 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3052 break;
3053 }
paul718e3742002-12-13 20:15:29 +00003054
3055 if (rib)
3056 {
3057 /* Same distance static route is there. Update it with new
3058 nexthop. */
paul718e3742002-12-13 20:15:29 +00003059 route_unlock_node (rn);
3060
3061 switch (si->type)
3062 {
3063 case STATIC_IPV6_GATEWAY:
3064 nexthop_ipv6_add (rib, &si->ipv6);
3065 break;
3066 case STATIC_IPV6_IFNAME:
3067 nexthop_ifname_add (rib, si->ifname);
3068 break;
3069 case STATIC_IPV6_GATEWAY_IFNAME:
3070 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
3071 break;
3072 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00003073 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003074 }
3075 else
3076 {
3077 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00003078 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
3079
paul718e3742002-12-13 20:15:29 +00003080 rib->type = ZEBRA_ROUTE_STATIC;
3081 rib->distance = si->distance;
3082 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07003083 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00003084 rib->nexthop_num = 0;
3085
3086 switch (si->type)
3087 {
3088 case STATIC_IPV6_GATEWAY:
3089 nexthop_ipv6_add (rib, &si->ipv6);
3090 break;
3091 case STATIC_IPV6_IFNAME:
3092 nexthop_ifname_add (rib, si->ifname);
3093 break;
3094 case STATIC_IPV6_GATEWAY_IFNAME:
3095 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
3096 break;
3097 }
3098
hasso81dfcaa2003-05-25 19:21:25 +00003099 /* Save the flags of this static routes (reject, blackhole) */
3100 rib->flags = si->flags;
3101
paul718e3742002-12-13 20:15:29 +00003102 /* Link this rib to the tree. */
3103 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003104 }
3105}
3106
paula1ac18c2005-06-28 17:17:12 +00003107static int
paul718e3742002-12-13 20:15:29 +00003108static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
3109{
3110 if (nexthop->type == NEXTHOP_TYPE_IPV6
3111 && si->type == STATIC_IPV6_GATEWAY
3112 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
3113 return 1;
3114 if (nexthop->type == NEXTHOP_TYPE_IFNAME
3115 && si->type == STATIC_IPV6_IFNAME
3116 && strcmp (nexthop->ifname, si->ifname) == 0)
3117 return 1;
3118 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3119 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3120 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3121 && strcmp (nexthop->ifname, si->ifname) == 0)
3122 return 1;
paule8e19462006-01-19 20:16:55 +00003123 return 0;
paul718e3742002-12-13 20:15:29 +00003124}
3125
paula1ac18c2005-06-28 17:17:12 +00003126static void
paul718e3742002-12-13 20:15:29 +00003127static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3128{
3129 struct route_table *table;
3130 struct route_node *rn;
3131 struct rib *rib;
3132 struct nexthop *nexthop;
3133
3134 /* Lookup table. */
3135 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3136 if (! table)
3137 return;
3138
3139 /* Lookup existing route with type and distance. */
3140 rn = route_node_lookup (table, (struct prefix *) p);
3141 if (! rn)
3142 return;
3143
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003144 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003145 {
3146 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3147 continue;
3148
3149 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3150 break;
3151 }
3152
paul718e3742002-12-13 20:15:29 +00003153 if (! rib)
3154 {
3155 route_unlock_node (rn);
3156 return;
3157 }
3158
3159 /* Lookup nexthop. */
3160 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3161 if (static_ipv6_nexthop_same (nexthop, si))
3162 break;
3163
3164 /* Can't find nexthop. */
3165 if (! nexthop)
3166 {
3167 route_unlock_node (rn);
3168 return;
3169 }
3170
3171 /* Check nexthop. */
3172 if (rib->nexthop_num == 1)
3173 {
3174 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003175 }
3176 else
3177 {
paul6baeb982003-10-28 03:47:15 +00003178 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3179 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003180 nexthop_delete (rib, nexthop);
3181 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003182 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003183 }
paul718e3742002-12-13 20:15:29 +00003184 /* Unlock node. */
3185 route_unlock_node (rn);
3186}
3187
3188/* Add static route into static route configuration. */
3189int
3190static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003191 const char *ifname, u_char flags, u_char distance,
3192 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003193{
3194 struct route_node *rn;
3195 struct static_ipv6 *si;
3196 struct static_ipv6 *pp;
3197 struct static_ipv6 *cp;
3198 struct route_table *stable;
3199
3200 /* Lookup table. */
3201 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3202 if (! stable)
3203 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003204
3205 if (!gate &&
3206 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3207 return -1;
3208
3209 if (!ifname &&
3210 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3211 return -1;
paul718e3742002-12-13 20:15:29 +00003212
3213 /* Lookup static route prefix. */
3214 rn = route_node_get (stable, p);
3215
3216 /* Do nothing if there is a same static route. */
3217 for (si = rn->info; si; si = si->next)
3218 {
3219 if (distance == si->distance
3220 && type == si->type
3221 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3222 && (! ifname || strcmp (ifname, si->ifname) == 0))
3223 {
3224 route_unlock_node (rn);
3225 return 0;
3226 }
3227 }
3228
3229 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003230 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003231
3232 si->type = type;
3233 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003234 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003235
3236 switch (type)
3237 {
3238 case STATIC_IPV6_GATEWAY:
3239 si->ipv6 = *gate;
3240 break;
3241 case STATIC_IPV6_IFNAME:
3242 si->ifname = XSTRDUP (0, ifname);
3243 break;
3244 case STATIC_IPV6_GATEWAY_IFNAME:
3245 si->ipv6 = *gate;
3246 si->ifname = XSTRDUP (0, ifname);
3247 break;
3248 }
3249
3250 /* Add new static route information to the tree with sort by
3251 distance value and gateway address. */
3252 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3253 {
3254 if (si->distance < cp->distance)
3255 break;
3256 if (si->distance > cp->distance)
3257 continue;
3258 }
3259
3260 /* Make linked list. */
3261 if (pp)
3262 pp->next = si;
3263 else
3264 rn->info = si;
3265 if (cp)
3266 cp->prev = si;
3267 si->prev = pp;
3268 si->next = cp;
3269
3270 /* Install into rib. */
3271 static_install_ipv6 (p, si);
3272
3273 return 1;
3274}
3275
3276/* Delete static route from static route configuration. */
3277int
3278static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003279 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003280{
3281 struct route_node *rn;
3282 struct static_ipv6 *si;
3283 struct route_table *stable;
3284
3285 /* Lookup table. */
3286 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3287 if (! stable)
3288 return -1;
3289
3290 /* Lookup static route prefix. */
3291 rn = route_node_lookup (stable, p);
3292 if (! rn)
3293 return 0;
3294
3295 /* Find same static route is the tree */
3296 for (si = rn->info; si; si = si->next)
3297 if (distance == si->distance
3298 && type == si->type
3299 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3300 && (! ifname || strcmp (ifname, si->ifname) == 0))
3301 break;
3302
3303 /* Can't find static route. */
3304 if (! si)
3305 {
3306 route_unlock_node (rn);
3307 return 0;
3308 }
3309
3310 /* Install into rib. */
3311 static_uninstall_ipv6 (p, si);
3312
3313 /* Unlink static route from linked list. */
3314 if (si->prev)
3315 si->prev->next = si->next;
3316 else
3317 rn->info = si->next;
3318 if (si->next)
3319 si->next->prev = si->prev;
3320
3321 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003322 if (ifname)
3323 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003324 XFREE (MTYPE_STATIC_IPV6, si);
3325
3326 return 1;
3327}
3328#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003329
paul718e3742002-12-13 20:15:29 +00003330/* RIB update function. */
3331void
paula1ac18c2005-06-28 17:17:12 +00003332rib_update (void)
paul718e3742002-12-13 20:15:29 +00003333{
3334 struct route_node *rn;
3335 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003336
paul718e3742002-12-13 20:15:29 +00003337 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3338 if (table)
3339 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003340 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003341 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003342
3343 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3344 if (table)
3345 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003346 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003347 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003348}
3349
David Lamparter6b0655a2014-06-04 06:53:35 +02003350
paul718e3742002-12-13 20:15:29 +00003351/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003352static void
paul718e3742002-12-13 20:15:29 +00003353rib_weed_table (struct route_table *table)
3354{
3355 struct route_node *rn;
3356 struct rib *rib;
3357 struct rib *next;
3358
3359 if (table)
3360 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003361 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003362 {
Paul Jakma6d691122006-07-27 21:49:00 +00003363 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3364 continue;
3365
paulb21b19c2003-06-15 01:28:29 +00003366 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003367 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003368 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003369 }
3370}
3371
3372/* Delete all routes from non main table. */
3373void
paula1ac18c2005-06-28 17:17:12 +00003374rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003375{
3376 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3377 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3378}
David Lamparter6b0655a2014-06-04 06:53:35 +02003379
paul718e3742002-12-13 20:15:29 +00003380/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003381static void
paul718e3742002-12-13 20:15:29 +00003382rib_sweep_table (struct route_table *table)
3383{
3384 struct route_node *rn;
3385 struct rib *rib;
3386 struct rib *next;
3387 int ret = 0;
3388
3389 if (table)
3390 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003391 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003392 {
Paul Jakma6d691122006-07-27 21:49:00 +00003393 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3394 continue;
3395
paul718e3742002-12-13 20:15:29 +00003396 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3397 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3398 {
3399 ret = rib_uninstall_kernel (rn, rib);
3400 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003401 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003402 }
3403 }
3404}
3405
3406/* Sweep all RIB tables. */
3407void
paula1ac18c2005-06-28 17:17:12 +00003408rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003409{
3410 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3411 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3412}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003413
3414/* Remove specific by protocol routes from 'table'. */
3415static unsigned long
3416rib_score_proto_table (u_char proto, struct route_table *table)
3417{
3418 struct route_node *rn;
3419 struct rib *rib;
3420 struct rib *next;
3421 unsigned long n = 0;
3422
3423 if (table)
3424 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003425 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003426 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003427 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3428 continue;
3429 if (rib->type == proto)
3430 {
3431 rib_delnode (rn, rib);
3432 n++;
3433 }
3434 }
3435
3436 return n;
3437}
3438
3439/* Remove specific by protocol routes. */
3440unsigned long
3441rib_score_proto (u_char proto)
3442{
3443 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3444 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3445}
3446
paul718e3742002-12-13 20:15:29 +00003447/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003448static void
paul718e3742002-12-13 20:15:29 +00003449rib_close_table (struct route_table *table)
3450{
3451 struct route_node *rn;
David Lamparterc048dcc2015-01-12 07:05:06 +01003452 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003453 struct rib *rib;
3454
3455 if (table)
3456 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003457 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003458 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003459 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3460 continue;
3461
David Lamparterc048dcc2015-01-12 07:05:06 +01003462 if (info->safi == SAFI_UNICAST)
3463 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003464
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003465 if (! RIB_SYSTEM_ROUTE (rib))
3466 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003467 }
paul718e3742002-12-13 20:15:29 +00003468}
3469
3470/* Close all RIB tables. */
3471void
paula1ac18c2005-06-28 17:17:12 +00003472rib_close (void)
paul718e3742002-12-13 20:15:29 +00003473{
3474 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3475 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3476}
David Lamparter6b0655a2014-06-04 06:53:35 +02003477
paul718e3742002-12-13 20:15:29 +00003478/* Routing information base initialize. */
3479void
paula1ac18c2005-06-28 17:17:12 +00003480rib_init (void)
paul718e3742002-12-13 20:15:29 +00003481{
paul4d38fdb2005-04-28 17:35:14 +00003482 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003483 /* VRF initialization. */
3484 vrf_init ();
3485}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003486
3487/*
3488 * vrf_id_get_next
3489 *
3490 * Get the first vrf id that is greater than the given vrf id if any.
3491 *
3492 * Returns TRUE if a vrf id was found, FALSE otherwise.
3493 */
3494static inline int
3495vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3496{
3497 while (++id < vector_active (vrf_vector))
3498 {
3499 if (vrf_lookup (id))
3500 {
3501 *next_id_p = id;
3502 return 1;
3503 }
3504 }
3505
3506 return 0;
3507}
3508
3509/*
3510 * rib_tables_iter_next
3511 *
3512 * Returns the next table in the iteration.
3513 */
3514struct route_table *
3515rib_tables_iter_next (rib_tables_iter_t *iter)
3516{
3517 struct route_table *table;
3518
3519 /*
3520 * Array that helps us go over all AFI/SAFI combinations via one
3521 * index.
3522 */
3523 static struct {
3524 afi_t afi;
3525 safi_t safi;
3526 } afi_safis[] = {
3527 { AFI_IP, SAFI_UNICAST },
3528 { AFI_IP, SAFI_MULTICAST },
3529 { AFI_IP6, SAFI_UNICAST },
3530 { AFI_IP6, SAFI_MULTICAST },
3531 };
3532
3533 table = NULL;
3534
3535 switch (iter->state)
3536 {
3537
3538 case RIB_TABLES_ITER_S_INIT:
3539 iter->vrf_id = 0;
3540 iter->afi_safi_ix = -1;
3541
3542 /* Fall through */
3543
3544 case RIB_TABLES_ITER_S_ITERATING:
3545 iter->afi_safi_ix++;
3546 while (1)
3547 {
3548
3549 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3550 {
3551 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3552 afi_safis[iter->afi_safi_ix].safi,
3553 iter->vrf_id);
3554 if (table)
3555 break;
3556
3557 iter->afi_safi_ix++;
3558 }
3559
3560 /*
3561 * Found another table in this vrf.
3562 */
3563 if (table)
3564 break;
3565
3566 /*
3567 * Done with all tables in the current vrf, go to the next
3568 * one.
3569 */
3570 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3571 break;
3572
3573 iter->afi_safi_ix = 0;
3574 }
3575
3576 break;
3577
3578 case RIB_TABLES_ITER_S_DONE:
3579 return NULL;
3580 }
3581
3582 if (table)
3583 iter->state = RIB_TABLES_ITER_S_ITERATING;
3584 else
3585 iter->state = RIB_TABLES_ITER_S_DONE;
3586
3587 return table;
3588}