blob: cc7f48fa5bbd4e34926dc2cc42909c02b9b71b8c [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "str.h"
28#include "command.h"
29#include "if.h"
30#include "log.h"
31#include "sockunion.h"
paul4d38fdb2005-04-28 17:35:14 +000032#include "linklist.h"
33#include "thread.h"
34#include "workqueue.h"
Paul Jakma7514fb72007-05-02 16:05:35 +000035#include "prefix.h"
36#include "routemap.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "zebra/rib.h"
39#include "zebra/rt.h"
40#include "zebra/zserv.h"
41#include "zebra/redistribute.h"
42#include "zebra/debug.h"
Avneesh Sachdev5adc2522012-11-13 22:48:59 +000043#include "zebra/zebra_fpm.h"
paul718e3742002-12-13 20:15:29 +000044
45/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000046extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000047
Paul Jakma457eb9a2006-07-27 19:59:58 +000048/* Hold time for RIB process, should be very minimal.
49 * it is useful to able to set it otherwise for testing, hence exported
50 * as global here for test-rig code.
51 */
52int rib_process_hold_time = 10;
53
paul718e3742002-12-13 20:15:29 +000054/* Each route type's string and default distance value. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010055static const struct
paul718e3742002-12-13 20:15:29 +000056{
57 int key;
58 int distance;
Paul Jakma57345092011-12-25 17:52:09 +010059} route_info[ZEBRA_ROUTE_MAX] =
paul718e3742002-12-13 20:15:29 +000060{
Paul Jakma57345092011-12-25 17:52:09 +010061 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
62 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
63 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
64 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
65 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
66 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
67 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
68 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
69 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
70 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
71 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
David Lamparter7052f222009-08-27 00:28:28 +020072 /* no entry/default: 150 */
paul718e3742002-12-13 20:15:29 +000073};
David Lamparter6b0655a2014-06-04 06:53:35 +020074
paul718e3742002-12-13 20:15:29 +000075/* Vector for routing table. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010076static vector vrf_vector;
paul718e3742002-12-13 20:15:29 +000077
David Lamparterbd078122015-01-06 19:53:24 +010078/* RPF lookup behaviour */
79static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
80
David Lampartereed3c482015-03-03 08:51:53 +010081static void __attribute__((format (printf, 4, 5)))
David Lamparter94813742014-04-24 20:22:53 +020082_rnode_zlog(const char *_func, struct route_node *rn, int priority,
83 const char *msgfmt, ...)
84{
85 char buf[INET6_ADDRSTRLEN + 4], *bptr;
86 char msgbuf[512];
87 va_list ap;
88
89 va_start(ap, msgfmt);
90 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
91 va_end(ap);
92
93 if (rn)
94 {
David Lamparterab2ba612015-01-22 19:02:13 +010095 rib_table_info_t *info = rn->table->info;
96
David Lamparter94813742014-04-24 20:22:53 +020097 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
98 bptr = buf + strlen(buf);
David Lamparterab2ba612015-01-22 19:02:13 +010099 snprintf(bptr, buf + sizeof(buf) - bptr, "/%d%s", rn->p.prefixlen,
100 info->safi == SAFI_MULTICAST ? " (MRIB)" : "");
David Lamparter94813742014-04-24 20:22:53 +0200101 }
102 else
103 {
104 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
105 }
106
107 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
108}
109
110#define rnode_debug(node, ...) \
111 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
112#define rnode_info(node, ...) \
113 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
114
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000115/*
116 * vrf_table_create
117 */
118static void
119vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
120{
121 rib_table_info_t *info;
122 struct route_table *table;
123
124 assert (!vrf->table[afi][safi]);
125
126 table = route_table_init ();
127 vrf->table[afi][safi] = table;
128
129 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
130 info->vrf = vrf;
131 info->afi = afi;
132 info->safi = safi;
133 table->info = info;
134}
135
paul718e3742002-12-13 20:15:29 +0000136/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +0000137static struct vrf *
hassofce954f2004-10-07 20:29:24 +0000138vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +0000139{
140 struct vrf *vrf;
141
142 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
143
144 /* Put name. */
145 if (name)
146 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
147
148 /* Allocate routing table and static table. */
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000149 vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
150 vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000151 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
152 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000153 vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
154 vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
G.Balajicddf3912011-11-26 21:59:32 +0400155 vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
156 vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
157
paul718e3742002-12-13 20:15:29 +0000158
159 return vrf;
160}
161
paul718e3742002-12-13 20:15:29 +0000162/* Lookup VRF by identifier. */
163struct vrf *
164vrf_lookup (u_int32_t id)
165{
166 return vector_lookup (vrf_vector, id);
167}
168
paul718e3742002-12-13 20:15:29 +0000169/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000170static void
171vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000172{
173 struct vrf *default_table;
174
175 /* Allocate VRF vector. */
176 vrf_vector = vector_init (1);
177
178 /* Allocate default main table. */
179 default_table = vrf_alloc ("Default-IP-Routing-Table");
180
181 /* Default table index must be 0. */
182 vector_set_index (vrf_vector, 0, default_table);
183}
184
185/* Lookup route table. */
186struct route_table *
187vrf_table (afi_t afi, safi_t safi, u_int32_t id)
188{
189 struct vrf *vrf;
190
191 vrf = vrf_lookup (id);
192 if (! vrf)
193 return NULL;
194
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000195 if( afi >= AFI_MAX || safi >= SAFI_MAX )
196 return NULL;
197
paul718e3742002-12-13 20:15:29 +0000198 return vrf->table[afi][safi];
199}
200
201/* Lookup static route table. */
202struct route_table *
203vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
204{
205 struct vrf *vrf;
206
207 vrf = vrf_lookup (id);
208 if (! vrf)
209 return NULL;
210
Leonid Rosenboim9499bf22012-12-06 20:17:41 +0000211 if( afi >= AFI_MAX || safi >= SAFI_MAX )
212 return NULL;
213
paul718e3742002-12-13 20:15:29 +0000214 return vrf->stable[afi][safi];
215}
David Lamparter6b0655a2014-06-04 06:53:35 +0200216
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000217/*
218 * nexthop_type_to_str
219 */
220const char *
221nexthop_type_to_str (enum nexthop_types_t nh_type)
222{
223 static const char *desc[] = {
224 "none",
225 "Directly connected",
226 "Interface route",
227 "IPv4 nexthop",
228 "IPv4 nexthop with ifindex",
229 "IPv4 nexthop with ifname",
230 "IPv6 nexthop",
231 "IPv6 nexthop with ifindex",
232 "IPv6 nexthop with ifname",
233 "Null0 nexthop",
234 };
235
236 if (nh_type >= ZEBRA_NUM_OF (desc))
237 return "<Invalid nh type>";
238
239 return desc[nh_type];
240}
241
Christian Frankefa713d92013-07-05 15:35:37 +0000242/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000243static void
Christian Frankefa713d92013-07-05 15:35:37 +0000244_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000245{
246 struct nexthop *last;
247
Christian Frankefa713d92013-07-05 15:35:37 +0000248 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000249 ;
250 if (last)
251 last->next = nexthop;
252 else
Christian Frankefa713d92013-07-05 15:35:37 +0000253 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000254 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000255}
paul718e3742002-12-13 20:15:29 +0000256
Christian Frankefa713d92013-07-05 15:35:37 +0000257/* Add nexthop to the end of a rib node's nexthop list */
258static void
259nexthop_add (struct rib *rib, struct nexthop *nexthop)
260{
261 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000262 rib->nexthop_num++;
263}
264
265/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000266static void
paul718e3742002-12-13 20:15:29 +0000267nexthop_delete (struct rib *rib, struct nexthop *nexthop)
268{
269 if (nexthop->next)
270 nexthop->next->prev = nexthop->prev;
271 if (nexthop->prev)
272 nexthop->prev->next = nexthop->next;
273 else
274 rib->nexthop = nexthop->next;
275 rib->nexthop_num--;
276}
277
Christian Frankefa713d92013-07-05 15:35:37 +0000278static void nexthops_free(struct nexthop *nexthop);
279
paul718e3742002-12-13 20:15:29 +0000280/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000281static void
paul718e3742002-12-13 20:15:29 +0000282nexthop_free (struct nexthop *nexthop)
283{
paula4b70762003-05-16 17:19:48 +0000284 if (nexthop->ifname)
285 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000286 if (nexthop->resolved)
287 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000288 XFREE (MTYPE_NEXTHOP, nexthop);
289}
290
Christian Frankefa713d92013-07-05 15:35:37 +0000291/* Frees a list of nexthops */
292static void
293nexthops_free (struct nexthop *nexthop)
294{
295 struct nexthop *nh, *next;
296
297 for (nh = nexthop; nh; nh = next)
298 {
299 next = nh->next;
300 nexthop_free (nh);
301 }
302}
303
paul718e3742002-12-13 20:15:29 +0000304struct nexthop *
305nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
306{
307 struct nexthop *nexthop;
308
Stephen Hemminger393deb92008-08-18 14:13:29 -0700309 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000310 nexthop->type = NEXTHOP_TYPE_IFINDEX;
311 nexthop->ifindex = ifindex;
312
313 nexthop_add (rib, nexthop);
314
315 return nexthop;
316}
317
318struct nexthop *
319nexthop_ifname_add (struct rib *rib, char *ifname)
320{
321 struct nexthop *nexthop;
322
Stephen Hemminger393deb92008-08-18 14:13:29 -0700323 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000324 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000325 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000326
327 nexthop_add (rib, nexthop);
328
329 return nexthop;
330}
331
332struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000333nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000334{
335 struct nexthop *nexthop;
336
Stephen Hemminger393deb92008-08-18 14:13:29 -0700337 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000338 nexthop->type = NEXTHOP_TYPE_IPV4;
339 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000340 if (src)
341 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000342
343 nexthop_add (rib, nexthop);
344
345 return nexthop;
346}
347
Josh Bailey26e2ae32012-03-22 01:09:21 -0700348struct nexthop *
paul718e3742002-12-13 20:15:29 +0000349nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000350 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000351{
352 struct nexthop *nexthop;
353
Stephen Hemminger393deb92008-08-18 14:13:29 -0700354 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000355 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
356 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000357 if (src)
358 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000359 nexthop->ifindex = ifindex;
360
361 nexthop_add (rib, nexthop);
362
363 return nexthop;
364}
365
366#ifdef HAVE_IPV6
367struct nexthop *
368nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
369{
370 struct nexthop *nexthop;
371
Stephen Hemminger393deb92008-08-18 14:13:29 -0700372 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000373 nexthop->type = NEXTHOP_TYPE_IPV6;
374 nexthop->gate.ipv6 = *ipv6;
375
376 nexthop_add (rib, nexthop);
377
378 return nexthop;
379}
380
paula1ac18c2005-06-28 17:17:12 +0000381static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000382nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
383 char *ifname)
384{
385 struct nexthop *nexthop;
386
Stephen Hemminger393deb92008-08-18 14:13:29 -0700387 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000388 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
389 nexthop->gate.ipv6 = *ipv6;
390 nexthop->ifname = XSTRDUP (0, ifname);
391
392 nexthop_add (rib, nexthop);
393
394 return nexthop;
395}
396
paula1ac18c2005-06-28 17:17:12 +0000397static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000398nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
399 unsigned int ifindex)
400{
401 struct nexthop *nexthop;
402
Stephen Hemminger393deb92008-08-18 14:13:29 -0700403 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000404 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
405 nexthop->gate.ipv6 = *ipv6;
406 nexthop->ifindex = ifindex;
407
408 nexthop_add (rib, nexthop);
409
410 return nexthop;
411}
412#endif /* HAVE_IPV6 */
413
paul595db7f2003-05-25 21:35:06 +0000414struct nexthop *
415nexthop_blackhole_add (struct rib *rib)
416{
417 struct nexthop *nexthop;
418
Stephen Hemminger393deb92008-08-18 14:13:29 -0700419 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000420 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
421 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
422
423 nexthop_add (rib, nexthop);
424
425 return nexthop;
426}
427
Christian Frankefa713d92013-07-05 15:35:37 +0000428/* This method checks whether a recursive nexthop has at
429 * least one resolved nexthop in the fib.
430 */
431int
432nexthop_has_fib_child(struct nexthop *nexthop)
433{
434 struct nexthop *nh;
435
436 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
437 return 0;
438
439 for (nh = nexthop->resolved; nh; nh = nh->next)
440 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
441 return 1;
442
443 return 0;
444}
445
paul718e3742002-12-13 20:15:29 +0000446/* If force flag is not set, do not modify falgs at all for uninstall
447 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000448static int
paul718e3742002-12-13 20:15:29 +0000449nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
450 struct route_node *top)
451{
452 struct prefix_ipv4 p;
453 struct route_table *table;
454 struct route_node *rn;
455 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000456 int resolved;
paul718e3742002-12-13 20:15:29 +0000457 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000458 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000459
460 if (nexthop->type == NEXTHOP_TYPE_IPV4)
461 nexthop->ifindex = 0;
462
463 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000464 {
465 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
466 nexthops_free(nexthop->resolved);
467 nexthop->resolved = NULL;
468 }
paul718e3742002-12-13 20:15:29 +0000469
470 /* Make lookup prefix. */
471 memset (&p, 0, sizeof (struct prefix_ipv4));
472 p.family = AF_INET;
473 p.prefixlen = IPV4_MAX_PREFIXLEN;
474 p.prefix = nexthop->gate.ipv4;
475
476 /* Lookup table. */
477 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
478 if (! table)
479 return 0;
480
481 rn = route_node_match (table, (struct prefix *) &p);
482 while (rn)
483 {
484 route_unlock_node (rn);
485
David Warda50c1072009-12-03 15:34:39 +0300486 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000487 if (rn == top)
488 return 0;
489
490 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000491 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100492 {
493 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
494 continue;
495 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
496 break;
497 }
paul718e3742002-12-13 20:15:29 +0000498
499 /* If there is no selected route or matched route is EGP, go up
500 tree. */
501 if (! match
502 || match->type == ZEBRA_ROUTE_BGP)
503 {
504 do {
505 rn = rn->parent;
506 } while (rn && rn->info == NULL);
507 if (rn)
508 route_lock_node (rn);
509 }
510 else
511 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000512 /* If the longest prefix match for the nexthop yields
513 * a blackhole, mark it as inactive. */
514 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
515 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
516 return 0;
517
paul718e3742002-12-13 20:15:29 +0000518 if (match->type == ZEBRA_ROUTE_CONNECT)
519 {
520 /* Directly point connected route. */
521 newhop = match->nexthop;
522 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
523 nexthop->ifindex = newhop->ifindex;
524
525 return 1;
526 }
527 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
528 {
Christian Frankefa713d92013-07-05 15:35:37 +0000529 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000530 for (newhop = match->nexthop; newhop; newhop = newhop->next)
531 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
532 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
533 {
534 if (set)
535 {
536 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000537
538 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
539 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000540 /* If the resolving route specifies a gateway, use it */
541 if (newhop->type == NEXTHOP_TYPE_IPV4
542 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
543 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
544 {
545 resolved_hop->type = newhop->type;
546 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000547
Christian Frankec3e6b592013-07-05 15:35:40 +0000548 if (newhop->ifindex)
549 {
550 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
551 resolved_hop->ifindex = newhop->ifindex;
552 }
553 }
Christian Frankefa713d92013-07-05 15:35:37 +0000554
Christian Frankec3e6b592013-07-05 15:35:40 +0000555 /* If the resolving route is an interface route,
556 * it means the gateway we are looking up is connected
557 * to that interface. (The actual network is _not_ onlink).
558 * Therefore, the resolved route should have the original
559 * gateway as nexthop as it is directly connected.
560 *
561 * On Linux, we have to set the onlink netlink flag because
562 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000563 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000564 || newhop->type == NEXTHOP_TYPE_IFNAME)
565 {
566 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
567 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
568 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
569 resolved_hop->ifindex = newhop->ifindex;
570 }
Christian Frankefa713d92013-07-05 15:35:37 +0000571
572 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000573 }
Christian Frankefa713d92013-07-05 15:35:37 +0000574 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000575 }
Christian Frankefa713d92013-07-05 15:35:37 +0000576 return resolved;
paul718e3742002-12-13 20:15:29 +0000577 }
578 else
579 {
580 return 0;
581 }
582 }
583 }
584 return 0;
585}
586
587#ifdef HAVE_IPV6
588/* If force flag is not set, do not modify falgs at all for uninstall
589 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000590static int
paul718e3742002-12-13 20:15:29 +0000591nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
592 struct route_node *top)
593{
594 struct prefix_ipv6 p;
595 struct route_table *table;
596 struct route_node *rn;
597 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000598 int resolved;
paul718e3742002-12-13 20:15:29 +0000599 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000600 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000601
602 if (nexthop->type == NEXTHOP_TYPE_IPV6)
603 nexthop->ifindex = 0;
604
605 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000606 {
607 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
608 nexthops_free(nexthop->resolved);
609 nexthop->resolved = NULL;
610 }
paul718e3742002-12-13 20:15:29 +0000611
612 /* Make lookup prefix. */
613 memset (&p, 0, sizeof (struct prefix_ipv6));
614 p.family = AF_INET6;
615 p.prefixlen = IPV6_MAX_PREFIXLEN;
616 p.prefix = nexthop->gate.ipv6;
617
618 /* Lookup table. */
619 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
620 if (! table)
621 return 0;
622
623 rn = route_node_match (table, (struct prefix *) &p);
624 while (rn)
625 {
626 route_unlock_node (rn);
627
David Warda50c1072009-12-03 15:34:39 +0300628 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000629 if (rn == top)
630 return 0;
631
632 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000633 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100634 {
635 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
636 continue;
637 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
638 break;
639 }
paul718e3742002-12-13 20:15:29 +0000640
641 /* If there is no selected route or matched route is EGP, go up
642 tree. */
643 if (! match
644 || match->type == ZEBRA_ROUTE_BGP)
645 {
646 do {
647 rn = rn->parent;
648 } while (rn && rn->info == NULL);
649 if (rn)
650 route_lock_node (rn);
651 }
652 else
653 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000654 /* If the longest prefix match for the nexthop yields
655 * a blackhole, mark it as inactive. */
656 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
657 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
658 return 0;
659
paul718e3742002-12-13 20:15:29 +0000660 if (match->type == ZEBRA_ROUTE_CONNECT)
661 {
662 /* Directly point connected route. */
663 newhop = match->nexthop;
664
665 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
666 nexthop->ifindex = newhop->ifindex;
667
668 return 1;
669 }
670 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
671 {
Christian Frankefa713d92013-07-05 15:35:37 +0000672 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000673 for (newhop = match->nexthop; newhop; newhop = newhop->next)
674 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
675 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
676 {
677 if (set)
678 {
679 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000680
681 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
682 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000683 /* See nexthop_active_ipv4 for a description how the
684 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000685 if (newhop->type == NEXTHOP_TYPE_IPV6
686 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
687 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000688 {
689 resolved_hop->type = newhop->type;
690 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
691
692 if (newhop->ifindex)
693 {
694 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
695 resolved_hop->ifindex = newhop->ifindex;
696 }
697 }
Christian Frankefa713d92013-07-05 15:35:37 +0000698
paul718e3742002-12-13 20:15:29 +0000699 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000700 || newhop->type == NEXTHOP_TYPE_IFNAME)
701 {
702 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
703 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
704 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
705 resolved_hop->ifindex = newhop->ifindex;
706 }
Christian Frankefa713d92013-07-05 15:35:37 +0000707
708 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000709 }
Christian Frankefa713d92013-07-05 15:35:37 +0000710 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000711 }
Christian Frankefa713d92013-07-05 15:35:37 +0000712 return resolved;
paul718e3742002-12-13 20:15:29 +0000713 }
714 else
715 {
716 return 0;
717 }
718 }
719 }
720 return 0;
721}
722#endif /* HAVE_IPV6 */
723
724struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100725rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
726 struct route_node **rn_out)
Everton Marques3dea1782014-09-22 19:35:51 -0300727{
728 struct route_table *table;
729 struct route_node *rn;
730 struct rib *match;
731 struct nexthop *newhop, *tnewhop;
732 int recursing;
733
734 /* Lookup table. */
735 table = vrf_table (AFI_IP, safi, 0);
736 if (! table)
737 return 0;
738
739 rn = route_node_match_ipv4 (table, &addr);
740
741 while (rn)
742 {
743 route_unlock_node (rn);
744
745 /* Pick up selected route. */
746 RNODE_FOREACH_RIB (rn, match)
747 {
748 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
749 continue;
750 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
751 break;
752 }
753
754 /* If there is no selected route or matched route is EGP, go up
755 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300756 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300757 {
758 do {
759 rn = rn->parent;
760 } while (rn && rn->info == NULL);
761 if (rn)
762 route_lock_node (rn);
763 }
764 else
765 {
David Lamparter24480d42015-01-22 19:09:36 +0100766 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300767 {
David Lamparter24480d42015-01-22 19:09:36 +0100768 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300769 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
770 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100771 {
772 found = 1;
773 break;
774 }
775 if (!found)
776 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300777 }
David Lamparter24480d42015-01-22 19:09:36 +0100778
779 if (rn_out)
780 *rn_out = rn;
781 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300782 }
783 }
784 return NULL;
785}
786
787struct rib *
David Lamparterbd078122015-01-06 19:53:24 +0100788rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
789{
790 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
791 struct route_node *m_rn = NULL, *u_rn = NULL;
792 int skip_bgp = 0; /* bool */
793
794 switch (ipv4_multicast_mode)
795 {
796 case MCAST_MRIB_ONLY:
797 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
798 case MCAST_URIB_ONLY:
799 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
800 case MCAST_NO_CONFIG:
801 case MCAST_MIX_MRIB_FIRST:
802 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
803 if (!mrib)
804 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
805 break;
806 case MCAST_MIX_DISTANCE:
807 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
808 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
809 if (mrib && urib)
810 rib = urib->distance < mrib->distance ? urib : mrib;
811 else if (mrib)
812 rib = mrib;
813 else if (urib)
814 rib = urib;
815 break;
816 case MCAST_MIX_PFXLEN:
817 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
818 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
819 if (mrib && urib)
820 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
821 else if (mrib)
822 rib = mrib;
823 else if (urib)
824 rib = urib;
825 break;
826 }
827
828 if (rn_out)
829 *rn_out = (rib == mrib) ? m_rn : u_rn;
830
831 if (IS_ZEBRA_DEBUG_RIB)
832 {
833 char buf[BUFSIZ];
834 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
835
836 zlog_debug("%s: %s: found %s, using %s",
837 __func__, buf,
838 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
839 urib ? "URIB" : "nothing",
840 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
841 }
842 return rib;
843}
844
845void
846multicast_mode_ipv4_set (enum multicast_mode mode)
847{
848 if (IS_ZEBRA_DEBUG_RIB)
849 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
850 ipv4_multicast_mode = mode;
851}
852
853enum multicast_mode
854multicast_mode_ipv4_get (void)
855{
856 return ipv4_multicast_mode;
857}
858
859struct rib *
paul718e3742002-12-13 20:15:29 +0000860rib_lookup_ipv4 (struct prefix_ipv4 *p)
861{
862 struct route_table *table;
863 struct route_node *rn;
864 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000865 struct nexthop *nexthop, *tnexthop;
866 int recursing;
paul718e3742002-12-13 20:15:29 +0000867
868 /* Lookup table. */
869 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
870 if (! table)
871 return 0;
872
873 rn = route_node_lookup (table, (struct prefix *) p);
874
875 /* No route for this prefix. */
876 if (! rn)
877 return NULL;
878
879 /* Unlock node. */
880 route_unlock_node (rn);
881
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000882 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100883 {
884 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
885 continue;
886 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
887 break;
888 }
paul718e3742002-12-13 20:15:29 +0000889
890 if (! match || match->type == ZEBRA_ROUTE_BGP)
891 return NULL;
892
893 if (match->type == ZEBRA_ROUTE_CONNECT)
894 return match;
895
Christian Frankefa713d92013-07-05 15:35:37 +0000896 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000897 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
898 return match;
899
900 return NULL;
901}
902
Denis Ovsienkodc958242007-08-13 16:03:06 +0000903/*
904 * This clone function, unlike its original rib_lookup_ipv4(), checks
905 * if specified IPv4 route record (prefix/mask -> gate) exists in
906 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
907 *
908 * Return values:
909 * -1: error
910 * 0: exact match found
911 * 1: a match was found with a different gate
912 * 2: connected route found
913 * 3: no matches found
914 */
915int
916rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
917{
918 struct route_table *table;
919 struct route_node *rn;
920 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000921 struct nexthop *nexthop, *tnexthop;
922 int recursing;
923 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000924
925 /* Lookup table. */
926 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
927 if (! table)
928 return ZEBRA_RIB_LOOKUP_ERROR;
929
930 /* Scan the RIB table for exactly matching RIB entry. */
931 rn = route_node_lookup (table, (struct prefix *) p);
932
933 /* No route for this prefix. */
934 if (! rn)
935 return ZEBRA_RIB_NOTFOUND;
936
937 /* Unlock node. */
938 route_unlock_node (rn);
939
940 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000941 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100942 {
943 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
944 continue;
945 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
946 break;
947 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000948
949 /* None such found :( */
950 if (!match)
951 return ZEBRA_RIB_NOTFOUND;
952
953 if (match->type == ZEBRA_ROUTE_CONNECT)
954 return ZEBRA_RIB_FOUND_CONNECTED;
955
956 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000957 nexthops_active = 0;
958 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000959 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000960 {
Christian Frankefa713d92013-07-05 15:35:37 +0000961 nexthops_active = 1;
962 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
963 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000964 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000965 {
966 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
967 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
968 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
969 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
970 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
971 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000972 }
Christian Frankefa713d92013-07-05 15:35:37 +0000973
974 if (nexthops_active)
975 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000976
977 return ZEBRA_RIB_NOTFOUND;
978}
979
paul718e3742002-12-13 20:15:29 +0000980#ifdef HAVE_IPV6
981struct rib *
982rib_match_ipv6 (struct in6_addr *addr)
983{
984 struct prefix_ipv6 p;
985 struct route_table *table;
986 struct route_node *rn;
987 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000988 struct nexthop *newhop, *tnewhop;
989 int recursing;
paul718e3742002-12-13 20:15:29 +0000990
991 /* Lookup table. */
992 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
993 if (! table)
994 return 0;
995
996 memset (&p, 0, sizeof (struct prefix_ipv6));
997 p.family = AF_INET6;
998 p.prefixlen = IPV6_MAX_PREFIXLEN;
999 IPV6_ADDR_COPY (&p.prefix, addr);
1000
1001 rn = route_node_match (table, (struct prefix *) &p);
1002
1003 while (rn)
1004 {
1005 route_unlock_node (rn);
1006
1007 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001008 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +01001009 {
1010 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
1011 continue;
1012 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
1013 break;
1014 }
paul718e3742002-12-13 20:15:29 +00001015
1016 /* If there is no selected route or matched route is EGP, go up
1017 tree. */
1018 if (! match
1019 || match->type == ZEBRA_ROUTE_BGP)
1020 {
1021 do {
1022 rn = rn->parent;
1023 } while (rn && rn->info == NULL);
1024 if (rn)
1025 route_lock_node (rn);
1026 }
1027 else
1028 {
1029 if (match->type == ZEBRA_ROUTE_CONNECT)
1030 /* Directly point connected route. */
1031 return match;
1032 else
1033 {
Christian Frankefa713d92013-07-05 15:35:37 +00001034 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +00001035 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1036 return match;
1037 return NULL;
1038 }
1039 }
1040 }
1041 return NULL;
1042}
1043#endif /* HAVE_IPV6 */
1044
Paul Jakma7514fb72007-05-02 16:05:35 +00001045#define RIB_SYSTEM_ROUTE(R) \
1046 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
1047
Denis Ovsienkodc958242007-08-13 16:03:06 +00001048/* This function verifies reachability of one given nexthop, which can be
1049 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
1050 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
1051 * nexthop->ifindex will be updated appropriately as well.
1052 * An existing route map can turn (otherwise active) nexthop into inactive, but
1053 * not vice versa.
1054 *
1055 * The return value is the final value of 'ACTIVE' flag.
1056 */
1057
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001058static unsigned
paul718e3742002-12-13 20:15:29 +00001059nexthop_active_check (struct route_node *rn, struct rib *rib,
1060 struct nexthop *nexthop, int set)
1061{
Christian Frankef3a17322013-07-05 15:35:41 +00001062 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +00001063 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +00001064 route_map_result_t ret = RMAP_MATCH;
1065 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
1066 struct route_map *rmap;
1067 int family;
paul718e3742002-12-13 20:15:29 +00001068
Paul Jakma7514fb72007-05-02 16:05:35 +00001069 family = 0;
paul718e3742002-12-13 20:15:29 +00001070 switch (nexthop->type)
1071 {
1072 case NEXTHOP_TYPE_IFINDEX:
1073 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001074 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001075 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1076 else
1077 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1078 break;
paul718e3742002-12-13 20:15:29 +00001079 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +00001080 family = AFI_IP6;
1081 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +00001082 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001083 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001084 {
1085 if (set)
1086 nexthop->ifindex = ifp->ifindex;
1087 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1088 }
1089 else
1090 {
1091 if (set)
1092 nexthop->ifindex = 0;
1093 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1094 }
1095 break;
1096 case NEXTHOP_TYPE_IPV4:
1097 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001098 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001099 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1100 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1101 else
1102 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1103 break;
1104#ifdef HAVE_IPV6
1105 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001106 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001107 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1108 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1109 else
1110 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1111 break;
1112 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001113 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001114 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1115 {
1116 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001117 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001118 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1119 else
1120 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1121 }
1122 else
1123 {
1124 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1125 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1126 else
1127 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1128 }
1129 break;
1130#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001131 case NEXTHOP_TYPE_BLACKHOLE:
1132 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1133 break;
paul718e3742002-12-13 20:15:29 +00001134 default:
1135 break;
1136 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001137 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1138 return 0;
1139
Christian Frankef3a17322013-07-05 15:35:41 +00001140 /* XXX: What exactly do those checks do? Do we support
1141 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001142 if (RIB_SYSTEM_ROUTE(rib) ||
1143 (family == AFI_IP && rn->p.family != AF_INET) ||
1144 (family == AFI_IP6 && rn->p.family != AF_INET6))
1145 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1146
Christian Frankef3a17322013-07-05 15:35:41 +00001147 /* The original code didn't determine the family correctly
1148 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1149 * from the rib_table_info in those cases.
1150 * Possibly it may be better to use only the rib_table_info
1151 * in every case.
1152 */
1153 if (!family)
1154 family = info->afi;
1155
Paul Jakma7514fb72007-05-02 16:05:35 +00001156 rmap = 0;
1157 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1158 proto_rm[family][rib->type])
1159 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1160 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1161 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1162 if (rmap) {
1163 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1164 }
1165
1166 if (ret == RMAP_DENYMATCH)
1167 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001168 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1169}
1170
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001171/* Iterate over all nexthops of the given RIB entry and refresh their
1172 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1173 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1174 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1175 * transparently passed to nexthop_active_check().
1176 *
1177 * Return value is the new number of active nexthops.
1178 */
1179
paula1ac18c2005-06-28 17:17:12 +00001180static int
paul718e3742002-12-13 20:15:29 +00001181nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1182{
1183 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001184 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001185
1186 rib->nexthop_active_num = 0;
1187 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1188
1189 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001190 {
1191 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001192 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001193 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1194 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001195 if (prev_active != new_active ||
1196 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001197 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1198 }
paul718e3742002-12-13 20:15:29 +00001199 return rib->nexthop_active_num;
1200}
paul6baeb982003-10-28 03:47:15 +00001201
David Lamparter6b0655a2014-06-04 06:53:35 +02001202
paul718e3742002-12-13 20:15:29 +00001203
paula1ac18c2005-06-28 17:17:12 +00001204static void
paul718e3742002-12-13 20:15:29 +00001205rib_install_kernel (struct route_node *rn, struct rib *rib)
1206{
1207 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001208 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001209 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001210 int recursing;
paul718e3742002-12-13 20:15:29 +00001211
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001212 if (info->safi != SAFI_UNICAST)
1213 {
1214 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1215 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1216 return;
1217 }
1218
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001219 /*
1220 * Make sure we update the FPM any time we send new information to
1221 * the kernel.
1222 */
1223 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001224 switch (PREFIX_FAMILY (&rn->p))
1225 {
1226 case AF_INET:
1227 ret = kernel_add_ipv4 (&rn->p, rib);
1228 break;
1229#ifdef HAVE_IPV6
1230 case AF_INET6:
1231 ret = kernel_add_ipv6 (&rn->p, rib);
1232 break;
1233#endif /* HAVE_IPV6 */
1234 }
1235
Denis Ovsienkodc958242007-08-13 16:03:06 +00001236 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001237 if (ret < 0)
1238 {
Christian Frankefa713d92013-07-05 15:35:37 +00001239 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001240 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1241 }
1242}
1243
1244/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001245static int
paul718e3742002-12-13 20:15:29 +00001246rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1247{
1248 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001249 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001250 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001251 int recursing;
paul718e3742002-12-13 20:15:29 +00001252
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001253 if (info->safi != SAFI_UNICAST)
1254 {
1255 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1256 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1257 return ret;
1258 }
1259
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001260 /*
1261 * Make sure we update the FPM any time we send new information to
1262 * the kernel.
1263 */
1264 zfpm_trigger_update (rn, "uninstalling from kernel");
1265
paul718e3742002-12-13 20:15:29 +00001266 switch (PREFIX_FAMILY (&rn->p))
1267 {
1268 case AF_INET:
1269 ret = kernel_delete_ipv4 (&rn->p, rib);
1270 break;
1271#ifdef HAVE_IPV6
1272 case AF_INET6:
1273 ret = kernel_delete_ipv6 (&rn->p, rib);
1274 break;
1275#endif /* HAVE_IPV6 */
1276 }
1277
Christian Frankefa713d92013-07-05 15:35:37 +00001278 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001279 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1280
1281 return ret;
1282}
1283
1284/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001285static void
paul718e3742002-12-13 20:15:29 +00001286rib_uninstall (struct route_node *rn, struct rib *rib)
1287{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001288 rib_table_info_t *info = rn->table->info;
1289
paul718e3742002-12-13 20:15:29 +00001290 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1291 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001292 if (info->safi == SAFI_UNICAST)
1293 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001294
paul718e3742002-12-13 20:15:29 +00001295 redistribute_delete (&rn->p, rib);
1296 if (! RIB_SYSTEM_ROUTE (rib))
1297 rib_uninstall_kernel (rn, rib);
1298 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1299 }
1300}
1301
Paul Jakma6d691122006-07-27 21:49:00 +00001302static void rib_unlink (struct route_node *, struct rib *);
1303
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001304/*
1305 * rib_can_delete_dest
1306 *
1307 * Returns TRUE if the given dest can be deleted from the table.
1308 */
1309static int
1310rib_can_delete_dest (rib_dest_t *dest)
1311{
1312 if (dest->routes)
1313 {
1314 return 0;
1315 }
1316
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001317 /*
1318 * Don't delete the dest if we have to update the FPM about this
1319 * prefix.
1320 */
1321 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1322 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1323 return 0;
1324
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001325 return 1;
1326}
1327
1328/*
1329 * rib_gc_dest
1330 *
1331 * Garbage collect the rib dest corresponding to the given route node
1332 * if appropriate.
1333 *
1334 * Returns TRUE if the dest was deleted, FALSE otherwise.
1335 */
1336int
1337rib_gc_dest (struct route_node *rn)
1338{
1339 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001340
1341 dest = rib_dest_from_rnode (rn);
1342 if (!dest)
1343 return 0;
1344
1345 if (!rib_can_delete_dest (dest))
1346 return 0;
1347
1348 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001349 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001350
1351 dest->rnode = NULL;
1352 XFREE (MTYPE_RIB_DEST, dest);
1353 rn->info = NULL;
1354
1355 /*
1356 * Release the one reference that we keep on the route node.
1357 */
1358 route_unlock_node (rn);
1359 return 1;
1360}
1361
paul718e3742002-12-13 20:15:29 +00001362/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001363static void
1364rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001365{
1366 struct rib *rib;
1367 struct rib *next;
1368 struct rib *fib = NULL;
1369 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001370 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001371 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001372 struct nexthop *nexthop = NULL, *tnexthop;
1373 int recursing;
Balaji95116332014-10-23 15:25:25 +00001374 rib_table_info_t *info;
1375
paul4d38fdb2005-04-28 17:35:14 +00001376 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001377
1378 info = rn->table->info;
1379
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001380 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001381 {
paul718e3742002-12-13 20:15:29 +00001382 /* Currently installed rib. */
1383 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001384 {
1385 assert (fib == NULL);
1386 fib = rib;
1387 }
1388
1389 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1390 * which we need to do do further work with below.
1391 */
1392 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1393 {
1394 if (rib != fib)
1395 {
1396 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001397 rnode_debug (rn, "rn %p, removing rib %p",
1398 (void *)rn, (void *)rib);
1399 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001400 }
1401 else
1402 del = rib;
1403
1404 continue;
1405 }
paul4d38fdb2005-04-28 17:35:14 +00001406
paul718e3742002-12-13 20:15:29 +00001407 /* Skip unreachable nexthop. */
1408 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001409 continue;
paul718e3742002-12-13 20:15:29 +00001410
1411 /* Infinit distance. */
1412 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001413 continue;
paul718e3742002-12-13 20:15:29 +00001414
paulaf887b52006-01-18 14:52:52 +00001415 /* Newly selected rib, the common case. */
1416 if (!select)
1417 {
1418 select = rib;
1419 continue;
1420 }
1421
1422 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001423 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001424 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001425 * - lower metric beats higher for equal distance
1426 * - last, hence oldest, route wins tie break.
1427 */
paula1038a12006-01-30 14:08:51 +00001428
1429 /* Connected routes. Pick the last connected
1430 * route of the set of lowest metric connected routes.
1431 */
paula8d9c1f2006-01-25 06:31:04 +00001432 if (rib->type == ZEBRA_ROUTE_CONNECT)
1433 {
paula1038a12006-01-30 14:08:51 +00001434 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001435 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001436 select = rib;
1437 continue;
paula8d9c1f2006-01-25 06:31:04 +00001438 }
1439 else if (select->type == ZEBRA_ROUTE_CONNECT)
1440 continue;
1441
1442 /* higher distance loses */
1443 if (rib->distance > select->distance)
1444 continue;
1445
1446 /* lower wins */
1447 if (rib->distance < select->distance)
1448 {
paulaf887b52006-01-18 14:52:52 +00001449 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001450 continue;
1451 }
1452
1453 /* metric tie-breaks equal distance */
1454 if (rib->metric <= select->metric)
1455 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001456 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001457
1458 /* After the cycle is finished, the following pointers will be set:
1459 * select --- the winner RIB entry, if any was found, otherwise NULL
1460 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1461 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1462 * rib --- NULL
1463 */
1464
1465 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001466 if (select && select == fib)
1467 {
Paul Jakma6d691122006-07-27 21:49:00 +00001468 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001469 rnode_debug (rn, "Updating existing route, select %p, fib %p",
David Lampartereed3c482015-03-03 08:51:53 +01001470 (void *)select, (void *)fib);
paul718e3742002-12-13 20:15:29 +00001471 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001472 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001473 if (info->safi == SAFI_UNICAST)
1474 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001475
paul4d38fdb2005-04-28 17:35:14 +00001476 redistribute_delete (&rn->p, select);
1477 if (! RIB_SYSTEM_ROUTE (select))
1478 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001479
paul4d38fdb2005-04-28 17:35:14 +00001480 /* Set real nexthop. */
1481 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001482
paul4d38fdb2005-04-28 17:35:14 +00001483 if (! RIB_SYSTEM_ROUTE (select))
1484 rib_install_kernel (rn, select);
1485 redistribute_add (&rn->p, select);
1486 }
pauld753e9e2003-01-22 19:45:50 +00001487 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001488 {
1489 /* Housekeeping code to deal with
1490 race conditions in kernel with linux
1491 netlink reporting interface up before IPv4 or IPv6 protocol
1492 is ready to add routes.
1493 This makes sure the routes are IN the kernel.
1494 */
pauld753e9e2003-01-22 19:45:50 +00001495
Christian Frankefa713d92013-07-05 15:35:37 +00001496 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001497 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001498 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001499 installed = 1;
1500 break;
paul4d38fdb2005-04-28 17:35:14 +00001501 }
1502 if (! installed)
1503 rib_install_kernel (rn, select);
1504 }
Paul Jakma6d691122006-07-27 21:49:00 +00001505 goto end;
paul718e3742002-12-13 20:15:29 +00001506 }
1507
Denis Ovsienkodc958242007-08-13 16:03:06 +00001508 /* At this point we either haven't found the best RIB entry or it is
1509 * different from what we currently intend to flag with SELECTED. In both
1510 * cases, if a RIB block is present in FIB, it should be withdrawn.
1511 */
paul718e3742002-12-13 20:15:29 +00001512 if (fib)
1513 {
Paul Jakma6d691122006-07-27 21:49:00 +00001514 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001515 rnode_debug (rn, "Removing existing route, fib %p", (void *)fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001516
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001517 if (info->safi == SAFI_UNICAST)
1518 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001519
paul718e3742002-12-13 20:15:29 +00001520 redistribute_delete (&rn->p, fib);
1521 if (! RIB_SYSTEM_ROUTE (fib))
1522 rib_uninstall_kernel (rn, fib);
1523 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1524
1525 /* Set real nexthop. */
1526 nexthop_active_update (rn, fib, 1);
1527 }
1528
Denis Ovsienkodc958242007-08-13 16:03:06 +00001529 /* Regardless of some RIB entry being SELECTED or not before, now we can
1530 * tell, that if a new winner exists, FIB is still not updated with this
1531 * data, but ready to be.
1532 */
paul718e3742002-12-13 20:15:29 +00001533 if (select)
1534 {
Paul Jakma6d691122006-07-27 21:49:00 +00001535 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001536 rnode_debug (rn, "Adding route, select %p", (void *)select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001537
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001538 if (info->safi == SAFI_UNICAST)
1539 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001540
paul718e3742002-12-13 20:15:29 +00001541 /* Set real nexthop. */
1542 nexthop_active_update (rn, select, 1);
1543
1544 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001545 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001546 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1547 redistribute_add (&rn->p, select);
1548 }
paul4d38fdb2005-04-28 17:35:14 +00001549
Paul Jakma6d691122006-07-27 21:49:00 +00001550 /* FIB route was removed, should be deleted */
1551 if (del)
1552 {
1553 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001554 rnode_debug (rn, "Deleting fib %p, rn %p", (void *)del, (void *)rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001555 rib_unlink (rn, del);
1556 }
paul4d38fdb2005-04-28 17:35:14 +00001557
Paul Jakma6d691122006-07-27 21:49:00 +00001558end:
1559 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001560 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001561
1562 /*
1563 * Check if the dest can be deleted now.
1564 */
1565 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001566}
1567
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001568/* Take a list of route_node structs and return 1, if there was a record
1569 * picked from it and processed by rib_process(). Don't process more,
1570 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001571 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001572static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001573process_subq (struct list * subq, u_char qindex)
1574{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001575 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001576 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001577
1578 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001579 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001580
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001581 rnode = listgetdata (lnode);
1582 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001583
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001584 if (rnode->info)
1585 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1586
Chris Caputo67b94672009-07-18 04:02:26 +00001587#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001588 else
1589 {
1590 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1591 __func__, rnode, rnode->lock);
1592 zlog_backtrace(LOG_DEBUG);
1593 }
Chris Caputo67b94672009-07-18 04:02:26 +00001594#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001595 route_unlock_node (rnode);
1596 list_delete_node (subq, lnode);
1597 return 1;
1598}
1599
1600/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1601 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1602 * is pointed to the meta queue structure.
1603 */
1604static wq_item_status
1605meta_queue_process (struct work_queue *dummy, void *data)
1606{
1607 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001608 unsigned i;
1609
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001610 for (i = 0; i < MQ_SIZE; i++)
1611 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001612 {
1613 mq->size--;
1614 break;
1615 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001616 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1617}
1618
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001619/*
1620 * Map from rib types to queue type (priority) in meta queue
1621 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001622static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1623 [ZEBRA_ROUTE_SYSTEM] = 4,
1624 [ZEBRA_ROUTE_KERNEL] = 0,
1625 [ZEBRA_ROUTE_CONNECT] = 0,
1626 [ZEBRA_ROUTE_STATIC] = 1,
1627 [ZEBRA_ROUTE_RIP] = 2,
1628 [ZEBRA_ROUTE_RIPNG] = 2,
1629 [ZEBRA_ROUTE_OSPF] = 2,
1630 [ZEBRA_ROUTE_OSPF6] = 2,
1631 [ZEBRA_ROUTE_ISIS] = 2,
1632 [ZEBRA_ROUTE_BGP] = 3,
1633 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001634 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001635};
1636
1637/* Look into the RN and queue it into one or more priority queues,
1638 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001639 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001640static void
1641rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001642{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001643 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001644
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001645 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001646 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001647 u_char qindex = meta_queue_map[rib->type];
1648
1649 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001650 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1651 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001652 {
1653 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001654 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001655 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001656 continue;
1657 }
1658
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001659 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001660 listnode_add (mq->subq[qindex], rn);
1661 route_lock_node (rn);
1662 mq->size++;
1663
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001664 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001665 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001666 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001667 }
paul4d38fdb2005-04-28 17:35:14 +00001668}
1669
Paul Jakma6d691122006-07-27 21:49:00 +00001670/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001671static void
Paul Jakma6d691122006-07-27 21:49:00 +00001672rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001673{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001674 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001675
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001676 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001677 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001678 {
1679 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001680 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001681 zlog_backtrace(LOG_DEBUG);
1682 return;
1683 }
1684
1685 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001686 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001687
1688 assert (zebra);
1689
1690 if (zebra->ribq == NULL)
1691 {
1692 zlog_err ("%s: work_queue does not exist!", __func__);
1693 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001694 }
paul4d38fdb2005-04-28 17:35:14 +00001695
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001696 /*
1697 * The RIB queue should normally be either empty or holding the only
1698 * work_queue_item element. In the latter case this element would
1699 * hold a pointer to the meta queue structure, which must be used to
1700 * actually queue the route nodes to process. So create the MQ
1701 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001702 * This semantics was introduced after 0.99.9 release.
1703 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001704 if (!zebra->ribq->items->count)
1705 work_queue_add (zebra->ribq, zebra->mq);
1706
1707 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001708
1709 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001710 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001711
1712 return;
paul4d38fdb2005-04-28 17:35:14 +00001713}
1714
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001715/* Create new meta queue.
1716 A destructor function doesn't seem to be necessary here.
1717 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001718static struct meta_queue *
1719meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001720{
1721 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001722 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001723
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001724 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1725 assert(new);
1726
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001727 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001728 {
1729 new->subq[i] = list_new ();
1730 assert(new->subq[i]);
1731 }
1732
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001733 return new;
1734}
1735
paul4d38fdb2005-04-28 17:35:14 +00001736/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001737static void
paul4d38fdb2005-04-28 17:35:14 +00001738rib_queue_init (struct zebra_t *zebra)
1739{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001740 assert (zebra);
1741
paul4d38fdb2005-04-28 17:35:14 +00001742 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001743 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001744 {
Paul Jakma6d691122006-07-27 21:49:00 +00001745 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001746 return;
1747 }
1748
1749 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001750 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001751 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001752 /* XXX: TODO: These should be runtime configurable via vty */
1753 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001754 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001755
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001756 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001757 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001758 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001759 return;
1760 }
1761 return;
paul718e3742002-12-13 20:15:29 +00001762}
1763
Paul Jakma6d691122006-07-27 21:49:00 +00001764/* RIB updates are processed via a queue of pointers to route_nodes.
1765 *
1766 * The queue length is bounded by the maximal size of the routing table,
1767 * as a route_node will not be requeued, if already queued.
1768 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001769 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1770 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1771 * and then submit route_node to queue for best-path selection later.
1772 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001773 *
1774 * Deleted RIBs are reaped during best-path selection.
1775 *
1776 * rib_addnode
1777 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001778 * |-------->| | best RIB, if required
1779 * | |
1780 * static_install->|->rib_addqueue...... -> rib_process
1781 * | |
1782 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001783 * |-> set RIB_ENTRY_REMOVE |
1784 * rib_delnode (RIB freed)
1785 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001786 * The 'info' pointer of a route_node points to a rib_dest_t
1787 * ('dest'). Queueing state for a route_node is kept on the dest. The
1788 * dest is created on-demand by rib_link() and is kept around at least
1789 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001790 *
1791 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1792 *
1793 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001794 * - dest attached to route_node:
1795 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001796 * - route_node processing queue
1797 * - managed by: rib_addqueue, rib_process.
1798 *
1799 */
1800
paul718e3742002-12-13 20:15:29 +00001801/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001802static void
Paul Jakma6d691122006-07-27 21:49:00 +00001803rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001804{
1805 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001806 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001807
paul4d38fdb2005-04-28 17:35:14 +00001808 assert (rib && rn);
1809
Paul Jakma6d691122006-07-27 21:49:00 +00001810 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001811 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001812
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001813 dest = rib_dest_from_rnode (rn);
1814 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001815 {
1816 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001817 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001818
1819 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1820 route_lock_node (rn); /* rn route table reference */
1821 rn->info = dest;
1822 dest->rnode = rn;
1823 }
1824
1825 head = dest->routes;
1826 if (head)
1827 {
Paul Jakma6d691122006-07-27 21:49:00 +00001828 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001829 }
paul718e3742002-12-13 20:15:29 +00001830 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001831 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001832 rib_queue_add (&zebrad, rn);
1833}
1834
1835static void
1836rib_addnode (struct route_node *rn, struct rib *rib)
1837{
1838 /* RIB node has been un-removed before route-node is processed.
1839 * route_node must hence already be on the queue for processing..
1840 */
1841 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1842 {
1843 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001844 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001845
Paul Jakma6d691122006-07-27 21:49:00 +00001846 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1847 return;
1848 }
1849 rib_link (rn, rib);
1850}
1851
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001852/*
1853 * rib_unlink
1854 *
1855 * Detach a rib structure from a route_node.
1856 *
1857 * Note that a call to rib_unlink() should be followed by a call to
1858 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1859 * longer required to be deleted.
1860 */
Paul Jakma6d691122006-07-27 21:49:00 +00001861static void
1862rib_unlink (struct route_node *rn, struct rib *rib)
1863{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001864 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001865
1866 assert (rn && rib);
1867
1868 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001869 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001870
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001871 dest = rib_dest_from_rnode (rn);
1872
Paul Jakma6d691122006-07-27 21:49:00 +00001873 if (rib->next)
1874 rib->next->prev = rib->prev;
1875
1876 if (rib->prev)
1877 rib->prev->next = rib->next;
1878 else
1879 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001880 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001881 }
1882
1883 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001884 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001885 XFREE (MTYPE_RIB, rib);
1886
paul718e3742002-12-13 20:15:29 +00001887}
1888
paula1ac18c2005-06-28 17:17:12 +00001889static void
paul718e3742002-12-13 20:15:29 +00001890rib_delnode (struct route_node *rn, struct rib *rib)
1891{
Paul Jakma6d691122006-07-27 21:49:00 +00001892 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001893 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001894 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1895 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001896}
1897
1898int
1899rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001900 struct in_addr *gate, struct in_addr *src,
1901 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001902 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001903{
1904 struct rib *rib;
1905 struct rib *same = NULL;
1906 struct route_table *table;
1907 struct route_node *rn;
1908 struct nexthop *nexthop;
1909
1910 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04001911 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00001912 if (! table)
1913 return 0;
1914
1915 /* Make it sure prefixlen is applied to the prefix. */
1916 apply_mask_ipv4 (p);
1917
1918 /* Set default distance by route type. */
1919 if (distance == 0)
1920 {
Balaji.G837d16c2012-09-26 14:09:10 +05301921 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001922 distance = 150;
1923 else
1924 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001925
1926 /* iBGP distance is 200. */
1927 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1928 distance = 200;
1929 }
1930
1931 /* Lookup route node.*/
1932 rn = route_node_get (table, (struct prefix *) p);
1933
1934 /* If same type of route are installed, treat it as a implicit
1935 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001936 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001937 {
Paul Jakma6d691122006-07-27 21:49:00 +00001938 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1939 continue;
1940
hassoebf1ead2005-09-21 14:58:20 +00001941 if (rib->type != type)
1942 continue;
1943 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001944 {
1945 same = rib;
1946 break;
1947 }
hassoebf1ead2005-09-21 14:58:20 +00001948 /* Duplicate connected route comes in. */
1949 else if ((nexthop = rib->nexthop) &&
1950 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001951 nexthop->ifindex == ifindex &&
1952 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001953 {
1954 rib->refcnt++;
1955 return 0 ;
1956 }
paul718e3742002-12-13 20:15:29 +00001957 }
1958
1959 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001960 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001961 rib->type = type;
1962 rib->distance = distance;
1963 rib->flags = flags;
1964 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001965 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001966 rib->nexthop_num = 0;
1967 rib->uptime = time (NULL);
1968
1969 /* Nexthop settings. */
1970 if (gate)
1971 {
1972 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001973 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001974 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001975 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001976 }
1977 else
1978 nexthop_ifindex_add (rib, ifindex);
1979
1980 /* If this route is kernel route, set FIB flag to the route. */
1981 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1982 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1983 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1984
1985 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001986 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001987 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1988 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001989 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001990
paul718e3742002-12-13 20:15:29 +00001991 /* Free implicit route.*/
1992 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001993 {
1994 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001995 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1996 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001997 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001998 }
paul4d38fdb2005-04-28 17:35:14 +00001999
2000 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002001 return 0;
2002}
2003
Denis Ovsienkodc958242007-08-13 16:03:06 +00002004/* This function dumps the contents of a given RIB entry into
2005 * standard debug log. Calling function name and IP prefix in
2006 * question are passed as 1st and 2nd arguments.
2007 */
2008
David Lamparterf7bf4152013-10-22 17:10:21 +00002009void _rib_dump (const char * func,
2010 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002011{
David Lamparterf7bf4152013-10-22 17:10:21 +00002012 const struct prefix *p = pp.p;
Vincent Bernatfed643f2012-10-23 16:00:42 +00002013 char straddr[INET6_ADDRSTRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00002014 struct nexthop *nexthop, *tnexthop;
2015 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00002016
Vincent Bernatfed643f2012-10-23 16:00:42 +00002017 inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN);
David Lampartereed3c482015-03-03 08:51:53 +01002018 zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, (void *)rib,
2019 straddr, p->prefixlen);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002020 zlog_debug
2021 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002022 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00002023 func,
2024 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03002025 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002026 rib->type,
2027 rib->table
2028 );
2029 zlog_debug
2030 (
2031 "%s: metric == %u, distance == %u, flags == %u, status == %u",
2032 func,
2033 rib->metric,
2034 rib->distance,
2035 rib->flags,
2036 rib->status
2037 );
2038 zlog_debug
2039 (
2040 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
2041 func,
2042 rib->nexthop_num,
2043 rib->nexthop_active_num,
2044 rib->nexthop_fib_num
2045 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00002046
Christian Frankefa713d92013-07-05 15:35:37 +00002047 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2048 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00002049 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00002050 zlog_debug
2051 (
2052 "%s: %s %s with flags %s%s%s",
2053 func,
2054 (recursing ? " NH" : "NH"),
2055 straddr,
2056 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
2057 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
2058 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
2059 );
2060 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00002061 zlog_debug ("%s: dump complete", func);
2062}
2063
2064/* This is an exported helper to rtm_read() to dump the strange
2065 * RIB entry found by rib_lookup_ipv4_route()
2066 */
2067
2068void rib_lookup_and_dump (struct prefix_ipv4 * p)
2069{
2070 struct route_table *table;
2071 struct route_node *rn;
2072 struct rib *rib;
2073 char prefix_buf[INET_ADDRSTRLEN];
2074
2075 /* Lookup table. */
2076 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2077 if (! table)
2078 {
2079 zlog_err ("%s: vrf_table() returned NULL", __func__);
2080 return;
2081 }
2082
2083 inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
2084 /* Scan the RIB table for exactly matching RIB entry. */
2085 rn = route_node_lookup (table, (struct prefix *) p);
2086
2087 /* No route for this prefix. */
2088 if (! rn)
2089 {
2090 zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
2091 return;
2092 }
2093
2094 /* Unlock node. */
2095 route_unlock_node (rn);
2096
2097 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002098 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002099 {
2100 zlog_debug
2101 (
2102 "%s: rn %p, rib %p: %s, %s",
2103 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01002104 (void *)rn,
2105 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002106 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2107 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2108 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002109 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002110 }
2111}
2112
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002113/* Check if requested address assignment will fail due to another
2114 * route being installed by zebra in FIB already. Take necessary
2115 * actions, if needed: remove such a route from FIB and deSELECT
2116 * corresponding RIB entry. Then put affected RN into RIBQ head.
2117 */
2118void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2119{
2120 struct route_table *table;
2121 struct route_node *rn;
2122 struct rib *rib;
2123 unsigned changed = 0;
2124
2125 if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
2126 {
2127 zlog_err ("%s: vrf_table() returned NULL", __func__);
2128 return;
2129 }
2130
2131 /* No matches would be the simplest case. */
2132 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2133 return;
2134
2135 /* Unlock node. */
2136 route_unlock_node (rn);
2137
2138 /* Check all RIB entries. In case any changes have to be done, requeue
2139 * the RN into RIBQ head. If the routing message about the new connected
2140 * route (generated by the IP address we are going to assign very soon)
2141 * comes before the RIBQ is processed, the new RIB entry will join
2142 * RIBQ record already on head. This is necessary for proper revalidation
2143 * of the rest of the RIB.
2144 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002145 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002146 {
2147 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2148 ! RIB_SYSTEM_ROUTE (rib))
2149 {
2150 changed = 1;
2151 if (IS_ZEBRA_DEBUG_RIB)
2152 {
2153 char buf[INET_ADDRSTRLEN];
2154 inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
2155 zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
David Lamparterf7bf4152013-10-22 17:10:21 +00002156 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002157 }
2158 rib_uninstall (rn, rib);
2159 }
2160 }
2161 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002162 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002163}
2164
paul718e3742002-12-13 20:15:29 +00002165int
G.Balajicddf3912011-11-26 21:59:32 +04002166rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002167{
2168 struct route_table *table;
2169 struct route_node *rn;
2170 struct rib *same;
2171 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002172
paul718e3742002-12-13 20:15:29 +00002173 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002174 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002175 if (! table)
2176 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002177
paul718e3742002-12-13 20:15:29 +00002178 /* Make it sure prefixlen is applied to the prefix. */
2179 apply_mask_ipv4 (p);
2180
2181 /* Set default distance by route type. */
2182 if (rib->distance == 0)
2183 {
2184 rib->distance = route_info[rib->type].distance;
2185
2186 /* iBGP distance is 200. */
2187 if (rib->type == ZEBRA_ROUTE_BGP
2188 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2189 rib->distance = 200;
2190 }
2191
2192 /* Lookup route node.*/
2193 rn = route_node_get (table, (struct prefix *) p);
2194
2195 /* If same type of route are installed, treat it as a implicit
2196 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002197 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002198 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002199 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002200 continue;
2201
paul718e3742002-12-13 20:15:29 +00002202 if (same->type == rib->type && same->table == rib->table
2203 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002204 break;
paul718e3742002-12-13 20:15:29 +00002205 }
paul4d38fdb2005-04-28 17:35:14 +00002206
paul718e3742002-12-13 20:15:29 +00002207 /* If this route is kernel route, set FIB flag to the route. */
2208 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2209 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2210 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2211
2212 /* Link new rib to node.*/
2213 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002214 if (IS_ZEBRA_DEBUG_RIB)
2215 {
2216 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002217 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002218 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002219 }
paul718e3742002-12-13 20:15:29 +00002220
paul718e3742002-12-13 20:15:29 +00002221 /* Free implicit route.*/
2222 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002223 {
2224 if (IS_ZEBRA_DEBUG_RIB)
2225 {
2226 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002227 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002228 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002229 }
paul4d38fdb2005-04-28 17:35:14 +00002230 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002231 }
paul4d38fdb2005-04-28 17:35:14 +00002232
2233 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002234 return 0;
2235}
2236
hassoebf1ead2005-09-21 14:58:20 +00002237/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002238int
2239rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002240 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002241{
2242 struct route_table *table;
2243 struct route_node *rn;
2244 struct rib *rib;
2245 struct rib *fib = NULL;
2246 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002247 struct nexthop *nexthop, *tnexthop;
2248 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002249 char buf1[INET_ADDRSTRLEN];
2250 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002251
2252 /* Lookup table. */
G.Balajicddf3912011-11-26 21:59:32 +04002253 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002254 if (! table)
2255 return 0;
2256
2257 /* Apply mask. */
2258 apply_mask_ipv4 (p);
2259
Christian Frankeb52aef12013-11-27 17:06:15 +00002260 if (IS_ZEBRA_DEBUG_KERNEL)
2261 {
2262 if (gate)
2263 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
2264 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2265 p->prefixlen,
2266 inet_ntoa (*gate),
2267 ifindex);
2268 else
2269 zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d",
2270 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
2271 p->prefixlen,
2272 ifindex);
2273 }
paul5ec90d22003-06-19 01:41:37 +00002274
paul718e3742002-12-13 20:15:29 +00002275 /* Lookup route node. */
2276 rn = route_node_lookup (table, (struct prefix *) p);
2277 if (! rn)
2278 {
2279 if (IS_ZEBRA_DEBUG_KERNEL)
2280 {
2281 if (gate)
ajsb6178002004-12-07 21:12:56 +00002282 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002283 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002284 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002285 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002286 ifindex);
2287 else
ajsb6178002004-12-07 21:12:56 +00002288 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002289 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002290 p->prefixlen,
2291 ifindex);
2292 }
2293 return ZEBRA_ERR_RTNOEXIST;
2294 }
2295
2296 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002297 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002298 {
Paul Jakma6d691122006-07-27 21:49:00 +00002299 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2300 continue;
2301
paul718e3742002-12-13 20:15:29 +00002302 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2303 fib = rib;
2304
hassoebf1ead2005-09-21 14:58:20 +00002305 if (rib->type != type)
2306 continue;
2307 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002308 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002309 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002310 if (nexthop->ifindex != ifindex)
2311 continue;
hassoebf1ead2005-09-21 14:58:20 +00002312 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002313 {
hassoebf1ead2005-09-21 14:58:20 +00002314 rib->refcnt--;
2315 route_unlock_node (rn);
2316 route_unlock_node (rn);
2317 return 0;
paul718e3742002-12-13 20:15:29 +00002318 }
hassoebf1ead2005-09-21 14:58:20 +00002319 same = rib;
2320 break;
paul718e3742002-12-13 20:15:29 +00002321 }
hassoebf1ead2005-09-21 14:58:20 +00002322 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002323 else
paul5ec90d22003-06-19 01:41:37 +00002324 {
Christian Frankefa713d92013-07-05 15:35:37 +00002325 if (gate == NULL)
2326 {
2327 same = rib;
2328 break;
2329 }
2330 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2331 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2332 {
2333 same = rib;
2334 break;
2335 }
2336 if (same)
2337 break;
2338 }
paul718e3742002-12-13 20:15:29 +00002339 }
paul718e3742002-12-13 20:15:29 +00002340 /* If same type of route can't be found and this message is from
2341 kernel. */
2342 if (! same)
2343 {
2344 if (fib && type == ZEBRA_ROUTE_KERNEL)
2345 {
2346 /* Unset flags. */
2347 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2348 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2349
2350 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2351 }
2352 else
2353 {
2354 if (IS_ZEBRA_DEBUG_KERNEL)
2355 {
2356 if (gate)
ajsb6178002004-12-07 21:12:56 +00002357 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002358 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002359 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002360 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002361 ifindex,
2362 type);
2363 else
ajsb6178002004-12-07 21:12:56 +00002364 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002365 inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002366 p->prefixlen,
2367 ifindex,
2368 type);
2369 }
2370 route_unlock_node (rn);
2371 return ZEBRA_ERR_RTNOEXIST;
2372 }
2373 }
paul4d38fdb2005-04-28 17:35:14 +00002374
paul718e3742002-12-13 20:15:29 +00002375 if (same)
2376 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002377
paul718e3742002-12-13 20:15:29 +00002378 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002379 return 0;
2380}
David Lamparter6b0655a2014-06-04 06:53:35 +02002381
paul718e3742002-12-13 20:15:29 +00002382/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002383static void
Everton Marques33d86db2014-07-14 11:19:00 -03002384static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002385{
2386 struct rib *rib;
2387 struct route_node *rn;
2388 struct route_table *table;
2389
2390 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002391 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002392 if (! table)
2393 return;
2394
2395 /* Lookup existing route */
2396 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002397 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002398 {
2399 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2400 continue;
2401
2402 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2403 break;
2404 }
paul718e3742002-12-13 20:15:29 +00002405
2406 if (rib)
2407 {
2408 /* Same distance static route is there. Update it with new
2409 nexthop. */
paul718e3742002-12-13 20:15:29 +00002410 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002411 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002412 {
2413 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002414 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002415 break;
2416 case STATIC_IPV4_IFNAME:
2417 nexthop_ifname_add (rib, si->gate.ifname);
2418 break;
2419 case STATIC_IPV4_BLACKHOLE:
2420 nexthop_blackhole_add (rib);
2421 break;
paul4d38fdb2005-04-28 17:35:14 +00002422 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002423 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002424 }
2425 else
2426 {
2427 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002428 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2429
paul718e3742002-12-13 20:15:29 +00002430 rib->type = ZEBRA_ROUTE_STATIC;
2431 rib->distance = si->distance;
2432 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002433 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002434 rib->nexthop_num = 0;
2435
2436 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002437 {
2438 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002439 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002440 break;
2441 case STATIC_IPV4_IFNAME:
2442 nexthop_ifname_add (rib, si->gate.ifname);
2443 break;
2444 case STATIC_IPV4_BLACKHOLE:
2445 nexthop_blackhole_add (rib);
2446 break;
2447 }
paul718e3742002-12-13 20:15:29 +00002448
hasso81dfcaa2003-05-25 19:21:25 +00002449 /* Save the flags of this static routes (reject, blackhole) */
2450 rib->flags = si->flags;
2451
paul718e3742002-12-13 20:15:29 +00002452 /* Link this rib to the tree. */
2453 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002454 }
2455}
2456
paula1ac18c2005-06-28 17:17:12 +00002457static int
paul718e3742002-12-13 20:15:29 +00002458static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2459{
2460 if (nexthop->type == NEXTHOP_TYPE_IPV4
2461 && si->type == STATIC_IPV4_GATEWAY
2462 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2463 return 1;
2464 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2465 && si->type == STATIC_IPV4_IFNAME
2466 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2467 return 1;
paul595db7f2003-05-25 21:35:06 +00002468 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2469 && si->type == STATIC_IPV4_BLACKHOLE)
2470 return 1;
paule8e19462006-01-19 20:16:55 +00002471 return 0;
paul718e3742002-12-13 20:15:29 +00002472}
2473
2474/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002475static void
Everton Marques33d86db2014-07-14 11:19:00 -03002476static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002477{
2478 struct route_node *rn;
2479 struct rib *rib;
2480 struct nexthop *nexthop;
2481 struct route_table *table;
2482
2483 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002484 table = vrf_table (AFI_IP, safi, 0);
paul718e3742002-12-13 20:15:29 +00002485 if (! table)
2486 return;
paul4d38fdb2005-04-28 17:35:14 +00002487
paul718e3742002-12-13 20:15:29 +00002488 /* Lookup existing route with type and distance. */
2489 rn = route_node_lookup (table, p);
2490 if (! rn)
2491 return;
2492
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002493 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002494 {
2495 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2496 continue;
2497
2498 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2499 break;
2500 }
paul718e3742002-12-13 20:15:29 +00002501
2502 if (! rib)
2503 {
2504 route_unlock_node (rn);
2505 return;
2506 }
2507
2508 /* Lookup nexthop. */
2509 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2510 if (static_ipv4_nexthop_same (nexthop, si))
2511 break;
2512
2513 /* Can't find nexthop. */
2514 if (! nexthop)
2515 {
2516 route_unlock_node (rn);
2517 return;
2518 }
2519
2520 /* Check nexthop. */
2521 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002522 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002523 else
2524 {
paul6baeb982003-10-28 03:47:15 +00002525 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2526 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002527 nexthop_delete (rib, nexthop);
2528 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002529 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002530 }
paul718e3742002-12-13 20:15:29 +00002531 /* Unlock node. */
2532 route_unlock_node (rn);
2533}
2534
paul718e3742002-12-13 20:15:29 +00002535int
Everton Marques33d86db2014-07-14 11:19:00 -03002536static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2537 const char *ifname, u_char flags, u_char distance,
2538 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002539{
2540 u_char type = 0;
2541 struct route_node *rn;
2542 struct static_ipv4 *si;
2543 struct static_ipv4 *pp;
2544 struct static_ipv4 *cp;
2545 struct static_ipv4 *update = NULL;
2546 struct route_table *stable;
2547
2548 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002549 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002550 if (! stable)
2551 return -1;
2552
2553 /* Lookup static route prefix. */
2554 rn = route_node_get (stable, p);
2555
2556 /* Make flags. */
2557 if (gate)
2558 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002559 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002560 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002561 else
2562 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002563
2564 /* Do nothing if there is a same static route. */
2565 for (si = rn->info; si; si = si->next)
2566 {
2567 if (type == si->type
2568 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2569 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2570 {
2571 if (distance == si->distance)
2572 {
2573 route_unlock_node (rn);
2574 return 0;
2575 }
2576 else
2577 update = si;
2578 }
2579 }
2580
Paul Jakma3c0755d2006-12-08 00:53:14 +00002581 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002582 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002583 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002584
2585 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002586 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002587
2588 si->type = type;
2589 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002590 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002591
2592 if (gate)
2593 si->gate.ipv4 = *gate;
2594 if (ifname)
2595 si->gate.ifname = XSTRDUP (0, ifname);
2596
2597 /* Add new static route information to the tree with sort by
2598 distance value and gateway address. */
2599 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2600 {
2601 if (si->distance < cp->distance)
2602 break;
2603 if (si->distance > cp->distance)
2604 continue;
2605 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2606 {
2607 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2608 break;
2609 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2610 continue;
2611 }
2612 }
2613
2614 /* Make linked list. */
2615 if (pp)
2616 pp->next = si;
2617 else
2618 rn->info = si;
2619 if (cp)
2620 cp->prev = si;
2621 si->prev = pp;
2622 si->next = cp;
2623
2624 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002625 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002626
2627 return 1;
2628}
2629
paul718e3742002-12-13 20:15:29 +00002630int
Everton Marques33d86db2014-07-14 11:19:00 -03002631static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2632 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002633{
2634 u_char type = 0;
2635 struct route_node *rn;
2636 struct static_ipv4 *si;
2637 struct route_table *stable;
2638
2639 /* Lookup table. */
Everton Marques33d86db2014-07-14 11:19:00 -03002640 stable = vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002641 if (! stable)
2642 return -1;
2643
2644 /* Lookup static route prefix. */
2645 rn = route_node_lookup (stable, p);
2646 if (! rn)
2647 return 0;
2648
2649 /* Make flags. */
2650 if (gate)
2651 type = STATIC_IPV4_GATEWAY;
2652 else if (ifname)
2653 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002654 else
2655 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002656
2657 /* Find same static route is the tree */
2658 for (si = rn->info; si; si = si->next)
2659 if (type == si->type
2660 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2661 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2662 break;
2663
2664 /* Can't find static route. */
2665 if (! si)
2666 {
2667 route_unlock_node (rn);
2668 return 0;
2669 }
2670
2671 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002672 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002673
2674 /* Unlink static route from linked list. */
2675 if (si->prev)
2676 si->prev->next = si->next;
2677 else
2678 rn->info = si->next;
2679 if (si->next)
2680 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002681 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002682
2683 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002684 if (ifname)
2685 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002686 XFREE (MTYPE_STATIC_IPV4, si);
2687
paul143a3852003-09-29 20:06:13 +00002688 route_unlock_node (rn);
2689
paul718e3742002-12-13 20:15:29 +00002690 return 1;
2691}
2692
paul718e3742002-12-13 20:15:29 +00002693#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00002694int
2695rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002696 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002697 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002698{
2699 struct rib *rib;
2700 struct rib *same = NULL;
2701 struct route_table *table;
2702 struct route_node *rn;
2703 struct nexthop *nexthop;
2704
paul718e3742002-12-13 20:15:29 +00002705 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002706 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002707 if (! table)
2708 return 0;
2709
2710 /* Make sure mask is applied. */
2711 apply_mask_ipv6 (p);
2712
2713 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002714 if (!distance)
2715 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002716
2717 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2718 distance = 200;
2719
paul718e3742002-12-13 20:15:29 +00002720 /* Lookup route node.*/
2721 rn = route_node_get (table, (struct prefix *) p);
2722
2723 /* If same type of route are installed, treat it as a implicit
2724 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002725 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002726 {
Paul Jakma6d691122006-07-27 21:49:00 +00002727 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2728 continue;
2729
hassoebf1ead2005-09-21 14:58:20 +00002730 if (rib->type != type)
2731 continue;
2732 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002733 {
2734 same = rib;
paul718e3742002-12-13 20:15:29 +00002735 break;
2736 }
hassoebf1ead2005-09-21 14:58:20 +00002737 else if ((nexthop = rib->nexthop) &&
2738 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2739 nexthop->ifindex == ifindex)
2740 {
2741 rib->refcnt++;
2742 return 0;
2743 }
paul718e3742002-12-13 20:15:29 +00002744 }
2745
2746 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002747 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2748
paul718e3742002-12-13 20:15:29 +00002749 rib->type = type;
2750 rib->distance = distance;
2751 rib->flags = flags;
2752 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002753 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002754 rib->nexthop_num = 0;
2755 rib->uptime = time (NULL);
2756
2757 /* Nexthop settings. */
2758 if (gate)
2759 {
2760 if (ifindex)
2761 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2762 else
2763 nexthop_ipv6_add (rib, gate);
2764 }
2765 else
2766 nexthop_ifindex_add (rib, ifindex);
2767
2768 /* If this route is kernel route, set FIB flag to the route. */
2769 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2770 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2771 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2772
2773 /* Link new rib to node.*/
2774 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002775 if (IS_ZEBRA_DEBUG_RIB)
2776 {
2777 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002778 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002779 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002780 }
paul718e3742002-12-13 20:15:29 +00002781
paul718e3742002-12-13 20:15:29 +00002782 /* Free implicit route.*/
2783 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002784 {
2785 if (IS_ZEBRA_DEBUG_RIB)
2786 {
2787 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002788 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002789 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002790 }
paul4d38fdb2005-04-28 17:35:14 +00002791 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002792 }
paul4d38fdb2005-04-28 17:35:14 +00002793
2794 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002795 return 0;
2796}
2797
hassoebf1ead2005-09-21 14:58:20 +00002798/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002799int
2800rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002801 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002802{
2803 struct route_table *table;
2804 struct route_node *rn;
2805 struct rib *rib;
2806 struct rib *fib = NULL;
2807 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002808 struct nexthop *nexthop, *tnexthop;
2809 int recursing;
Stephen Hemminger81cce012009-04-28 14:28:00 -07002810 char buf1[INET6_ADDRSTRLEN];
2811 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002812
2813 /* Apply mask. */
2814 apply_mask_ipv6 (p);
2815
2816 /* Lookup table. */
G.Balajif768f362011-11-26 22:10:39 +04002817 table = vrf_table (AFI_IP6, safi, 0);
paul718e3742002-12-13 20:15:29 +00002818 if (! table)
2819 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002820
paul718e3742002-12-13 20:15:29 +00002821 /* Lookup route node. */
2822 rn = route_node_lookup (table, (struct prefix *) p);
2823 if (! rn)
2824 {
2825 if (IS_ZEBRA_DEBUG_KERNEL)
2826 {
2827 if (gate)
ajsb6178002004-12-07 21:12:56 +00002828 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002829 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002830 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002831 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002832 ifindex);
2833 else
ajsb6178002004-12-07 21:12:56 +00002834 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002835 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002836 p->prefixlen,
2837 ifindex);
2838 }
2839 return ZEBRA_ERR_RTNOEXIST;
2840 }
2841
2842 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002843 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002844 {
Paul Jakma6d691122006-07-27 21:49:00 +00002845 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2846 continue;
2847
paul718e3742002-12-13 20:15:29 +00002848 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2849 fib = rib;
2850
hassoebf1ead2005-09-21 14:58:20 +00002851 if (rib->type != type)
2852 continue;
2853 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002854 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002855 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002856 if (nexthop->ifindex != ifindex)
2857 continue;
hassoebf1ead2005-09-21 14:58:20 +00002858 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002859 {
hassoebf1ead2005-09-21 14:58:20 +00002860 rib->refcnt--;
2861 route_unlock_node (rn);
2862 route_unlock_node (rn);
2863 return 0;
paul718e3742002-12-13 20:15:29 +00002864 }
hassoebf1ead2005-09-21 14:58:20 +00002865 same = rib;
2866 break;
paul718e3742002-12-13 20:15:29 +00002867 }
hassoebf1ead2005-09-21 14:58:20 +00002868 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002869 else
2870 {
2871 if (gate == NULL)
2872 {
2873 same = rib;
2874 break;
2875 }
2876 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2877 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2878 {
2879 same = rib;
2880 break;
2881 }
2882 if (same)
2883 break;
2884 }
paul718e3742002-12-13 20:15:29 +00002885 }
2886
2887 /* If same type of route can't be found and this message is from
2888 kernel. */
2889 if (! same)
2890 {
2891 if (fib && type == ZEBRA_ROUTE_KERNEL)
2892 {
2893 /* Unset flags. */
2894 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2895 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2896
2897 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2898 }
2899 else
2900 {
2901 if (IS_ZEBRA_DEBUG_KERNEL)
2902 {
2903 if (gate)
ajsb6178002004-12-07 21:12:56 +00002904 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002905 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002906 p->prefixlen,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002907 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002908 ifindex,
2909 type);
2910 else
ajsb6178002004-12-07 21:12:56 +00002911 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
Stephen Hemminger81cce012009-04-28 14:28:00 -07002912 inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002913 p->prefixlen,
2914 ifindex,
2915 type);
2916 }
2917 route_unlock_node (rn);
2918 return ZEBRA_ERR_RTNOEXIST;
2919 }
2920 }
2921
2922 if (same)
2923 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002924
paul718e3742002-12-13 20:15:29 +00002925 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002926 return 0;
2927}
David Lamparter6b0655a2014-06-04 06:53:35 +02002928
paul718e3742002-12-13 20:15:29 +00002929/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002930static void
paul718e3742002-12-13 20:15:29 +00002931static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2932{
2933 struct rib *rib;
2934 struct route_table *table;
2935 struct route_node *rn;
2936
2937 /* Lookup table. */
2938 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2939 if (! table)
2940 return;
2941
2942 /* Lookup existing route */
2943 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002944 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002945 {
2946 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2947 continue;
2948
2949 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2950 break;
2951 }
paul718e3742002-12-13 20:15:29 +00002952
2953 if (rib)
2954 {
2955 /* Same distance static route is there. Update it with new
2956 nexthop. */
paul718e3742002-12-13 20:15:29 +00002957 route_unlock_node (rn);
2958
2959 switch (si->type)
2960 {
2961 case STATIC_IPV6_GATEWAY:
2962 nexthop_ipv6_add (rib, &si->ipv6);
2963 break;
2964 case STATIC_IPV6_IFNAME:
2965 nexthop_ifname_add (rib, si->ifname);
2966 break;
2967 case STATIC_IPV6_GATEWAY_IFNAME:
2968 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2969 break;
2970 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002971 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002972 }
2973 else
2974 {
2975 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002976 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2977
paul718e3742002-12-13 20:15:29 +00002978 rib->type = ZEBRA_ROUTE_STATIC;
2979 rib->distance = si->distance;
2980 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002981 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002982 rib->nexthop_num = 0;
2983
2984 switch (si->type)
2985 {
2986 case STATIC_IPV6_GATEWAY:
2987 nexthop_ipv6_add (rib, &si->ipv6);
2988 break;
2989 case STATIC_IPV6_IFNAME:
2990 nexthop_ifname_add (rib, si->ifname);
2991 break;
2992 case STATIC_IPV6_GATEWAY_IFNAME:
2993 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2994 break;
2995 }
2996
hasso81dfcaa2003-05-25 19:21:25 +00002997 /* Save the flags of this static routes (reject, blackhole) */
2998 rib->flags = si->flags;
2999
paul718e3742002-12-13 20:15:29 +00003000 /* Link this rib to the tree. */
3001 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003002 }
3003}
3004
paula1ac18c2005-06-28 17:17:12 +00003005static int
paul718e3742002-12-13 20:15:29 +00003006static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
3007{
3008 if (nexthop->type == NEXTHOP_TYPE_IPV6
3009 && si->type == STATIC_IPV6_GATEWAY
3010 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
3011 return 1;
3012 if (nexthop->type == NEXTHOP_TYPE_IFNAME
3013 && si->type == STATIC_IPV6_IFNAME
3014 && strcmp (nexthop->ifname, si->ifname) == 0)
3015 return 1;
3016 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
3017 && si->type == STATIC_IPV6_GATEWAY_IFNAME
3018 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
3019 && strcmp (nexthop->ifname, si->ifname) == 0)
3020 return 1;
paule8e19462006-01-19 20:16:55 +00003021 return 0;
paul718e3742002-12-13 20:15:29 +00003022}
3023
paula1ac18c2005-06-28 17:17:12 +00003024static void
paul718e3742002-12-13 20:15:29 +00003025static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
3026{
3027 struct route_table *table;
3028 struct route_node *rn;
3029 struct rib *rib;
3030 struct nexthop *nexthop;
3031
3032 /* Lookup table. */
3033 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3034 if (! table)
3035 return;
3036
3037 /* Lookup existing route with type and distance. */
3038 rn = route_node_lookup (table, (struct prefix *) p);
3039 if (! rn)
3040 return;
3041
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003042 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003043 {
3044 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3045 continue;
3046
3047 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
3048 break;
3049 }
3050
paul718e3742002-12-13 20:15:29 +00003051 if (! rib)
3052 {
3053 route_unlock_node (rn);
3054 return;
3055 }
3056
3057 /* Lookup nexthop. */
3058 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
3059 if (static_ipv6_nexthop_same (nexthop, si))
3060 break;
3061
3062 /* Can't find nexthop. */
3063 if (! nexthop)
3064 {
3065 route_unlock_node (rn);
3066 return;
3067 }
3068
3069 /* Check nexthop. */
3070 if (rib->nexthop_num == 1)
3071 {
3072 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003073 }
3074 else
3075 {
paul6baeb982003-10-28 03:47:15 +00003076 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
3077 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00003078 nexthop_delete (rib, nexthop);
3079 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00003080 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003081 }
paul718e3742002-12-13 20:15:29 +00003082 /* Unlock node. */
3083 route_unlock_node (rn);
3084}
3085
3086/* Add static route into static route configuration. */
3087int
3088static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003089 const char *ifname, u_char flags, u_char distance,
3090 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003091{
3092 struct route_node *rn;
3093 struct static_ipv6 *si;
3094 struct static_ipv6 *pp;
3095 struct static_ipv6 *cp;
3096 struct route_table *stable;
3097
3098 /* Lookup table. */
3099 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3100 if (! stable)
3101 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003102
3103 if (!gate &&
3104 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3105 return -1;
3106
3107 if (!ifname &&
3108 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3109 return -1;
paul718e3742002-12-13 20:15:29 +00003110
3111 /* Lookup static route prefix. */
3112 rn = route_node_get (stable, p);
3113
3114 /* Do nothing if there is a same static route. */
3115 for (si = rn->info; si; si = si->next)
3116 {
3117 if (distance == si->distance
3118 && type == si->type
3119 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3120 && (! ifname || strcmp (ifname, si->ifname) == 0))
3121 {
3122 route_unlock_node (rn);
3123 return 0;
3124 }
3125 }
3126
3127 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003128 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003129
3130 si->type = type;
3131 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003132 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003133
3134 switch (type)
3135 {
3136 case STATIC_IPV6_GATEWAY:
3137 si->ipv6 = *gate;
3138 break;
3139 case STATIC_IPV6_IFNAME:
3140 si->ifname = XSTRDUP (0, ifname);
3141 break;
3142 case STATIC_IPV6_GATEWAY_IFNAME:
3143 si->ipv6 = *gate;
3144 si->ifname = XSTRDUP (0, ifname);
3145 break;
3146 }
3147
3148 /* Add new static route information to the tree with sort by
3149 distance value and gateway address. */
3150 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3151 {
3152 if (si->distance < cp->distance)
3153 break;
3154 if (si->distance > cp->distance)
3155 continue;
3156 }
3157
3158 /* Make linked list. */
3159 if (pp)
3160 pp->next = si;
3161 else
3162 rn->info = si;
3163 if (cp)
3164 cp->prev = si;
3165 si->prev = pp;
3166 si->next = cp;
3167
3168 /* Install into rib. */
3169 static_install_ipv6 (p, si);
3170
3171 return 1;
3172}
3173
3174/* Delete static route from static route configuration. */
3175int
3176static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003177 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003178{
3179 struct route_node *rn;
3180 struct static_ipv6 *si;
3181 struct route_table *stable;
3182
3183 /* Lookup table. */
3184 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
3185 if (! stable)
3186 return -1;
3187
3188 /* Lookup static route prefix. */
3189 rn = route_node_lookup (stable, p);
3190 if (! rn)
3191 return 0;
3192
3193 /* Find same static route is the tree */
3194 for (si = rn->info; si; si = si->next)
3195 if (distance == si->distance
3196 && type == si->type
3197 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3198 && (! ifname || strcmp (ifname, si->ifname) == 0))
3199 break;
3200
3201 /* Can't find static route. */
3202 if (! si)
3203 {
3204 route_unlock_node (rn);
3205 return 0;
3206 }
3207
3208 /* Install into rib. */
3209 static_uninstall_ipv6 (p, si);
3210
3211 /* Unlink static route from linked list. */
3212 if (si->prev)
3213 si->prev->next = si->next;
3214 else
3215 rn->info = si->next;
3216 if (si->next)
3217 si->next->prev = si->prev;
3218
3219 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003220 if (ifname)
3221 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003222 XFREE (MTYPE_STATIC_IPV6, si);
3223
3224 return 1;
3225}
3226#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003227
paul718e3742002-12-13 20:15:29 +00003228/* RIB update function. */
3229void
paula1ac18c2005-06-28 17:17:12 +00003230rib_update (void)
paul718e3742002-12-13 20:15:29 +00003231{
3232 struct route_node *rn;
3233 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003234
paul718e3742002-12-13 20:15:29 +00003235 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
3236 if (table)
3237 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003238 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003239 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003240
3241 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
3242 if (table)
3243 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003244 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003245 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003246}
3247
David Lamparter6b0655a2014-06-04 06:53:35 +02003248
paul718e3742002-12-13 20:15:29 +00003249/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003250static void
paul718e3742002-12-13 20:15:29 +00003251rib_weed_table (struct route_table *table)
3252{
3253 struct route_node *rn;
3254 struct rib *rib;
3255 struct rib *next;
3256
3257 if (table)
3258 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003259 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003260 {
Paul Jakma6d691122006-07-27 21:49:00 +00003261 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3262 continue;
3263
paulb21b19c2003-06-15 01:28:29 +00003264 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003265 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003266 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003267 }
3268}
3269
3270/* Delete all routes from non main table. */
3271void
paula1ac18c2005-06-28 17:17:12 +00003272rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003273{
3274 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3275 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3276}
David Lamparter6b0655a2014-06-04 06:53:35 +02003277
paul718e3742002-12-13 20:15:29 +00003278/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003279static void
paul718e3742002-12-13 20:15:29 +00003280rib_sweep_table (struct route_table *table)
3281{
3282 struct route_node *rn;
3283 struct rib *rib;
3284 struct rib *next;
3285 int ret = 0;
3286
3287 if (table)
3288 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003289 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003290 {
Paul Jakma6d691122006-07-27 21:49:00 +00003291 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3292 continue;
3293
paul718e3742002-12-13 20:15:29 +00003294 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3295 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3296 {
3297 ret = rib_uninstall_kernel (rn, rib);
3298 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003299 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003300 }
3301 }
3302}
3303
3304/* Sweep all RIB tables. */
3305void
paula1ac18c2005-06-28 17:17:12 +00003306rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003307{
3308 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3309 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3310}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003311
3312/* Remove specific by protocol routes from 'table'. */
3313static unsigned long
3314rib_score_proto_table (u_char proto, struct route_table *table)
3315{
3316 struct route_node *rn;
3317 struct rib *rib;
3318 struct rib *next;
3319 unsigned long n = 0;
3320
3321 if (table)
3322 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003323 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003324 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003325 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3326 continue;
3327 if (rib->type == proto)
3328 {
3329 rib_delnode (rn, rib);
3330 n++;
3331 }
3332 }
3333
3334 return n;
3335}
3336
3337/* Remove specific by protocol routes. */
3338unsigned long
3339rib_score_proto (u_char proto)
3340{
3341 return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
3342 +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3343}
3344
paul718e3742002-12-13 20:15:29 +00003345/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003346static void
paul718e3742002-12-13 20:15:29 +00003347rib_close_table (struct route_table *table)
3348{
3349 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003350 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003351 struct rib *rib;
3352
3353 if (table)
3354 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003355 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003356 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003357 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3358 continue;
3359
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003360 if (info->safi == SAFI_UNICAST)
3361 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003362
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003363 if (! RIB_SYSTEM_ROUTE (rib))
3364 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003365 }
paul718e3742002-12-13 20:15:29 +00003366}
3367
3368/* Close all RIB tables. */
3369void
paula1ac18c2005-06-28 17:17:12 +00003370rib_close (void)
paul718e3742002-12-13 20:15:29 +00003371{
3372 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
3373 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
3374}
David Lamparter6b0655a2014-06-04 06:53:35 +02003375
paul718e3742002-12-13 20:15:29 +00003376/* Routing information base initialize. */
3377void
paula1ac18c2005-06-28 17:17:12 +00003378rib_init (void)
paul718e3742002-12-13 20:15:29 +00003379{
paul4d38fdb2005-04-28 17:35:14 +00003380 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003381 /* VRF initialization. */
3382 vrf_init ();
3383}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003384
3385/*
3386 * vrf_id_get_next
3387 *
3388 * Get the first vrf id that is greater than the given vrf id if any.
3389 *
3390 * Returns TRUE if a vrf id was found, FALSE otherwise.
3391 */
3392static inline int
3393vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
3394{
3395 while (++id < vector_active (vrf_vector))
3396 {
3397 if (vrf_lookup (id))
3398 {
3399 *next_id_p = id;
3400 return 1;
3401 }
3402 }
3403
3404 return 0;
3405}
3406
3407/*
3408 * rib_tables_iter_next
3409 *
3410 * Returns the next table in the iteration.
3411 */
3412struct route_table *
3413rib_tables_iter_next (rib_tables_iter_t *iter)
3414{
3415 struct route_table *table;
3416
3417 /*
3418 * Array that helps us go over all AFI/SAFI combinations via one
3419 * index.
3420 */
3421 static struct {
3422 afi_t afi;
3423 safi_t safi;
3424 } afi_safis[] = {
3425 { AFI_IP, SAFI_UNICAST },
3426 { AFI_IP, SAFI_MULTICAST },
3427 { AFI_IP6, SAFI_UNICAST },
3428 { AFI_IP6, SAFI_MULTICAST },
3429 };
3430
3431 table = NULL;
3432
3433 switch (iter->state)
3434 {
3435
3436 case RIB_TABLES_ITER_S_INIT:
3437 iter->vrf_id = 0;
3438 iter->afi_safi_ix = -1;
3439
3440 /* Fall through */
3441
3442 case RIB_TABLES_ITER_S_ITERATING:
3443 iter->afi_safi_ix++;
3444 while (1)
3445 {
3446
3447 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3448 {
3449 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
3450 afi_safis[iter->afi_safi_ix].safi,
3451 iter->vrf_id);
3452 if (table)
3453 break;
3454
3455 iter->afi_safi_ix++;
3456 }
3457
3458 /*
3459 * Found another table in this vrf.
3460 */
3461 if (table)
3462 break;
3463
3464 /*
3465 * Done with all tables in the current vrf, go to the next
3466 * one.
3467 */
3468 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3469 break;
3470
3471 iter->afi_safi_ix = 0;
3472 }
3473
3474 break;
3475
3476 case RIB_TABLES_ITER_S_DONE:
3477 return NULL;
3478 }
3479
3480 if (table)
3481 iter->state = RIB_TABLES_ITER_S_ITERATING;
3482 else
3483 iter->state = RIB_TABLES_ITER_S_DONE;
3484
3485 return table;
3486}