blob: 18eece81bc752ebf307814717257862280ff95bb [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"
Feng Lu41f44a22015-05-22 11:39:56 +020037#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "zebra/rib.h"
40#include "zebra/rt.h"
41#include "zebra/zserv.h"
42#include "zebra/redistribute.h"
43#include "zebra/debug.h"
Avneesh Sachdev5adc2522012-11-13 22:48:59 +000044#include "zebra/zebra_fpm.h"
paul718e3742002-12-13 20:15:29 +000045
46/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000047extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000048
Paul Jakma457eb9a2006-07-27 19:59:58 +000049/* Hold time for RIB process, should be very minimal.
50 * it is useful to able to set it otherwise for testing, hence exported
51 * as global here for test-rig code.
52 */
53int rib_process_hold_time = 10;
54
paul718e3742002-12-13 20:15:29 +000055/* Each route type's string and default distance value. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010056static const struct
paul718e3742002-12-13 20:15:29 +000057{
58 int key;
59 int distance;
Paul Jakma57345092011-12-25 17:52:09 +010060} route_info[ZEBRA_ROUTE_MAX] =
paul718e3742002-12-13 20:15:29 +000061{
Paul Jakma57345092011-12-25 17:52:09 +010062 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
63 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
64 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
65 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
66 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
67 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
68 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
69 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
70 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
71 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
72 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
David Lamparter7052f222009-08-27 00:28:28 +020073 /* no entry/default: 150 */
paul718e3742002-12-13 20:15:29 +000074};
David Lamparter6b0655a2014-06-04 06:53:35 +020075
David Lamparterbd078122015-01-06 19:53:24 +010076/* RPF lookup behaviour */
77static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
78
David Lampartereed3c482015-03-03 08:51:53 +010079static void __attribute__((format (printf, 4, 5)))
David Lamparter94813742014-04-24 20:22:53 +020080_rnode_zlog(const char *_func, struct route_node *rn, int priority,
81 const char *msgfmt, ...)
82{
Feng Lu0d0686f2015-05-22 11:40:02 +020083 char prefix[PREFIX_STRLEN], buf[256];
David Lamparter94813742014-04-24 20:22:53 +020084 char msgbuf[512];
85 va_list ap;
86
87 va_start(ap, msgfmt);
88 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
89 va_end(ap);
90
91 if (rn)
92 {
David Lamparterab2ba612015-01-22 19:02:13 +010093 rib_table_info_t *info = rn->table->info;
94
Feng Lu0d0686f2015-05-22 11:40:02 +020095 snprintf(buf, sizeof(buf), "%s%s vrf %u",
96 prefix2str(&rn->p, prefix, sizeof(prefix)),
97 info->safi == SAFI_MULTICAST ? " (MRIB)" : "",
98 info->zvrf->vrf_id);
David Lamparter94813742014-04-24 20:22:53 +020099 }
100 else
101 {
102 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
103 }
104
105 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
106}
107
108#define rnode_debug(node, ...) \
109 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
110#define rnode_info(node, ...) \
111 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
112
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000113/*
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000114 * nexthop_type_to_str
115 */
116const char *
117nexthop_type_to_str (enum nexthop_types_t nh_type)
118{
119 static const char *desc[] = {
120 "none",
121 "Directly connected",
122 "Interface route",
123 "IPv4 nexthop",
124 "IPv4 nexthop with ifindex",
125 "IPv4 nexthop with ifname",
126 "IPv6 nexthop",
127 "IPv6 nexthop with ifindex",
128 "IPv6 nexthop with ifname",
129 "Null0 nexthop",
130 };
131
132 if (nh_type >= ZEBRA_NUM_OF (desc))
133 return "<Invalid nh type>";
134
135 return desc[nh_type];
136}
137
Christian Frankefa713d92013-07-05 15:35:37 +0000138/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000139static void
Christian Frankefa713d92013-07-05 15:35:37 +0000140_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000141{
142 struct nexthop *last;
143
Christian Frankefa713d92013-07-05 15:35:37 +0000144 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000145 ;
146 if (last)
147 last->next = nexthop;
148 else
Christian Frankefa713d92013-07-05 15:35:37 +0000149 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000150 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000151}
paul718e3742002-12-13 20:15:29 +0000152
Christian Frankefa713d92013-07-05 15:35:37 +0000153/* Add nexthop to the end of a rib node's nexthop list */
154static void
155nexthop_add (struct rib *rib, struct nexthop *nexthop)
156{
157 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000158 rib->nexthop_num++;
159}
160
161/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000162static void
paul718e3742002-12-13 20:15:29 +0000163nexthop_delete (struct rib *rib, struct nexthop *nexthop)
164{
165 if (nexthop->next)
166 nexthop->next->prev = nexthop->prev;
167 if (nexthop->prev)
168 nexthop->prev->next = nexthop->next;
169 else
170 rib->nexthop = nexthop->next;
171 rib->nexthop_num--;
172}
173
Christian Frankefa713d92013-07-05 15:35:37 +0000174static void nexthops_free(struct nexthop *nexthop);
175
paul718e3742002-12-13 20:15:29 +0000176/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000177static void
paul718e3742002-12-13 20:15:29 +0000178nexthop_free (struct nexthop *nexthop)
179{
paula4b70762003-05-16 17:19:48 +0000180 if (nexthop->ifname)
181 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000182 if (nexthop->resolved)
183 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000184 XFREE (MTYPE_NEXTHOP, nexthop);
185}
186
Christian Frankefa713d92013-07-05 15:35:37 +0000187/* Frees a list of nexthops */
188static void
189nexthops_free (struct nexthop *nexthop)
190{
191 struct nexthop *nh, *next;
192
193 for (nh = nexthop; nh; nh = next)
194 {
195 next = nh->next;
196 nexthop_free (nh);
197 }
198}
199
paul718e3742002-12-13 20:15:29 +0000200struct nexthop *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000201nexthop_ifindex_add (struct rib *rib, ifindex_t ifindex)
paul718e3742002-12-13 20:15:29 +0000202{
203 struct nexthop *nexthop;
204
Stephen Hemminger393deb92008-08-18 14:13:29 -0700205 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000206 nexthop->type = NEXTHOP_TYPE_IFINDEX;
207 nexthop->ifindex = ifindex;
208
209 nexthop_add (rib, nexthop);
210
211 return nexthop;
212}
213
214struct nexthop *
215nexthop_ifname_add (struct rib *rib, char *ifname)
216{
217 struct nexthop *nexthop;
218
Stephen Hemminger393deb92008-08-18 14:13:29 -0700219 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000220 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000221 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000222
223 nexthop_add (rib, nexthop);
224
225 return nexthop;
226}
227
228struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000229nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000230{
231 struct nexthop *nexthop;
232
Stephen Hemminger393deb92008-08-18 14:13:29 -0700233 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000234 nexthop->type = NEXTHOP_TYPE_IPV4;
235 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000236 if (src)
237 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000238
239 nexthop_add (rib, nexthop);
240
241 return nexthop;
242}
243
Josh Bailey26e2ae32012-03-22 01:09:21 -0700244struct nexthop *
paul718e3742002-12-13 20:15:29 +0000245nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma9099f9b2016-01-18 10:12:10 +0000246 struct in_addr *src, ifindex_t ifindex)
paul718e3742002-12-13 20:15:29 +0000247{
248 struct nexthop *nexthop;
249
Stephen Hemminger393deb92008-08-18 14:13:29 -0700250 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000251 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
252 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000253 if (src)
254 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000255 nexthop->ifindex = ifindex;
256
257 nexthop_add (rib, nexthop);
258
259 return nexthop;
260}
261
paul718e3742002-12-13 20:15:29 +0000262struct nexthop *
263nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
264{
265 struct nexthop *nexthop;
266
Stephen Hemminger393deb92008-08-18 14:13:29 -0700267 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000268 nexthop->type = NEXTHOP_TYPE_IPV6;
269 nexthop->gate.ipv6 = *ipv6;
270
271 nexthop_add (rib, nexthop);
272
273 return nexthop;
274}
275
paula1ac18c2005-06-28 17:17:12 +0000276static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000277nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
278 char *ifname)
279{
280 struct nexthop *nexthop;
281
Stephen Hemminger393deb92008-08-18 14:13:29 -0700282 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000283 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
284 nexthop->gate.ipv6 = *ipv6;
285 nexthop->ifname = XSTRDUP (0, ifname);
286
287 nexthop_add (rib, nexthop);
288
289 return nexthop;
290}
291
paula1ac18c2005-06-28 17:17:12 +0000292static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000293nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
Paul Jakma9099f9b2016-01-18 10:12:10 +0000294 ifindex_t ifindex)
paul718e3742002-12-13 20:15:29 +0000295{
296 struct nexthop *nexthop;
297
Stephen Hemminger393deb92008-08-18 14:13:29 -0700298 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000299 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
300 nexthop->gate.ipv6 = *ipv6;
301 nexthop->ifindex = ifindex;
302
303 nexthop_add (rib, nexthop);
304
305 return nexthop;
306}
paul718e3742002-12-13 20:15:29 +0000307
paul595db7f2003-05-25 21:35:06 +0000308struct nexthop *
309nexthop_blackhole_add (struct rib *rib)
310{
311 struct nexthop *nexthop;
312
Stephen Hemminger393deb92008-08-18 14:13:29 -0700313 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000314 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
315 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
316
317 nexthop_add (rib, nexthop);
318
319 return nexthop;
320}
321
Christian Frankefa713d92013-07-05 15:35:37 +0000322/* This method checks whether a recursive nexthop has at
323 * least one resolved nexthop in the fib.
324 */
325int
326nexthop_has_fib_child(struct nexthop *nexthop)
327{
328 struct nexthop *nh;
329
330 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
331 return 0;
332
333 for (nh = nexthop->resolved; nh; nh = nh->next)
334 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
335 return 1;
336
337 return 0;
338}
339
paul718e3742002-12-13 20:15:29 +0000340/* If force flag is not set, do not modify falgs at all for uninstall
341 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000342static int
paul718e3742002-12-13 20:15:29 +0000343nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
344 struct route_node *top)
345{
346 struct prefix_ipv4 p;
347 struct route_table *table;
348 struct route_node *rn;
349 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000350 int resolved;
paul718e3742002-12-13 20:15:29 +0000351 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000352 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000353
354 if (nexthop->type == NEXTHOP_TYPE_IPV4)
355 nexthop->ifindex = 0;
356
357 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000358 {
359 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
360 nexthops_free(nexthop->resolved);
361 nexthop->resolved = NULL;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200362 rib->nexthop_mtu = 0;
Christian Frankefa713d92013-07-05 15:35:37 +0000363 }
paul718e3742002-12-13 20:15:29 +0000364
365 /* Make lookup prefix. */
366 memset (&p, 0, sizeof (struct prefix_ipv4));
367 p.family = AF_INET;
368 p.prefixlen = IPV4_MAX_PREFIXLEN;
369 p.prefix = nexthop->gate.ipv4;
370
371 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200372 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +0000373 if (! table)
374 return 0;
375
376 rn = route_node_match (table, (struct prefix *) &p);
377 while (rn)
378 {
379 route_unlock_node (rn);
380
David Warda50c1072009-12-03 15:34:39 +0300381 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000382 if (rn == top)
383 return 0;
384
385 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000386 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100387 {
388 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
389 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200390 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100391 break;
392 }
paul718e3742002-12-13 20:15:29 +0000393
394 /* If there is no selected route or matched route is EGP, go up
395 tree. */
396 if (! match
397 || match->type == ZEBRA_ROUTE_BGP)
398 {
399 do {
400 rn = rn->parent;
401 } while (rn && rn->info == NULL);
402 if (rn)
403 route_lock_node (rn);
404 }
405 else
406 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000407 /* If the longest prefix match for the nexthop yields
408 * a blackhole, mark it as inactive. */
409 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
410 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
411 return 0;
412
paul718e3742002-12-13 20:15:29 +0000413 if (match->type == ZEBRA_ROUTE_CONNECT)
414 {
415 /* Directly point connected route. */
416 newhop = match->nexthop;
417 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
418 nexthop->ifindex = newhop->ifindex;
419
420 return 1;
421 }
422 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
423 {
Christian Frankefa713d92013-07-05 15:35:37 +0000424 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000425 for (newhop = match->nexthop; newhop; newhop = newhop->next)
426 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
427 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
428 {
429 if (set)
430 {
431 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000432
433 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
434 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000435 /* If the resolving route specifies a gateway, use it */
436 if (newhop->type == NEXTHOP_TYPE_IPV4
437 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
438 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
439 {
440 resolved_hop->type = newhop->type;
441 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Timo Teräs82a66352016-01-15 17:36:30 +0200442 resolved_hop->ifindex = newhop->ifindex;
Christian Frankec3e6b592013-07-05 15:35:40 +0000443 }
Christian Frankefa713d92013-07-05 15:35:37 +0000444
Timo Teräs82a66352016-01-15 17:36:30 +0200445 /* If the resolving route is an interface route, it
446 * means the gateway we are looking up is connected
447 * to that interface. Therefore, the resolved route
448 * should have the original gateway as nexthop as it
449 * is directly connected. */
paul718e3742002-12-13 20:15:29 +0000450 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000451 || newhop->type == NEXTHOP_TYPE_IFNAME)
452 {
Christian Frankec3e6b592013-07-05 15:35:40 +0000453 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
454 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
455 resolved_hop->ifindex = newhop->ifindex;
456 }
Christian Frankefa713d92013-07-05 15:35:37 +0000457
458 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000459 }
Christian Frankefa713d92013-07-05 15:35:37 +0000460 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000461 }
Timo Teräsb11f3b52015-11-02 16:50:07 +0200462 if (resolved && set)
463 rib->nexthop_mtu = match->mtu;
Christian Frankefa713d92013-07-05 15:35:37 +0000464 return resolved;
paul718e3742002-12-13 20:15:29 +0000465 }
466 else
467 {
468 return 0;
469 }
470 }
471 }
472 return 0;
473}
474
paul718e3742002-12-13 20:15:29 +0000475/* If force flag is not set, do not modify falgs at all for uninstall
476 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000477static int
paul718e3742002-12-13 20:15:29 +0000478nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
479 struct route_node *top)
480{
481 struct prefix_ipv6 p;
482 struct route_table *table;
483 struct route_node *rn;
484 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000485 int resolved;
paul718e3742002-12-13 20:15:29 +0000486 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000487 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000488
489 if (nexthop->type == NEXTHOP_TYPE_IPV6)
490 nexthop->ifindex = 0;
491
492 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000493 {
494 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
495 nexthops_free(nexthop->resolved);
496 nexthop->resolved = NULL;
497 }
paul718e3742002-12-13 20:15:29 +0000498
499 /* Make lookup prefix. */
500 memset (&p, 0, sizeof (struct prefix_ipv6));
501 p.family = AF_INET6;
502 p.prefixlen = IPV6_MAX_PREFIXLEN;
503 p.prefix = nexthop->gate.ipv6;
504
505 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200506 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +0000507 if (! table)
508 return 0;
509
510 rn = route_node_match (table, (struct prefix *) &p);
511 while (rn)
512 {
513 route_unlock_node (rn);
514
David Warda50c1072009-12-03 15:34:39 +0300515 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000516 if (rn == top)
517 return 0;
518
519 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000520 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100521 {
522 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
523 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200524 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100525 break;
526 }
paul718e3742002-12-13 20:15:29 +0000527
528 /* If there is no selected route or matched route is EGP, go up
529 tree. */
530 if (! match
531 || match->type == ZEBRA_ROUTE_BGP)
532 {
533 do {
534 rn = rn->parent;
535 } while (rn && rn->info == NULL);
536 if (rn)
537 route_lock_node (rn);
538 }
539 else
540 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000541 /* If the longest prefix match for the nexthop yields
542 * a blackhole, mark it as inactive. */
543 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
544 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
545 return 0;
546
paul718e3742002-12-13 20:15:29 +0000547 if (match->type == ZEBRA_ROUTE_CONNECT)
548 {
549 /* Directly point connected route. */
550 newhop = match->nexthop;
551
552 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
553 nexthop->ifindex = newhop->ifindex;
554
555 return 1;
556 }
557 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
558 {
Christian Frankefa713d92013-07-05 15:35:37 +0000559 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000560 for (newhop = match->nexthop; newhop; newhop = newhop->next)
561 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
562 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
563 {
564 if (set)
565 {
566 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000567
568 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
569 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000570 /* See nexthop_active_ipv4 for a description how the
571 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000572 if (newhop->type == NEXTHOP_TYPE_IPV6
573 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
574 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000575 {
576 resolved_hop->type = newhop->type;
577 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
578
579 if (newhop->ifindex)
580 {
581 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
582 resolved_hop->ifindex = newhop->ifindex;
583 }
584 }
Christian Frankefa713d92013-07-05 15:35:37 +0000585
paul718e3742002-12-13 20:15:29 +0000586 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000587 || newhop->type == NEXTHOP_TYPE_IFNAME)
588 {
589 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
590 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
591 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
592 resolved_hop->ifindex = newhop->ifindex;
593 }
Christian Frankefa713d92013-07-05 15:35:37 +0000594
595 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000596 }
Christian Frankefa713d92013-07-05 15:35:37 +0000597 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000598 }
Christian Frankefa713d92013-07-05 15:35:37 +0000599 return resolved;
paul718e3742002-12-13 20:15:29 +0000600 }
601 else
602 {
603 return 0;
604 }
605 }
606 }
607 return 0;
608}
paul718e3742002-12-13 20:15:29 +0000609
610struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100611rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
Feng Lu0d0686f2015-05-22 11:40:02 +0200612 struct route_node **rn_out, vrf_id_t vrf_id)
Everton Marques3dea1782014-09-22 19:35:51 -0300613{
614 struct route_table *table;
615 struct route_node *rn;
616 struct rib *match;
617 struct nexthop *newhop, *tnewhop;
618 int recursing;
619
620 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200621 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
Everton Marques3dea1782014-09-22 19:35:51 -0300622 if (! table)
623 return 0;
624
625 rn = route_node_match_ipv4 (table, &addr);
626
627 while (rn)
628 {
629 route_unlock_node (rn);
630
631 /* Pick up selected route. */
632 RNODE_FOREACH_RIB (rn, match)
633 {
634 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
635 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200636 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Everton Marques3dea1782014-09-22 19:35:51 -0300637 break;
638 }
639
640 /* If there is no selected route or matched route is EGP, go up
641 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300642 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300643 {
644 do {
645 rn = rn->parent;
646 } while (rn && rn->info == NULL);
647 if (rn)
648 route_lock_node (rn);
649 }
650 else
651 {
David Lamparter24480d42015-01-22 19:09:36 +0100652 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300653 {
David Lamparter24480d42015-01-22 19:09:36 +0100654 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300655 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
656 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100657 {
658 found = 1;
659 break;
660 }
661 if (!found)
662 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300663 }
David Lamparter24480d42015-01-22 19:09:36 +0100664
665 if (rn_out)
666 *rn_out = rn;
667 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300668 }
669 }
670 return NULL;
671}
672
673struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200674rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out,
675 vrf_id_t vrf_id)
David Lamparterbd078122015-01-06 19:53:24 +0100676{
677 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
678 struct route_node *m_rn = NULL, *u_rn = NULL;
679 int skip_bgp = 0; /* bool */
680
681 switch (ipv4_multicast_mode)
682 {
683 case MCAST_MRIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200684 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out,
685 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100686 case MCAST_URIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200687 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out,
688 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100689 case MCAST_NO_CONFIG:
690 case MCAST_MIX_MRIB_FIRST:
Feng Lu0d0686f2015-05-22 11:40:02 +0200691 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
692 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100693 if (!mrib)
Feng Lu0d0686f2015-05-22 11:40:02 +0200694 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
695 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100696 break;
697 case MCAST_MIX_DISTANCE:
Feng Lu0d0686f2015-05-22 11:40:02 +0200698 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
699 vrf_id);
700 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
701 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100702 if (mrib && urib)
703 rib = urib->distance < mrib->distance ? urib : mrib;
704 else if (mrib)
705 rib = mrib;
706 else if (urib)
707 rib = urib;
708 break;
709 case MCAST_MIX_PFXLEN:
Feng Lu0d0686f2015-05-22 11:40:02 +0200710 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
711 vrf_id);
712 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
713 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100714 if (mrib && urib)
715 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
716 else if (mrib)
717 rib = mrib;
718 else if (urib)
719 rib = urib;
720 break;
721 }
722
723 if (rn_out)
724 *rn_out = (rib == mrib) ? m_rn : u_rn;
725
726 if (IS_ZEBRA_DEBUG_RIB)
727 {
728 char buf[BUFSIZ];
729 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
730
Feng Lu0d0686f2015-05-22 11:40:02 +0200731 zlog_debug("%s: %s vrf %u: found %s, using %s",
732 __func__, buf, vrf_id,
David Lamparterbd078122015-01-06 19:53:24 +0100733 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
734 urib ? "URIB" : "nothing",
735 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
736 }
737 return rib;
738}
739
740void
741multicast_mode_ipv4_set (enum multicast_mode mode)
742{
743 if (IS_ZEBRA_DEBUG_RIB)
744 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
745 ipv4_multicast_mode = mode;
746}
747
748enum multicast_mode
749multicast_mode_ipv4_get (void)
750{
751 return ipv4_multicast_mode;
752}
753
754struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200755rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000756{
757 struct route_table *table;
758 struct route_node *rn;
759 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000760 struct nexthop *nexthop, *tnexthop;
761 int recursing;
paul718e3742002-12-13 20:15:29 +0000762
763 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200764 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000765 if (! table)
766 return 0;
767
768 rn = route_node_lookup (table, (struct prefix *) p);
769
770 /* No route for this prefix. */
771 if (! rn)
772 return NULL;
773
774 /* Unlock node. */
775 route_unlock_node (rn);
776
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000777 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100778 {
779 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
780 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200781 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100782 break;
783 }
paul718e3742002-12-13 20:15:29 +0000784
785 if (! match || match->type == ZEBRA_ROUTE_BGP)
786 return NULL;
787
788 if (match->type == ZEBRA_ROUTE_CONNECT)
789 return match;
790
Christian Frankefa713d92013-07-05 15:35:37 +0000791 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000792 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
793 return match;
794
795 return NULL;
796}
797
Denis Ovsienkodc958242007-08-13 16:03:06 +0000798/*
799 * This clone function, unlike its original rib_lookup_ipv4(), checks
800 * if specified IPv4 route record (prefix/mask -> gate) exists in
801 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
802 *
803 * Return values:
804 * -1: error
805 * 0: exact match found
806 * 1: a match was found with a different gate
807 * 2: connected route found
808 * 3: no matches found
809 */
810int
Feng Lu0d0686f2015-05-22 11:40:02 +0200811rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
812 vrf_id_t vrf_id)
Denis Ovsienkodc958242007-08-13 16:03:06 +0000813{
814 struct route_table *table;
815 struct route_node *rn;
816 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000817 struct nexthop *nexthop, *tnexthop;
818 int recursing;
819 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000820
821 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200822 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000823 if (! table)
824 return ZEBRA_RIB_LOOKUP_ERROR;
825
826 /* Scan the RIB table for exactly matching RIB entry. */
827 rn = route_node_lookup (table, (struct prefix *) p);
828
829 /* No route for this prefix. */
830 if (! rn)
831 return ZEBRA_RIB_NOTFOUND;
832
833 /* Unlock node. */
834 route_unlock_node (rn);
835
836 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000837 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100838 {
839 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
840 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200841 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100842 break;
843 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000844
845 /* None such found :( */
846 if (!match)
847 return ZEBRA_RIB_NOTFOUND;
848
849 if (match->type == ZEBRA_ROUTE_CONNECT)
850 return ZEBRA_RIB_FOUND_CONNECTED;
851
852 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000853 nexthops_active = 0;
854 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000855 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000856 {
Christian Frankefa713d92013-07-05 15:35:37 +0000857 nexthops_active = 1;
858 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
859 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000860 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000861 {
862 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
863 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
864 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
865 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
866 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
867 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000868 }
Christian Frankefa713d92013-07-05 15:35:37 +0000869
870 if (nexthops_active)
871 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000872
873 return ZEBRA_RIB_NOTFOUND;
874}
875
paul718e3742002-12-13 20:15:29 +0000876struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200877rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000878{
879 struct prefix_ipv6 p;
880 struct route_table *table;
881 struct route_node *rn;
882 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000883 struct nexthop *newhop, *tnewhop;
884 int recursing;
paul718e3742002-12-13 20:15:29 +0000885
886 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200887 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000888 if (! table)
889 return 0;
890
891 memset (&p, 0, sizeof (struct prefix_ipv6));
892 p.family = AF_INET6;
893 p.prefixlen = IPV6_MAX_PREFIXLEN;
894 IPV6_ADDR_COPY (&p.prefix, addr);
895
896 rn = route_node_match (table, (struct prefix *) &p);
897
898 while (rn)
899 {
900 route_unlock_node (rn);
901
902 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000903 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100904 {
905 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
906 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200907 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100908 break;
909 }
paul718e3742002-12-13 20:15:29 +0000910
911 /* If there is no selected route or matched route is EGP, go up
912 tree. */
913 if (! match
914 || match->type == ZEBRA_ROUTE_BGP)
915 {
916 do {
917 rn = rn->parent;
918 } while (rn && rn->info == NULL);
919 if (rn)
920 route_lock_node (rn);
921 }
922 else
923 {
924 if (match->type == ZEBRA_ROUTE_CONNECT)
925 /* Directly point connected route. */
926 return match;
927 else
928 {
Christian Frankefa713d92013-07-05 15:35:37 +0000929 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000930 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
931 return match;
932 return NULL;
933 }
934 }
935 }
936 return NULL;
937}
paul718e3742002-12-13 20:15:29 +0000938
Paul Jakma7514fb72007-05-02 16:05:35 +0000939#define RIB_SYSTEM_ROUTE(R) \
940 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
941
Denis Ovsienkodc958242007-08-13 16:03:06 +0000942/* This function verifies reachability of one given nexthop, which can be
943 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
944 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
945 * nexthop->ifindex will be updated appropriately as well.
946 * An existing route map can turn (otherwise active) nexthop into inactive, but
947 * not vice versa.
948 *
949 * The return value is the final value of 'ACTIVE' flag.
950 */
951
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300952static unsigned
paul718e3742002-12-13 20:15:29 +0000953nexthop_active_check (struct route_node *rn, struct rib *rib,
954 struct nexthop *nexthop, int set)
955{
Christian Frankef3a17322013-07-05 15:35:41 +0000956 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +0000957 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000958 route_map_result_t ret = RMAP_MATCH;
959 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
960 struct route_map *rmap;
961 int family;
paul718e3742002-12-13 20:15:29 +0000962
Paul Jakma7514fb72007-05-02 16:05:35 +0000963 family = 0;
paul718e3742002-12-13 20:15:29 +0000964 switch (nexthop->type)
965 {
966 case NEXTHOP_TYPE_IFINDEX:
Feng Lu0d0686f2015-05-22 11:40:02 +0200967 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000968 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000969 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
970 else
971 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
972 break;
paul718e3742002-12-13 20:15:29 +0000973 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000974 family = AFI_IP6;
975 case NEXTHOP_TYPE_IFNAME:
Feng Lu0d0686f2015-05-22 11:40:02 +0200976 ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000977 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000978 {
979 if (set)
980 nexthop->ifindex = ifp->ifindex;
981 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
982 }
983 else
984 {
985 if (set)
986 nexthop->ifindex = 0;
987 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
988 }
989 break;
990 case NEXTHOP_TYPE_IPV4:
991 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000992 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000993 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
994 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
995 else
996 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
997 break;
paul718e3742002-12-13 20:15:29 +0000998 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000999 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001000 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1001 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1002 else
1003 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1004 break;
1005 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001006 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001007 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1008 {
Feng Lu0d0686f2015-05-22 11:40:02 +02001009 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001010 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001011 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1012 else
1013 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1014 }
1015 else
1016 {
1017 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1018 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1019 else
1020 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1021 }
1022 break;
paul595db7f2003-05-25 21:35:06 +00001023 case NEXTHOP_TYPE_BLACKHOLE:
1024 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1025 break;
paul718e3742002-12-13 20:15:29 +00001026 default:
1027 break;
1028 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001029 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1030 return 0;
1031
Christian Frankef3a17322013-07-05 15:35:41 +00001032 /* XXX: What exactly do those checks do? Do we support
1033 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001034 if (RIB_SYSTEM_ROUTE(rib) ||
1035 (family == AFI_IP && rn->p.family != AF_INET) ||
1036 (family == AFI_IP6 && rn->p.family != AF_INET6))
1037 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1038
Christian Frankef3a17322013-07-05 15:35:41 +00001039 /* The original code didn't determine the family correctly
1040 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1041 * from the rib_table_info in those cases.
1042 * Possibly it may be better to use only the rib_table_info
1043 * in every case.
1044 */
1045 if (!family)
1046 family = info->afi;
1047
Paul Jakma7514fb72007-05-02 16:05:35 +00001048 rmap = 0;
1049 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1050 proto_rm[family][rib->type])
1051 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1052 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1053 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1054 if (rmap) {
Feng Lu1885d0a2015-05-22 11:40:04 +02001055 struct nexthop_vrfid nh_vrf = {nexthop, rib->vrf_id};
1056 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, &nh_vrf);
Paul Jakma7514fb72007-05-02 16:05:35 +00001057 }
1058
1059 if (ret == RMAP_DENYMATCH)
1060 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001061 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1062}
1063
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001064/* Iterate over all nexthops of the given RIB entry and refresh their
1065 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1066 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
Timo Teräs7eb61362015-11-02 16:50:05 +02001067 * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001068 * transparently passed to nexthop_active_check().
1069 *
1070 * Return value is the new number of active nexthops.
1071 */
1072
paula1ac18c2005-06-28 17:17:12 +00001073static int
paul718e3742002-12-13 20:15:29 +00001074nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1075{
1076 struct nexthop *nexthop;
Paul Jakma9099f9b2016-01-18 10:12:10 +00001077 unsigned int prev_active, new_active;
1078 ifindex_t prev_index;
1079
paul718e3742002-12-13 20:15:29 +00001080 rib->nexthop_active_num = 0;
paul718e3742002-12-13 20:15:29 +00001081
1082 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001083 {
1084 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001085 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001086 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1087 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001088 if (prev_active != new_active ||
1089 prev_index != nexthop->ifindex)
Timo Teräs7eb61362015-11-02 16:50:05 +02001090 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001091 }
paul718e3742002-12-13 20:15:29 +00001092 return rib->nexthop_active_num;
1093}
paul6baeb982003-10-28 03:47:15 +00001094
David Lamparter6b0655a2014-06-04 06:53:35 +02001095
paul718e3742002-12-13 20:15:29 +00001096
Timo Teräs0abf6792016-01-15 17:36:29 +02001097static int
1098rib_update_kernel (struct route_node *rn, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001099{
1100 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001101 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001102 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001103 int recursing;
paul718e3742002-12-13 20:15:29 +00001104
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001105 if (info->safi != SAFI_UNICAST)
1106 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001107 if (new)
1108 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1109 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1110 if (old)
1111 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1112 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1113 return 0;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001114 }
1115
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001116 /*
1117 * Make sure we update the FPM any time we send new information to
1118 * the kernel.
1119 */
Timo Teräs0abf6792016-01-15 17:36:29 +02001120 zfpm_trigger_update (rn, "updating in kernel");
1121
1122 ret = kernel_route_rib (&rn->p, old, new);
paul718e3742002-12-13 20:15:29 +00001123
Denis Ovsienkodc958242007-08-13 16:03:06 +00001124 /* This condition is never met, if we are using rt_socket.c */
Timo Teräs0abf6792016-01-15 17:36:29 +02001125 if (ret < 0 && new)
Timo Teräs7e73eb72016-04-09 17:22:32 +03001126 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001127 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1128 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
Timo Teräs7e73eb72016-04-09 17:22:32 +03001129 }
1130 else if (old && old != new)
1131 {
1132 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1133 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1134 }
paul718e3742002-12-13 20:15:29 +00001135
1136 return ret;
1137}
1138
1139/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001140static void
paul718e3742002-12-13 20:15:29 +00001141rib_uninstall (struct route_node *rn, struct rib *rib)
1142{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001143 rib_table_info_t *info = rn->table->info;
1144
Timo Teräs325823a2016-01-15 17:36:31 +02001145 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00001146 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001147 if (info->safi == SAFI_UNICAST)
1148 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001149
paul718e3742002-12-13 20:15:29 +00001150 redistribute_delete (&rn->p, rib);
1151 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02001152 rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00001153 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1154 }
1155}
1156
Paul Jakma6d691122006-07-27 21:49:00 +00001157static void rib_unlink (struct route_node *, struct rib *);
1158
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001159/*
1160 * rib_can_delete_dest
1161 *
1162 * Returns TRUE if the given dest can be deleted from the table.
1163 */
1164static int
1165rib_can_delete_dest (rib_dest_t *dest)
1166{
1167 if (dest->routes)
1168 {
1169 return 0;
1170 }
1171
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001172 /*
1173 * Don't delete the dest if we have to update the FPM about this
1174 * prefix.
1175 */
1176 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1177 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1178 return 0;
1179
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001180 return 1;
1181}
1182
1183/*
1184 * rib_gc_dest
1185 *
1186 * Garbage collect the rib dest corresponding to the given route node
1187 * if appropriate.
1188 *
1189 * Returns TRUE if the dest was deleted, FALSE otherwise.
1190 */
1191int
1192rib_gc_dest (struct route_node *rn)
1193{
1194 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001195
1196 dest = rib_dest_from_rnode (rn);
1197 if (!dest)
1198 return 0;
1199
1200 if (!rib_can_delete_dest (dest))
1201 return 0;
1202
1203 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001204 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001205
1206 dest->rnode = NULL;
1207 XFREE (MTYPE_RIB_DEST, dest);
1208 rn->info = NULL;
1209
1210 /*
1211 * Release the one reference that we keep on the route node.
1212 */
1213 route_unlock_node (rn);
1214 return 1;
1215}
1216
Timo Teräs0abf6792016-01-15 17:36:29 +02001217/* Check if 'alternate' RIB entry is better than 'current'. */
1218static struct rib *
1219rib_choose_best (struct rib *current, struct rib *alternate)
1220{
1221 if (current == NULL)
1222 return alternate;
1223
1224 /* filter route selection in following order:
1225 * - connected beats other types
1226 * - lower distance beats higher
1227 * - lower metric beats higher for equal distance
1228 * - last, hence oldest, route wins tie break.
1229 */
1230
1231 /* Connected routes. Pick the last connected
1232 * route of the set of lowest metric connected routes.
1233 */
1234 if (alternate->type == ZEBRA_ROUTE_CONNECT)
1235 {
1236 if (current->type != ZEBRA_ROUTE_CONNECT
1237 || alternate->metric <= current->metric)
1238 return alternate;
1239
1240 return current;
1241 }
1242
1243 if (current->type == ZEBRA_ROUTE_CONNECT)
1244 return current;
1245
1246 /* higher distance loses */
1247 if (alternate->distance < current->distance)
1248 return alternate;
1249 if (current->distance < alternate->distance)
1250 return current;
1251
1252 /* metric tie-breaks equal distance */
1253 if (alternate->metric <= current->metric)
1254 return alternate;
1255
1256 return current;
1257}
1258
paul718e3742002-12-13 20:15:29 +00001259/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001260static void
1261rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001262{
1263 struct rib *rib;
1264 struct rib *next;
Timo Teräs325823a2016-01-15 17:36:31 +02001265 struct rib *old_selected = NULL;
1266 struct rib *new_selected = NULL;
Timo Teräs0abf6792016-01-15 17:36:29 +02001267 struct rib *old_fib = NULL;
1268 struct rib *new_fib = NULL;
pauld753e9e2003-01-22 19:45:50 +00001269 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001270 struct nexthop *nexthop = NULL, *tnexthop;
1271 int recursing;
Balaji95116332014-10-23 15:25:25 +00001272 rib_table_info_t *info;
1273
paul4d38fdb2005-04-28 17:35:14 +00001274 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001275
1276 info = rn->table->info;
1277
Timo Teräs0abf6792016-01-15 17:36:29 +02001278 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001279 {
Timo Teräs7e73eb72016-04-09 17:22:32 +03001280 UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
1281
paul718e3742002-12-13 20:15:29 +00001282 /* Currently installed rib. */
1283 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001284 {
Timo Teräs325823a2016-01-15 17:36:31 +02001285 assert (old_selected == NULL);
1286 old_selected = rib;
1287 }
1288 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1289 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001290 assert (old_fib == NULL);
1291 old_fib = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001292 }
Timo Teräs0abf6792016-01-15 17:36:29 +02001293
1294 /* Skip deleted entries from selection */
Paul Jakma6d691122006-07-27 21:49:00 +00001295 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
Timo Teräs0abf6792016-01-15 17:36:29 +02001296 continue;
paul4d38fdb2005-04-28 17:35:14 +00001297
paul718e3742002-12-13 20:15:29 +00001298 /* Skip unreachable nexthop. */
1299 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001300 continue;
paul718e3742002-12-13 20:15:29 +00001301
1302 /* Infinit distance. */
1303 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001304 continue;
paul718e3742002-12-13 20:15:29 +00001305
Timo Teräs325823a2016-01-15 17:36:31 +02001306 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
1307 new_fib = rib_choose_best(new_fib, rib);
1308 else
1309 new_selected = rib_choose_best(new_selected, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001310 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001311
Timo Teräs325823a2016-01-15 17:36:31 +02001312 /* If no FIB override route, use the selected route also for FIB */
1313 if (new_fib == NULL)
1314 new_fib = new_selected;
1315
Denis Ovsienkodc958242007-08-13 16:03:06 +00001316 /* After the cycle is finished, the following pointers will be set:
Timo Teräs325823a2016-01-15 17:36:31 +02001317 * old_selected --- RIB entry currently having SELECTED
1318 * new_selected --- RIB entry that is newly SELECTED
1319 * old_fib --- RIB entry currently in kernel FIB
1320 * new_fib --- RIB entry that is newly to be in kernel FIB
1321 *
1322 * new_selected will get SELECTED flag, and is going to be redistributed
1323 * the zclients. new_fib (which can be new_selected) will be installed in kernel.
Denis Ovsienkodc958242007-08-13 16:03:06 +00001324 */
1325
Timo Teräs0abf6792016-01-15 17:36:29 +02001326 /* Set real nexthops. */
1327 if (new_fib)
1328 nexthop_active_update (rn, new_fib, 1);
Timo Teräs325823a2016-01-15 17:36:31 +02001329 if (new_selected && new_selected != new_fib)
Timo Teräs7e73eb72016-04-09 17:22:32 +03001330 nexthop_active_update (rn, new_selected, 1);
Timo Teräs0abf6792016-01-15 17:36:29 +02001331
1332 /* Update kernel if FIB entry has changed */
1333 if (old_fib != new_fib
1334 || (new_fib && CHECK_FLAG (new_fib->status, RIB_ENTRY_CHANGED)))
paul718e3742002-12-13 20:15:29 +00001335 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001336 if (old_fib && old_fib != new_fib)
1337 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001338 if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
1339 rib_update_kernel (rn, old_fib, NULL);
Timo Teräs325823a2016-01-15 17:36:31 +02001340 UNSET_FLAG (old_fib->status, RIB_ENTRY_SELECTED_FIB);
Timo Teräs0abf6792016-01-15 17:36:29 +02001341 }
1342
1343 if (new_fib)
1344 {
1345 /* Install new or replace existing FIB entry */
Timo Teräs325823a2016-01-15 17:36:31 +02001346 SET_FLAG (new_fib->status, RIB_ENTRY_SELECTED_FIB);
Timo Teräs0abf6792016-01-15 17:36:29 +02001347 if (! RIB_SYSTEM_ROUTE (new_fib))
1348 rib_update_kernel (rn, old_fib, new_fib);
1349 }
1350
1351 if (info->safi == SAFI_UNICAST)
1352 zfpm_trigger_update (rn, "updating existing route");
1353 }
1354 else if (old_fib == new_fib && new_fib && ! RIB_SYSTEM_ROUTE (new_fib))
1355 {
1356 /* Housekeeping code to deal with race conditions in kernel with
1357 * linux netlink reporting interface up before IPv4 or IPv6 protocol
1358 * is ready to add routes. This makes sure routes are IN the kernel.
1359 */
1360 for (ALL_NEXTHOPS_RO(new_fib->nexthop, nexthop, tnexthop, recursing))
1361 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1362 {
1363 installed = 1;
1364 break;
1365 }
1366 if (! installed)
1367 rib_update_kernel (rn, NULL, new_fib);
1368 }
1369
Timo Teräs325823a2016-01-15 17:36:31 +02001370 /* Redistribute SELECTED entry */
1371 if (old_selected != new_selected
1372 || (new_selected && CHECK_FLAG (new_selected->status, RIB_ENTRY_CHANGED)))
1373 {
1374 if (old_selected)
1375 {
1376 if (! new_selected)
1377 redistribute_delete (&rn->p, old_selected);
1378 if (old_selected != new_selected)
1379 UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED);
1380 }
1381
1382 if (new_selected)
1383 {
1384 /* Install new or replace existing redistributed entry */
1385 SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED);
1386 redistribute_add (&rn->p, new_selected);
1387 }
1388 }
1389
Timo Teräs0abf6792016-01-15 17:36:29 +02001390 /* Remove all RIB entries queued for removal */
1391 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1392 {
1393 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
paul4d38fdb2005-04-28 17:35:14 +00001394 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001395 if (IS_ZEBRA_DEBUG_RIB)
1396 rnode_debug (rn, "rn %p, removing rib %p",
1397 (void *)rn, (void *)rib);
1398 rib_unlink (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001399 }
paul718e3742002-12-13 20:15:29 +00001400 }
1401
Paul Jakma6d691122006-07-27 21:49:00 +00001402 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001403 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001404
1405 /*
1406 * Check if the dest can be deleted now.
1407 */
1408 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001409}
1410
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001411/* Take a list of route_node structs and return 1, if there was a record
1412 * picked from it and processed by rib_process(). Don't process more,
1413 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001414 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001415static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001416process_subq (struct list * subq, u_char qindex)
1417{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001418 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001419 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001420
1421 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001422 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001423
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001424 rnode = listgetdata (lnode);
1425 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001426
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001427 if (rnode->info)
1428 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1429
Chris Caputo67b94672009-07-18 04:02:26 +00001430#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001431 else
1432 {
1433 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1434 __func__, rnode, rnode->lock);
1435 zlog_backtrace(LOG_DEBUG);
1436 }
Chris Caputo67b94672009-07-18 04:02:26 +00001437#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001438 route_unlock_node (rnode);
1439 list_delete_node (subq, lnode);
1440 return 1;
1441}
1442
1443/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1444 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1445 * is pointed to the meta queue structure.
1446 */
1447static wq_item_status
1448meta_queue_process (struct work_queue *dummy, void *data)
1449{
1450 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001451 unsigned i;
1452
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001453 for (i = 0; i < MQ_SIZE; i++)
1454 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001455 {
1456 mq->size--;
1457 break;
1458 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001459 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1460}
1461
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001462/*
1463 * Map from rib types to queue type (priority) in meta queue
1464 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001465static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1466 [ZEBRA_ROUTE_SYSTEM] = 4,
1467 [ZEBRA_ROUTE_KERNEL] = 0,
1468 [ZEBRA_ROUTE_CONNECT] = 0,
1469 [ZEBRA_ROUTE_STATIC] = 1,
1470 [ZEBRA_ROUTE_RIP] = 2,
1471 [ZEBRA_ROUTE_RIPNG] = 2,
1472 [ZEBRA_ROUTE_OSPF] = 2,
1473 [ZEBRA_ROUTE_OSPF6] = 2,
1474 [ZEBRA_ROUTE_ISIS] = 2,
1475 [ZEBRA_ROUTE_BGP] = 3,
1476 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001477 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001478};
1479
1480/* Look into the RN and queue it into one or more priority queues,
1481 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001482 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001483static void
1484rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001485{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001486 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001487
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001488 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001489 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001490 u_char qindex = meta_queue_map[rib->type];
1491
1492 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001493 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1494 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001495 {
1496 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001497 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001498 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001499 continue;
1500 }
1501
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001502 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001503 listnode_add (mq->subq[qindex], rn);
1504 route_lock_node (rn);
1505 mq->size++;
1506
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001507 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001508 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001509 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001510 }
paul4d38fdb2005-04-28 17:35:14 +00001511}
1512
Paul Jakma6d691122006-07-27 21:49:00 +00001513/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001514static void
Paul Jakma6d691122006-07-27 21:49:00 +00001515rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001516{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001517 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001518
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001519 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001520 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001521 {
1522 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001523 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001524 zlog_backtrace(LOG_DEBUG);
1525 return;
1526 }
1527
1528 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001529 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001530
1531 assert (zebra);
1532
1533 if (zebra->ribq == NULL)
1534 {
1535 zlog_err ("%s: work_queue does not exist!", __func__);
1536 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001537 }
paul4d38fdb2005-04-28 17:35:14 +00001538
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001539 /*
1540 * The RIB queue should normally be either empty or holding the only
1541 * work_queue_item element. In the latter case this element would
1542 * hold a pointer to the meta queue structure, which must be used to
1543 * actually queue the route nodes to process. So create the MQ
1544 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001545 * This semantics was introduced after 0.99.9 release.
1546 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001547 if (!zebra->ribq->items->count)
1548 work_queue_add (zebra->ribq, zebra->mq);
1549
1550 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001551
1552 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001553 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001554
1555 return;
paul4d38fdb2005-04-28 17:35:14 +00001556}
1557
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001558/* Create new meta queue.
1559 A destructor function doesn't seem to be necessary here.
1560 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001561static struct meta_queue *
1562meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001563{
1564 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001565 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001566
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001567 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1568 assert(new);
1569
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001570 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001571 {
1572 new->subq[i] = list_new ();
1573 assert(new->subq[i]);
1574 }
1575
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001576 return new;
1577}
1578
paul4d38fdb2005-04-28 17:35:14 +00001579/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001580static void
paul4d38fdb2005-04-28 17:35:14 +00001581rib_queue_init (struct zebra_t *zebra)
1582{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001583 assert (zebra);
1584
paul4d38fdb2005-04-28 17:35:14 +00001585 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001586 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001587 {
Paul Jakma6d691122006-07-27 21:49:00 +00001588 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001589 return;
1590 }
1591
1592 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001593 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001594 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001595 /* XXX: TODO: These should be runtime configurable via vty */
1596 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001597 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001598
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001599 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001600 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001601 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001602 return;
1603 }
1604 return;
paul718e3742002-12-13 20:15:29 +00001605}
1606
Paul Jakma6d691122006-07-27 21:49:00 +00001607/* RIB updates are processed via a queue of pointers to route_nodes.
1608 *
1609 * The queue length is bounded by the maximal size of the routing table,
1610 * as a route_node will not be requeued, if already queued.
1611 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001612 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05001613 * state, or static_install_route (when an existing RIB is updated)
Paul Jakma3c0755d2006-12-08 00:53:14 +00001614 * and then submit route_node to queue for best-path selection later.
1615 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001616 *
1617 * Deleted RIBs are reaped during best-path selection.
1618 *
1619 * rib_addnode
1620 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001621 * |-------->| | best RIB, if required
1622 * | |
1623 * static_install->|->rib_addqueue...... -> rib_process
1624 * | |
1625 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001626 * |-> set RIB_ENTRY_REMOVE |
1627 * rib_delnode (RIB freed)
1628 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001629 * The 'info' pointer of a route_node points to a rib_dest_t
1630 * ('dest'). Queueing state for a route_node is kept on the dest. The
1631 * dest is created on-demand by rib_link() and is kept around at least
1632 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001633 *
1634 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1635 *
1636 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001637 * - dest attached to route_node:
1638 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001639 * - route_node processing queue
1640 * - managed by: rib_addqueue, rib_process.
1641 *
1642 */
1643
paul718e3742002-12-13 20:15:29 +00001644/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001645static void
Paul Jakma6d691122006-07-27 21:49:00 +00001646rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001647{
1648 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001649 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001650
paul4d38fdb2005-04-28 17:35:14 +00001651 assert (rib && rn);
1652
Paul Jakma6d691122006-07-27 21:49:00 +00001653 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001654 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001655
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001656 dest = rib_dest_from_rnode (rn);
1657 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001658 {
1659 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001660 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001661
1662 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1663 route_lock_node (rn); /* rn route table reference */
1664 rn->info = dest;
1665 dest->rnode = rn;
1666 }
1667
1668 head = dest->routes;
1669 if (head)
1670 {
Paul Jakma6d691122006-07-27 21:49:00 +00001671 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001672 }
paul718e3742002-12-13 20:15:29 +00001673 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001674 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001675 rib_queue_add (&zebrad, rn);
1676}
1677
1678static void
1679rib_addnode (struct route_node *rn, struct rib *rib)
1680{
1681 /* RIB node has been un-removed before route-node is processed.
1682 * route_node must hence already be on the queue for processing..
1683 */
1684 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1685 {
1686 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001687 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001688
Paul Jakma6d691122006-07-27 21:49:00 +00001689 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1690 return;
1691 }
1692 rib_link (rn, rib);
1693}
1694
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001695/*
1696 * rib_unlink
1697 *
1698 * Detach a rib structure from a route_node.
1699 *
1700 * Note that a call to rib_unlink() should be followed by a call to
1701 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1702 * longer required to be deleted.
1703 */
Paul Jakma6d691122006-07-27 21:49:00 +00001704static void
1705rib_unlink (struct route_node *rn, struct rib *rib)
1706{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001707 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001708
1709 assert (rn && rib);
1710
1711 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001712 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001713
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001714 dest = rib_dest_from_rnode (rn);
1715
Paul Jakma6d691122006-07-27 21:49:00 +00001716 if (rib->next)
1717 rib->next->prev = rib->prev;
1718
1719 if (rib->prev)
1720 rib->prev->next = rib->next;
1721 else
1722 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001723 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001724 }
1725
1726 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001727 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001728 XFREE (MTYPE_RIB, rib);
1729
paul718e3742002-12-13 20:15:29 +00001730}
1731
paula1ac18c2005-06-28 17:17:12 +00001732static void
paul718e3742002-12-13 20:15:29 +00001733rib_delnode (struct route_node *rn, struct rib *rib)
1734{
Paul Jakma6d691122006-07-27 21:49:00 +00001735 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001736 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001737 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1738 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001739}
1740
1741int
1742rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001743 struct in_addr *gate, struct in_addr *src,
Paul Jakma9099f9b2016-01-18 10:12:10 +00001744 ifindex_t ifindex, vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001745 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001746{
1747 struct rib *rib;
1748 struct rib *same = NULL;
1749 struct route_table *table;
1750 struct route_node *rn;
1751 struct nexthop *nexthop;
1752
1753 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001754 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00001755 if (! table)
1756 return 0;
1757
1758 /* Make it sure prefixlen is applied to the prefix. */
1759 apply_mask_ipv4 (p);
1760
1761 /* Set default distance by route type. */
1762 if (distance == 0)
1763 {
Balaji.G837d16c2012-09-26 14:09:10 +05301764 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001765 distance = 150;
1766 else
1767 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001768
1769 /* iBGP distance is 200. */
1770 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1771 distance = 200;
1772 }
1773
1774 /* Lookup route node.*/
1775 rn = route_node_get (table, (struct prefix *) p);
1776
1777 /* If same type of route are installed, treat it as a implicit
1778 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001779 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001780 {
Paul Jakma6d691122006-07-27 21:49:00 +00001781 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1782 continue;
1783
hassoebf1ead2005-09-21 14:58:20 +00001784 if (rib->type != type)
1785 continue;
1786 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001787 {
1788 same = rib;
1789 break;
1790 }
hassoebf1ead2005-09-21 14:58:20 +00001791 /* Duplicate connected route comes in. */
1792 else if ((nexthop = rib->nexthop) &&
1793 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001794 nexthop->ifindex == ifindex &&
1795 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001796 {
1797 rib->refcnt++;
1798 return 0 ;
1799 }
paul718e3742002-12-13 20:15:29 +00001800 }
1801
1802 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001803 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001804 rib->type = type;
1805 rib->distance = distance;
1806 rib->flags = flags;
1807 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001808 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02001809 rib->vrf_id = vrf_id;
1810 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00001811 rib->nexthop_num = 0;
1812 rib->uptime = time (NULL);
1813
1814 /* Nexthop settings. */
1815 if (gate)
1816 {
1817 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001818 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001819 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001820 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001821 }
1822 else
1823 nexthop_ifindex_add (rib, ifindex);
1824
1825 /* If this route is kernel route, set FIB flag to the route. */
1826 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1827 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1828 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1829
1830 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001831 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001832 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1833 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001834 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001835
paul718e3742002-12-13 20:15:29 +00001836 /* Free implicit route.*/
1837 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001838 {
1839 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001840 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1841 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001842 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001843 }
paul4d38fdb2005-04-28 17:35:14 +00001844
1845 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001846 return 0;
1847}
1848
Denis Ovsienkodc958242007-08-13 16:03:06 +00001849/* This function dumps the contents of a given RIB entry into
1850 * standard debug log. Calling function name and IP prefix in
1851 * question are passed as 1st and 2nd arguments.
1852 */
1853
David Lamparterf7bf4152013-10-22 17:10:21 +00001854void _rib_dump (const char * func,
1855 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001856{
David Lamparterf7bf4152013-10-22 17:10:21 +00001857 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001858 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001859 struct nexthop *nexthop, *tnexthop;
1860 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001861
Feng Lu0d0686f2015-05-22 11:40:02 +02001862 zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
1863 prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001864 zlog_debug
1865 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001866 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001867 func,
1868 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001869 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001870 rib->type,
1871 rib->table
1872 );
1873 zlog_debug
1874 (
1875 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1876 func,
1877 rib->metric,
1878 rib->distance,
1879 rib->flags,
1880 rib->status
1881 );
1882 zlog_debug
1883 (
1884 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1885 func,
1886 rib->nexthop_num,
1887 rib->nexthop_active_num,
1888 rib->nexthop_fib_num
1889 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001890
Christian Frankefa713d92013-07-05 15:35:37 +00001891 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1892 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001893 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001894 zlog_debug
1895 (
1896 "%s: %s %s with flags %s%s%s",
1897 func,
1898 (recursing ? " NH" : "NH"),
1899 straddr,
1900 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1901 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1902 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1903 );
1904 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001905 zlog_debug ("%s: dump complete", func);
1906}
1907
1908/* This is an exported helper to rtm_read() to dump the strange
1909 * RIB entry found by rib_lookup_ipv4_route()
1910 */
1911
1912void rib_lookup_and_dump (struct prefix_ipv4 * p)
1913{
1914 struct route_table *table;
1915 struct route_node *rn;
1916 struct rib *rib;
1917 char prefix_buf[INET_ADDRSTRLEN];
1918
1919 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001920 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001921 if (! table)
1922 {
Feng Lu41f44a22015-05-22 11:39:56 +02001923 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001924 return;
1925 }
1926
Denis Ovsienkodc958242007-08-13 16:03:06 +00001927 /* Scan the RIB table for exactly matching RIB entry. */
1928 rn = route_node_lookup (table, (struct prefix *) p);
1929
1930 /* No route for this prefix. */
1931 if (! rn)
1932 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001933 zlog_debug ("%s: lookup failed for %s", __func__,
1934 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001935 return;
1936 }
1937
1938 /* Unlock node. */
1939 route_unlock_node (rn);
1940
1941 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001942 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001943 {
1944 zlog_debug
1945 (
1946 "%s: rn %p, rib %p: %s, %s",
1947 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01001948 (void *)rn,
1949 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001950 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1951 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1952 );
David Lamparterf7bf4152013-10-22 17:10:21 +00001953 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001954 }
1955}
1956
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001957/* Check if requested address assignment will fail due to another
1958 * route being installed by zebra in FIB already. Take necessary
1959 * actions, if needed: remove such a route from FIB and deSELECT
1960 * corresponding RIB entry. Then put affected RN into RIBQ head.
1961 */
1962void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1963{
1964 struct route_table *table;
1965 struct route_node *rn;
1966 struct rib *rib;
1967 unsigned changed = 0;
1968
Feng Lu41f44a22015-05-22 11:39:56 +02001969 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001970 {
Feng Lu41f44a22015-05-22 11:39:56 +02001971 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001972 return;
1973 }
1974
1975 /* No matches would be the simplest case. */
1976 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1977 return;
1978
1979 /* Unlock node. */
1980 route_unlock_node (rn);
1981
1982 /* Check all RIB entries. In case any changes have to be done, requeue
1983 * the RN into RIBQ head. If the routing message about the new connected
1984 * route (generated by the IP address we are going to assign very soon)
1985 * comes before the RIBQ is processed, the new RIB entry will join
1986 * RIBQ record already on head. This is necessary for proper revalidation
1987 * of the rest of the RIB.
1988 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001989 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001990 {
Timo Teräs325823a2016-01-15 17:36:31 +02001991 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB) &&
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001992 ! RIB_SYSTEM_ROUTE (rib))
1993 {
1994 changed = 1;
1995 if (IS_ZEBRA_DEBUG_RIB)
1996 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001997 char buf[PREFIX_STRLEN];
1998 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
1999 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00002000 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002001 }
2002 rib_uninstall (rn, rib);
2003 }
2004 }
2005 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002006 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002007}
2008
paul718e3742002-12-13 20:15:29 +00002009int
G.Balajicddf3912011-11-26 21:59:32 +04002010rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002011{
2012 struct route_table *table;
2013 struct route_node *rn;
2014 struct rib *same;
2015 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002016
paul718e3742002-12-13 20:15:29 +00002017 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002018 table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +00002019 if (! table)
2020 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002021
paul718e3742002-12-13 20:15:29 +00002022 /* Make it sure prefixlen is applied to the prefix. */
2023 apply_mask_ipv4 (p);
2024
2025 /* Set default distance by route type. */
2026 if (rib->distance == 0)
2027 {
2028 rib->distance = route_info[rib->type].distance;
2029
2030 /* iBGP distance is 200. */
2031 if (rib->type == ZEBRA_ROUTE_BGP
2032 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2033 rib->distance = 200;
2034 }
2035
2036 /* Lookup route node.*/
2037 rn = route_node_get (table, (struct prefix *) p);
2038
2039 /* If same type of route are installed, treat it as a implicit
2040 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002041 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002042 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002043 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002044 continue;
2045
paul718e3742002-12-13 20:15:29 +00002046 if (same->type == rib->type && same->table == rib->table
2047 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002048 break;
paul718e3742002-12-13 20:15:29 +00002049 }
paul4d38fdb2005-04-28 17:35:14 +00002050
paul718e3742002-12-13 20:15:29 +00002051 /* If this route is kernel route, set FIB flag to the route. */
2052 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2053 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2054 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2055
2056 /* Link new rib to node.*/
2057 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002058 if (IS_ZEBRA_DEBUG_RIB)
2059 {
2060 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002061 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002062 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002063 }
paul718e3742002-12-13 20:15:29 +00002064
paul718e3742002-12-13 20:15:29 +00002065 /* Free implicit route.*/
2066 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002067 {
2068 if (IS_ZEBRA_DEBUG_RIB)
2069 {
2070 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002071 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002072 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002073 }
paul4d38fdb2005-04-28 17:35:14 +00002074 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002075 }
paul4d38fdb2005-04-28 17:35:14 +00002076
2077 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002078 return 0;
2079}
2080
hassoebf1ead2005-09-21 14:58:20 +00002081/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002082int
2083rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma9099f9b2016-01-18 10:12:10 +00002084 struct in_addr *gate, ifindex_t ifindex,
2085 vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002086{
2087 struct route_table *table;
2088 struct route_node *rn;
2089 struct rib *rib;
2090 struct rib *fib = NULL;
2091 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002092 struct nexthop *nexthop, *tnexthop;
2093 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002094 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002095 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002096
2097 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002098 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002099 if (! table)
2100 return 0;
2101
2102 /* Apply mask. */
2103 apply_mask_ipv4 (p);
2104
Christian Frankeb52aef12013-11-27 17:06:15 +00002105 if (IS_ZEBRA_DEBUG_KERNEL)
2106 {
2107 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002108 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
2109 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002110 inet_ntoa (*gate),
2111 ifindex);
2112 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002113 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
2114 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002115 ifindex);
2116 }
paul5ec90d22003-06-19 01:41:37 +00002117
paul718e3742002-12-13 20:15:29 +00002118 /* Lookup route node. */
2119 rn = route_node_lookup (table, (struct prefix *) p);
2120 if (! rn)
2121 {
2122 if (IS_ZEBRA_DEBUG_KERNEL)
2123 {
2124 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002125 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2126 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002127 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002128 ifindex);
2129 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002130 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2131 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002132 ifindex);
2133 }
2134 return ZEBRA_ERR_RTNOEXIST;
2135 }
2136
2137 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002138 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002139 {
Paul Jakma6d691122006-07-27 21:49:00 +00002140 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2141 continue;
2142
Timo Teräs325823a2016-01-15 17:36:31 +02002143 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00002144 fib = rib;
2145
hassoebf1ead2005-09-21 14:58:20 +00002146 if (rib->type != type)
2147 continue;
2148 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002149 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002150 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002151 if (nexthop->ifindex != ifindex)
2152 continue;
hassoebf1ead2005-09-21 14:58:20 +00002153 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002154 {
hassoebf1ead2005-09-21 14:58:20 +00002155 rib->refcnt--;
2156 route_unlock_node (rn);
2157 route_unlock_node (rn);
2158 return 0;
paul718e3742002-12-13 20:15:29 +00002159 }
hassoebf1ead2005-09-21 14:58:20 +00002160 same = rib;
2161 break;
paul718e3742002-12-13 20:15:29 +00002162 }
hassoebf1ead2005-09-21 14:58:20 +00002163 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002164 else
paul5ec90d22003-06-19 01:41:37 +00002165 {
Christian Frankefa713d92013-07-05 15:35:37 +00002166 if (gate == NULL)
2167 {
2168 same = rib;
2169 break;
2170 }
2171 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2172 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2173 {
2174 same = rib;
2175 break;
2176 }
2177 if (same)
2178 break;
2179 }
paul718e3742002-12-13 20:15:29 +00002180 }
paul718e3742002-12-13 20:15:29 +00002181 /* If same type of route can't be found and this message is from
2182 kernel. */
2183 if (! same)
2184 {
2185 if (fib && type == ZEBRA_ROUTE_KERNEL)
2186 {
2187 /* Unset flags. */
2188 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2189 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2190
Timo Teräs325823a2016-01-15 17:36:31 +02002191 UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
paul718e3742002-12-13 20:15:29 +00002192 }
2193 else
2194 {
2195 if (IS_ZEBRA_DEBUG_KERNEL)
2196 {
2197 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002198 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2199 "doesn't exist in rib",
2200 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002201 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002202 ifindex,
2203 type);
2204 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002205 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2206 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002207 ifindex,
2208 type);
2209 }
2210 route_unlock_node (rn);
2211 return ZEBRA_ERR_RTNOEXIST;
2212 }
2213 }
paul4d38fdb2005-04-28 17:35:14 +00002214
paul718e3742002-12-13 20:15:29 +00002215 if (same)
2216 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002217
paul718e3742002-12-13 20:15:29 +00002218 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002219 return 0;
2220}
David Lamparter6b0655a2014-06-04 06:53:35 +02002221
paul718e3742002-12-13 20:15:29 +00002222/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002223static void
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002224static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002225{
2226 struct rib *rib;
2227 struct route_node *rn;
2228 struct route_table *table;
2229
2230 /* Lookup table. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002231 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002232 if (! table)
2233 return;
2234
2235 /* Lookup existing route */
2236 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002237 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002238 {
2239 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2240 continue;
2241
2242 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2243 break;
2244 }
paul718e3742002-12-13 20:15:29 +00002245
2246 if (rib)
2247 {
2248 /* Same distance static route is there. Update it with new
2249 nexthop. */
paul718e3742002-12-13 20:15:29 +00002250 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002251 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002252 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002253 case STATIC_IPV4_GATEWAY:
2254 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2255 break;
2256 case STATIC_IPV4_IFNAME:
2257 nexthop_ifname_add (rib, si->ifname);
2258 break;
2259 case STATIC_IPV4_BLACKHOLE:
2260 nexthop_blackhole_add (rib);
2261 break;
2262 case STATIC_IPV6_GATEWAY:
2263 nexthop_ipv6_add (rib, &si->addr.ipv6);
2264 break;
2265 case STATIC_IPV6_IFNAME:
2266 nexthop_ifname_add (rib, si->ifname);
2267 break;
2268 case STATIC_IPV6_GATEWAY_IFNAME:
2269 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2270 break;
paul4d38fdb2005-04-28 17:35:14 +00002271 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002272 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002273 }
2274 else
2275 {
2276 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002277 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2278
paul718e3742002-12-13 20:15:29 +00002279 rib->type = ZEBRA_ROUTE_STATIC;
2280 rib->distance = si->distance;
2281 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002282 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002283 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002284 rib->nexthop_num = 0;
2285
2286 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002287 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002288 case STATIC_IPV4_GATEWAY:
2289 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2290 break;
2291 case STATIC_IPV4_IFNAME:
2292 nexthop_ifname_add (rib, si->ifname);
2293 break;
2294 case STATIC_IPV4_BLACKHOLE:
2295 nexthop_blackhole_add (rib);
2296 break;
2297 case STATIC_IPV6_GATEWAY:
2298 nexthop_ipv6_add (rib, &si->addr.ipv6);
2299 break;
2300 case STATIC_IPV6_IFNAME:
2301 nexthop_ifname_add (rib, si->ifname);
2302 break;
2303 case STATIC_IPV6_GATEWAY_IFNAME:
2304 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2305 break;
paul7021c422003-07-15 12:52:22 +00002306 }
paul718e3742002-12-13 20:15:29 +00002307
hasso81dfcaa2003-05-25 19:21:25 +00002308 /* Save the flags of this static routes (reject, blackhole) */
2309 rib->flags = si->flags;
2310
paul718e3742002-12-13 20:15:29 +00002311 /* Link this rib to the tree. */
2312 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002313 }
2314}
2315
paula1ac18c2005-06-28 17:17:12 +00002316static int
Donald Sharpa979ab72015-11-04 13:26:38 -05002317static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002318{
2319 if (nexthop->type == NEXTHOP_TYPE_IPV4
2320 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002321 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002322 return 1;
2323 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2324 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002325 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002326 return 1;
paul595db7f2003-05-25 21:35:06 +00002327 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2328 && si->type == STATIC_IPV4_BLACKHOLE)
2329 return 1;
Donald Sharpa979ab72015-11-04 13:26:38 -05002330 if (nexthop->type == NEXTHOP_TYPE_IPV6
2331 && si->type == STATIC_IPV6_GATEWAY
2332 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
2333 return 1;
2334 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2335 && si->type == STATIC_IPV6_IFNAME
2336 && strcmp (nexthop->ifname, si->ifname) == 0)
2337 return 1;
2338 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2339 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2340 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
2341 && strcmp (nexthop->ifname, si->ifname) == 0)
2342 return 1;
paule8e19462006-01-19 20:16:55 +00002343 return 0;
paul718e3742002-12-13 20:15:29 +00002344}
2345
2346/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002347static void
Donald Sharp949b7192015-11-04 13:26:39 -05002348static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002349{
2350 struct route_node *rn;
2351 struct rib *rib;
2352 struct nexthop *nexthop;
2353 struct route_table *table;
2354
2355 /* Lookup table. */
Donald Sharp949b7192015-11-04 13:26:39 -05002356 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002357 if (! table)
2358 return;
paul4d38fdb2005-04-28 17:35:14 +00002359
paul718e3742002-12-13 20:15:29 +00002360 /* Lookup existing route with type and distance. */
2361 rn = route_node_lookup (table, p);
2362 if (! rn)
2363 return;
2364
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002365 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002366 {
2367 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2368 continue;
2369
2370 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2371 break;
2372 }
paul718e3742002-12-13 20:15:29 +00002373
2374 if (! rib)
2375 {
2376 route_unlock_node (rn);
2377 return;
2378 }
2379
2380 /* Lookup nexthop. */
2381 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Donald Sharpa979ab72015-11-04 13:26:38 -05002382 if (static_nexthop_same (nexthop, si))
paul718e3742002-12-13 20:15:29 +00002383 break;
2384
2385 /* Can't find nexthop. */
2386 if (! nexthop)
2387 {
2388 route_unlock_node (rn);
2389 return;
2390 }
2391
2392 /* Check nexthop. */
2393 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002394 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002395 else
2396 {
paul6baeb982003-10-28 03:47:15 +00002397 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2398 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002399 nexthop_delete (rib, nexthop);
2400 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002401 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002402 }
paul718e3742002-12-13 20:15:29 +00002403 /* Unlock node. */
2404 route_unlock_node (rn);
2405}
2406
paul718e3742002-12-13 20:15:29 +00002407int
Everton Marques33d86db2014-07-14 11:19:00 -03002408static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2409 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002410 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002411{
2412 u_char type = 0;
2413 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002414 struct static_route *si;
2415 struct static_route *pp;
2416 struct static_route *cp;
2417 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002418 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2419 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002420
paul718e3742002-12-13 20:15:29 +00002421 if (! stable)
2422 return -1;
2423
2424 /* Lookup static route prefix. */
2425 rn = route_node_get (stable, p);
2426
2427 /* Make flags. */
2428 if (gate)
2429 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002430 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002431 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002432 else
2433 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002434
2435 /* Do nothing if there is a same static route. */
2436 for (si = rn->info; si; si = si->next)
2437 {
2438 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002439 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2440 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002441 {
2442 if (distance == si->distance)
2443 {
2444 route_unlock_node (rn);
2445 return 0;
2446 }
2447 else
2448 update = si;
2449 }
2450 }
2451
Paul Jakma3c0755d2006-12-08 00:53:14 +00002452 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002453 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002454 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002455
2456 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002457 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002458
2459 si->type = type;
2460 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002461 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002462 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002463
2464 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002465 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002466 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002467 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002468
2469 /* Add new static route information to the tree with sort by
2470 distance value and gateway address. */
2471 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2472 {
2473 if (si->distance < cp->distance)
2474 break;
2475 if (si->distance > cp->distance)
2476 continue;
2477 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2478 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002479 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002480 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002481 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002482 continue;
2483 }
2484 }
2485
2486 /* Make linked list. */
2487 if (pp)
2488 pp->next = si;
2489 else
2490 rn->info = si;
2491 if (cp)
2492 cp->prev = si;
2493 si->prev = pp;
2494 si->next = cp;
2495
2496 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002497 static_install_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002498
2499 return 1;
2500}
2501
paul718e3742002-12-13 20:15:29 +00002502int
Everton Marques33d86db2014-07-14 11:19:00 -03002503static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002504 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002505{
2506 u_char type = 0;
2507 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002508 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002509 struct route_table *stable;
2510
2511 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002512 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002513 if (! stable)
2514 return -1;
2515
2516 /* Lookup static route prefix. */
2517 rn = route_node_lookup (stable, p);
2518 if (! rn)
2519 return 0;
2520
2521 /* Make flags. */
2522 if (gate)
2523 type = STATIC_IPV4_GATEWAY;
2524 else if (ifname)
2525 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002526 else
2527 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002528
2529 /* Find same static route is the tree */
2530 for (si = rn->info; si; si = si->next)
2531 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002532 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2533 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002534 break;
2535
2536 /* Can't find static route. */
2537 if (! si)
2538 {
2539 route_unlock_node (rn);
2540 return 0;
2541 }
2542
2543 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002544 static_uninstall_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002545
2546 /* Unlink static route from linked list. */
2547 if (si->prev)
2548 si->prev->next = si->next;
2549 else
2550 rn->info = si->next;
2551 if (si->next)
2552 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002553 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002554
2555 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002556 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002557 XFREE (0, si->ifname);
2558 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002559
paul143a3852003-09-29 20:06:13 +00002560 route_unlock_node (rn);
2561
paul718e3742002-12-13 20:15:29 +00002562 return 1;
2563}
2564
paul718e3742002-12-13 20:15:29 +00002565int
2566rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Paul Jakma9099f9b2016-01-18 10:12:10 +00002567 struct in6_addr *gate, ifindex_t ifindex,
Feng Lu0d0686f2015-05-22 11:40:02 +02002568 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002569 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002570{
2571 struct rib *rib;
2572 struct rib *same = NULL;
2573 struct route_table *table;
2574 struct route_node *rn;
2575 struct nexthop *nexthop;
2576
paul718e3742002-12-13 20:15:29 +00002577 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002578 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002579 if (! table)
2580 return 0;
2581
2582 /* Make sure mask is applied. */
2583 apply_mask_ipv6 (p);
2584
2585 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002586 if (!distance)
2587 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002588
2589 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2590 distance = 200;
2591
paul718e3742002-12-13 20:15:29 +00002592 /* Lookup route node.*/
2593 rn = route_node_get (table, (struct prefix *) p);
2594
2595 /* If same type of route are installed, treat it as a implicit
2596 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002597 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002598 {
Paul Jakma6d691122006-07-27 21:49:00 +00002599 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2600 continue;
2601
hassoebf1ead2005-09-21 14:58:20 +00002602 if (rib->type != type)
2603 continue;
2604 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002605 {
2606 same = rib;
paul718e3742002-12-13 20:15:29 +00002607 break;
2608 }
hassoebf1ead2005-09-21 14:58:20 +00002609 else if ((nexthop = rib->nexthop) &&
2610 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2611 nexthop->ifindex == ifindex)
2612 {
2613 rib->refcnt++;
2614 return 0;
2615 }
paul718e3742002-12-13 20:15:29 +00002616 }
2617
2618 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002619 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2620
paul718e3742002-12-13 20:15:29 +00002621 rib->type = type;
2622 rib->distance = distance;
2623 rib->flags = flags;
2624 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002625 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002626 rib->vrf_id = vrf_id;
2627 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002628 rib->nexthop_num = 0;
2629 rib->uptime = time (NULL);
2630
2631 /* Nexthop settings. */
2632 if (gate)
2633 {
2634 if (ifindex)
2635 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2636 else
2637 nexthop_ipv6_add (rib, gate);
2638 }
2639 else
2640 nexthop_ifindex_add (rib, ifindex);
2641
2642 /* If this route is kernel route, set FIB flag to the route. */
2643 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2644 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2645 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2646
2647 /* Link new rib to node.*/
2648 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002649 if (IS_ZEBRA_DEBUG_RIB)
2650 {
2651 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002652 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002653 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002654 }
paul718e3742002-12-13 20:15:29 +00002655
paul718e3742002-12-13 20:15:29 +00002656 /* Free implicit route.*/
2657 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002658 {
2659 if (IS_ZEBRA_DEBUG_RIB)
2660 {
2661 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002662 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002663 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002664 }
paul4d38fdb2005-04-28 17:35:14 +00002665 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002666 }
paul4d38fdb2005-04-28 17:35:14 +00002667
2668 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002669 return 0;
2670}
2671
hassoebf1ead2005-09-21 14:58:20 +00002672/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002673int
2674rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Paul Jakma9099f9b2016-01-18 10:12:10 +00002675 struct in6_addr *gate, ifindex_t ifindex,
2676 vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002677{
2678 struct route_table *table;
2679 struct route_node *rn;
2680 struct rib *rib;
2681 struct rib *fib = NULL;
2682 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002683 struct nexthop *nexthop, *tnexthop;
2684 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002685 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002686 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002687
2688 /* Apply mask. */
2689 apply_mask_ipv6 (p);
2690
2691 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002692 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002693 if (! table)
2694 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002695
paul718e3742002-12-13 20:15:29 +00002696 /* Lookup route node. */
2697 rn = route_node_lookup (table, (struct prefix *) p);
2698 if (! rn)
2699 {
2700 if (IS_ZEBRA_DEBUG_KERNEL)
2701 {
2702 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002703 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2704 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002705 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002706 ifindex);
2707 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002708 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2709 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002710 ifindex);
2711 }
2712 return ZEBRA_ERR_RTNOEXIST;
2713 }
2714
2715 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002716 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002717 {
Paul Jakma6d691122006-07-27 21:49:00 +00002718 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2719 continue;
2720
Timo Teräs325823a2016-01-15 17:36:31 +02002721 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00002722 fib = rib;
2723
hassoebf1ead2005-09-21 14:58:20 +00002724 if (rib->type != type)
2725 continue;
2726 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002727 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002728 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002729 if (nexthop->ifindex != ifindex)
2730 continue;
hassoebf1ead2005-09-21 14:58:20 +00002731 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002732 {
hassoebf1ead2005-09-21 14:58:20 +00002733 rib->refcnt--;
2734 route_unlock_node (rn);
2735 route_unlock_node (rn);
2736 return 0;
paul718e3742002-12-13 20:15:29 +00002737 }
hassoebf1ead2005-09-21 14:58:20 +00002738 same = rib;
2739 break;
paul718e3742002-12-13 20:15:29 +00002740 }
hassoebf1ead2005-09-21 14:58:20 +00002741 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002742 else
2743 {
2744 if (gate == NULL)
2745 {
2746 same = rib;
2747 break;
2748 }
2749 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2750 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2751 {
2752 same = rib;
2753 break;
2754 }
2755 if (same)
2756 break;
2757 }
paul718e3742002-12-13 20:15:29 +00002758 }
2759
2760 /* If same type of route can't be found and this message is from
2761 kernel. */
2762 if (! same)
2763 {
2764 if (fib && type == ZEBRA_ROUTE_KERNEL)
2765 {
2766 /* Unset flags. */
2767 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2768 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2769
Timo Teräs325823a2016-01-15 17:36:31 +02002770 UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
paul718e3742002-12-13 20:15:29 +00002771 }
2772 else
2773 {
2774 if (IS_ZEBRA_DEBUG_KERNEL)
2775 {
2776 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002777 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2778 "doesn't exist in rib",
2779 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002780 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002781 ifindex,
2782 type);
2783 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002784 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2785 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002786 ifindex,
2787 type);
2788 }
2789 route_unlock_node (rn);
2790 return ZEBRA_ERR_RTNOEXIST;
2791 }
2792 }
2793
2794 if (same)
2795 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002796
paul718e3742002-12-13 20:15:29 +00002797 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002798 return 0;
2799}
David Lamparter6b0655a2014-06-04 06:53:35 +02002800
paul718e3742002-12-13 20:15:29 +00002801
2802/* Add static route into static route configuration. */
2803int
2804static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002805 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002806 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002807{
2808 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002809 struct static_route *si;
2810 struct static_route *pp;
2811 struct static_route *cp;
Donald Sharpc1900e02015-11-04 13:26:40 -05002812 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002813 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2814 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002815
paul718e3742002-12-13 20:15:29 +00002816 if (! stable)
2817 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002818
2819 if (!gate &&
2820 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2821 return -1;
2822
2823 if (!ifname &&
2824 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2825 return -1;
paul718e3742002-12-13 20:15:29 +00002826
2827 /* Lookup static route prefix. */
2828 rn = route_node_get (stable, p);
2829
2830 /* Do nothing if there is a same static route. */
2831 for (si = rn->info; si; si = si->next)
2832 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002833 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002834 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002835 && (! ifname || strcmp (ifname, si->ifname) == 0))
2836 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002837 if (distance == si->distance)
2838 {
2839 route_unlock_node (rn);
2840 return 0;
2841 }
2842 else
2843 update = si;
paul718e3742002-12-13 20:15:29 +00002844 }
2845 }
2846
Donald Sharpc1900e02015-11-04 13:26:40 -05002847 if (update)
2848 static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
2849
paul718e3742002-12-13 20:15:29 +00002850 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002851 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002852
2853 si->type = type;
2854 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002855 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002856 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002857
2858 switch (type)
2859 {
2860 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002861 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002862 break;
2863 case STATIC_IPV6_IFNAME:
2864 si->ifname = XSTRDUP (0, ifname);
2865 break;
2866 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002867 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002868 si->ifname = XSTRDUP (0, ifname);
2869 break;
2870 }
2871
2872 /* Add new static route information to the tree with sort by
2873 distance value and gateway address. */
2874 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2875 {
2876 if (si->distance < cp->distance)
2877 break;
2878 if (si->distance > cp->distance)
2879 continue;
2880 }
2881
2882 /* Make linked list. */
2883 if (pp)
2884 pp->next = si;
2885 else
2886 rn->info = si;
2887 if (cp)
2888 cp->prev = si;
2889 si->prev = pp;
2890 si->next = cp;
2891
2892 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002893 static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002894
2895 return 1;
2896}
2897
2898/* Delete static route from static route configuration. */
2899int
2900static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002901 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002902{
2903 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002904 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002905 struct route_table *stable;
2906
2907 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002908 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002909 if (! stable)
2910 return -1;
2911
2912 /* Lookup static route prefix. */
2913 rn = route_node_lookup (stable, p);
2914 if (! rn)
2915 return 0;
2916
2917 /* Find same static route is the tree */
2918 for (si = rn->info; si; si = si->next)
2919 if (distance == si->distance
2920 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002921 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002922 && (! ifname || strcmp (ifname, si->ifname) == 0))
2923 break;
2924
2925 /* Can't find static route. */
2926 if (! si)
2927 {
2928 route_unlock_node (rn);
2929 return 0;
2930 }
2931
2932 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002933 static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002934
2935 /* Unlink static route from linked list. */
2936 if (si->prev)
2937 si->prev->next = si->next;
2938 else
2939 rn->info = si->next;
2940 if (si->next)
2941 si->next->prev = si->prev;
2942
2943 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002944 if (ifname)
2945 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05002946 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002947
2948 return 1;
2949}
David Lamparter6b0655a2014-06-04 06:53:35 +02002950
paul718e3742002-12-13 20:15:29 +00002951/* RIB update function. */
2952void
Feng Lu0d0686f2015-05-22 11:40:02 +02002953rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002954{
2955 struct route_node *rn;
2956 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002957
Feng Lu0d0686f2015-05-22 11:40:02 +02002958 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002959 if (table)
2960 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002961 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002962 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002963
Feng Lu0d0686f2015-05-22 11:40:02 +02002964 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002965 if (table)
2966 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002967 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002968 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002969}
2970
David Lamparter6b0655a2014-06-04 06:53:35 +02002971
paul718e3742002-12-13 20:15:29 +00002972/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002973static void
paul718e3742002-12-13 20:15:29 +00002974rib_weed_table (struct route_table *table)
2975{
2976 struct route_node *rn;
2977 struct rib *rib;
2978 struct rib *next;
2979
2980 if (table)
2981 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002982 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002983 {
Paul Jakma6d691122006-07-27 21:49:00 +00002984 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2985 continue;
2986
paulb21b19c2003-06-15 01:28:29 +00002987 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002988 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002989 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002990 }
2991}
2992
2993/* Delete all routes from non main table. */
2994void
paula1ac18c2005-06-28 17:17:12 +00002995rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002996{
Feng Lu0d0686f2015-05-22 11:40:02 +02002997 vrf_iter_t iter;
2998 struct zebra_vrf *zvrf;
2999
3000 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3001 if ((zvrf = vrf_iter2info (iter)) != NULL)
3002 {
3003 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3004 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3005 }
paul718e3742002-12-13 20:15:29 +00003006}
David Lamparter6b0655a2014-06-04 06:53:35 +02003007
Feng Lu0d0686f2015-05-22 11:40:02 +02003008#if 0
paul718e3742002-12-13 20:15:29 +00003009/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003010static void
paul718e3742002-12-13 20:15:29 +00003011rib_sweep_table (struct route_table *table)
3012{
3013 struct route_node *rn;
3014 struct rib *rib;
3015 struct rib *next;
3016 int ret = 0;
3017
3018 if (table)
3019 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003020 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003021 {
Paul Jakma6d691122006-07-27 21:49:00 +00003022 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3023 continue;
3024
paul718e3742002-12-13 20:15:29 +00003025 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3026 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3027 {
Timo Teräs0abf6792016-01-15 17:36:29 +02003028 ret = rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00003029 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003030 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003031 }
3032 }
3033}
Feng Lu0d0686f2015-05-22 11:40:02 +02003034#endif
paul718e3742002-12-13 20:15:29 +00003035
3036/* Sweep all RIB tables. */
3037void
paula1ac18c2005-06-28 17:17:12 +00003038rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003039{
Feng Lu0d0686f2015-05-22 11:40:02 +02003040 vrf_iter_t iter;
3041 struct zebra_vrf *zvrf;
3042
3043 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3044 if ((zvrf = vrf_iter2info (iter)) != NULL)
3045 {
3046 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3047 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3048 }
paul718e3742002-12-13 20:15:29 +00003049}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003050
3051/* Remove specific by protocol routes from 'table'. */
3052static unsigned long
3053rib_score_proto_table (u_char proto, struct route_table *table)
3054{
3055 struct route_node *rn;
3056 struct rib *rib;
3057 struct rib *next;
3058 unsigned long n = 0;
3059
3060 if (table)
3061 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003062 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003063 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003064 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3065 continue;
3066 if (rib->type == proto)
3067 {
3068 rib_delnode (rn, rib);
3069 n++;
3070 }
3071 }
3072
3073 return n;
3074}
3075
3076/* Remove specific by protocol routes. */
3077unsigned long
3078rib_score_proto (u_char proto)
3079{
Feng Lu0d0686f2015-05-22 11:40:02 +02003080 vrf_iter_t iter;
3081 struct zebra_vrf *zvrf;
3082 unsigned long cnt = 0;
3083
3084 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3085 if ((zvrf = vrf_iter2info (iter)) != NULL)
3086 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3087 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3088
3089 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003090}
3091
paul718e3742002-12-13 20:15:29 +00003092/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003093void
paul718e3742002-12-13 20:15:29 +00003094rib_close_table (struct route_table *table)
3095{
3096 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003097 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003098 struct rib *rib;
3099
3100 if (table)
3101 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003102 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003103 {
Timo Teräs325823a2016-01-15 17:36:31 +02003104 if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003105 continue;
3106
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003107 if (info->safi == SAFI_UNICAST)
3108 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003109
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003110 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02003111 rib_update_kernel (rn, rib, NULL);
Paul Jakma6d691122006-07-27 21:49:00 +00003112 }
paul718e3742002-12-13 20:15:29 +00003113}
3114
3115/* Close all RIB tables. */
3116void
paula1ac18c2005-06-28 17:17:12 +00003117rib_close (void)
paul718e3742002-12-13 20:15:29 +00003118{
Feng Lu0d0686f2015-05-22 11:40:02 +02003119 vrf_iter_t iter;
3120 struct zebra_vrf *zvrf;
3121
3122 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3123 if ((zvrf = vrf_iter2info (iter)) != NULL)
3124 {
3125 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3126 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3127 }
paul718e3742002-12-13 20:15:29 +00003128}
David Lamparter6b0655a2014-06-04 06:53:35 +02003129
paul718e3742002-12-13 20:15:29 +00003130/* Routing information base initialize. */
3131void
paula1ac18c2005-06-28 17:17:12 +00003132rib_init (void)
paul718e3742002-12-13 20:15:29 +00003133{
paul4d38fdb2005-04-28 17:35:14 +00003134 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003135}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003136
3137/*
3138 * vrf_id_get_next
3139 *
3140 * Get the first vrf id that is greater than the given vrf id if any.
3141 *
3142 * Returns TRUE if a vrf id was found, FALSE otherwise.
3143 */
3144static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003145vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003146{
Feng Lu41f44a22015-05-22 11:39:56 +02003147 vrf_iter_t iter = vrf_iterator (vrf_id);
3148 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3149
3150 /* The same one ? Then find out the next. */
3151 if (zvrf && (zvrf->vrf_id == vrf_id))
3152 zvrf = vrf_iter2info (vrf_next (iter));
3153
3154 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003155 {
Feng Lu41f44a22015-05-22 11:39:56 +02003156 *next_id_p = zvrf->vrf_id;
3157 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003158 }
3159
3160 return 0;
3161}
3162
3163/*
3164 * rib_tables_iter_next
3165 *
3166 * Returns the next table in the iteration.
3167 */
3168struct route_table *
3169rib_tables_iter_next (rib_tables_iter_t *iter)
3170{
3171 struct route_table *table;
3172
3173 /*
3174 * Array that helps us go over all AFI/SAFI combinations via one
3175 * index.
3176 */
3177 static struct {
3178 afi_t afi;
3179 safi_t safi;
3180 } afi_safis[] = {
3181 { AFI_IP, SAFI_UNICAST },
3182 { AFI_IP, SAFI_MULTICAST },
3183 { AFI_IP6, SAFI_UNICAST },
3184 { AFI_IP6, SAFI_MULTICAST },
3185 };
3186
3187 table = NULL;
3188
3189 switch (iter->state)
3190 {
3191
3192 case RIB_TABLES_ITER_S_INIT:
Donald Sharp0d271292015-11-19 07:21:30 -05003193 iter->vrf_id = VRF_DEFAULT;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003194 iter->afi_safi_ix = -1;
3195
3196 /* Fall through */
3197
3198 case RIB_TABLES_ITER_S_ITERATING:
3199 iter->afi_safi_ix++;
3200 while (1)
3201 {
3202
3203 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3204 {
Feng Lu41f44a22015-05-22 11:39:56 +02003205 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003206 afi_safis[iter->afi_safi_ix].safi,
3207 iter->vrf_id);
3208 if (table)
3209 break;
3210
3211 iter->afi_safi_ix++;
3212 }
3213
3214 /*
3215 * Found another table in this vrf.
3216 */
3217 if (table)
3218 break;
3219
3220 /*
3221 * Done with all tables in the current vrf, go to the next
3222 * one.
3223 */
3224 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3225 break;
3226
3227 iter->afi_safi_ix = 0;
3228 }
3229
3230 break;
3231
3232 case RIB_TABLES_ITER_S_DONE:
3233 return NULL;
3234 }
3235
3236 if (table)
3237 iter->state = RIB_TABLES_ITER_S_ITERATING;
3238 else
3239 iter->state = RIB_TABLES_ITER_S_DONE;
3240
3241 return table;
3242}
Feng Lu41f44a22015-05-22 11:39:56 +02003243
3244/*
3245 * Create a routing table for the specific AFI/SAFI in the given VRF.
3246 */
3247static void
3248zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3249{
3250 rib_table_info_t *info;
3251 struct route_table *table;
3252
3253 assert (!zvrf->table[afi][safi]);
3254
3255 table = route_table_init ();
3256 zvrf->table[afi][safi] = table;
3257
3258 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3259 info->zvrf = zvrf;
3260 info->afi = afi;
3261 info->safi = safi;
3262 table->info = info;
3263}
3264
3265/* Allocate new zebra VRF. */
3266struct zebra_vrf *
3267zebra_vrf_alloc (vrf_id_t vrf_id)
3268{
3269 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003270#ifdef HAVE_NETLINK
3271 char nl_name[64];
3272#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003273
3274 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3275
3276 /* Allocate routing table and static table. */
3277 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3278 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3279 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3280 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3281 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3282 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3283 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3284 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3285
3286 /* Set VRF ID */
3287 zvrf->vrf_id = vrf_id;
3288
Feng Lu758fb8f2014-07-03 18:23:09 +08003289#ifdef HAVE_NETLINK
3290 /* Initialize netlink sockets */
3291 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3292 zvrf->netlink.sock = -1;
3293 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3294
3295 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3296 zvrf->netlink_cmd.sock = -1;
3297 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3298#endif
3299
Feng Lu41f44a22015-05-22 11:39:56 +02003300 return zvrf;
3301}
3302
3303/* Lookup the routing table in an enabled VRF. */
3304struct route_table *
3305zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3306{
3307 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3308
3309 if (!zvrf)
3310 return NULL;
3311
3312 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3313 return NULL;
3314
3315 return zvrf->table[afi][safi];
3316}
3317
3318/* Lookup the static routing table in a VRF. */
3319struct route_table *
3320zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3321{
3322 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3323
3324 if (!zvrf)
3325 return NULL;
3326
3327 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3328 return NULL;
3329
3330 return zvrf->stable[afi][safi];
3331}
3332