blob: 1650dabf0e2360f47259e2b1f8da35f6dd011cd3 [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;
Timo Teräs7eb61362015-11-02 16:50:05 +02001081 UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
paul718e3742002-12-13 20:15:29 +00001082
1083 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001084 {
1085 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001086 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001087 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1088 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001089 if (prev_active != new_active ||
1090 prev_index != nexthop->ifindex)
Timo Teräs7eb61362015-11-02 16:50:05 +02001091 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001092 }
paul718e3742002-12-13 20:15:29 +00001093 return rib->nexthop_active_num;
1094}
paul6baeb982003-10-28 03:47:15 +00001095
David Lamparter6b0655a2014-06-04 06:53:35 +02001096
paul718e3742002-12-13 20:15:29 +00001097
Timo Teräs0abf6792016-01-15 17:36:29 +02001098static int
1099rib_update_kernel (struct route_node *rn, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001100{
1101 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001102 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001103 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001104 int recursing;
paul718e3742002-12-13 20:15:29 +00001105
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001106 if (info->safi != SAFI_UNICAST)
1107 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001108 if (new)
1109 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1110 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1111 if (old)
1112 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1113 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1114 return 0;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001115 }
1116
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001117 /*
1118 * Make sure we update the FPM any time we send new information to
1119 * the kernel.
1120 */
Timo Teräs0abf6792016-01-15 17:36:29 +02001121 zfpm_trigger_update (rn, "updating in kernel");
1122
1123 ret = kernel_route_rib (&rn->p, old, new);
paul718e3742002-12-13 20:15:29 +00001124
Denis Ovsienkodc958242007-08-13 16:03:06 +00001125 /* This condition is never met, if we are using rt_socket.c */
Timo Teräs0abf6792016-01-15 17:36:29 +02001126 if (ret < 0 && new)
1127 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1128 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001129
Timo Teräs0abf6792016-01-15 17:36:29 +02001130 if (old)
1131 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1132 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001133
1134 return ret;
1135}
1136
1137/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001138static void
paul718e3742002-12-13 20:15:29 +00001139rib_uninstall (struct route_node *rn, struct rib *rib)
1140{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001141 rib_table_info_t *info = rn->table->info;
1142
Timo Teräs325823a2016-01-15 17:36:31 +02001143 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00001144 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001145 if (info->safi == SAFI_UNICAST)
1146 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001147
paul718e3742002-12-13 20:15:29 +00001148 redistribute_delete (&rn->p, rib);
1149 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02001150 rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00001151 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1152 }
1153}
1154
Paul Jakma6d691122006-07-27 21:49:00 +00001155static void rib_unlink (struct route_node *, struct rib *);
1156
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001157/*
1158 * rib_can_delete_dest
1159 *
1160 * Returns TRUE if the given dest can be deleted from the table.
1161 */
1162static int
1163rib_can_delete_dest (rib_dest_t *dest)
1164{
1165 if (dest->routes)
1166 {
1167 return 0;
1168 }
1169
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001170 /*
1171 * Don't delete the dest if we have to update the FPM about this
1172 * prefix.
1173 */
1174 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1175 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1176 return 0;
1177
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001178 return 1;
1179}
1180
1181/*
1182 * rib_gc_dest
1183 *
1184 * Garbage collect the rib dest corresponding to the given route node
1185 * if appropriate.
1186 *
1187 * Returns TRUE if the dest was deleted, FALSE otherwise.
1188 */
1189int
1190rib_gc_dest (struct route_node *rn)
1191{
1192 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001193
1194 dest = rib_dest_from_rnode (rn);
1195 if (!dest)
1196 return 0;
1197
1198 if (!rib_can_delete_dest (dest))
1199 return 0;
1200
1201 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001202 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001203
1204 dest->rnode = NULL;
1205 XFREE (MTYPE_RIB_DEST, dest);
1206 rn->info = NULL;
1207
1208 /*
1209 * Release the one reference that we keep on the route node.
1210 */
1211 route_unlock_node (rn);
1212 return 1;
1213}
1214
Timo Teräs0abf6792016-01-15 17:36:29 +02001215/* Check if 'alternate' RIB entry is better than 'current'. */
1216static struct rib *
1217rib_choose_best (struct rib *current, struct rib *alternate)
1218{
1219 if (current == NULL)
1220 return alternate;
1221
1222 /* filter route selection in following order:
1223 * - connected beats other types
1224 * - lower distance beats higher
1225 * - lower metric beats higher for equal distance
1226 * - last, hence oldest, route wins tie break.
1227 */
1228
1229 /* Connected routes. Pick the last connected
1230 * route of the set of lowest metric connected routes.
1231 */
1232 if (alternate->type == ZEBRA_ROUTE_CONNECT)
1233 {
1234 if (current->type != ZEBRA_ROUTE_CONNECT
1235 || alternate->metric <= current->metric)
1236 return alternate;
1237
1238 return current;
1239 }
1240
1241 if (current->type == ZEBRA_ROUTE_CONNECT)
1242 return current;
1243
1244 /* higher distance loses */
1245 if (alternate->distance < current->distance)
1246 return alternate;
1247 if (current->distance < alternate->distance)
1248 return current;
1249
1250 /* metric tie-breaks equal distance */
1251 if (alternate->metric <= current->metric)
1252 return alternate;
1253
1254 return current;
1255}
1256
paul718e3742002-12-13 20:15:29 +00001257/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001258static void
1259rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001260{
1261 struct rib *rib;
1262 struct rib *next;
Timo Teräs325823a2016-01-15 17:36:31 +02001263 struct rib *old_selected = NULL;
1264 struct rib *new_selected = NULL;
Timo Teräs0abf6792016-01-15 17:36:29 +02001265 struct rib *old_fib = NULL;
1266 struct rib *new_fib = NULL;
pauld753e9e2003-01-22 19:45:50 +00001267 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001268 struct nexthop *nexthop = NULL, *tnexthop;
1269 int recursing;
Balaji95116332014-10-23 15:25:25 +00001270 rib_table_info_t *info;
1271
paul4d38fdb2005-04-28 17:35:14 +00001272 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001273
1274 info = rn->table->info;
1275
Timo Teräs0abf6792016-01-15 17:36:29 +02001276 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001277 {
paul718e3742002-12-13 20:15:29 +00001278 /* Currently installed rib. */
1279 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001280 {
Timo Teräs325823a2016-01-15 17:36:31 +02001281 assert (old_selected == NULL);
1282 old_selected = rib;
1283 }
1284 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1285 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001286 assert (old_fib == NULL);
1287 old_fib = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001288 }
Timo Teräs0abf6792016-01-15 17:36:29 +02001289
1290 /* Skip deleted entries from selection */
Paul Jakma6d691122006-07-27 21:49:00 +00001291 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
Timo Teräs0abf6792016-01-15 17:36:29 +02001292 continue;
paul4d38fdb2005-04-28 17:35:14 +00001293
paul718e3742002-12-13 20:15:29 +00001294 /* Skip unreachable nexthop. */
1295 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001296 continue;
paul718e3742002-12-13 20:15:29 +00001297
1298 /* Infinit distance. */
1299 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001300 continue;
paul718e3742002-12-13 20:15:29 +00001301
Timo Teräs325823a2016-01-15 17:36:31 +02001302 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
1303 new_fib = rib_choose_best(new_fib, rib);
1304 else
1305 new_selected = rib_choose_best(new_selected, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001306 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001307
Timo Teräs325823a2016-01-15 17:36:31 +02001308 /* If no FIB override route, use the selected route also for FIB */
1309 if (new_fib == NULL)
1310 new_fib = new_selected;
1311
Denis Ovsienkodc958242007-08-13 16:03:06 +00001312 /* After the cycle is finished, the following pointers will be set:
Timo Teräs325823a2016-01-15 17:36:31 +02001313 * old_selected --- RIB entry currently having SELECTED
1314 * new_selected --- RIB entry that is newly SELECTED
1315 * old_fib --- RIB entry currently in kernel FIB
1316 * new_fib --- RIB entry that is newly to be in kernel FIB
1317 *
1318 * new_selected will get SELECTED flag, and is going to be redistributed
1319 * the zclients. new_fib (which can be new_selected) will be installed in kernel.
Denis Ovsienkodc958242007-08-13 16:03:06 +00001320 */
1321
Timo Teräs0abf6792016-01-15 17:36:29 +02001322 /* Set real nexthops. */
1323 if (new_fib)
1324 nexthop_active_update (rn, new_fib, 1);
Timo Teräs325823a2016-01-15 17:36:31 +02001325 if (new_selected && new_selected != new_fib)
1326 nexthop_active_update (rn, new_selected, 1);
Timo Teräs0abf6792016-01-15 17:36:29 +02001327
1328 /* Update kernel if FIB entry has changed */
1329 if (old_fib != new_fib
1330 || (new_fib && CHECK_FLAG (new_fib->status, RIB_ENTRY_CHANGED)))
paul718e3742002-12-13 20:15:29 +00001331 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001332 if (old_fib && old_fib != new_fib)
1333 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001334 if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
1335 rib_update_kernel (rn, old_fib, NULL);
Timo Teräs325823a2016-01-15 17:36:31 +02001336 UNSET_FLAG (old_fib->status, RIB_ENTRY_SELECTED_FIB);
Timo Teräs0abf6792016-01-15 17:36:29 +02001337 }
1338
1339 if (new_fib)
1340 {
1341 /* Install new or replace existing FIB entry */
Timo Teräs325823a2016-01-15 17:36:31 +02001342 SET_FLAG (new_fib->status, RIB_ENTRY_SELECTED_FIB);
Timo Teräs0abf6792016-01-15 17:36:29 +02001343 if (! RIB_SYSTEM_ROUTE (new_fib))
1344 rib_update_kernel (rn, old_fib, new_fib);
1345 }
1346
1347 if (info->safi == SAFI_UNICAST)
1348 zfpm_trigger_update (rn, "updating existing route");
1349 }
1350 else if (old_fib == new_fib && new_fib && ! RIB_SYSTEM_ROUTE (new_fib))
1351 {
1352 /* Housekeeping code to deal with race conditions in kernel with
1353 * linux netlink reporting interface up before IPv4 or IPv6 protocol
1354 * is ready to add routes. This makes sure routes are IN the kernel.
1355 */
1356 for (ALL_NEXTHOPS_RO(new_fib->nexthop, nexthop, tnexthop, recursing))
1357 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1358 {
1359 installed = 1;
1360 break;
1361 }
1362 if (! installed)
1363 rib_update_kernel (rn, NULL, new_fib);
1364 }
1365
Timo Teräs325823a2016-01-15 17:36:31 +02001366 /* Redistribute SELECTED entry */
1367 if (old_selected != new_selected
1368 || (new_selected && CHECK_FLAG (new_selected->status, RIB_ENTRY_CHANGED)))
1369 {
1370 if (old_selected)
1371 {
1372 if (! new_selected)
1373 redistribute_delete (&rn->p, old_selected);
1374 if (old_selected != new_selected)
1375 UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED);
1376 }
1377
1378 if (new_selected)
1379 {
1380 /* Install new or replace existing redistributed entry */
1381 SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED);
1382 redistribute_add (&rn->p, new_selected);
1383 }
1384 }
1385
Timo Teräs0abf6792016-01-15 17:36:29 +02001386 /* Remove all RIB entries queued for removal */
1387 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1388 {
1389 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
paul4d38fdb2005-04-28 17:35:14 +00001390 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001391 if (IS_ZEBRA_DEBUG_RIB)
1392 rnode_debug (rn, "rn %p, removing rib %p",
1393 (void *)rn, (void *)rib);
1394 rib_unlink (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001395 }
paul718e3742002-12-13 20:15:29 +00001396 }
1397
Paul Jakma6d691122006-07-27 21:49:00 +00001398 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001399 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001400
1401 /*
1402 * Check if the dest can be deleted now.
1403 */
1404 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001405}
1406
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001407/* Take a list of route_node structs and return 1, if there was a record
1408 * picked from it and processed by rib_process(). Don't process more,
1409 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001410 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001411static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001412process_subq (struct list * subq, u_char qindex)
1413{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001414 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001415 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001416
1417 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001418 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001419
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001420 rnode = listgetdata (lnode);
1421 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001422
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001423 if (rnode->info)
1424 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1425
Chris Caputo67b94672009-07-18 04:02:26 +00001426#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001427 else
1428 {
1429 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1430 __func__, rnode, rnode->lock);
1431 zlog_backtrace(LOG_DEBUG);
1432 }
Chris Caputo67b94672009-07-18 04:02:26 +00001433#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001434 route_unlock_node (rnode);
1435 list_delete_node (subq, lnode);
1436 return 1;
1437}
1438
1439/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1440 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1441 * is pointed to the meta queue structure.
1442 */
1443static wq_item_status
1444meta_queue_process (struct work_queue *dummy, void *data)
1445{
1446 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001447 unsigned i;
1448
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001449 for (i = 0; i < MQ_SIZE; i++)
1450 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001451 {
1452 mq->size--;
1453 break;
1454 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001455 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1456}
1457
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001458/*
1459 * Map from rib types to queue type (priority) in meta queue
1460 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001461static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1462 [ZEBRA_ROUTE_SYSTEM] = 4,
1463 [ZEBRA_ROUTE_KERNEL] = 0,
1464 [ZEBRA_ROUTE_CONNECT] = 0,
1465 [ZEBRA_ROUTE_STATIC] = 1,
1466 [ZEBRA_ROUTE_RIP] = 2,
1467 [ZEBRA_ROUTE_RIPNG] = 2,
1468 [ZEBRA_ROUTE_OSPF] = 2,
1469 [ZEBRA_ROUTE_OSPF6] = 2,
1470 [ZEBRA_ROUTE_ISIS] = 2,
1471 [ZEBRA_ROUTE_BGP] = 3,
1472 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001473 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001474};
1475
1476/* Look into the RN and queue it into one or more priority queues,
1477 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001478 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001479static void
1480rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001481{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001482 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001483
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001484 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001485 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001486 u_char qindex = meta_queue_map[rib->type];
1487
1488 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001489 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1490 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001491 {
1492 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001493 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001494 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001495 continue;
1496 }
1497
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001498 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001499 listnode_add (mq->subq[qindex], rn);
1500 route_lock_node (rn);
1501 mq->size++;
1502
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001503 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001504 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001505 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001506 }
paul4d38fdb2005-04-28 17:35:14 +00001507}
1508
Paul Jakma6d691122006-07-27 21:49:00 +00001509/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001510static void
Paul Jakma6d691122006-07-27 21:49:00 +00001511rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001512{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001513 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001514
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001515 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001516 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001517 {
1518 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001519 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001520 zlog_backtrace(LOG_DEBUG);
1521 return;
1522 }
1523
1524 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001525 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001526
1527 assert (zebra);
1528
1529 if (zebra->ribq == NULL)
1530 {
1531 zlog_err ("%s: work_queue does not exist!", __func__);
1532 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001533 }
paul4d38fdb2005-04-28 17:35:14 +00001534
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001535 /*
1536 * The RIB queue should normally be either empty or holding the only
1537 * work_queue_item element. In the latter case this element would
1538 * hold a pointer to the meta queue structure, which must be used to
1539 * actually queue the route nodes to process. So create the MQ
1540 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001541 * This semantics was introduced after 0.99.9 release.
1542 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001543 if (!zebra->ribq->items->count)
1544 work_queue_add (zebra->ribq, zebra->mq);
1545
1546 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001547
1548 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001549 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001550
1551 return;
paul4d38fdb2005-04-28 17:35:14 +00001552}
1553
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001554/* Create new meta queue.
1555 A destructor function doesn't seem to be necessary here.
1556 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001557static struct meta_queue *
1558meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001559{
1560 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001561 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001562
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001563 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1564 assert(new);
1565
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001566 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001567 {
1568 new->subq[i] = list_new ();
1569 assert(new->subq[i]);
1570 }
1571
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001572 return new;
1573}
1574
paul4d38fdb2005-04-28 17:35:14 +00001575/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001576static void
paul4d38fdb2005-04-28 17:35:14 +00001577rib_queue_init (struct zebra_t *zebra)
1578{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001579 assert (zebra);
1580
paul4d38fdb2005-04-28 17:35:14 +00001581 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001582 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001583 {
Paul Jakma6d691122006-07-27 21:49:00 +00001584 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001585 return;
1586 }
1587
1588 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001589 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001590 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001591 /* XXX: TODO: These should be runtime configurable via vty */
1592 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001593 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001594
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001595 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001596 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001597 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001598 return;
1599 }
1600 return;
paul718e3742002-12-13 20:15:29 +00001601}
1602
Paul Jakma6d691122006-07-27 21:49:00 +00001603/* RIB updates are processed via a queue of pointers to route_nodes.
1604 *
1605 * The queue length is bounded by the maximal size of the routing table,
1606 * as a route_node will not be requeued, if already queued.
1607 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001608 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05001609 * state, or static_install_route (when an existing RIB is updated)
Paul Jakma3c0755d2006-12-08 00:53:14 +00001610 * and then submit route_node to queue for best-path selection later.
1611 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001612 *
1613 * Deleted RIBs are reaped during best-path selection.
1614 *
1615 * rib_addnode
1616 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001617 * |-------->| | best RIB, if required
1618 * | |
1619 * static_install->|->rib_addqueue...... -> rib_process
1620 * | |
1621 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001622 * |-> set RIB_ENTRY_REMOVE |
1623 * rib_delnode (RIB freed)
1624 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001625 * The 'info' pointer of a route_node points to a rib_dest_t
1626 * ('dest'). Queueing state for a route_node is kept on the dest. The
1627 * dest is created on-demand by rib_link() and is kept around at least
1628 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001629 *
1630 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1631 *
1632 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001633 * - dest attached to route_node:
1634 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001635 * - route_node processing queue
1636 * - managed by: rib_addqueue, rib_process.
1637 *
1638 */
1639
paul718e3742002-12-13 20:15:29 +00001640/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001641static void
Paul Jakma6d691122006-07-27 21:49:00 +00001642rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001643{
1644 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001645 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001646
paul4d38fdb2005-04-28 17:35:14 +00001647 assert (rib && rn);
1648
Paul Jakma6d691122006-07-27 21:49:00 +00001649 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001650 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001651
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001652 dest = rib_dest_from_rnode (rn);
1653 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001654 {
1655 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001656 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001657
1658 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1659 route_lock_node (rn); /* rn route table reference */
1660 rn->info = dest;
1661 dest->rnode = rn;
1662 }
1663
1664 head = dest->routes;
1665 if (head)
1666 {
Paul Jakma6d691122006-07-27 21:49:00 +00001667 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001668 }
paul718e3742002-12-13 20:15:29 +00001669 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001670 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001671 rib_queue_add (&zebrad, rn);
1672}
1673
1674static void
1675rib_addnode (struct route_node *rn, struct rib *rib)
1676{
1677 /* RIB node has been un-removed before route-node is processed.
1678 * route_node must hence already be on the queue for processing..
1679 */
1680 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1681 {
1682 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001683 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001684
Paul Jakma6d691122006-07-27 21:49:00 +00001685 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1686 return;
1687 }
1688 rib_link (rn, rib);
1689}
1690
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001691/*
1692 * rib_unlink
1693 *
1694 * Detach a rib structure from a route_node.
1695 *
1696 * Note that a call to rib_unlink() should be followed by a call to
1697 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1698 * longer required to be deleted.
1699 */
Paul Jakma6d691122006-07-27 21:49:00 +00001700static void
1701rib_unlink (struct route_node *rn, struct rib *rib)
1702{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001703 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001704
1705 assert (rn && rib);
1706
1707 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001708 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001709
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001710 dest = rib_dest_from_rnode (rn);
1711
Paul Jakma6d691122006-07-27 21:49:00 +00001712 if (rib->next)
1713 rib->next->prev = rib->prev;
1714
1715 if (rib->prev)
1716 rib->prev->next = rib->next;
1717 else
1718 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001719 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001720 }
1721
1722 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001723 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001724 XFREE (MTYPE_RIB, rib);
1725
paul718e3742002-12-13 20:15:29 +00001726}
1727
paula1ac18c2005-06-28 17:17:12 +00001728static void
paul718e3742002-12-13 20:15:29 +00001729rib_delnode (struct route_node *rn, struct rib *rib)
1730{
Paul Jakma6d691122006-07-27 21:49:00 +00001731 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001732 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001733 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1734 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001735}
1736
1737int
1738rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001739 struct in_addr *gate, struct in_addr *src,
Paul Jakma9099f9b2016-01-18 10:12:10 +00001740 ifindex_t ifindex, vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001741 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001742{
1743 struct rib *rib;
1744 struct rib *same = NULL;
1745 struct route_table *table;
1746 struct route_node *rn;
1747 struct nexthop *nexthop;
1748
1749 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001750 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00001751 if (! table)
1752 return 0;
1753
1754 /* Make it sure prefixlen is applied to the prefix. */
1755 apply_mask_ipv4 (p);
1756
1757 /* Set default distance by route type. */
1758 if (distance == 0)
1759 {
Balaji.G837d16c2012-09-26 14:09:10 +05301760 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001761 distance = 150;
1762 else
1763 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001764
1765 /* iBGP distance is 200. */
1766 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1767 distance = 200;
1768 }
1769
1770 /* Lookup route node.*/
1771 rn = route_node_get (table, (struct prefix *) p);
1772
1773 /* If same type of route are installed, treat it as a implicit
1774 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001775 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001776 {
Paul Jakma6d691122006-07-27 21:49:00 +00001777 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1778 continue;
1779
hassoebf1ead2005-09-21 14:58:20 +00001780 if (rib->type != type)
1781 continue;
1782 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001783 {
1784 same = rib;
1785 break;
1786 }
hassoebf1ead2005-09-21 14:58:20 +00001787 /* Duplicate connected route comes in. */
1788 else if ((nexthop = rib->nexthop) &&
1789 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001790 nexthop->ifindex == ifindex &&
1791 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001792 {
1793 rib->refcnt++;
1794 return 0 ;
1795 }
paul718e3742002-12-13 20:15:29 +00001796 }
1797
1798 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001799 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001800 rib->type = type;
1801 rib->distance = distance;
1802 rib->flags = flags;
1803 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001804 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02001805 rib->vrf_id = vrf_id;
1806 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00001807 rib->nexthop_num = 0;
1808 rib->uptime = time (NULL);
1809
1810 /* Nexthop settings. */
1811 if (gate)
1812 {
1813 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001814 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001815 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001816 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001817 }
1818 else
1819 nexthop_ifindex_add (rib, ifindex);
1820
1821 /* If this route is kernel route, set FIB flag to the route. */
1822 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1823 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1824 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1825
1826 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001827 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001828 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1829 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001830 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001831
paul718e3742002-12-13 20:15:29 +00001832 /* Free implicit route.*/
1833 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001834 {
1835 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001836 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1837 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001838 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001839 }
paul4d38fdb2005-04-28 17:35:14 +00001840
1841 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001842 return 0;
1843}
1844
Denis Ovsienkodc958242007-08-13 16:03:06 +00001845/* This function dumps the contents of a given RIB entry into
1846 * standard debug log. Calling function name and IP prefix in
1847 * question are passed as 1st and 2nd arguments.
1848 */
1849
David Lamparterf7bf4152013-10-22 17:10:21 +00001850void _rib_dump (const char * func,
1851 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001852{
David Lamparterf7bf4152013-10-22 17:10:21 +00001853 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001854 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001855 struct nexthop *nexthop, *tnexthop;
1856 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001857
Feng Lu0d0686f2015-05-22 11:40:02 +02001858 zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
1859 prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001860 zlog_debug
1861 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001862 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001863 func,
1864 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001865 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001866 rib->type,
1867 rib->table
1868 );
1869 zlog_debug
1870 (
1871 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1872 func,
1873 rib->metric,
1874 rib->distance,
1875 rib->flags,
1876 rib->status
1877 );
1878 zlog_debug
1879 (
1880 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1881 func,
1882 rib->nexthop_num,
1883 rib->nexthop_active_num,
1884 rib->nexthop_fib_num
1885 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001886
Christian Frankefa713d92013-07-05 15:35:37 +00001887 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1888 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001889 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001890 zlog_debug
1891 (
1892 "%s: %s %s with flags %s%s%s",
1893 func,
1894 (recursing ? " NH" : "NH"),
1895 straddr,
1896 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1897 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1898 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1899 );
1900 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001901 zlog_debug ("%s: dump complete", func);
1902}
1903
1904/* This is an exported helper to rtm_read() to dump the strange
1905 * RIB entry found by rib_lookup_ipv4_route()
1906 */
1907
1908void rib_lookup_and_dump (struct prefix_ipv4 * p)
1909{
1910 struct route_table *table;
1911 struct route_node *rn;
1912 struct rib *rib;
1913 char prefix_buf[INET_ADDRSTRLEN];
1914
1915 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001916 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001917 if (! table)
1918 {
Feng Lu41f44a22015-05-22 11:39:56 +02001919 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001920 return;
1921 }
1922
Denis Ovsienkodc958242007-08-13 16:03:06 +00001923 /* Scan the RIB table for exactly matching RIB entry. */
1924 rn = route_node_lookup (table, (struct prefix *) p);
1925
1926 /* No route for this prefix. */
1927 if (! rn)
1928 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001929 zlog_debug ("%s: lookup failed for %s", __func__,
1930 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001931 return;
1932 }
1933
1934 /* Unlock node. */
1935 route_unlock_node (rn);
1936
1937 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001938 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001939 {
1940 zlog_debug
1941 (
1942 "%s: rn %p, rib %p: %s, %s",
1943 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01001944 (void *)rn,
1945 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001946 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1947 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1948 );
David Lamparterf7bf4152013-10-22 17:10:21 +00001949 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001950 }
1951}
1952
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001953/* Check if requested address assignment will fail due to another
1954 * route being installed by zebra in FIB already. Take necessary
1955 * actions, if needed: remove such a route from FIB and deSELECT
1956 * corresponding RIB entry. Then put affected RN into RIBQ head.
1957 */
1958void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1959{
1960 struct route_table *table;
1961 struct route_node *rn;
1962 struct rib *rib;
1963 unsigned changed = 0;
1964
Feng Lu41f44a22015-05-22 11:39:56 +02001965 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001966 {
Feng Lu41f44a22015-05-22 11:39:56 +02001967 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001968 return;
1969 }
1970
1971 /* No matches would be the simplest case. */
1972 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1973 return;
1974
1975 /* Unlock node. */
1976 route_unlock_node (rn);
1977
1978 /* Check all RIB entries. In case any changes have to be done, requeue
1979 * the RN into RIBQ head. If the routing message about the new connected
1980 * route (generated by the IP address we are going to assign very soon)
1981 * comes before the RIBQ is processed, the new RIB entry will join
1982 * RIBQ record already on head. This is necessary for proper revalidation
1983 * of the rest of the RIB.
1984 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001985 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001986 {
Timo Teräs325823a2016-01-15 17:36:31 +02001987 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB) &&
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001988 ! RIB_SYSTEM_ROUTE (rib))
1989 {
1990 changed = 1;
1991 if (IS_ZEBRA_DEBUG_RIB)
1992 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001993 char buf[PREFIX_STRLEN];
1994 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
1995 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00001996 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001997 }
1998 rib_uninstall (rn, rib);
1999 }
2000 }
2001 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002002 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002003}
2004
paul718e3742002-12-13 20:15:29 +00002005int
G.Balajicddf3912011-11-26 21:59:32 +04002006rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002007{
2008 struct route_table *table;
2009 struct route_node *rn;
2010 struct rib *same;
2011 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002012
paul718e3742002-12-13 20:15:29 +00002013 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002014 table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +00002015 if (! table)
2016 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002017
paul718e3742002-12-13 20:15:29 +00002018 /* Make it sure prefixlen is applied to the prefix. */
2019 apply_mask_ipv4 (p);
2020
2021 /* Set default distance by route type. */
2022 if (rib->distance == 0)
2023 {
2024 rib->distance = route_info[rib->type].distance;
2025
2026 /* iBGP distance is 200. */
2027 if (rib->type == ZEBRA_ROUTE_BGP
2028 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2029 rib->distance = 200;
2030 }
2031
2032 /* Lookup route node.*/
2033 rn = route_node_get (table, (struct prefix *) p);
2034
2035 /* If same type of route are installed, treat it as a implicit
2036 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002037 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002038 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002039 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002040 continue;
2041
paul718e3742002-12-13 20:15:29 +00002042 if (same->type == rib->type && same->table == rib->table
2043 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002044 break;
paul718e3742002-12-13 20:15:29 +00002045 }
paul4d38fdb2005-04-28 17:35:14 +00002046
paul718e3742002-12-13 20:15:29 +00002047 /* If this route is kernel route, set FIB flag to the route. */
2048 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2049 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2050 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2051
2052 /* Link new rib to node.*/
2053 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002054 if (IS_ZEBRA_DEBUG_RIB)
2055 {
2056 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002057 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002058 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002059 }
paul718e3742002-12-13 20:15:29 +00002060
paul718e3742002-12-13 20:15:29 +00002061 /* Free implicit route.*/
2062 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002063 {
2064 if (IS_ZEBRA_DEBUG_RIB)
2065 {
2066 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002067 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002068 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002069 }
paul4d38fdb2005-04-28 17:35:14 +00002070 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002071 }
paul4d38fdb2005-04-28 17:35:14 +00002072
2073 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002074 return 0;
2075}
2076
hassoebf1ead2005-09-21 14:58:20 +00002077/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002078int
2079rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma9099f9b2016-01-18 10:12:10 +00002080 struct in_addr *gate, ifindex_t ifindex,
2081 vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002082{
2083 struct route_table *table;
2084 struct route_node *rn;
2085 struct rib *rib;
2086 struct rib *fib = NULL;
2087 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002088 struct nexthop *nexthop, *tnexthop;
2089 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002090 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002091 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002092
2093 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002094 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002095 if (! table)
2096 return 0;
2097
2098 /* Apply mask. */
2099 apply_mask_ipv4 (p);
2100
Christian Frankeb52aef12013-11-27 17:06:15 +00002101 if (IS_ZEBRA_DEBUG_KERNEL)
2102 {
2103 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002104 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
2105 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002106 inet_ntoa (*gate),
2107 ifindex);
2108 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002109 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
2110 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002111 ifindex);
2112 }
paul5ec90d22003-06-19 01:41:37 +00002113
paul718e3742002-12-13 20:15:29 +00002114 /* Lookup route node. */
2115 rn = route_node_lookup (table, (struct prefix *) p);
2116 if (! rn)
2117 {
2118 if (IS_ZEBRA_DEBUG_KERNEL)
2119 {
2120 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002121 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2122 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002123 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002124 ifindex);
2125 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002126 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2127 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002128 ifindex);
2129 }
2130 return ZEBRA_ERR_RTNOEXIST;
2131 }
2132
2133 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002134 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002135 {
Paul Jakma6d691122006-07-27 21:49:00 +00002136 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2137 continue;
2138
Timo Teräs325823a2016-01-15 17:36:31 +02002139 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00002140 fib = rib;
2141
hassoebf1ead2005-09-21 14:58:20 +00002142 if (rib->type != type)
2143 continue;
2144 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002145 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002146 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002147 if (nexthop->ifindex != ifindex)
2148 continue;
hassoebf1ead2005-09-21 14:58:20 +00002149 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002150 {
hassoebf1ead2005-09-21 14:58:20 +00002151 rib->refcnt--;
2152 route_unlock_node (rn);
2153 route_unlock_node (rn);
2154 return 0;
paul718e3742002-12-13 20:15:29 +00002155 }
hassoebf1ead2005-09-21 14:58:20 +00002156 same = rib;
2157 break;
paul718e3742002-12-13 20:15:29 +00002158 }
hassoebf1ead2005-09-21 14:58:20 +00002159 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002160 else
paul5ec90d22003-06-19 01:41:37 +00002161 {
Christian Frankefa713d92013-07-05 15:35:37 +00002162 if (gate == NULL)
2163 {
2164 same = rib;
2165 break;
2166 }
2167 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2168 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2169 {
2170 same = rib;
2171 break;
2172 }
2173 if (same)
2174 break;
2175 }
paul718e3742002-12-13 20:15:29 +00002176 }
paul718e3742002-12-13 20:15:29 +00002177 /* If same type of route can't be found and this message is from
2178 kernel. */
2179 if (! same)
2180 {
2181 if (fib && type == ZEBRA_ROUTE_KERNEL)
2182 {
2183 /* Unset flags. */
2184 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2185 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2186
Timo Teräs325823a2016-01-15 17:36:31 +02002187 UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
paul718e3742002-12-13 20:15:29 +00002188 }
2189 else
2190 {
2191 if (IS_ZEBRA_DEBUG_KERNEL)
2192 {
2193 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002194 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2195 "doesn't exist in rib",
2196 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002197 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002198 ifindex,
2199 type);
2200 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002201 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2202 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002203 ifindex,
2204 type);
2205 }
2206 route_unlock_node (rn);
2207 return ZEBRA_ERR_RTNOEXIST;
2208 }
2209 }
paul4d38fdb2005-04-28 17:35:14 +00002210
paul718e3742002-12-13 20:15:29 +00002211 if (same)
2212 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002213
paul718e3742002-12-13 20:15:29 +00002214 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002215 return 0;
2216}
David Lamparter6b0655a2014-06-04 06:53:35 +02002217
paul718e3742002-12-13 20:15:29 +00002218/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002219static void
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002220static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002221{
2222 struct rib *rib;
2223 struct route_node *rn;
2224 struct route_table *table;
2225
2226 /* Lookup table. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002227 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002228 if (! table)
2229 return;
2230
2231 /* Lookup existing route */
2232 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002233 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002234 {
2235 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2236 continue;
2237
2238 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2239 break;
2240 }
paul718e3742002-12-13 20:15:29 +00002241
2242 if (rib)
2243 {
2244 /* Same distance static route is there. Update it with new
2245 nexthop. */
paul718e3742002-12-13 20:15:29 +00002246 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002247 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002248 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002249 case STATIC_IPV4_GATEWAY:
2250 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2251 break;
2252 case STATIC_IPV4_IFNAME:
2253 nexthop_ifname_add (rib, si->ifname);
2254 break;
2255 case STATIC_IPV4_BLACKHOLE:
2256 nexthop_blackhole_add (rib);
2257 break;
2258 case STATIC_IPV6_GATEWAY:
2259 nexthop_ipv6_add (rib, &si->addr.ipv6);
2260 break;
2261 case STATIC_IPV6_IFNAME:
2262 nexthop_ifname_add (rib, si->ifname);
2263 break;
2264 case STATIC_IPV6_GATEWAY_IFNAME:
2265 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2266 break;
paul4d38fdb2005-04-28 17:35:14 +00002267 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002268 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002269 }
2270 else
2271 {
2272 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002273 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2274
paul718e3742002-12-13 20:15:29 +00002275 rib->type = ZEBRA_ROUTE_STATIC;
2276 rib->distance = si->distance;
2277 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002278 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002279 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002280 rib->nexthop_num = 0;
2281
2282 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002283 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002284 case STATIC_IPV4_GATEWAY:
2285 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2286 break;
2287 case STATIC_IPV4_IFNAME:
2288 nexthop_ifname_add (rib, si->ifname);
2289 break;
2290 case STATIC_IPV4_BLACKHOLE:
2291 nexthop_blackhole_add (rib);
2292 break;
2293 case STATIC_IPV6_GATEWAY:
2294 nexthop_ipv6_add (rib, &si->addr.ipv6);
2295 break;
2296 case STATIC_IPV6_IFNAME:
2297 nexthop_ifname_add (rib, si->ifname);
2298 break;
2299 case STATIC_IPV6_GATEWAY_IFNAME:
2300 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2301 break;
paul7021c422003-07-15 12:52:22 +00002302 }
paul718e3742002-12-13 20:15:29 +00002303
hasso81dfcaa2003-05-25 19:21:25 +00002304 /* Save the flags of this static routes (reject, blackhole) */
2305 rib->flags = si->flags;
2306
paul718e3742002-12-13 20:15:29 +00002307 /* Link this rib to the tree. */
2308 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002309 }
2310}
2311
paula1ac18c2005-06-28 17:17:12 +00002312static int
Donald Sharpa979ab72015-11-04 13:26:38 -05002313static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002314{
2315 if (nexthop->type == NEXTHOP_TYPE_IPV4
2316 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002317 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002318 return 1;
2319 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2320 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002321 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002322 return 1;
paul595db7f2003-05-25 21:35:06 +00002323 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2324 && si->type == STATIC_IPV4_BLACKHOLE)
2325 return 1;
Donald Sharpa979ab72015-11-04 13:26:38 -05002326 if (nexthop->type == NEXTHOP_TYPE_IPV6
2327 && si->type == STATIC_IPV6_GATEWAY
2328 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
2329 return 1;
2330 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2331 && si->type == STATIC_IPV6_IFNAME
2332 && strcmp (nexthop->ifname, si->ifname) == 0)
2333 return 1;
2334 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2335 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2336 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
2337 && strcmp (nexthop->ifname, si->ifname) == 0)
2338 return 1;
paule8e19462006-01-19 20:16:55 +00002339 return 0;
paul718e3742002-12-13 20:15:29 +00002340}
2341
2342/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002343static void
Donald Sharp949b7192015-11-04 13:26:39 -05002344static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002345{
2346 struct route_node *rn;
2347 struct rib *rib;
2348 struct nexthop *nexthop;
2349 struct route_table *table;
2350
2351 /* Lookup table. */
Donald Sharp949b7192015-11-04 13:26:39 -05002352 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002353 if (! table)
2354 return;
paul4d38fdb2005-04-28 17:35:14 +00002355
paul718e3742002-12-13 20:15:29 +00002356 /* Lookup existing route with type and distance. */
2357 rn = route_node_lookup (table, p);
2358 if (! rn)
2359 return;
2360
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002361 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002362 {
2363 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2364 continue;
2365
2366 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2367 break;
2368 }
paul718e3742002-12-13 20:15:29 +00002369
2370 if (! rib)
2371 {
2372 route_unlock_node (rn);
2373 return;
2374 }
2375
2376 /* Lookup nexthop. */
2377 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Donald Sharpa979ab72015-11-04 13:26:38 -05002378 if (static_nexthop_same (nexthop, si))
paul718e3742002-12-13 20:15:29 +00002379 break;
2380
2381 /* Can't find nexthop. */
2382 if (! nexthop)
2383 {
2384 route_unlock_node (rn);
2385 return;
2386 }
2387
2388 /* Check nexthop. */
2389 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002390 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002391 else
2392 {
paul6baeb982003-10-28 03:47:15 +00002393 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2394 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002395 nexthop_delete (rib, nexthop);
2396 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002397 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002398 }
paul718e3742002-12-13 20:15:29 +00002399 /* Unlock node. */
2400 route_unlock_node (rn);
2401}
2402
paul718e3742002-12-13 20:15:29 +00002403int
Everton Marques33d86db2014-07-14 11:19:00 -03002404static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2405 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002406 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002407{
2408 u_char type = 0;
2409 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002410 struct static_route *si;
2411 struct static_route *pp;
2412 struct static_route *cp;
2413 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002414 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2415 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002416
paul718e3742002-12-13 20:15:29 +00002417 if (! stable)
2418 return -1;
2419
2420 /* Lookup static route prefix. */
2421 rn = route_node_get (stable, p);
2422
2423 /* Make flags. */
2424 if (gate)
2425 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002426 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002427 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002428 else
2429 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002430
2431 /* Do nothing if there is a same static route. */
2432 for (si = rn->info; si; si = si->next)
2433 {
2434 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002435 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2436 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002437 {
2438 if (distance == si->distance)
2439 {
2440 route_unlock_node (rn);
2441 return 0;
2442 }
2443 else
2444 update = si;
2445 }
2446 }
2447
Paul Jakma3c0755d2006-12-08 00:53:14 +00002448 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002449 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002450 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002451
2452 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002453 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002454
2455 si->type = type;
2456 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002457 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002458 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002459
2460 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002461 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002462 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002463 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002464
2465 /* Add new static route information to the tree with sort by
2466 distance value and gateway address. */
2467 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2468 {
2469 if (si->distance < cp->distance)
2470 break;
2471 if (si->distance > cp->distance)
2472 continue;
2473 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2474 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002475 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002476 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002477 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002478 continue;
2479 }
2480 }
2481
2482 /* Make linked list. */
2483 if (pp)
2484 pp->next = si;
2485 else
2486 rn->info = si;
2487 if (cp)
2488 cp->prev = si;
2489 si->prev = pp;
2490 si->next = cp;
2491
2492 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002493 static_install_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002494
2495 return 1;
2496}
2497
paul718e3742002-12-13 20:15:29 +00002498int
Everton Marques33d86db2014-07-14 11:19:00 -03002499static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002500 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002501{
2502 u_char type = 0;
2503 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002504 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002505 struct route_table *stable;
2506
2507 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002508 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002509 if (! stable)
2510 return -1;
2511
2512 /* Lookup static route prefix. */
2513 rn = route_node_lookup (stable, p);
2514 if (! rn)
2515 return 0;
2516
2517 /* Make flags. */
2518 if (gate)
2519 type = STATIC_IPV4_GATEWAY;
2520 else if (ifname)
2521 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002522 else
2523 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002524
2525 /* Find same static route is the tree */
2526 for (si = rn->info; si; si = si->next)
2527 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002528 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2529 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002530 break;
2531
2532 /* Can't find static route. */
2533 if (! si)
2534 {
2535 route_unlock_node (rn);
2536 return 0;
2537 }
2538
2539 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002540 static_uninstall_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002541
2542 /* Unlink static route from linked list. */
2543 if (si->prev)
2544 si->prev->next = si->next;
2545 else
2546 rn->info = si->next;
2547 if (si->next)
2548 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002549 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002550
2551 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002552 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002553 XFREE (0, si->ifname);
2554 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002555
paul143a3852003-09-29 20:06:13 +00002556 route_unlock_node (rn);
2557
paul718e3742002-12-13 20:15:29 +00002558 return 1;
2559}
2560
paul718e3742002-12-13 20:15:29 +00002561int
2562rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Paul Jakma9099f9b2016-01-18 10:12:10 +00002563 struct in6_addr *gate, ifindex_t ifindex,
Feng Lu0d0686f2015-05-22 11:40:02 +02002564 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002565 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002566{
2567 struct rib *rib;
2568 struct rib *same = NULL;
2569 struct route_table *table;
2570 struct route_node *rn;
2571 struct nexthop *nexthop;
2572
paul718e3742002-12-13 20:15:29 +00002573 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002574 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002575 if (! table)
2576 return 0;
2577
2578 /* Make sure mask is applied. */
2579 apply_mask_ipv6 (p);
2580
2581 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002582 if (!distance)
2583 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002584
2585 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2586 distance = 200;
2587
paul718e3742002-12-13 20:15:29 +00002588 /* Lookup route node.*/
2589 rn = route_node_get (table, (struct prefix *) p);
2590
2591 /* If same type of route are installed, treat it as a implicit
2592 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002593 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002594 {
Paul Jakma6d691122006-07-27 21:49:00 +00002595 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2596 continue;
2597
hassoebf1ead2005-09-21 14:58:20 +00002598 if (rib->type != type)
2599 continue;
2600 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002601 {
2602 same = rib;
paul718e3742002-12-13 20:15:29 +00002603 break;
2604 }
hassoebf1ead2005-09-21 14:58:20 +00002605 else if ((nexthop = rib->nexthop) &&
2606 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2607 nexthop->ifindex == ifindex)
2608 {
2609 rib->refcnt++;
2610 return 0;
2611 }
paul718e3742002-12-13 20:15:29 +00002612 }
2613
2614 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002615 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2616
paul718e3742002-12-13 20:15:29 +00002617 rib->type = type;
2618 rib->distance = distance;
2619 rib->flags = flags;
2620 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002621 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002622 rib->vrf_id = vrf_id;
2623 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002624 rib->nexthop_num = 0;
2625 rib->uptime = time (NULL);
2626
2627 /* Nexthop settings. */
2628 if (gate)
2629 {
2630 if (ifindex)
2631 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2632 else
2633 nexthop_ipv6_add (rib, gate);
2634 }
2635 else
2636 nexthop_ifindex_add (rib, ifindex);
2637
2638 /* If this route is kernel route, set FIB flag to the route. */
2639 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2640 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2641 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2642
2643 /* Link new rib to node.*/
2644 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002645 if (IS_ZEBRA_DEBUG_RIB)
2646 {
2647 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002648 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002649 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002650 }
paul718e3742002-12-13 20:15:29 +00002651
paul718e3742002-12-13 20:15:29 +00002652 /* Free implicit route.*/
2653 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002654 {
2655 if (IS_ZEBRA_DEBUG_RIB)
2656 {
2657 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002658 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002659 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002660 }
paul4d38fdb2005-04-28 17:35:14 +00002661 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002662 }
paul4d38fdb2005-04-28 17:35:14 +00002663
2664 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002665 return 0;
2666}
2667
hassoebf1ead2005-09-21 14:58:20 +00002668/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002669int
2670rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Paul Jakma9099f9b2016-01-18 10:12:10 +00002671 struct in6_addr *gate, ifindex_t ifindex,
2672 vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002673{
2674 struct route_table *table;
2675 struct route_node *rn;
2676 struct rib *rib;
2677 struct rib *fib = NULL;
2678 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002679 struct nexthop *nexthop, *tnexthop;
2680 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002681 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002682 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002683
2684 /* Apply mask. */
2685 apply_mask_ipv6 (p);
2686
2687 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002688 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002689 if (! table)
2690 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002691
paul718e3742002-12-13 20:15:29 +00002692 /* Lookup route node. */
2693 rn = route_node_lookup (table, (struct prefix *) p);
2694 if (! rn)
2695 {
2696 if (IS_ZEBRA_DEBUG_KERNEL)
2697 {
2698 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002699 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2700 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002701 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002702 ifindex);
2703 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002704 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2705 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002706 ifindex);
2707 }
2708 return ZEBRA_ERR_RTNOEXIST;
2709 }
2710
2711 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002712 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002713 {
Paul Jakma6d691122006-07-27 21:49:00 +00002714 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2715 continue;
2716
Timo Teräs325823a2016-01-15 17:36:31 +02002717 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00002718 fib = rib;
2719
hassoebf1ead2005-09-21 14:58:20 +00002720 if (rib->type != type)
2721 continue;
2722 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002723 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002724 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002725 if (nexthop->ifindex != ifindex)
2726 continue;
hassoebf1ead2005-09-21 14:58:20 +00002727 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002728 {
hassoebf1ead2005-09-21 14:58:20 +00002729 rib->refcnt--;
2730 route_unlock_node (rn);
2731 route_unlock_node (rn);
2732 return 0;
paul718e3742002-12-13 20:15:29 +00002733 }
hassoebf1ead2005-09-21 14:58:20 +00002734 same = rib;
2735 break;
paul718e3742002-12-13 20:15:29 +00002736 }
hassoebf1ead2005-09-21 14:58:20 +00002737 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002738 else
2739 {
2740 if (gate == NULL)
2741 {
2742 same = rib;
2743 break;
2744 }
2745 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2746 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2747 {
2748 same = rib;
2749 break;
2750 }
2751 if (same)
2752 break;
2753 }
paul718e3742002-12-13 20:15:29 +00002754 }
2755
2756 /* If same type of route can't be found and this message is from
2757 kernel. */
2758 if (! same)
2759 {
2760 if (fib && type == ZEBRA_ROUTE_KERNEL)
2761 {
2762 /* Unset flags. */
2763 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2764 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2765
Timo Teräs325823a2016-01-15 17:36:31 +02002766 UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
paul718e3742002-12-13 20:15:29 +00002767 }
2768 else
2769 {
2770 if (IS_ZEBRA_DEBUG_KERNEL)
2771 {
2772 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002773 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2774 "doesn't exist in rib",
2775 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002776 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002777 ifindex,
2778 type);
2779 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002780 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2781 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002782 ifindex,
2783 type);
2784 }
2785 route_unlock_node (rn);
2786 return ZEBRA_ERR_RTNOEXIST;
2787 }
2788 }
2789
2790 if (same)
2791 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002792
paul718e3742002-12-13 20:15:29 +00002793 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002794 return 0;
2795}
David Lamparter6b0655a2014-06-04 06:53:35 +02002796
paul718e3742002-12-13 20:15:29 +00002797
2798/* Add static route into static route configuration. */
2799int
2800static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002801 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002802 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002803{
2804 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002805 struct static_route *si;
2806 struct static_route *pp;
2807 struct static_route *cp;
Donald Sharpc1900e02015-11-04 13:26:40 -05002808 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002809 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2810 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002811
paul718e3742002-12-13 20:15:29 +00002812 if (! stable)
2813 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002814
2815 if (!gate &&
2816 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2817 return -1;
2818
2819 if (!ifname &&
2820 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2821 return -1;
paul718e3742002-12-13 20:15:29 +00002822
2823 /* Lookup static route prefix. */
2824 rn = route_node_get (stable, p);
2825
2826 /* Do nothing if there is a same static route. */
2827 for (si = rn->info; si; si = si->next)
2828 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002829 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002830 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002831 && (! ifname || strcmp (ifname, si->ifname) == 0))
2832 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002833 if (distance == si->distance)
2834 {
2835 route_unlock_node (rn);
2836 return 0;
2837 }
2838 else
2839 update = si;
paul718e3742002-12-13 20:15:29 +00002840 }
2841 }
2842
Donald Sharpc1900e02015-11-04 13:26:40 -05002843 if (update)
2844 static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
2845
paul718e3742002-12-13 20:15:29 +00002846 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002847 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002848
2849 si->type = type;
2850 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002851 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002852 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002853
2854 switch (type)
2855 {
2856 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002857 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002858 break;
2859 case STATIC_IPV6_IFNAME:
2860 si->ifname = XSTRDUP (0, ifname);
2861 break;
2862 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002863 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002864 si->ifname = XSTRDUP (0, ifname);
2865 break;
2866 }
2867
2868 /* Add new static route information to the tree with sort by
2869 distance value and gateway address. */
2870 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2871 {
2872 if (si->distance < cp->distance)
2873 break;
2874 if (si->distance > cp->distance)
2875 continue;
2876 }
2877
2878 /* Make linked list. */
2879 if (pp)
2880 pp->next = si;
2881 else
2882 rn->info = si;
2883 if (cp)
2884 cp->prev = si;
2885 si->prev = pp;
2886 si->next = cp;
2887
2888 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002889 static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002890
2891 return 1;
2892}
2893
2894/* Delete static route from static route configuration. */
2895int
2896static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002897 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002898{
2899 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002900 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002901 struct route_table *stable;
2902
2903 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002904 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002905 if (! stable)
2906 return -1;
2907
2908 /* Lookup static route prefix. */
2909 rn = route_node_lookup (stable, p);
2910 if (! rn)
2911 return 0;
2912
2913 /* Find same static route is the tree */
2914 for (si = rn->info; si; si = si->next)
2915 if (distance == si->distance
2916 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002917 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002918 && (! ifname || strcmp (ifname, si->ifname) == 0))
2919 break;
2920
2921 /* Can't find static route. */
2922 if (! si)
2923 {
2924 route_unlock_node (rn);
2925 return 0;
2926 }
2927
2928 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002929 static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002930
2931 /* Unlink static route from linked list. */
2932 if (si->prev)
2933 si->prev->next = si->next;
2934 else
2935 rn->info = si->next;
2936 if (si->next)
2937 si->next->prev = si->prev;
2938
2939 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002940 if (ifname)
2941 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05002942 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002943
2944 return 1;
2945}
David Lamparter6b0655a2014-06-04 06:53:35 +02002946
paul718e3742002-12-13 20:15:29 +00002947/* RIB update function. */
2948void
Feng Lu0d0686f2015-05-22 11:40:02 +02002949rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002950{
2951 struct route_node *rn;
2952 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002953
Feng Lu0d0686f2015-05-22 11:40:02 +02002954 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002955 if (table)
2956 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002957 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002958 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002959
Feng Lu0d0686f2015-05-22 11:40:02 +02002960 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002961 if (table)
2962 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002963 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002964 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002965}
2966
David Lamparter6b0655a2014-06-04 06:53:35 +02002967
paul718e3742002-12-13 20:15:29 +00002968/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002969static void
paul718e3742002-12-13 20:15:29 +00002970rib_weed_table (struct route_table *table)
2971{
2972 struct route_node *rn;
2973 struct rib *rib;
2974 struct rib *next;
2975
2976 if (table)
2977 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002978 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002979 {
Paul Jakma6d691122006-07-27 21:49:00 +00002980 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2981 continue;
2982
paulb21b19c2003-06-15 01:28:29 +00002983 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002984 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002985 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002986 }
2987}
2988
2989/* Delete all routes from non main table. */
2990void
paula1ac18c2005-06-28 17:17:12 +00002991rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002992{
Feng Lu0d0686f2015-05-22 11:40:02 +02002993 vrf_iter_t iter;
2994 struct zebra_vrf *zvrf;
2995
2996 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
2997 if ((zvrf = vrf_iter2info (iter)) != NULL)
2998 {
2999 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3000 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3001 }
paul718e3742002-12-13 20:15:29 +00003002}
David Lamparter6b0655a2014-06-04 06:53:35 +02003003
Feng Lu0d0686f2015-05-22 11:40:02 +02003004#if 0
paul718e3742002-12-13 20:15:29 +00003005/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003006static void
paul718e3742002-12-13 20:15:29 +00003007rib_sweep_table (struct route_table *table)
3008{
3009 struct route_node *rn;
3010 struct rib *rib;
3011 struct rib *next;
3012 int ret = 0;
3013
3014 if (table)
3015 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003016 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003017 {
Paul Jakma6d691122006-07-27 21:49:00 +00003018 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3019 continue;
3020
paul718e3742002-12-13 20:15:29 +00003021 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3022 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3023 {
Timo Teräs0abf6792016-01-15 17:36:29 +02003024 ret = rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00003025 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003026 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003027 }
3028 }
3029}
Feng Lu0d0686f2015-05-22 11:40:02 +02003030#endif
paul718e3742002-12-13 20:15:29 +00003031
3032/* Sweep all RIB tables. */
3033void
paula1ac18c2005-06-28 17:17:12 +00003034rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003035{
Feng Lu0d0686f2015-05-22 11:40:02 +02003036 vrf_iter_t iter;
3037 struct zebra_vrf *zvrf;
3038
3039 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3040 if ((zvrf = vrf_iter2info (iter)) != NULL)
3041 {
3042 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3043 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3044 }
paul718e3742002-12-13 20:15:29 +00003045}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003046
3047/* Remove specific by protocol routes from 'table'. */
3048static unsigned long
3049rib_score_proto_table (u_char proto, struct route_table *table)
3050{
3051 struct route_node *rn;
3052 struct rib *rib;
3053 struct rib *next;
3054 unsigned long n = 0;
3055
3056 if (table)
3057 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003058 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003059 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003060 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3061 continue;
3062 if (rib->type == proto)
3063 {
3064 rib_delnode (rn, rib);
3065 n++;
3066 }
3067 }
3068
3069 return n;
3070}
3071
3072/* Remove specific by protocol routes. */
3073unsigned long
3074rib_score_proto (u_char proto)
3075{
Feng Lu0d0686f2015-05-22 11:40:02 +02003076 vrf_iter_t iter;
3077 struct zebra_vrf *zvrf;
3078 unsigned long cnt = 0;
3079
3080 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3081 if ((zvrf = vrf_iter2info (iter)) != NULL)
3082 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3083 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3084
3085 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003086}
3087
paul718e3742002-12-13 20:15:29 +00003088/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003089void
paul718e3742002-12-13 20:15:29 +00003090rib_close_table (struct route_table *table)
3091{
3092 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003093 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003094 struct rib *rib;
3095
3096 if (table)
3097 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003098 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003099 {
Timo Teräs325823a2016-01-15 17:36:31 +02003100 if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003101 continue;
3102
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003103 if (info->safi == SAFI_UNICAST)
3104 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003105
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003106 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02003107 rib_update_kernel (rn, rib, NULL);
Paul Jakma6d691122006-07-27 21:49:00 +00003108 }
paul718e3742002-12-13 20:15:29 +00003109}
3110
3111/* Close all RIB tables. */
3112void
paula1ac18c2005-06-28 17:17:12 +00003113rib_close (void)
paul718e3742002-12-13 20:15:29 +00003114{
Feng Lu0d0686f2015-05-22 11:40:02 +02003115 vrf_iter_t iter;
3116 struct zebra_vrf *zvrf;
3117
3118 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3119 if ((zvrf = vrf_iter2info (iter)) != NULL)
3120 {
3121 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3122 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3123 }
paul718e3742002-12-13 20:15:29 +00003124}
David Lamparter6b0655a2014-06-04 06:53:35 +02003125
paul718e3742002-12-13 20:15:29 +00003126/* Routing information base initialize. */
3127void
paula1ac18c2005-06-28 17:17:12 +00003128rib_init (void)
paul718e3742002-12-13 20:15:29 +00003129{
paul4d38fdb2005-04-28 17:35:14 +00003130 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003131}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003132
3133/*
3134 * vrf_id_get_next
3135 *
3136 * Get the first vrf id that is greater than the given vrf id if any.
3137 *
3138 * Returns TRUE if a vrf id was found, FALSE otherwise.
3139 */
3140static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003141vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003142{
Feng Lu41f44a22015-05-22 11:39:56 +02003143 vrf_iter_t iter = vrf_iterator (vrf_id);
3144 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3145
3146 /* The same one ? Then find out the next. */
3147 if (zvrf && (zvrf->vrf_id == vrf_id))
3148 zvrf = vrf_iter2info (vrf_next (iter));
3149
3150 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003151 {
Feng Lu41f44a22015-05-22 11:39:56 +02003152 *next_id_p = zvrf->vrf_id;
3153 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003154 }
3155
3156 return 0;
3157}
3158
3159/*
3160 * rib_tables_iter_next
3161 *
3162 * Returns the next table in the iteration.
3163 */
3164struct route_table *
3165rib_tables_iter_next (rib_tables_iter_t *iter)
3166{
3167 struct route_table *table;
3168
3169 /*
3170 * Array that helps us go over all AFI/SAFI combinations via one
3171 * index.
3172 */
3173 static struct {
3174 afi_t afi;
3175 safi_t safi;
3176 } afi_safis[] = {
3177 { AFI_IP, SAFI_UNICAST },
3178 { AFI_IP, SAFI_MULTICAST },
3179 { AFI_IP6, SAFI_UNICAST },
3180 { AFI_IP6, SAFI_MULTICAST },
3181 };
3182
3183 table = NULL;
3184
3185 switch (iter->state)
3186 {
3187
3188 case RIB_TABLES_ITER_S_INIT:
Donald Sharp0d271292015-11-19 07:21:30 -05003189 iter->vrf_id = VRF_DEFAULT;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003190 iter->afi_safi_ix = -1;
3191
3192 /* Fall through */
3193
3194 case RIB_TABLES_ITER_S_ITERATING:
3195 iter->afi_safi_ix++;
3196 while (1)
3197 {
3198
3199 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3200 {
Feng Lu41f44a22015-05-22 11:39:56 +02003201 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003202 afi_safis[iter->afi_safi_ix].safi,
3203 iter->vrf_id);
3204 if (table)
3205 break;
3206
3207 iter->afi_safi_ix++;
3208 }
3209
3210 /*
3211 * Found another table in this vrf.
3212 */
3213 if (table)
3214 break;
3215
3216 /*
3217 * Done with all tables in the current vrf, go to the next
3218 * one.
3219 */
3220 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3221 break;
3222
3223 iter->afi_safi_ix = 0;
3224 }
3225
3226 break;
3227
3228 case RIB_TABLES_ITER_S_DONE:
3229 return NULL;
3230 }
3231
3232 if (table)
3233 iter->state = RIB_TABLES_ITER_S_ITERATING;
3234 else
3235 iter->state = RIB_TABLES_ITER_S_DONE;
3236
3237 return table;
3238}
Feng Lu41f44a22015-05-22 11:39:56 +02003239
3240/*
3241 * Create a routing table for the specific AFI/SAFI in the given VRF.
3242 */
3243static void
3244zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3245{
3246 rib_table_info_t *info;
3247 struct route_table *table;
3248
3249 assert (!zvrf->table[afi][safi]);
3250
3251 table = route_table_init ();
3252 zvrf->table[afi][safi] = table;
3253
3254 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3255 info->zvrf = zvrf;
3256 info->afi = afi;
3257 info->safi = safi;
3258 table->info = info;
3259}
3260
3261/* Allocate new zebra VRF. */
3262struct zebra_vrf *
3263zebra_vrf_alloc (vrf_id_t vrf_id)
3264{
3265 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003266#ifdef HAVE_NETLINK
3267 char nl_name[64];
3268#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003269
3270 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3271
3272 /* Allocate routing table and static table. */
3273 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3274 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3275 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3276 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3277 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3278 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3279 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3280 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3281
3282 /* Set VRF ID */
3283 zvrf->vrf_id = vrf_id;
3284
Feng Lu758fb8f2014-07-03 18:23:09 +08003285#ifdef HAVE_NETLINK
3286 /* Initialize netlink sockets */
3287 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3288 zvrf->netlink.sock = -1;
3289 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3290
3291 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3292 zvrf->netlink_cmd.sock = -1;
3293 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3294#endif
3295
Feng Lu41f44a22015-05-22 11:39:56 +02003296 return zvrf;
3297}
3298
3299/* Lookup the routing table in an enabled VRF. */
3300struct route_table *
3301zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3302{
3303 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3304
3305 if (!zvrf)
3306 return NULL;
3307
3308 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3309 return NULL;
3310
3311 return zvrf->table[afi][safi];
3312}
3313
3314/* Lookup the static routing table in a VRF. */
3315struct route_table *
3316zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3317{
3318 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3319
3320 if (!zvrf)
3321 return NULL;
3322
3323 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3324 return NULL;
3325
3326 return zvrf->stable[afi][safi];
3327}
3328