blob: c6dbdec51c3583e0af3265809af8103480d5ecda [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "str.h"
28#include "command.h"
29#include "if.h"
30#include "log.h"
31#include "sockunion.h"
paul4d38fdb2005-04-28 17:35:14 +000032#include "linklist.h"
33#include "thread.h"
34#include "workqueue.h"
Paul Jakma7514fb72007-05-02 16:05:35 +000035#include "prefix.h"
36#include "routemap.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "zebra/rib.h"
39#include "zebra/rt.h"
40#include "zebra/zserv.h"
41#include "zebra/redistribute.h"
42#include "zebra/debug.h"
Avneesh Sachdev5adc2522012-11-13 22:48:59 +000043#include "zebra/zebra_fpm.h"
paul718e3742002-12-13 20:15:29 +000044
45/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000046extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000047
Paul Jakma457eb9a2006-07-27 19:59:58 +000048/* Hold time for RIB process, should be very minimal.
49 * it is useful to able to set it otherwise for testing, hence exported
50 * as global here for test-rig code.
51 */
52int rib_process_hold_time = 10;
53
paul718e3742002-12-13 20:15:29 +000054/* Each route type's string and default distance value. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010055static const struct
paul718e3742002-12-13 20:15:29 +000056{
57 int key;
58 int distance;
Paul Jakma57345092011-12-25 17:52:09 +010059} route_info[ZEBRA_ROUTE_MAX] =
paul718e3742002-12-13 20:15:29 +000060{
Paul Jakma57345092011-12-25 17:52:09 +010061 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
62 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
63 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
64 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
65 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
66 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
67 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
68 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
69 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
70 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
71 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
David Lamparter7052f222009-08-27 00:28:28 +020072 /* no entry/default: 150 */
paul718e3742002-12-13 20:15:29 +000073};
David Lamparter6b0655a2014-06-04 06:53:35 +020074
paul718e3742002-12-13 20:15:29 +000075/* Vector for routing table. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010076static vector vrf_vector;
paul718e3742002-12-13 20:15:29 +000077
David Lamparter240c56f2015-01-06 19:53:24 +010078/* RPF lookup behaviour */
79static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
80
David Lampartere0b0ac82014-04-24 20:22:53 +020081static void
82_rnode_zlog(const char *_func, struct route_node *rn, int priority,
83 const char *msgfmt, ...)
84{
85 char buf[INET6_ADDRSTRLEN + 4], *bptr;
86 char msgbuf[512];
87 va_list ap;
88
89 va_start(ap, msgfmt);
90 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
91 va_end(ap);
92
93 if (rn)
94 {
David Lamparterf7b3d1e2015-01-22 19:02:13 +010095 rib_table_info_t *info = rn->table->info;
96
David Lampartere0b0ac82014-04-24 20:22:53 +020097 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
98 bptr = buf + strlen(buf);
David Lamparterf7b3d1e2015-01-22 19:02:13 +010099 snprintf(bptr, buf + sizeof(buf) - bptr, "/%d%s", rn->p.prefixlen,
100 info->safi == SAFI_MULTICAST ? " (MRIB)" : "");
David Lampartere0b0ac82014-04-24 20:22:53 +0200101 }
102 else
103 {
104 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
105 }
106
107 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
108}
109
110#define rnode_debug(node, ...) \
111 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
112#define rnode_info(node, ...) \
113 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
114
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000115/*
116 * vrf_table_create
117 */
118static void
119vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
120{
121 rib_table_info_t *info;
122 struct route_table *table;
123
124 assert (!vrf->table[afi][safi]);
125
126 table = route_table_init ();
127 vrf->table[afi][safi] = table;
128
129 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
130 info->vrf = vrf;
131 info->afi = afi;
132 info->safi = safi;
133 table->info = info;
134}
135
paul718e3742002-12-13 20:15:29 +0000136/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +0000137static struct vrf *
hassofce954f2004-10-07 20:29:24 +0000138vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +0000139{
140 struct vrf *vrf;
141
142 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
143
144 /* Put name. */
145 if (name)
146 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
147
148 /* Allocate routing table and static table. */
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000149 vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
150 vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000151 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
152 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000153 vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
154 vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
G.Balajicddf3912011-11-26 21:59:32 +0400155 vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
156 vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
157
paul718e3742002-12-13 20:15:29 +0000158
159 return vrf;
160}
161
paul718e3742002-12-13 20:15:29 +0000162/* Lookup VRF by identifier. */
163struct vrf *
164vrf_lookup (u_int32_t id)
165{
166 return vector_lookup (vrf_vector, id);
167}
168
paul718e3742002-12-13 20:15:29 +0000169/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000170static void
171vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000172{
173 struct vrf *default_table;
174
175 /* Allocate VRF vector. */
176 vrf_vector = vector_init (1);
177
178 /* Allocate default main table. */
179 default_table = vrf_alloc ("Default-IP-Routing-Table");
180
181 /* Default table index must be 0. */
182 vector_set_index (vrf_vector, 0, default_table);
183}
184
185/* Lookup route table. */
186struct route_table *
187vrf_table (afi_t afi, safi_t safi, u_int32_t id)
188{
189 struct vrf *vrf;
190
191 vrf = vrf_lookup (id);
192 if (! vrf)
193 return NULL;
194
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000195 if( afi >= AFI_MAX || safi >= SAFI_MAX )
196 return NULL;
197
paul718e3742002-12-13 20:15:29 +0000198 return vrf->table[afi][safi];
199}
200
201/* Lookup static route table. */
202struct route_table *
203vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
204{
205 struct vrf *vrf;
206
207 vrf = vrf_lookup (id);
208 if (! vrf)
209 return NULL;
210
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000211 if( afi >= AFI_MAX || safi >= SAFI_MAX )
212 return NULL;
213
paul718e3742002-12-13 20:15:29 +0000214 return vrf->stable[afi][safi];
215}
David Lamparter6b0655a2014-06-04 06:53:35 +0200216
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000217/*
218 * nexthop_type_to_str
219 */
220const char *
221nexthop_type_to_str (enum nexthop_types_t nh_type)
222{
223 static const char *desc[] = {
224 "none",
225 "Directly connected",
226 "Interface route",
227 "IPv4 nexthop",
228 "IPv4 nexthop with ifindex",
229 "IPv4 nexthop with ifname",
230 "IPv6 nexthop",
231 "IPv6 nexthop with ifindex",
232 "IPv6 nexthop with ifname",
233 "Null0 nexthop",
234 };
235
236 if (nh_type >= ZEBRA_NUM_OF (desc))
237 return "<Invalid nh type>";
238
239 return desc[nh_type];
240}
241
Christian Frankefa713d92013-07-05 15:35:37 +0000242/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000243static void
Christian Frankefa713d92013-07-05 15:35:37 +0000244_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000245{
246 struct nexthop *last;
247
Christian Frankefa713d92013-07-05 15:35:37 +0000248 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000249 ;
250 if (last)
251 last->next = nexthop;
252 else
Christian Frankefa713d92013-07-05 15:35:37 +0000253 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000254 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000255}
paul718e3742002-12-13 20:15:29 +0000256
Christian Frankefa713d92013-07-05 15:35:37 +0000257/* Add nexthop to the end of a rib node's nexthop list */
258static void
259nexthop_add (struct rib *rib, struct nexthop *nexthop)
260{
261 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000262 rib->nexthop_num++;
263}
264
265/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000266static void
paul718e3742002-12-13 20:15:29 +0000267nexthop_delete (struct rib *rib, struct nexthop *nexthop)
268{
269 if (nexthop->next)
270 nexthop->next->prev = nexthop->prev;
271 if (nexthop->prev)
272 nexthop->prev->next = nexthop->next;
273 else
274 rib->nexthop = nexthop->next;
275 rib->nexthop_num--;
276}
277
Christian Frankefa713d92013-07-05 15:35:37 +0000278static void nexthops_free(struct nexthop *nexthop);
279
paul718e3742002-12-13 20:15:29 +0000280/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000281static void
paul718e3742002-12-13 20:15:29 +0000282nexthop_free (struct nexthop *nexthop)
283{
paula4b70762003-05-16 17:19:48 +0000284 if (nexthop->ifname)
285 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000286 if (nexthop->resolved)
287 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000288 XFREE (MTYPE_NEXTHOP, nexthop);
289}
290
Christian Frankefa713d92013-07-05 15:35:37 +0000291/* Frees a list of nexthops */
292static void
293nexthops_free (struct nexthop *nexthop)
294{
295 struct nexthop *nh, *next;
296
297 for (nh = nexthop; nh; nh = next)
298 {
299 next = nh->next;
300 nexthop_free (nh);
301 }
302}
303
paul718e3742002-12-13 20:15:29 +0000304struct nexthop *
305nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
306{
307 struct nexthop *nexthop;
308
Stephen Hemminger393deb92008-08-18 14:13:29 -0700309 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000310 nexthop->type = NEXTHOP_TYPE_IFINDEX;
311 nexthop->ifindex = ifindex;
312
313 nexthop_add (rib, nexthop);
314
315 return nexthop;
316}
317
318struct nexthop *
319nexthop_ifname_add (struct rib *rib, char *ifname)
320{
321 struct nexthop *nexthop;
322
Stephen Hemminger393deb92008-08-18 14:13:29 -0700323 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000324 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000325 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000326
327 nexthop_add (rib, nexthop);
328
329 return nexthop;
330}
331
332struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000333nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000334{
335 struct nexthop *nexthop;
336
Stephen Hemminger393deb92008-08-18 14:13:29 -0700337 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000338 nexthop->type = NEXTHOP_TYPE_IPV4;
339 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000340 if (src)
341 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000342
343 nexthop_add (rib, nexthop);
344
345 return nexthop;
346}
347
Josh Bailey26e2ae32012-03-22 01:09:21 -0700348struct nexthop *
paul718e3742002-12-13 20:15:29 +0000349nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000350 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000351{
352 struct nexthop *nexthop;
353
Stephen Hemminger393deb92008-08-18 14:13:29 -0700354 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000355 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
356 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000357 if (src)
358 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000359 nexthop->ifindex = ifindex;
360
361 nexthop_add (rib, nexthop);
362
363 return nexthop;
364}
365
366#ifdef HAVE_IPV6
367struct nexthop *
368nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
369{
370 struct nexthop *nexthop;
371
Stephen Hemminger393deb92008-08-18 14:13:29 -0700372 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000373 nexthop->type = NEXTHOP_TYPE_IPV6;
374 nexthop->gate.ipv6 = *ipv6;
375
376 nexthop_add (rib, nexthop);
377
378 return nexthop;
379}
380
paula1ac18c2005-06-28 17:17:12 +0000381static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000382nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
383 char *ifname)
384{
385 struct nexthop *nexthop;
386
Stephen Hemminger393deb92008-08-18 14:13:29 -0700387 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000388 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
389 nexthop->gate.ipv6 = *ipv6;
390 nexthop->ifname = XSTRDUP (0, ifname);
391
392 nexthop_add (rib, nexthop);
393
394 return nexthop;
395}
396
paula1ac18c2005-06-28 17:17:12 +0000397static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000398nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
399 unsigned int ifindex)
400{
401 struct nexthop *nexthop;
402
Stephen Hemminger393deb92008-08-18 14:13:29 -0700403 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000404 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
405 nexthop->gate.ipv6 = *ipv6;
406 nexthop->ifindex = ifindex;
407
408 nexthop_add (rib, nexthop);
409
410 return nexthop;
411}
412#endif /* HAVE_IPV6 */
413
paul595db7f2003-05-25 21:35:06 +0000414struct nexthop *
415nexthop_blackhole_add (struct rib *rib)
416{
417 struct nexthop *nexthop;
418
Stephen Hemminger393deb92008-08-18 14:13:29 -0700419 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000420 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
421 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
422
423 nexthop_add (rib, nexthop);
424
425 return nexthop;
426}
427
Christian Frankefa713d92013-07-05 15:35:37 +0000428/* This method checks whether a recursive nexthop has at
429 * least one resolved nexthop in the fib.
430 */
431int
432nexthop_has_fib_child(struct nexthop *nexthop)
433{
434 struct nexthop *nh;
435
436 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
437 return 0;
438
439 for (nh = nexthop->resolved; nh; nh = nh->next)
440 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
441 return 1;
442
443 return 0;
444}
445
paul718e3742002-12-13 20:15:29 +0000446/* If force flag is not set, do not modify falgs at all for uninstall
447 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000448static int
paul718e3742002-12-13 20:15:29 +0000449nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
450 struct route_node *top)
451{
452 struct prefix_ipv4 p;
453 struct route_table *table;
454 struct route_node *rn;
455 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000456 int resolved;
paul718e3742002-12-13 20:15:29 +0000457 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000458 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000459
460 if (nexthop->type == NEXTHOP_TYPE_IPV4)
461 nexthop->ifindex = 0;
462
463 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000464 {
465 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
466 nexthops_free(nexthop->resolved);
467 nexthop->resolved = NULL;
468 }
paul718e3742002-12-13 20:15:29 +0000469
470 /* Make lookup prefix. */
471 memset (&p, 0, sizeof (struct prefix_ipv4));
472 p.family = AF_INET;
473 p.prefixlen = IPV4_MAX_PREFIXLEN;
474 p.prefix = nexthop->gate.ipv4;
475
476 /* Lookup table. */
477 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
478 if (! table)
479 return 0;
480
481 rn = route_node_match (table, (struct prefix *) &p);
482 while (rn)
483 {
484 route_unlock_node (rn);
485
David Warda50c1072009-12-03 15:34:39 +0300486 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000487 if (rn == top)
488 return 0;
489
490 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000491 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100492 {
493 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
494 continue;
495 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
496 break;
497 }
paul718e3742002-12-13 20:15:29 +0000498
499 /* If there is no selected route or matched route is EGP, go up
500 tree. */
501 if (! match
502 || match->type == ZEBRA_ROUTE_BGP)
503 {
504 do {
505 rn = rn->parent;
506 } while (rn && rn->info == NULL);
507 if (rn)
508 route_lock_node (rn);
509 }
510 else
511 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000512 /* If the longest prefix match for the nexthop yields
513 * a blackhole, mark it as inactive. */
514 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
515 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
516 return 0;
517
paul718e3742002-12-13 20:15:29 +0000518 if (match->type == ZEBRA_ROUTE_CONNECT)
519 {
520 /* Directly point connected route. */
521 newhop = match->nexthop;
522 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
523 nexthop->ifindex = newhop->ifindex;
524
525 return 1;
526 }
Everton Marques871dbcf2009-08-11 15:43:05 -0300527 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) ||
528 match->type == ZEBRA_ROUTE_KERNEL)
Everton Marquesb24c7fe2014-09-22 18:00:15 -0300529 /*
530 || match->type == ZEBRA_ROUTE_KERNEL
531 This prevents zebra from marking recursive static route as inactive.
532 See pimd/TODO T26.
533 */
paul718e3742002-12-13 20:15:29 +0000534 {
Christian Frankefa713d92013-07-05 15:35:37 +0000535 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000536 for (newhop = match->nexthop; newhop; newhop = newhop->next)
537 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
538 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
539 {
540 if (set)
541 {
542 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000543
544 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
545 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000546 /* If the resolving route specifies a gateway, use it */
547 if (newhop->type == NEXTHOP_TYPE_IPV4
548 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
549 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
550 {
551 resolved_hop->type = newhop->type;
552 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000553
Christian Frankec3e6b592013-07-05 15:35:40 +0000554 if (newhop->ifindex)
555 {
556 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
557 resolved_hop->ifindex = newhop->ifindex;
558 }
559 }
Christian Frankefa713d92013-07-05 15:35:37 +0000560
Christian Frankec3e6b592013-07-05 15:35:40 +0000561 /* If the resolving route is an interface route,
562 * it means the gateway we are looking up is connected
563 * to that interface. (The actual network is _not_ onlink).
564 * Therefore, the resolved route should have the original
565 * gateway as nexthop as it is directly connected.
566 *
567 * On Linux, we have to set the onlink netlink flag because
568 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000569 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000570 || newhop->type == NEXTHOP_TYPE_IFNAME)
571 {
572 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
573 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
574 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
575 resolved_hop->ifindex = newhop->ifindex;
576 }
Christian Frankefa713d92013-07-05 15:35:37 +0000577
578 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000579 }
Christian Frankefa713d92013-07-05 15:35:37 +0000580 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000581 }
Christian Frankefa713d92013-07-05 15:35:37 +0000582 return resolved;
paul718e3742002-12-13 20:15:29 +0000583 }
584 else
585 {
586 return 0;
587 }
588 }
589 }
590 return 0;
591}
592
593#ifdef HAVE_IPV6
594/* If force flag is not set, do not modify falgs at all for uninstall
595 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000596static int
paul718e3742002-12-13 20:15:29 +0000597nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
598 struct route_node *top)
599{
600 struct prefix_ipv6 p;
601 struct route_table *table;
602 struct route_node *rn;
603 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000604 int resolved;
paul718e3742002-12-13 20:15:29 +0000605 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000606 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000607
608 if (nexthop->type == NEXTHOP_TYPE_IPV6)
609 nexthop->ifindex = 0;
610
611 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000612 {
613 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
614 nexthops_free(nexthop->resolved);
615 nexthop->resolved = NULL;
616 }
paul718e3742002-12-13 20:15:29 +0000617
618 /* Make lookup prefix. */
619 memset (&p, 0, sizeof (struct prefix_ipv6));
620 p.family = AF_INET6;
621 p.prefixlen = IPV6_MAX_PREFIXLEN;
622 p.prefix = nexthop->gate.ipv6;
623
624 /* Lookup table. */
625 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
626 if (! table)
627 return 0;
628
629 rn = route_node_match (table, (struct prefix *) &p);
630 while (rn)
631 {
632 route_unlock_node (rn);
633
David Warda50c1072009-12-03 15:34:39 +0300634 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000635 if (rn == top)
636 return 0;
637
638 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000639 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100640 {
641 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
642 continue;
643 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
644 break;
645 }
paul718e3742002-12-13 20:15:29 +0000646
647 /* If there is no selected route or matched route is EGP, go up
648 tree. */
649 if (! match
650 || match->type == ZEBRA_ROUTE_BGP)
651 {
652 do {
653 rn = rn->parent;
654 } while (rn && rn->info == NULL);
655 if (rn)
656 route_lock_node (rn);
657 }
658 else
659 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000660 /* If the longest prefix match for the nexthop yields
661 * a blackhole, mark it as inactive. */
662 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
663 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
664 return 0;
665
paul718e3742002-12-13 20:15:29 +0000666 if (match->type == ZEBRA_ROUTE_CONNECT)
667 {
668 /* Directly point connected route. */
669 newhop = match->nexthop;
670
671 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
672 nexthop->ifindex = newhop->ifindex;
673
674 return 1;
675 }
676 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
677 {
Christian Frankefa713d92013-07-05 15:35:37 +0000678 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000679 for (newhop = match->nexthop; newhop; newhop = newhop->next)
680 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
681 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
682 {
683 if (set)
684 {
685 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000686
687 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
688 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000689 /* See nexthop_active_ipv4 for a description how the
690 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000691 if (newhop->type == NEXTHOP_TYPE_IPV6
692 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
693 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000694 {
695 resolved_hop->type = newhop->type;
696 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
697
698 if (newhop->ifindex)
699 {
700 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
701 resolved_hop->ifindex = newhop->ifindex;
702 }
703 }
Christian Frankefa713d92013-07-05 15:35:37 +0000704
paul718e3742002-12-13 20:15:29 +0000705 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000706 || newhop->type == NEXTHOP_TYPE_IFNAME)
707 {
708 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
709 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
710 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
711 resolved_hop->ifindex = newhop->ifindex;
712 }
Christian Frankefa713d92013-07-05 15:35:37 +0000713
714 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000715 }
Christian Frankefa713d92013-07-05 15:35:37 +0000716 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000717 }
Christian Frankefa713d92013-07-05 15:35:37 +0000718 return resolved;
paul718e3742002-12-13 20:15:29 +0000719 }
720 else
721 {
722 return 0;
723 }
724 }
725 }
726 return 0;
727}
728#endif /* HAVE_IPV6 */
729
730struct rib *
David Lamparter29ce93e2015-01-22 19:09:36 +0100731rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
732 struct route_node **rn_out)
Everton Marques346a8b52014-09-22 19:35:51 -0300733{
734 struct route_table *table;
735 struct route_node *rn;
736 struct rib *match;
737 struct nexthop *newhop, *tnewhop;
738 int recursing;
739
740 /* Lookup table. */
741 table = vrf_table (AFI_IP, safi, 0);
742 if (! table)
743 return 0;
744
745 rn = route_node_match_ipv4 (table, &addr);
746
747 while (rn)
748 {
749 route_unlock_node (rn);
750
751 /* Pick up selected route. */
752 RNODE_FOREACH_RIB (rn, match)
753 {
754 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
755 continue;
756 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
757 break;
758 }
759
760 /* If there is no selected route or matched route is EGP, go up
761 tree. */
Everton Marques12150f02014-09-19 16:39:34 -0300762 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques346a8b52014-09-22 19:35:51 -0300763 {
764 do {
765 rn = rn->parent;
766 } while (rn && rn->info == NULL);
767 if (rn)
768 route_lock_node (rn);
769 }
770 else
771 {
David Lamparter29ce93e2015-01-22 19:09:36 +0100772 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques346a8b52014-09-22 19:35:51 -0300773 {
David Lamparter29ce93e2015-01-22 19:09:36 +0100774 int found = 0;
Everton Marques346a8b52014-09-22 19:35:51 -0300775 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
776 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter29ce93e2015-01-22 19:09:36 +0100777 {
778 found = 1;
779 break;
780 }
781 if (!found)
782 return NULL;
Everton Marques346a8b52014-09-22 19:35:51 -0300783 }
David Lamparter29ce93e2015-01-22 19:09:36 +0100784
785 if (rn_out)
786 *rn_out = rn;
787 return match;
Everton Marques346a8b52014-09-22 19:35:51 -0300788 }
789 }
790 return NULL;
791}
792
793struct rib *
David Lamparter240c56f2015-01-06 19:53:24 +0100794rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
795{
796 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
797 struct route_node *m_rn = NULL, *u_rn = NULL;
798 int skip_bgp = 0; /* bool */
799
800 switch (ipv4_multicast_mode)
801 {
802 case MCAST_MRIB_ONLY:
803 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
804 case MCAST_URIB_ONLY:
805 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
806 case MCAST_NO_CONFIG:
807 case MCAST_MIX_MRIB_FIRST:
808 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
809 if (!mrib)
810 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
811 break;
812 case MCAST_MIX_DISTANCE:
813 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
814 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
815 if (mrib && urib)
816 rib = urib->distance < mrib->distance ? urib : mrib;
817 else if (mrib)
818 rib = mrib;
819 else if (urib)
820 rib = urib;
821 break;
822 case MCAST_MIX_PFXLEN:
823 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
824 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
825 if (mrib && urib)
826 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
827 else if (mrib)
828 rib = mrib;
829 else if (urib)
830 rib = urib;
831 break;
832 }
833
834 if (rn_out)
835 *rn_out = (rib == mrib) ? m_rn : u_rn;
836
837 if (IS_ZEBRA_DEBUG_RIB)
838 {
839 char buf[BUFSIZ];
840 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
841
842 zlog_debug("%s: %s: found %s, using %s",
843 __func__, buf,
844 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
845 urib ? "URIB" : "nothing",
846 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
847 }
848 return rib;
849}
850
851void
852multicast_mode_ipv4_set (enum multicast_mode mode)
853{
854 if (IS_ZEBRA_DEBUG_RIB)
855 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
856 ipv4_multicast_mode = mode;
857}
858
859enum multicast_mode
860multicast_mode_ipv4_get (void)
861{
862 return ipv4_multicast_mode;
863}
864
865struct rib *
paul718e3742002-12-13 20:15:29 +0000866rib_lookup_ipv4 (struct prefix_ipv4 *p)
867{
868 struct route_table *table;
869 struct route_node *rn;
870 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000871 struct nexthop *nexthop, *tnexthop;
872 int recursing;
paul718e3742002-12-13 20:15:29 +0000873
874 /* Lookup table. */
875 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
876 if (! table)
877 return 0;
878
879 rn = route_node_lookup (table, (struct prefix *) p);
880
881 /* No route for this prefix. */
882 if (! rn)
883 return NULL;
884
885 /* Unlock node. */
886 route_unlock_node (rn);
887
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000888 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100889 {
890 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
891 continue;
892 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
893 break;
894 }
paul718e3742002-12-13 20:15:29 +0000895
896 if (! match || match->type == ZEBRA_ROUTE_BGP)
897 return NULL;
898
899 if (match->type == ZEBRA_ROUTE_CONNECT)
900 return match;
901
Christian Frankefa713d92013-07-05 15:35:37 +0000902 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000903 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
904 return match;
905
906 return NULL;
907}
908
Denis Ovsienkodc958242007-08-13 16:03:06 +0000909/*
910 * This clone function, unlike its original rib_lookup_ipv4(), checks
911 * if specified IPv4 route record (prefix/mask -> gate) exists in
912 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
913 *
914 * Return values:
915 * -1: error
916 * 0: exact match found
917 * 1: a match was found with a different gate
918 * 2: connected route found
919 * 3: no matches found
920 */
921int
922rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
923{
924 struct route_table *table;
925 struct route_node *rn;
926 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000927 struct nexthop *nexthop, *tnexthop;
928 int recursing;
929 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000930
931 /* Lookup table. */
932 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
933 if (! table)
934 return ZEBRA_RIB_LOOKUP_ERROR;
935
936 /* Scan the RIB table for exactly matching RIB entry. */
937 rn = route_node_lookup (table, (struct prefix *) p);
938
939 /* No route for this prefix. */
940 if (! rn)
941 return ZEBRA_RIB_NOTFOUND;
942
943 /* Unlock node. */
944 route_unlock_node (rn);
945
946 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000947 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100948 {
949 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
950 continue;
951 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
952 break;
953 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000954
955 /* None such found :( */
956 if (!match)
957 return ZEBRA_RIB_NOTFOUND;
958
959 if (match->type == ZEBRA_ROUTE_CONNECT)
960 return ZEBRA_RIB_FOUND_CONNECTED;
961
962 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000963 nexthops_active = 0;
964 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000965 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000966 {
Christian Frankefa713d92013-07-05 15:35:37 +0000967 nexthops_active = 1;
968 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
969 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000970 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000971 {
972 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
973 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
974 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
975 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
976 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
977 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000978 }
Christian Frankefa713d92013-07-05 15:35:37 +0000979
980 if (nexthops_active)
981 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000982
983 return ZEBRA_RIB_NOTFOUND;
984}
985
paul718e3742002-12-13 20:15:29 +0000986#ifdef HAVE_IPV6
987struct rib *
988rib_match_ipv6 (struct in6_addr *addr)
989{
990 struct prefix_ipv6 p;
991 struct route_table *table;
992 struct route_node *rn;
993 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000994 struct nexthop *newhop, *tnewhop;
995 int recursing;
paul718e3742002-12-13 20:15:29 +0000996
997 /* Lookup table. */
998 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
999 if (! table)
1000 return 0;
1001
1002 memset (&p, 0, sizeof (struct prefix_ipv6));
1003 p.family = AF_INET6;
1004 p.prefixlen = IPV6_MAX_PREFIXLEN;
1005 IPV6_ADDR_COPY (&p.prefix, addr);
1006
1007 rn = route_node_match (table, (struct prefix *) &p);
1008
1009 while (rn)
1010 {
1011 route_unlock_node (rn);
1012
1013 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001014 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +01001015 {
1016 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
1017 continue;
1018 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
1019 break;
1020 }
paul718e3742002-12-13 20:15:29 +00001021
1022 /* If there is no selected route or matched route is EGP, go up
1023 tree. */
1024 if (! match
1025 || match->type == ZEBRA_ROUTE_BGP)
1026 {
1027 do {
1028 rn = rn->parent;
1029 } while (rn && rn->info == NULL);
1030 if (rn)
1031 route_lock_node (rn);
1032 }
1033 else
1034 {
1035 if (match->type == ZEBRA_ROUTE_CONNECT)
1036 /* Directly point connected route. */
1037 return match;
1038 else
1039 {
Christian Frankefa713d92013-07-05 15:35:37 +00001040 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +00001041 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1042 return match;
1043 return NULL;
1044 }
1045 }
1046 }
1047 return NULL;
1048}
1049#endif /* HAVE_IPV6 */
1050
Paul Jakma7514fb72007-05-02 16:05:35 +00001051#define RIB_SYSTEM_ROUTE(R) \
1052 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
1053
Denis Ovsienkodc958242007-08-13 16:03:06 +00001054/* This function verifies reachability of one given nexthop, which can be
1055 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
1056 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
1057 * nexthop->ifindex will be updated appropriately as well.
1058 * An existing route map can turn (otherwise active) nexthop into inactive, but
1059 * not vice versa.
1060 *
1061 * The return value is the final value of 'ACTIVE' flag.
1062 */
1063
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001064static unsigned
paul718e3742002-12-13 20:15:29 +00001065nexthop_active_check (struct route_node *rn, struct rib *rib,
1066 struct nexthop *nexthop, int set)
1067{
Christian Frankef3a17322013-07-05 15:35:41 +00001068 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +00001069 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +00001070 route_map_result_t ret = RMAP_MATCH;
1071 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
1072 struct route_map *rmap;
1073 int family;
paul718e3742002-12-13 20:15:29 +00001074
Paul Jakma7514fb72007-05-02 16:05:35 +00001075 family = 0;
paul718e3742002-12-13 20:15:29 +00001076 switch (nexthop->type)
1077 {
1078 case NEXTHOP_TYPE_IFINDEX:
1079 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001080 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001081 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1082 else
1083 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1084 break;
paul718e3742002-12-13 20:15:29 +00001085 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001086 family = AFI_IP6;
1087 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001088 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001089 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001090 {
1091 if (set)
1092 nexthop->ifindex = ifp->ifindex;
1093 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1094 }
1095 else
1096 {
1097 if (set)
1098 nexthop->ifindex = 0;
1099 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1100 }
1101 break;
1102 case NEXTHOP_TYPE_IPV4:
1103 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001104 family = AFI_IP;
Everton Marquesb24c7fe2014-09-22 18:00:15 -03001105 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1106 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1107 else
1108 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001109 break;
1110#ifdef HAVE_IPV6
1111 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001112 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001113 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1114 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1115 else
1116 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1117 break;
1118 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001119 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001120 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1121 {
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 }
1128 else
1129 {
1130 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1131 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1132 else
1133 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1134 }
1135 break;
1136#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001137 case NEXTHOP_TYPE_BLACKHOLE:
1138 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1139 break;
paul718e3742002-12-13 20:15:29 +00001140 default:
1141 break;
1142 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001143 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1144 return 0;
1145
Christian Frankef3a17322013-07-05 15:35:41 +00001146 /* XXX: What exactly do those checks do? Do we support
1147 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001148 if (RIB_SYSTEM_ROUTE(rib) ||
1149 (family == AFI_IP && rn->p.family != AF_INET) ||
1150 (family == AFI_IP6 && rn->p.family != AF_INET6))
1151 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1152
Christian Frankef3a17322013-07-05 15:35:41 +00001153 /* The original code didn't determine the family correctly
1154 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1155 * from the rib_table_info in those cases.
1156 * Possibly it may be better to use only the rib_table_info
1157 * in every case.
1158 */
1159 if (!family)
1160 family = info->afi;
1161
Paul Jakma7514fb72007-05-02 16:05:35 +00001162 rmap = 0;
1163 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1164 proto_rm[family][rib->type])
1165 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1166 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1167 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1168 if (rmap) {
1169 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1170 }
1171
1172 if (ret == RMAP_DENYMATCH)
1173 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001174 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1175}
1176
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001177/* Iterate over all nexthops of the given RIB entry and refresh their
1178 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1179 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1180 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1181 * transparently passed to nexthop_active_check().
1182 *
1183 * Return value is the new number of active nexthops.
1184 */
1185
paula1ac18c2005-06-28 17:17:12 +00001186static int
paul718e3742002-12-13 20:15:29 +00001187nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1188{
1189 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001190 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001191
1192 rib->nexthop_active_num = 0;
1193 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1194
1195 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001196 {
1197 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001198 prev_index = nexthop->ifindex;
Everton Marquesb24c7fe2014-09-22 18:00:15 -03001199 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001200 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001201 if (prev_active != new_active ||
1202 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001203 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1204 }
paul718e3742002-12-13 20:15:29 +00001205 return rib->nexthop_active_num;
1206}
paul6baeb982003-10-28 03:47:15 +00001207
David Lamparter6b0655a2014-06-04 06:53:35 +02001208
paul718e3742002-12-13 20:15:29 +00001209
paula1ac18c2005-06-28 17:17:12 +00001210static void
paul718e3742002-12-13 20:15:29 +00001211rib_install_kernel (struct route_node *rn, struct rib *rib)
1212{
1213 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001214 struct nexthop *nexthop, *tnexthop;
David Lamparterc048dcc2015-01-12 07:05:06 +01001215 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001216 int recursing;
paul718e3742002-12-13 20:15:29 +00001217
David Lamparterc048dcc2015-01-12 07:05:06 +01001218 if (info->safi != SAFI_UNICAST)
1219 {
1220 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1221 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1222 return;
1223 }
1224
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001225 /*
1226 * Make sure we update the FPM any time we send new information to
1227 * the kernel.
1228 */
1229 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001230 switch (PREFIX_FAMILY (&rn->p))
1231 {
1232 case AF_INET:
1233 ret = kernel_add_ipv4 (&rn->p, rib);
1234 break;
1235#ifdef HAVE_IPV6
1236 case AF_INET6:
1237 ret = kernel_add_ipv6 (&rn->p, rib);
1238 break;
1239#endif /* HAVE_IPV6 */
1240 }
1241
Denis Ovsienkodc958242007-08-13 16:03:06 +00001242 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001243 if (ret < 0)
1244 {
Christian Frankefa713d92013-07-05 15:35:37 +00001245 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001246 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1247 }
1248}
1249
1250/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001251static int
paul718e3742002-12-13 20:15:29 +00001252rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1253{
1254 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001255 struct nexthop *nexthop, *tnexthop;
David Lamparterc048dcc2015-01-12 07:05:06 +01001256 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001257 int recursing;
paul718e3742002-12-13 20:15:29 +00001258
David Lamparterc048dcc2015-01-12 07:05:06 +01001259 if (info->safi != SAFI_UNICAST)
1260 {
1261 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1262 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1263 return ret;
1264 }
1265
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001266 /*
1267 * Make sure we update the FPM any time we send new information to
1268 * the kernel.
1269 */
1270 zfpm_trigger_update (rn, "uninstalling from kernel");
1271
paul718e3742002-12-13 20:15:29 +00001272 switch (PREFIX_FAMILY (&rn->p))
1273 {
1274 case AF_INET:
1275 ret = kernel_delete_ipv4 (&rn->p, rib);
1276 break;
1277#ifdef HAVE_IPV6
1278 case AF_INET6:
1279 ret = kernel_delete_ipv6 (&rn->p, rib);
1280 break;
1281#endif /* HAVE_IPV6 */
1282 }
1283
Christian Frankefa713d92013-07-05 15:35:37 +00001284 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001285 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1286
1287 return ret;
1288}
1289
1290/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001291static void
paul718e3742002-12-13 20:15:29 +00001292rib_uninstall (struct route_node *rn, struct rib *rib)
1293{
David Lamparterc048dcc2015-01-12 07:05:06 +01001294 rib_table_info_t *info = rn->table->info;
1295
paul718e3742002-12-13 20:15:29 +00001296 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1297 {
David Lamparterc048dcc2015-01-12 07:05:06 +01001298 if (info->safi == SAFI_UNICAST)
1299 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001300
paul718e3742002-12-13 20:15:29 +00001301 redistribute_delete (&rn->p, rib);
1302 if (! RIB_SYSTEM_ROUTE (rib))
1303 rib_uninstall_kernel (rn, rib);
1304 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1305 }
1306}
1307
Paul Jakma6d691122006-07-27 21:49:00 +00001308static void rib_unlink (struct route_node *, struct rib *);
1309
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001310/*
1311 * rib_can_delete_dest
1312 *
1313 * Returns TRUE if the given dest can be deleted from the table.
1314 */
1315static int
1316rib_can_delete_dest (rib_dest_t *dest)
1317{
1318 if (dest->routes)
1319 {
1320 return 0;
1321 }
1322
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001323 /*
1324 * Don't delete the dest if we have to update the FPM about this
1325 * prefix.
1326 */
1327 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1328 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1329 return 0;
1330
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001331 return 1;
1332}
1333
1334/*
1335 * rib_gc_dest
1336 *
1337 * Garbage collect the rib dest corresponding to the given route node
1338 * if appropriate.
1339 *
1340 * Returns TRUE if the dest was deleted, FALSE otherwise.
1341 */
1342int
1343rib_gc_dest (struct route_node *rn)
1344{
1345 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001346
1347 dest = rib_dest_from_rnode (rn);
1348 if (!dest)
1349 return 0;
1350
1351 if (!rib_can_delete_dest (dest))
1352 return 0;
1353
1354 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001355 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001356
1357 dest->rnode = NULL;
1358 XFREE (MTYPE_RIB_DEST, dest);
1359 rn->info = NULL;
1360
1361 /*
1362 * Release the one reference that we keep on the route node.
1363 */
1364 route_unlock_node (rn);
1365 return 1;
1366}
1367
paul718e3742002-12-13 20:15:29 +00001368/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001369static void
1370rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001371{
1372 struct rib *rib;
1373 struct rib *next;
1374 struct rib *fib = NULL;
1375 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001376 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001377 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001378 struct nexthop *nexthop = NULL, *tnexthop;
1379 int recursing;
Balaji95116332014-10-23 15:25:25 +00001380 rib_table_info_t *info;
1381
paul4d38fdb2005-04-28 17:35:14 +00001382 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001383
1384 info = rn->table->info;
1385
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001386 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001387 {
paul718e3742002-12-13 20:15:29 +00001388 /* Currently installed rib. */
1389 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001390 {
1391 assert (fib == NULL);
1392 fib = rib;
1393 }
1394
1395 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1396 * which we need to do do further work with below.
1397 */
1398 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1399 {
1400 if (rib != fib)
1401 {
1402 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001403 rnode_debug (rn, "rn %p, removing rib %p", rn, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001404 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001405 }
1406 else
1407 del = rib;
1408
1409 continue;
1410 }
paul4d38fdb2005-04-28 17:35:14 +00001411
paul718e3742002-12-13 20:15:29 +00001412 /* Skip unreachable nexthop. */
1413 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001414 continue;
paul718e3742002-12-13 20:15:29 +00001415
1416 /* Infinit distance. */
1417 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001418 continue;
paul718e3742002-12-13 20:15:29 +00001419
paulaf887b52006-01-18 14:52:52 +00001420 /* Newly selected rib, the common case. */
1421 if (!select)
1422 {
1423 select = rib;
1424 continue;
1425 }
1426
1427 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001428 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001429 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001430 * - lower metric beats higher for equal distance
1431 * - last, hence oldest, route wins tie break.
1432 */
paula1038a12006-01-30 14:08:51 +00001433
1434 /* Connected routes. Pick the last connected
1435 * route of the set of lowest metric connected routes.
1436 */
paula8d9c1f2006-01-25 06:31:04 +00001437 if (rib->type == ZEBRA_ROUTE_CONNECT)
1438 {
paula1038a12006-01-30 14:08:51 +00001439 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001440 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001441 select = rib;
1442 continue;
paula8d9c1f2006-01-25 06:31:04 +00001443 }
1444 else if (select->type == ZEBRA_ROUTE_CONNECT)
1445 continue;
1446
1447 /* higher distance loses */
1448 if (rib->distance > select->distance)
1449 continue;
1450
1451 /* lower wins */
1452 if (rib->distance < select->distance)
1453 {
paulaf887b52006-01-18 14:52:52 +00001454 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001455 continue;
1456 }
1457
1458 /* metric tie-breaks equal distance */
1459 if (rib->metric <= select->metric)
1460 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001461 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001462
1463 /* After the cycle is finished, the following pointers will be set:
1464 * select --- the winner RIB entry, if any was found, otherwise NULL
1465 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1466 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1467 * rib --- NULL
1468 */
1469
1470 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001471 if (select && select == fib)
1472 {
Paul Jakma6d691122006-07-27 21:49:00 +00001473 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001474 rnode_debug (rn, "Updating existing route, select %p, fib %p",
1475 select, fib);
paul718e3742002-12-13 20:15:29 +00001476 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001477 {
David Lamparterc048dcc2015-01-12 07:05:06 +01001478 if (info->safi == SAFI_UNICAST)
1479 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001480
paul4d38fdb2005-04-28 17:35:14 +00001481 redistribute_delete (&rn->p, select);
1482 if (! RIB_SYSTEM_ROUTE (select))
1483 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001484
paul4d38fdb2005-04-28 17:35:14 +00001485 /* Set real nexthop. */
1486 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001487
paul4d38fdb2005-04-28 17:35:14 +00001488 if (! RIB_SYSTEM_ROUTE (select))
1489 rib_install_kernel (rn, select);
1490 redistribute_add (&rn->p, select);
1491 }
pauld753e9e2003-01-22 19:45:50 +00001492 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001493 {
1494 /* Housekeeping code to deal with
1495 race conditions in kernel with linux
1496 netlink reporting interface up before IPv4 or IPv6 protocol
1497 is ready to add routes.
1498 This makes sure the routes are IN the kernel.
1499 */
pauld753e9e2003-01-22 19:45:50 +00001500
Christian Frankefa713d92013-07-05 15:35:37 +00001501 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001502 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001503 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001504 installed = 1;
1505 break;
paul4d38fdb2005-04-28 17:35:14 +00001506 }
1507 if (! installed)
1508 rib_install_kernel (rn, select);
1509 }
Paul Jakma6d691122006-07-27 21:49:00 +00001510 goto end;
paul718e3742002-12-13 20:15:29 +00001511 }
1512
Denis Ovsienkodc958242007-08-13 16:03:06 +00001513 /* At this point we either haven't found the best RIB entry or it is
1514 * different from what we currently intend to flag with SELECTED. In both
1515 * cases, if a RIB block is present in FIB, it should be withdrawn.
1516 */
paul718e3742002-12-13 20:15:29 +00001517 if (fib)
1518 {
Paul Jakma6d691122006-07-27 21:49:00 +00001519 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001520 rnode_debug (rn, "Removing existing route, fib %p", fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001521
David Lamparterc048dcc2015-01-12 07:05:06 +01001522 if (info->safi == SAFI_UNICAST)
1523 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001524
paul718e3742002-12-13 20:15:29 +00001525 redistribute_delete (&rn->p, fib);
1526 if (! RIB_SYSTEM_ROUTE (fib))
1527 rib_uninstall_kernel (rn, fib);
1528 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1529
1530 /* Set real nexthop. */
1531 nexthop_active_update (rn, fib, 1);
1532 }
1533
Denis Ovsienkodc958242007-08-13 16:03:06 +00001534 /* Regardless of some RIB entry being SELECTED or not before, now we can
1535 * tell, that if a new winner exists, FIB is still not updated with this
1536 * data, but ready to be.
1537 */
paul718e3742002-12-13 20:15:29 +00001538 if (select)
1539 {
Paul Jakma6d691122006-07-27 21:49:00 +00001540 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001541 rnode_debug (rn, "Adding route, select %p", select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001542
David Lamparterc048dcc2015-01-12 07:05:06 +01001543 if (info->safi == SAFI_UNICAST)
1544 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001545
paul718e3742002-12-13 20:15:29 +00001546 /* Set real nexthop. */
1547 nexthop_active_update (rn, select, 1);
1548
1549 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001550 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001551 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1552 redistribute_add (&rn->p, select);
1553 }
paul4d38fdb2005-04-28 17:35:14 +00001554
Paul Jakma6d691122006-07-27 21:49:00 +00001555 /* FIB route was removed, should be deleted */
1556 if (del)
1557 {
1558 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001559 rnode_debug (rn, "Deleting fib %p, rn %p", del, rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001560 rib_unlink (rn, del);
1561 }
paul4d38fdb2005-04-28 17:35:14 +00001562
Paul Jakma6d691122006-07-27 21:49:00 +00001563end:
1564 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001565 rnode_debug (rn, "rn %p dequeued", rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001566
1567 /*
1568 * Check if the dest can be deleted now.
1569 */
1570 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001571}
1572
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001573/* Take a list of route_node structs and return 1, if there was a record
1574 * picked from it and processed by rib_process(). Don't process more,
1575 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001576 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001577static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001578process_subq (struct list * subq, u_char qindex)
1579{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001580 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001581 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001582
1583 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001584 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001585
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001586 rnode = listgetdata (lnode);
1587 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001588
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001589 if (rnode->info)
1590 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1591
Chris Caputo67b94672009-07-18 04:02:26 +00001592#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001593 else
1594 {
1595 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1596 __func__, rnode, rnode->lock);
1597 zlog_backtrace(LOG_DEBUG);
1598 }
Chris Caputo67b94672009-07-18 04:02:26 +00001599#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001600 route_unlock_node (rnode);
1601 list_delete_node (subq, lnode);
1602 return 1;
1603}
1604
1605/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1606 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1607 * is pointed to the meta queue structure.
1608 */
1609static wq_item_status
1610meta_queue_process (struct work_queue *dummy, void *data)
1611{
1612 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001613 unsigned i;
1614
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001615 for (i = 0; i < MQ_SIZE; i++)
1616 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001617 {
1618 mq->size--;
1619 break;
1620 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001621 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1622}
1623
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001624/*
1625 * Map from rib types to queue type (priority) in meta queue
1626 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001627static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1628 [ZEBRA_ROUTE_SYSTEM] = 4,
1629 [ZEBRA_ROUTE_KERNEL] = 0,
1630 [ZEBRA_ROUTE_CONNECT] = 0,
1631 [ZEBRA_ROUTE_STATIC] = 1,
1632 [ZEBRA_ROUTE_RIP] = 2,
1633 [ZEBRA_ROUTE_RIPNG] = 2,
1634 [ZEBRA_ROUTE_OSPF] = 2,
1635 [ZEBRA_ROUTE_OSPF6] = 2,
1636 [ZEBRA_ROUTE_ISIS] = 2,
1637 [ZEBRA_ROUTE_BGP] = 3,
1638 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001639 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001640};
1641
1642/* Look into the RN and queue it into one or more priority queues,
1643 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001644 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001645static void
1646rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001647{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001648 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001649
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001650 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001651 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001652 u_char qindex = meta_queue_map[rib->type];
1653
1654 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001655 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1656 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001657 {
1658 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001659 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
1660 rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001661 continue;
1662 }
1663
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001664 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001665 listnode_add (mq->subq[qindex], rn);
1666 route_lock_node (rn);
1667 mq->size++;
1668
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001669 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001670 rnode_debug (rn, "queued rn %p into sub-queue %u",
1671 rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001672 }
paul4d38fdb2005-04-28 17:35:14 +00001673}
1674
Paul Jakma6d691122006-07-27 21:49:00 +00001675/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001676static void
Paul Jakma6d691122006-07-27 21:49:00 +00001677rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001678{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001679 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001680
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001681 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001682 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001683 {
1684 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1685 __func__, rn, rn->lock);
1686 zlog_backtrace(LOG_DEBUG);
1687 return;
1688 }
1689
1690 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001691 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001692
1693 assert (zebra);
1694
1695 if (zebra->ribq == NULL)
1696 {
1697 zlog_err ("%s: work_queue does not exist!", __func__);
1698 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001699 }
paul4d38fdb2005-04-28 17:35:14 +00001700
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001701 /*
1702 * The RIB queue should normally be either empty or holding the only
1703 * work_queue_item element. In the latter case this element would
1704 * hold a pointer to the meta queue structure, which must be used to
1705 * actually queue the route nodes to process. So create the MQ
1706 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001707 * This semantics was introduced after 0.99.9 release.
1708 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001709 if (!zebra->ribq->items->count)
1710 work_queue_add (zebra->ribq, zebra->mq);
1711
1712 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001713
1714 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartere0b0ac82014-04-24 20:22:53 +02001715 rnode_debug (rn, "rn %p queued", rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001716
1717 return;
paul4d38fdb2005-04-28 17:35:14 +00001718}
1719
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001720/* Create new meta queue.
1721 A destructor function doesn't seem to be necessary here.
1722 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001723static struct meta_queue *
1724meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001725{
1726 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001727 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001728
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001729 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1730 assert(new);
1731
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001732 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001733 {
1734 new->subq[i] = list_new ();
1735 assert(new->subq[i]);
1736 }
1737
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001738 return new;
1739}
1740
paul4d38fdb2005-04-28 17:35:14 +00001741/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001742static void
paul4d38fdb2005-04-28 17:35:14 +00001743rib_queue_init (struct zebra_t *zebra)
1744{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001745 assert (zebra);
1746
paul4d38fdb2005-04-28 17:35:14 +00001747 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001748 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001749 {
Paul Jakma6d691122006-07-27 21:49:00 +00001750 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001751 return;
1752 }
1753
1754 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001755 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001756 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001757 /* XXX: TODO: These should be runtime configurable via vty */
1758 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001759 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001760
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001761 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001762 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001763 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001764 return;
1765 }
1766 return;
paul718e3742002-12-13 20:15:29 +00001767}
1768
Paul Jakma6d691122006-07-27 21:49:00 +00001769/* RIB updates are processed via a queue of pointers to route_nodes.
1770 *
1771 * The queue length is bounded by the maximal size of the routing table,
1772 * as a route_node will not be requeued, if already queued.
1773 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001774 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1775 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1776 * and then submit route_node to queue for best-path selection later.
1777 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001778 *
1779 * Deleted RIBs are reaped during best-path selection.
1780 *
1781 * rib_addnode
1782 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001783 * |-------->| | best RIB, if required
1784 * | |
1785 * static_install->|->rib_addqueue...... -> rib_process
1786 * | |
1787 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001788 * |-> set RIB_ENTRY_REMOVE |
1789 * rib_delnode (RIB freed)
1790 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001791 * The 'info' pointer of a route_node points to a rib_dest_t
1792 * ('dest'). Queueing state for a route_node is kept on the dest. The
1793 * dest is created on-demand by rib_link() and is kept around at least
1794 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001795 *
1796 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1797 *
1798 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001799 * - dest attached to route_node:
1800 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001801 * - route_node processing queue
1802 * - managed by: rib_addqueue, rib_process.
1803 *
1804 */
1805
paul718e3742002-12-13 20:15:29 +00001806/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001807static void
Paul Jakma6d691122006-07-27 21:49:00 +00001808rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001809{
1810 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001811 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001812
paul4d38fdb2005-04-28 17:35:14 +00001813 assert (rib && rn);
1814
Paul Jakma6d691122006-07-27 21:49:00 +00001815 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001816 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001817
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001818 dest = rib_dest_from_rnode (rn);
1819 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001820 {
1821 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001822 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001823
1824 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1825 route_lock_node (rn); /* rn route table reference */
1826 rn->info = dest;
1827 dest->rnode = rn;
1828 }
1829
1830 head = dest->routes;
1831 if (head)
1832 {
Paul Jakma6d691122006-07-27 21:49:00 +00001833 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001834 }
paul718e3742002-12-13 20:15:29 +00001835 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001836 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001837 rib_queue_add (&zebrad, rn);
1838}
1839
1840static void
1841rib_addnode (struct route_node *rn, struct rib *rib)
1842{
1843 /* RIB node has been un-removed before route-node is processed.
1844 * route_node must hence already be on the queue for processing..
1845 */
1846 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1847 {
1848 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001849 rnode_debug (rn, "rn %p, un-removed rib %p", rn, rib);
1850
Paul Jakma6d691122006-07-27 21:49:00 +00001851 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1852 return;
1853 }
1854 rib_link (rn, rib);
1855}
1856
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001857/*
1858 * rib_unlink
1859 *
1860 * Detach a rib structure from a route_node.
1861 *
1862 * Note that a call to rib_unlink() should be followed by a call to
1863 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1864 * longer required to be deleted.
1865 */
Paul Jakma6d691122006-07-27 21:49:00 +00001866static void
1867rib_unlink (struct route_node *rn, struct rib *rib)
1868{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001869 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001870
1871 assert (rn && rib);
1872
1873 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001874 rnode_debug (rn, "rn %p, rib %p", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001875
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001876 dest = rib_dest_from_rnode (rn);
1877
Paul Jakma6d691122006-07-27 21:49:00 +00001878 if (rib->next)
1879 rib->next->prev = rib->prev;
1880
1881 if (rib->prev)
1882 rib->prev->next = rib->next;
1883 else
1884 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001885 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001886 }
1887
1888 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001889 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001890 XFREE (MTYPE_RIB, rib);
1891
paul718e3742002-12-13 20:15:29 +00001892}
1893
paula1ac18c2005-06-28 17:17:12 +00001894static void
paul718e3742002-12-13 20:15:29 +00001895rib_delnode (struct route_node *rn, struct rib *rib)
1896{
Paul Jakma6d691122006-07-27 21:49:00 +00001897 if (IS_ZEBRA_DEBUG_RIB)
David Lampartere0b0ac82014-04-24 20:22:53 +02001898 rnode_debug (rn, "rn %p, rib %p, removing", rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001899 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1900 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001901}
1902
1903int
1904rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001905 struct in_addr *gate, struct in_addr *src,
1906 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001907 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001908{
1909 struct rib *rib;
1910 struct rib *same = NULL;
1911 struct route_table *table;
1912 struct route_node *rn;
1913 struct nexthop *nexthop;
1914
1915 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001916 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001917 if (! table)
1918 return 0;
1919
1920 /* Make it sure prefixlen is applied to the prefix. */
1921 apply_mask_ipv4 (p);
1922
1923 /* Set default distance by route type. */
1924 if (distance == 0)
1925 {
Balaji.G837d16c2012-09-26 14:09:10 +05301926 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001927 distance = 150;
1928 else
1929 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001930
1931 /* iBGP distance is 200. */
1932 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1933 distance = 200;
1934 }
1935
1936 /* Lookup route node.*/
1937 rn = route_node_get (table, (struct prefix *) p);
1938
1939 /* If same type of route are installed, treat it as a implicit
1940 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001941 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001942 {
Paul Jakma6d691122006-07-27 21:49:00 +00001943 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1944 continue;
1945
hassoebf1ead2005-09-21 14:58:20 +00001946 if (rib->type != type)
1947 continue;
1948 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001949 {
1950 same = rib;
1951 break;
1952 }
hassoebf1ead2005-09-21 14:58:20 +00001953 /* Duplicate connected route comes in. */
1954 else if ((nexthop = rib->nexthop) &&
1955 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001956 nexthop->ifindex == ifindex &&
1957 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001958 {
1959 rib->refcnt++;
1960 return 0 ;
1961 }
paul718e3742002-12-13 20:15:29 +00001962 }
1963
1964 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001965 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001966 rib->type = type;
1967 rib->distance = distance;
1968 rib->flags = flags;
1969 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001970 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001971 rib->nexthop_num = 0;
1972 rib->uptime = time (NULL);
1973
1974 /* Nexthop settings. */
1975 if (gate)
1976 {
1977 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001978 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001979 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001980 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001981 }
1982 else
1983 nexthop_ifindex_add (rib, ifindex);
1984
1985 /* If this route is kernel route, set FIB flag to the route. */
1986 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1987 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1988 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1989
1990 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001991 if (IS_ZEBRA_DEBUG_RIB)
1992 zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
paul718e3742002-12-13 20:15:29 +00001993 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001994
paul718e3742002-12-13 20:15:29 +00001995 /* Free implicit route.*/
1996 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001997 {
1998 if (IS_ZEBRA_DEBUG_RIB)
1999 zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002000 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002001 }
paul4d38fdb2005-04-28 17:35:14 +00002002
2003 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002004 return 0;
2005}
2006
Denis Ovsienkodc958242007-08-13 16:03:06 +00002007/* This function dumps the contents of a given RIB entry into
2008 * standard debug log. Calling function name and IP prefix in
2009 * question are passed as 1st and 2nd arguments.
2010 */
2011
David Lamparterf7bf4152013-10-22 17:10:21 +00002012void _rib_dump (const char * func,
2013 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002014{
David Lamparterf7bf4152013-10-22 17:10:21 +00002015 const struct prefix *p = pp.p;
Vincent Bernatfed643f2012-10-23 16:00:42 +00002016 char straddr[INET6_ADDRSTRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00002017 struct nexthop *nexthop, *tnexthop;
2018 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00002019
Vincent Bernatfed643f2012-10-23 16:00:42 +00002020 inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002021 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002022 zlog_debug
2023 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002024 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00002025 func,
2026 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002027 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002028 rib->type,
2029 rib->table
2030 );
2031 zlog_debug
2032 (
2033 "%s: metric == %u, distance == %u, flags == %u, status == %u",
2034 func,
2035 rib->metric,
2036 rib->distance,
2037 rib->flags,
2038 rib->status
2039 );
2040 zlog_debug
2041 (
2042 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
2043 func,
2044 rib->nexthop_num,
2045 rib->nexthop_active_num,
2046 rib->nexthop_fib_num
2047 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00002048
Christian Frankefa713d92013-07-05 15:35:37 +00002049 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2050 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00002051 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002052 zlog_debug
2053 (
2054 "%s: %s %s with flags %s%s%s",
2055 func,
2056 (recursing ? " NH" : "NH"),
2057 straddr,
2058 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
2059 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
2060 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
2061 );
2062 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00002063 zlog_debug ("%s: dump complete", func);
2064}
2065
2066/* This is an exported helper to rtm_read() to dump the strange
2067 * RIB entry found by rib_lookup_ipv4_route()
2068 */
2069
2070void rib_lookup_and_dump (struct prefix_ipv4 * p)
2071{
2072 struct route_table *table;
2073 struct route_node *rn;
2074 struct rib *rib;
2075 char prefix_buf[INET_ADDRSTRLEN];
2076
2077 /* Lookup table. */
2078 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2079 if (! table)
2080 {
2081 zlog_err ("%s: vrf_table() returned NULL", __func__);
2082 return;
2083 }
2084
2085 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
2086 /* Scan the RIB table for exactly matching RIB entry. */
2087 rn = route_node_lookup (table, (struct prefix *) p);
2088
2089 /* No route for this prefix. */
2090 if (! rn)
2091 {
2092 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
2093 return;
2094 }
2095
2096 /* Unlock node. */
2097 route_unlock_node (rn);
2098
2099 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002100 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002101 {
2102 zlog_debug
2103 (
2104 "%s: rn %p, rib %p: %s, %s",
2105 __func__,
2106 rn,
2107 rib,
2108 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2109 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2110 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002111 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002112 }
2113}
2114
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002115/* Check if requested address assignment will fail due to another
2116 * route being installed by zebra in FIB already. Take necessary
2117 * actions, if needed: remove such a route from FIB and deSELECT
2118 * corresponding RIB entry. Then put affected RN into RIBQ head.
2119 */
2120void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2121{
2122 struct route_table *table;
2123 struct route_node *rn;
2124 struct rib *rib;
2125 unsigned changed = 0;
2126
2127 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2128 {
2129 zlog_err ("%s: vrf_table() returned NULL", __func__);
2130 return;
2131 }
2132
2133 /* No matches would be the simplest case. */
2134 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2135 return;
2136
2137 /* Unlock node. */
2138 route_unlock_node (rn);
2139
2140 /* Check all RIB entries. In case any changes have to be done, requeue
2141 * the RN into RIBQ head. If the routing message about the new connected
2142 * route (generated by the IP address we are going to assign very soon)
2143 * comes before the RIBQ is processed, the new RIB entry will join
2144 * RIBQ record already on head. This is necessary for proper revalidation
2145 * of the rest of the RIB.
2146 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002147 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002148 {
2149 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2150 ! RIB_SYSTEM_ROUTE (rib))
2151 {
2152 changed = 1;
2153 if (IS_ZEBRA_DEBUG_RIB)
2154 {
2155 char buf[INET_ADDRSTRLEN];
2156 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
2157 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
David Lamparterf7bf4152013-10-22 17:10:21 +00002158 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002159 }
2160 rib_uninstall (rn, rib);
2161 }
2162 }
2163 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002164 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002165}
2166
paul718e3742002-12-13 20:15:29 +00002167int
G.Balajicddf3912011-11-26 21:59:32 +04002168rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002169{
2170 struct route_table *table;
2171 struct route_node *rn;
2172 struct rib *same;
2173 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002174
paul718e3742002-12-13 20:15:29 +00002175 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002176 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002177 if (! table)
2178 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002179
paul718e3742002-12-13 20:15:29 +00002180 /* Make it sure prefixlen is applied to the prefix. */
2181 apply_mask_ipv4 (p);
2182
2183 /* Set default distance by route type. */
2184 if (rib->distance == 0)
2185 {
2186 rib->distance = route_info[rib->type].distance;
2187
2188 /* iBGP distance is 200. */
2189 if (rib->type == ZEBRA_ROUTE_BGP
2190 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2191 rib->distance = 200;
2192 }
2193
2194 /* Lookup route node.*/
2195 rn = route_node_get (table, (struct prefix *) p);
2196
2197 /* If same type of route are installed, treat it as a implicit
2198 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002199 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002200 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002201 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002202 continue;
2203
paul718e3742002-12-13 20:15:29 +00002204 if (same->type == rib->type && same->table == rib->table
2205 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002206 break;
paul718e3742002-12-13 20:15:29 +00002207 }
paul4d38fdb2005-04-28 17:35:14 +00002208
paul718e3742002-12-13 20:15:29 +00002209 /* If this route is kernel route, set FIB flag to the route. */
2210 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2211 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2212 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2213
2214 /* Link new rib to node.*/
2215 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002216 if (IS_ZEBRA_DEBUG_RIB)
2217 {
2218 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2219 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002220 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002221 }
paul718e3742002-12-13 20:15:29 +00002222
paul718e3742002-12-13 20:15:29 +00002223 /* Free implicit route.*/
2224 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002225 {
2226 if (IS_ZEBRA_DEBUG_RIB)
2227 {
2228 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2229 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002230 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002231 }
paul4d38fdb2005-04-28 17:35:14 +00002232 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002233 }
paul4d38fdb2005-04-28 17:35:14 +00002234
2235 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002236 return 0;
2237}
2238
hassoebf1ead2005-09-21 14:58:20 +00002239/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002240int
2241rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002242 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002243{
2244 struct route_table *table;
2245 struct route_node *rn;
2246 struct rib *rib;
2247 struct rib *fib = NULL;
2248 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002249 struct nexthop *nexthop, *tnexthop;
2250 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002251 char buf1[INET_ADDRSTRLEN];
2252 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002253
2254 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002255 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002256 if (! table)
2257 return 0;
2258
2259 /* Apply mask. */
2260 apply_mask_ipv4 (p);
2261
Christian Frankeb52aef12013-11-27 17:06:15 +00002262 if (IS_ZEBRA_DEBUG_KERNEL)
2263 {
2264 if (gate)
2265 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
2266 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2267 p->prefixlen,
2268 inet_ntoa (*gate),
2269 ifindex);
2270 else
2271 zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d",
2272 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2273 p->prefixlen,
2274 ifindex);
2275 }
paul5ec90d22003-06-19 01:41:37 +00002276
paul718e3742002-12-13 20:15:29 +00002277 /* Lookup route node. */
2278 rn = route_node_lookup (table, (struct prefix *) p);
2279 if (! rn)
2280 {
2281 if (IS_ZEBRA_DEBUG_KERNEL)
2282 {
2283 if (gate)
ajsb6178002004-12-07 21:12:56 +00002284 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002285 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002286 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002287 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002288 ifindex);
2289 else
ajsb6178002004-12-07 21:12:56 +00002290 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002291 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002292 p->prefixlen,
2293 ifindex);
2294 }
2295 return ZEBRA_ERR_RTNOEXIST;
2296 }
2297
2298 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002299 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002300 {
Paul Jakma6d691122006-07-27 21:49:00 +00002301 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2302 continue;
2303
paul718e3742002-12-13 20:15:29 +00002304 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2305 fib = rib;
2306
hassoebf1ead2005-09-21 14:58:20 +00002307 if (rib->type != type)
2308 continue;
2309 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002310 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002311 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002312 if (nexthop->ifindex != ifindex)
2313 continue;
hassoebf1ead2005-09-21 14:58:20 +00002314 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002315 {
hassoebf1ead2005-09-21 14:58:20 +00002316 rib->refcnt--;
2317 route_unlock_node (rn);
2318 route_unlock_node (rn);
2319 return 0;
paul718e3742002-12-13 20:15:29 +00002320 }
hassoebf1ead2005-09-21 14:58:20 +00002321 same = rib;
2322 break;
paul718e3742002-12-13 20:15:29 +00002323 }
hassoebf1ead2005-09-21 14:58:20 +00002324 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002325 else
paul5ec90d22003-06-19 01:41:37 +00002326 {
Christian Frankefa713d92013-07-05 15:35:37 +00002327 if (gate == NULL)
2328 {
2329 same = rib;
2330 break;
2331 }
2332 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2333 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2334 {
2335 same = rib;
2336 break;
2337 }
2338 if (same)
2339 break;
2340 }
paul718e3742002-12-13 20:15:29 +00002341 }
paul718e3742002-12-13 20:15:29 +00002342 /* If same type of route can't be found and this message is from
2343 kernel. */
2344 if (! same)
2345 {
2346 if (fib && type == ZEBRA_ROUTE_KERNEL)
2347 {
2348 /* Unset flags. */
2349 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2350 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2351
2352 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2353 }
2354 else
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 type %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 type);
2365 else
ajsb6178002004-12-07 21:12:56 +00002366 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002367 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002368 p->prefixlen,
2369 ifindex,
2370 type);
2371 }
2372 route_unlock_node (rn);
2373 return ZEBRA_ERR_RTNOEXIST;
2374 }
2375 }
paul4d38fdb2005-04-28 17:35:14 +00002376
paul718e3742002-12-13 20:15:29 +00002377 if (same)
2378 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002379
paul718e3742002-12-13 20:15:29 +00002380 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002381 return 0;
2382}
David Lamparter6b0655a2014-06-04 06:53:35 +02002383
paul718e3742002-12-13 20:15:29 +00002384/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002385static void
Everton Marques96bb2662014-07-14 11:19:00 -03002386static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002387{
2388 struct rib *rib;
2389 struct route_node *rn;
2390 struct route_table *table;
2391
2392 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002393 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002394 if (! table)
2395 return;
2396
2397 /* Lookup existing route */
2398 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002399 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002400 {
2401 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2402 continue;
2403
2404 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2405 break;
2406 }
paul718e3742002-12-13 20:15:29 +00002407
2408 if (rib)
2409 {
2410 /* Same distance static route is there. Update it with new
2411 nexthop. */
paul718e3742002-12-13 20:15:29 +00002412 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002413 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002414 {
2415 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002416 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002417 break;
2418 case STATIC_IPV4_IFNAME:
2419 nexthop_ifname_add (rib, si->gate.ifname);
2420 break;
2421 case STATIC_IPV4_BLACKHOLE:
2422 nexthop_blackhole_add (rib);
2423 break;
paul4d38fdb2005-04-28 17:35:14 +00002424 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002425 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002426 }
2427 else
2428 {
2429 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002430 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2431
paul718e3742002-12-13 20:15:29 +00002432 rib->type = ZEBRA_ROUTE_STATIC;
2433 rib->distance = si->distance;
2434 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002435 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002436 rib->nexthop_num = 0;
2437
2438 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002439 {
2440 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002441 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002442 break;
2443 case STATIC_IPV4_IFNAME:
2444 nexthop_ifname_add (rib, si->gate.ifname);
2445 break;
2446 case STATIC_IPV4_BLACKHOLE:
2447 nexthop_blackhole_add (rib);
2448 break;
2449 }
paul718e3742002-12-13 20:15:29 +00002450
hasso81dfcaa2003-05-25 19:21:25 +00002451 /* Save the flags of this static routes (reject, blackhole) */
2452 rib->flags = si->flags;
2453
paul718e3742002-12-13 20:15:29 +00002454 /* Link this rib to the tree. */
2455 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002456 }
2457}
2458
paula1ac18c2005-06-28 17:17:12 +00002459static int
paul718e3742002-12-13 20:15:29 +00002460static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2461{
2462 if (nexthop->type == NEXTHOP_TYPE_IPV4
2463 && si->type == STATIC_IPV4_GATEWAY
2464 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2465 return 1;
2466 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2467 && si->type == STATIC_IPV4_IFNAME
2468 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2469 return 1;
paul595db7f2003-05-25 21:35:06 +00002470 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2471 && si->type == STATIC_IPV4_BLACKHOLE)
2472 return 1;
paule8e19462006-01-19 20:16:55 +00002473 return 0;
paul718e3742002-12-13 20:15:29 +00002474}
2475
2476/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002477static void
Everton Marques96bb2662014-07-14 11:19:00 -03002478static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002479{
2480 struct route_node *rn;
2481 struct rib *rib;
2482 struct nexthop *nexthop;
2483 struct route_table *table;
2484
2485 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002486 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002487 if (! table)
2488 return;
paul4d38fdb2005-04-28 17:35:14 +00002489
paul718e3742002-12-13 20:15:29 +00002490 /* Lookup existing route with type and distance. */
2491 rn = route_node_lookup (table, p);
2492 if (! rn)
2493 return;
2494
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002495 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002496 {
2497 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2498 continue;
2499
2500 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2501 break;
2502 }
paul718e3742002-12-13 20:15:29 +00002503
2504 if (! rib)
2505 {
2506 route_unlock_node (rn);
2507 return;
2508 }
2509
2510 /* Lookup nexthop. */
2511 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2512 if (static_ipv4_nexthop_same (nexthop, si))
2513 break;
2514
2515 /* Can't find nexthop. */
2516 if (! nexthop)
2517 {
2518 route_unlock_node (rn);
2519 return;
2520 }
2521
2522 /* Check nexthop. */
2523 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002524 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002525 else
2526 {
paul6baeb982003-10-28 03:47:15 +00002527 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2528 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002529 nexthop_delete (rib, nexthop);
2530 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002531 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002532 }
paul718e3742002-12-13 20:15:29 +00002533 /* Unlock node. */
2534 route_unlock_node (rn);
2535}
2536
paul718e3742002-12-13 20:15:29 +00002537int
Everton Marques96bb2662014-07-14 11:19:00 -03002538static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2539 const char *ifname, u_char flags, u_char distance,
2540 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002541{
2542 u_char type = 0;
2543 struct route_node *rn;
2544 struct static_ipv4 *si;
2545 struct static_ipv4 *pp;
2546 struct static_ipv4 *cp;
2547 struct static_ipv4 *update = NULL;
2548 struct route_table *stable;
2549
2550 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002551 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002552 if (! stable)
2553 return -1;
2554
2555 /* Lookup static route prefix. */
2556 rn = route_node_get (stable, p);
2557
2558 /* Make flags. */
2559 if (gate)
2560 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002561 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002562 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002563 else
2564 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002565
2566 /* Do nothing if there is a same static route. */
2567 for (si = rn->info; si; si = si->next)
2568 {
2569 if (type == si->type
2570 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2571 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2572 {
2573 if (distance == si->distance)
2574 {
2575 route_unlock_node (rn);
2576 return 0;
2577 }
2578 else
2579 update = si;
2580 }
2581 }
2582
Paul Jakma3c0755d2006-12-08 00:53:14 +00002583 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002584 if (update)
Everton Marques96bb2662014-07-14 11:19:00 -03002585 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002586
2587 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002588 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002589
2590 si->type = type;
2591 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002592 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002593
2594 if (gate)
2595 si->gate.ipv4 = *gate;
2596 if (ifname)
2597 si->gate.ifname = XSTRDUP (0, ifname);
2598
2599 /* Add new static route information to the tree with sort by
2600 distance value and gateway address. */
2601 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2602 {
2603 if (si->distance < cp->distance)
2604 break;
2605 if (si->distance > cp->distance)
2606 continue;
2607 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2608 {
2609 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2610 break;
2611 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2612 continue;
2613 }
2614 }
2615
2616 /* Make linked list. */
2617 if (pp)
2618 pp->next = si;
2619 else
2620 rn->info = si;
2621 if (cp)
2622 cp->prev = si;
2623 si->prev = pp;
2624 si->next = cp;
2625
2626 /* Install into rib. */
Everton Marques96bb2662014-07-14 11:19:00 -03002627 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002628
2629 return 1;
2630}
2631
paul718e3742002-12-13 20:15:29 +00002632int
Everton Marques96bb2662014-07-14 11:19:00 -03002633static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2634 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002635{
2636 u_char type = 0;
2637 struct route_node *rn;
2638 struct static_ipv4 *si;
2639 struct route_table *stable;
2640
2641 /* Lookup table. */
Everton Marques96bb2662014-07-14 11:19:00 -03002642 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002643 if (! stable)
2644 return -1;
2645
2646 /* Lookup static route prefix. */
2647 rn = route_node_lookup (stable, p);
2648 if (! rn)
2649 return 0;
2650
2651 /* Make flags. */
2652 if (gate)
2653 type = STATIC_IPV4_GATEWAY;
2654 else if (ifname)
2655 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002656 else
2657 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002658
2659 /* Find same static route is the tree */
2660 for (si = rn->info; si; si = si->next)
2661 if (type == si->type
2662 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2663 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2664 break;
2665
2666 /* Can't find static route. */
2667 if (! si)
2668 {
2669 route_unlock_node (rn);
2670 return 0;
2671 }
2672
2673 /* Install into rib. */
Everton Marques96bb2662014-07-14 11:19:00 -03002674 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002675
2676 /* Unlink static route from linked list. */
2677 if (si->prev)
2678 si->prev->next = si->next;
2679 else
2680 rn->info = si->next;
2681 if (si->next)
2682 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002683 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002684
2685 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002686 if (ifname)
2687 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002688 XFREE (MTYPE_STATIC_IPV4, si);
2689
paul143a3852003-09-29 20:06:13 +00002690 route_unlock_node (rn);
2691
paul718e3742002-12-13 20:15:29 +00002692 return 1;
2693}
2694
paul718e3742002-12-13 20:15:29 +00002695#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00002696static int
paul718e3742002-12-13 20:15:29 +00002697rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
2698 struct in6_addr *gate, unsigned int ifindex, int table)
2699{
hasso726f9b22003-05-25 21:04:54 +00002700 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
2701#if defined (MUSICA) || defined (LINUX)
2702 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
2703 if (p->prefixlen == 96)
2704 return 0;
2705#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00002706 return 1;
hasso726f9b22003-05-25 21:04:54 +00002707 }
paul718e3742002-12-13 20:15:29 +00002708 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
2709 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
2710 {
2711 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
2712 return 1;
2713 }
2714 return 0;
2715}
2716
2717int
2718rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002719 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002720 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002721{
2722 struct rib *rib;
2723 struct rib *same = NULL;
2724 struct route_table *table;
2725 struct route_node *rn;
2726 struct nexthop *nexthop;
2727
paul718e3742002-12-13 20:15:29 +00002728 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002729 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002730 if (! table)
2731 return 0;
2732
2733 /* Make sure mask is applied. */
2734 apply_mask_ipv6 (p);
2735
2736 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002737 if (!distance)
2738 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002739
2740 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2741 distance = 200;
2742
2743 /* Filter bogus route. */
2744 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
2745 return 0;
2746
2747 /* Lookup route node.*/
2748 rn = route_node_get (table, (struct prefix *) p);
2749
2750 /* If same type of route are installed, treat it as a implicit
2751 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002752 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002753 {
Paul Jakma6d691122006-07-27 21:49:00 +00002754 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2755 continue;
2756
hassoebf1ead2005-09-21 14:58:20 +00002757 if (rib->type != type)
2758 continue;
2759 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002760 {
2761 same = rib;
paul718e3742002-12-13 20:15:29 +00002762 break;
2763 }
hassoebf1ead2005-09-21 14:58:20 +00002764 else if ((nexthop = rib->nexthop) &&
2765 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2766 nexthop->ifindex == ifindex)
2767 {
2768 rib->refcnt++;
2769 return 0;
2770 }
paul718e3742002-12-13 20:15:29 +00002771 }
2772
2773 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002774 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2775
paul718e3742002-12-13 20:15:29 +00002776 rib->type = type;
2777 rib->distance = distance;
2778 rib->flags = flags;
2779 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002780 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002781 rib->nexthop_num = 0;
2782 rib->uptime = time (NULL);
2783
2784 /* Nexthop settings. */
2785 if (gate)
2786 {
2787 if (ifindex)
2788 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2789 else
2790 nexthop_ipv6_add (rib, gate);
2791 }
2792 else
2793 nexthop_ifindex_add (rib, ifindex);
2794
2795 /* If this route is kernel route, set FIB flag to the route. */
2796 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2797 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2798 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2799
2800 /* Link new rib to node.*/
2801 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002802 if (IS_ZEBRA_DEBUG_RIB)
2803 {
2804 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
2805 __func__, rn, rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002806 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002807 }
paul718e3742002-12-13 20:15:29 +00002808
paul718e3742002-12-13 20:15:29 +00002809 /* Free implicit route.*/
2810 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002811 {
2812 if (IS_ZEBRA_DEBUG_RIB)
2813 {
2814 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
2815 __func__, rn, same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002816 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002817 }
paul4d38fdb2005-04-28 17:35:14 +00002818 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002819 }
paul4d38fdb2005-04-28 17:35:14 +00002820
2821 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002822 return 0;
2823}
2824
hassoebf1ead2005-09-21 14:58:20 +00002825/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002826int
2827rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002828 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002829{
2830 struct route_table *table;
2831 struct route_node *rn;
2832 struct rib *rib;
2833 struct rib *fib = NULL;
2834 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002835 struct nexthop *nexthop, *tnexthop;
2836 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002837 char buf1[INET6_ADDRSTRLEN];
2838 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002839
2840 /* Apply mask. */
2841 apply_mask_ipv6 (p);
2842
2843 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002844 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002845 if (! table)
2846 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002847
paul718e3742002-12-13 20:15:29 +00002848 /* Lookup route node. */
2849 rn = route_node_lookup (table, (struct prefix *) p);
2850 if (! rn)
2851 {
2852 if (IS_ZEBRA_DEBUG_KERNEL)
2853 {
2854 if (gate)
ajsb6178002004-12-07 21:12:56 +00002855 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002856 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002857 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002858 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002859 ifindex);
2860 else
ajsb6178002004-12-07 21:12:56 +00002861 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002862 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002863 p->prefixlen,
2864 ifindex);
2865 }
2866 return ZEBRA_ERR_RTNOEXIST;
2867 }
2868
2869 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002870 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002871 {
Paul Jakma6d691122006-07-27 21:49:00 +00002872 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2873 continue;
2874
paul718e3742002-12-13 20:15:29 +00002875 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2876 fib = rib;
2877
hassoebf1ead2005-09-21 14:58:20 +00002878 if (rib->type != type)
2879 continue;
2880 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002881 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002882 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002883 if (nexthop->ifindex != ifindex)
2884 continue;
hassoebf1ead2005-09-21 14:58:20 +00002885 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002886 {
hassoebf1ead2005-09-21 14:58:20 +00002887 rib->refcnt--;
2888 route_unlock_node (rn);
2889 route_unlock_node (rn);
2890 return 0;
paul718e3742002-12-13 20:15:29 +00002891 }
hassoebf1ead2005-09-21 14:58:20 +00002892 same = rib;
2893 break;
paul718e3742002-12-13 20:15:29 +00002894 }
hassoebf1ead2005-09-21 14:58:20 +00002895 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002896 else
2897 {
2898 if (gate == NULL)
2899 {
2900 same = rib;
2901 break;
2902 }
2903 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2904 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2905 {
2906 same = rib;
2907 break;
2908 }
2909 if (same)
2910 break;
2911 }
paul718e3742002-12-13 20:15:29 +00002912 }
2913
2914 /* If same type of route can't be found and this message is from
2915 kernel. */
2916 if (! same)
2917 {
2918 if (fib && type == ZEBRA_ROUTE_KERNEL)
2919 {
2920 /* Unset flags. */
2921 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2922 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2923
2924 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2925 }
2926 else
2927 {
2928 if (IS_ZEBRA_DEBUG_KERNEL)
2929 {
2930 if (gate)
ajsb6178002004-12-07 21:12:56 +00002931 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002932 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002933 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002934 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002935 ifindex,
2936 type);
2937 else
ajsb6178002004-12-07 21:12:56 +00002938 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002939 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002940 p->prefixlen,
2941 ifindex,
2942 type);
2943 }
2944 route_unlock_node (rn);
2945 return ZEBRA_ERR_RTNOEXIST;
2946 }
2947 }
2948
2949 if (same)
2950 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002951
paul718e3742002-12-13 20:15:29 +00002952 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002953 return 0;
2954}
David Lamparter6b0655a2014-06-04 06:53:35 +02002955
paul718e3742002-12-13 20:15:29 +00002956/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002957static void
paul718e3742002-12-13 20:15:29 +00002958static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2959{
2960 struct rib *rib;
2961 struct route_table *table;
2962 struct route_node *rn;
2963
2964 /* Lookup table. */
2965 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2966 if (! table)
2967 return;
2968
2969 /* Lookup existing route */
2970 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002971 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002972 {
2973 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2974 continue;
2975
2976 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2977 break;
2978 }
paul718e3742002-12-13 20:15:29 +00002979
2980 if (rib)
2981 {
2982 /* Same distance static route is there. Update it with new
2983 nexthop. */
paul718e3742002-12-13 20:15:29 +00002984 route_unlock_node (rn);
2985
2986 switch (si->type)
2987 {
2988 case STATIC_IPV6_GATEWAY:
2989 nexthop_ipv6_add (rib, &si->ipv6);
2990 break;
2991 case STATIC_IPV6_IFNAME:
2992 nexthop_ifname_add (rib, si->ifname);
2993 break;
2994 case STATIC_IPV6_GATEWAY_IFNAME:
2995 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2996 break;
2997 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002998 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002999 }
3000 else
3001 {
3002 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00003003 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
3004
paul718e3742002-12-13 20:15:29 +00003005 rib->type = ZEBRA_ROUTE_STATIC;
3006 rib->distance = si->distance;
3007 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07003008 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00003009 rib->nexthop_num = 0;
3010
3011 switch (si->type)
3012 {
3013 case STATIC_IPV6_GATEWAY:
3014 nexthop_ipv6_add (rib, &si->ipv6);
3015 break;
3016 case STATIC_IPV6_IFNAME:
3017 nexthop_ifname_add (rib, si->ifname);
3018 break;
3019 case STATIC_IPV6_GATEWAY_IFNAME:
3020 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
3021 break;
3022 }
3023
hasso81dfcaa2003-05-25 19:21:25 +00003024 /* Save the flags of this static routes (reject, blackhole) */
3025 rib->flags = si->flags;
3026
paul718e3742002-12-13 20:15:29 +00003027 /* Link this rib to the tree. */
3028 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003029 }
3030}
3031
paula1ac18c2005-06-28 17:17:12 +00003032static int
paul718e3742002-12-13 20:15:29 +00003033static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
3034{
3035 if (nexthop->type == NEXTHOP_TYPE_IPV6
3036 && si->type == STATIC_IPV6_GATEWAY
3037 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
3038 return 1;
3039 if (nexthop->type == NEXTHOP_TYPE_IFNAME
3040 && si->type == STATIC_IPV6_IFNAME
3041 && strcmp (nexthop->ifname, si->ifname) == 0)
3042 return 1;
3043 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3044 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3045 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3046 && strcmp (nexthop->ifname, si->ifname) == 0)
3047 return 1;
paule8e19462006-01-19 20:16:55 +00003048 return 0;
paul718e3742002-12-13 20:15:29 +00003049}
3050
paula1ac18c2005-06-28 17:17:12 +00003051static void
paul718e3742002-12-13 20:15:29 +00003052static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3053{
3054 struct route_table *table;
3055 struct route_node *rn;
3056 struct rib *rib;
3057 struct nexthop *nexthop;
3058
3059 /* Lookup table. */
3060 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3061 if (! table)
3062 return;
3063
3064 /* Lookup existing route with type and distance. */
3065 rn = route_node_lookup (table, (struct prefix *) p);
3066 if (! rn)
3067 return;
3068
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003069 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003070 {
3071 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3072 continue;
3073
3074 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3075 break;
3076 }
3077
paul718e3742002-12-13 20:15:29 +00003078 if (! rib)
3079 {
3080 route_unlock_node (rn);
3081 return;
3082 }
3083
3084 /* Lookup nexthop. */
3085 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3086 if (static_ipv6_nexthop_same (nexthop, si))
3087 break;
3088
3089 /* Can't find nexthop. */
3090 if (! nexthop)
3091 {
3092 route_unlock_node (rn);
3093 return;
3094 }
3095
3096 /* Check nexthop. */
3097 if (rib->nexthop_num == 1)
3098 {
3099 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003100 }
3101 else
3102 {
paul6baeb982003-10-28 03:47:15 +00003103 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3104 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003105 nexthop_delete (rib, nexthop);
3106 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003107 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003108 }
paul718e3742002-12-13 20:15:29 +00003109 /* Unlock node. */
3110 route_unlock_node (rn);
3111}
3112
3113/* Add static route into static route configuration. */
3114int
3115static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003116 const char *ifname, u_char flags, u_char distance,
3117 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003118{
3119 struct route_node *rn;
3120 struct static_ipv6 *si;
3121 struct static_ipv6 *pp;
3122 struct static_ipv6 *cp;
3123 struct route_table *stable;
3124
3125 /* Lookup table. */
3126 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3127 if (! stable)
3128 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003129
3130 if (!gate &&
3131 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3132 return -1;
3133
3134 if (!ifname &&
3135 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3136 return -1;
paul718e3742002-12-13 20:15:29 +00003137
3138 /* Lookup static route prefix. */
3139 rn = route_node_get (stable, p);
3140
3141 /* Do nothing if there is a same static route. */
3142 for (si = rn->info; si; si = si->next)
3143 {
3144 if (distance == si->distance
3145 && type == si->type
3146 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3147 && (! ifname || strcmp (ifname, si->ifname) == 0))
3148 {
3149 route_unlock_node (rn);
3150 return 0;
3151 }
3152 }
3153
3154 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003155 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003156
3157 si->type = type;
3158 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003159 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003160
3161 switch (type)
3162 {
3163 case STATIC_IPV6_GATEWAY:
3164 si->ipv6 = *gate;
3165 break;
3166 case STATIC_IPV6_IFNAME:
3167 si->ifname = XSTRDUP (0, ifname);
3168 break;
3169 case STATIC_IPV6_GATEWAY_IFNAME:
3170 si->ipv6 = *gate;
3171 si->ifname = XSTRDUP (0, ifname);
3172 break;
3173 }
3174
3175 /* Add new static route information to the tree with sort by
3176 distance value and gateway address. */
3177 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3178 {
3179 if (si->distance < cp->distance)
3180 break;
3181 if (si->distance > cp->distance)
3182 continue;
3183 }
3184
3185 /* Make linked list. */
3186 if (pp)
3187 pp->next = si;
3188 else
3189 rn->info = si;
3190 if (cp)
3191 cp->prev = si;
3192 si->prev = pp;
3193 si->next = cp;
3194
3195 /* Install into rib. */
3196 static_install_ipv6 (p, si);
3197
3198 return 1;
3199}
3200
3201/* Delete static route from static route configuration. */
3202int
3203static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003204 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003205{
3206 struct route_node *rn;
3207 struct static_ipv6 *si;
3208 struct route_table *stable;
3209
3210 /* Lookup table. */
3211 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3212 if (! stable)
3213 return -1;
3214
3215 /* Lookup static route prefix. */
3216 rn = route_node_lookup (stable, p);
3217 if (! rn)
3218 return 0;
3219
3220 /* Find same static route is the tree */
3221 for (si = rn->info; si; si = si->next)
3222 if (distance == si->distance
3223 && type == si->type
3224 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3225 && (! ifname || strcmp (ifname, si->ifname) == 0))
3226 break;
3227
3228 /* Can't find static route. */
3229 if (! si)
3230 {
3231 route_unlock_node (rn);
3232 return 0;
3233 }
3234
3235 /* Install into rib. */
3236 static_uninstall_ipv6 (p, si);
3237
3238 /* Unlink static route from linked list. */
3239 if (si->prev)
3240 si->prev->next = si->next;
3241 else
3242 rn->info = si->next;
3243 if (si->next)
3244 si->next->prev = si->prev;
3245
3246 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003247 if (ifname)
3248 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003249 XFREE (MTYPE_STATIC_IPV6, si);
3250
3251 return 1;
3252}
3253#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003254
paul718e3742002-12-13 20:15:29 +00003255/* RIB update function. */
3256void
paula1ac18c2005-06-28 17:17:12 +00003257rib_update (void)
paul718e3742002-12-13 20:15:29 +00003258{
3259 struct route_node *rn;
3260 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003261
paul718e3742002-12-13 20:15:29 +00003262 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3263 if (table)
3264 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003265 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003266 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003267
3268 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3269 if (table)
3270 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003271 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003272 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003273}
3274
David Lamparter6b0655a2014-06-04 06:53:35 +02003275
paul718e3742002-12-13 20:15:29 +00003276/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003277static void
paul718e3742002-12-13 20:15:29 +00003278rib_weed_table (struct route_table *table)
3279{
3280 struct route_node *rn;
3281 struct rib *rib;
3282 struct rib *next;
3283
3284 if (table)
3285 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003286 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003287 {
Paul Jakma6d691122006-07-27 21:49:00 +00003288 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3289 continue;
3290
paulb21b19c2003-06-15 01:28:29 +00003291 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003292 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003293 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003294 }
3295}
3296
3297/* Delete all routes from non main table. */
3298void
paula1ac18c2005-06-28 17:17:12 +00003299rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003300{
3301 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3302 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3303}
David Lamparter6b0655a2014-06-04 06:53:35 +02003304
paul718e3742002-12-13 20:15:29 +00003305/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003306static void
paul718e3742002-12-13 20:15:29 +00003307rib_sweep_table (struct route_table *table)
3308{
3309 struct route_node *rn;
3310 struct rib *rib;
3311 struct rib *next;
3312 int ret = 0;
3313
3314 if (table)
3315 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003316 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003317 {
Paul Jakma6d691122006-07-27 21:49:00 +00003318 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3319 continue;
3320
paul718e3742002-12-13 20:15:29 +00003321 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3322 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3323 {
3324 ret = rib_uninstall_kernel (rn, rib);
3325 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003326 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003327 }
3328 }
3329}
3330
3331/* Sweep all RIB tables. */
3332void
paula1ac18c2005-06-28 17:17:12 +00003333rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003334{
3335 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3336 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3337}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003338
3339/* Remove specific by protocol routes from 'table'. */
3340static unsigned long
3341rib_score_proto_table (u_char proto, struct route_table *table)
3342{
3343 struct route_node *rn;
3344 struct rib *rib;
3345 struct rib *next;
3346 unsigned long n = 0;
3347
3348 if (table)
3349 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003350 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003351 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003352 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3353 continue;
3354 if (rib->type == proto)
3355 {
3356 rib_delnode (rn, rib);
3357 n++;
3358 }
3359 }
3360
3361 return n;
3362}
3363
3364/* Remove specific by protocol routes. */
3365unsigned long
3366rib_score_proto (u_char proto)
3367{
3368 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3369 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3370}
3371
paul718e3742002-12-13 20:15:29 +00003372/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003373static void
paul718e3742002-12-13 20:15:29 +00003374rib_close_table (struct route_table *table)
3375{
3376 struct route_node *rn;
David Lamparterc048dcc2015-01-12 07:05:06 +01003377 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003378 struct rib *rib;
3379
3380 if (table)
3381 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003382 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003383 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003384 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3385 continue;
3386
David Lamparterc048dcc2015-01-12 07:05:06 +01003387 if (info->safi == SAFI_UNICAST)
3388 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003389
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003390 if (! RIB_SYSTEM_ROUTE (rib))
3391 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003392 }
paul718e3742002-12-13 20:15:29 +00003393}
3394
3395/* Close all RIB tables. */
3396void
paula1ac18c2005-06-28 17:17:12 +00003397rib_close (void)
paul718e3742002-12-13 20:15:29 +00003398{
3399 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3400 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3401}
David Lamparter6b0655a2014-06-04 06:53:35 +02003402
paul718e3742002-12-13 20:15:29 +00003403/* Routing information base initialize. */
3404void
paula1ac18c2005-06-28 17:17:12 +00003405rib_init (void)
paul718e3742002-12-13 20:15:29 +00003406{
paul4d38fdb2005-04-28 17:35:14 +00003407 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003408 /* VRF initialization. */
3409 vrf_init ();
3410}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003411
3412/*
3413 * vrf_id_get_next
3414 *
3415 * Get the first vrf id that is greater than the given vrf id if any.
3416 *
3417 * Returns TRUE if a vrf id was found, FALSE otherwise.
3418 */
3419static inline int
3420vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3421{
3422 while (++id < vector_active (vrf_vector))
3423 {
3424 if (vrf_lookup (id))
3425 {
3426 *next_id_p = id;
3427 return 1;
3428 }
3429 }
3430
3431 return 0;
3432}
3433
3434/*
3435 * rib_tables_iter_next
3436 *
3437 * Returns the next table in the iteration.
3438 */
3439struct route_table *
3440rib_tables_iter_next (rib_tables_iter_t *iter)
3441{
3442 struct route_table *table;
3443
3444 /*
3445 * Array that helps us go over all AFI/SAFI combinations via one
3446 * index.
3447 */
3448 static struct {
3449 afi_t afi;
3450 safi_t safi;
3451 } afi_safis[] = {
3452 { AFI_IP, SAFI_UNICAST },
3453 { AFI_IP, SAFI_MULTICAST },
3454 { AFI_IP6, SAFI_UNICAST },
3455 { AFI_IP6, SAFI_MULTICAST },
3456 };
3457
3458 table = NULL;
3459
3460 switch (iter->state)
3461 {
3462
3463 case RIB_TABLES_ITER_S_INIT:
3464 iter->vrf_id = 0;
3465 iter->afi_safi_ix = -1;
3466
3467 /* Fall through */
3468
3469 case RIB_TABLES_ITER_S_ITERATING:
3470 iter->afi_safi_ix++;
3471 while (1)
3472 {
3473
3474 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3475 {
3476 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3477 afi_safis[iter->afi_safi_ix].safi,
3478 iter->vrf_id);
3479 if (table)
3480 break;
3481
3482 iter->afi_safi_ix++;
3483 }
3484
3485 /*
3486 * Found another table in this vrf.
3487 */
3488 if (table)
3489 break;
3490
3491 /*
3492 * Done with all tables in the current vrf, go to the next
3493 * one.
3494 */
3495 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3496 break;
3497
3498 iter->afi_safi_ix = 0;
3499 }
3500
3501 break;
3502
3503 case RIB_TABLES_ITER_S_DONE:
3504 return NULL;
3505 }
3506
3507 if (table)
3508 iter->state = RIB_TABLES_ITER_S_ITERATING;
3509 else
3510 iter->state = RIB_TABLES_ITER_S_DONE;
3511
3512 return table;
3513}