blob: 926408721876034f0958a76785ace7500041d8f6 [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 *
201nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
202{
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 Jakma7514fb72007-05-02 16:05:35 +0000246 struct in_addr *src, unsigned int 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,
294 unsigned int ifindex)
295{
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;
390 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
391 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;
524 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
525 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;
636 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
637 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;
781 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
782 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;
841 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
842 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;
907 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
908 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;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001077 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001078
1079 rib->nexthop_active_num = 0;
Timo Teräs7eb61362015-11-02 16:50:05 +02001080 UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
paul718e3742002-12-13 20:15:29 +00001081
1082 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001083 {
1084 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001085 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001086 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1087 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001088 if (prev_active != new_active ||
1089 prev_index != nexthop->ifindex)
Timo Teräs7eb61362015-11-02 16:50:05 +02001090 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001091 }
paul718e3742002-12-13 20:15:29 +00001092 return rib->nexthop_active_num;
1093}
paul6baeb982003-10-28 03:47:15 +00001094
David Lamparter6b0655a2014-06-04 06:53:35 +02001095
paul718e3742002-12-13 20:15:29 +00001096
Timo Teräs0abf6792016-01-15 17:36:29 +02001097static int
1098rib_update_kernel (struct route_node *rn, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001099{
1100 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001101 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001102 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001103 int recursing;
paul718e3742002-12-13 20:15:29 +00001104
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001105 if (info->safi != SAFI_UNICAST)
1106 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001107 if (new)
1108 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1109 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1110 if (old)
1111 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1112 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1113 return 0;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001114 }
1115
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001116 /*
1117 * Make sure we update the FPM any time we send new information to
1118 * the kernel.
1119 */
Timo Teräs0abf6792016-01-15 17:36:29 +02001120 zfpm_trigger_update (rn, "updating in kernel");
1121
1122 ret = kernel_route_rib (&rn->p, old, new);
paul718e3742002-12-13 20:15:29 +00001123
Denis Ovsienkodc958242007-08-13 16:03:06 +00001124 /* This condition is never met, if we are using rt_socket.c */
Timo Teräs0abf6792016-01-15 17:36:29 +02001125 if (ret < 0 && new)
1126 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1127 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001128
Timo Teräs0abf6792016-01-15 17:36:29 +02001129 if (old)
1130 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1131 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001132
1133 return ret;
1134}
1135
1136/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001137static void
paul718e3742002-12-13 20:15:29 +00001138rib_uninstall (struct route_node *rn, struct rib *rib)
1139{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001140 rib_table_info_t *info = rn->table->info;
1141
paul718e3742002-12-13 20:15:29 +00001142 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1143 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001144 if (info->safi == SAFI_UNICAST)
1145 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001146
paul718e3742002-12-13 20:15:29 +00001147 redistribute_delete (&rn->p, rib);
1148 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02001149 rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00001150 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1151 }
1152}
1153
Paul Jakma6d691122006-07-27 21:49:00 +00001154static void rib_unlink (struct route_node *, struct rib *);
1155
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001156/*
1157 * rib_can_delete_dest
1158 *
1159 * Returns TRUE if the given dest can be deleted from the table.
1160 */
1161static int
1162rib_can_delete_dest (rib_dest_t *dest)
1163{
1164 if (dest->routes)
1165 {
1166 return 0;
1167 }
1168
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001169 /*
1170 * Don't delete the dest if we have to update the FPM about this
1171 * prefix.
1172 */
1173 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1174 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1175 return 0;
1176
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001177 return 1;
1178}
1179
1180/*
1181 * rib_gc_dest
1182 *
1183 * Garbage collect the rib dest corresponding to the given route node
1184 * if appropriate.
1185 *
1186 * Returns TRUE if the dest was deleted, FALSE otherwise.
1187 */
1188int
1189rib_gc_dest (struct route_node *rn)
1190{
1191 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001192
1193 dest = rib_dest_from_rnode (rn);
1194 if (!dest)
1195 return 0;
1196
1197 if (!rib_can_delete_dest (dest))
1198 return 0;
1199
1200 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001201 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001202
1203 dest->rnode = NULL;
1204 XFREE (MTYPE_RIB_DEST, dest);
1205 rn->info = NULL;
1206
1207 /*
1208 * Release the one reference that we keep on the route node.
1209 */
1210 route_unlock_node (rn);
1211 return 1;
1212}
1213
Timo Teräs0abf6792016-01-15 17:36:29 +02001214/* Check if 'alternate' RIB entry is better than 'current'. */
1215static struct rib *
1216rib_choose_best (struct rib *current, struct rib *alternate)
1217{
1218 if (current == NULL)
1219 return alternate;
1220
1221 /* filter route selection in following order:
1222 * - connected beats other types
1223 * - lower distance beats higher
1224 * - lower metric beats higher for equal distance
1225 * - last, hence oldest, route wins tie break.
1226 */
1227
1228 /* Connected routes. Pick the last connected
1229 * route of the set of lowest metric connected routes.
1230 */
1231 if (alternate->type == ZEBRA_ROUTE_CONNECT)
1232 {
1233 if (current->type != ZEBRA_ROUTE_CONNECT
1234 || alternate->metric <= current->metric)
1235 return alternate;
1236
1237 return current;
1238 }
1239
1240 if (current->type == ZEBRA_ROUTE_CONNECT)
1241 return current;
1242
1243 /* higher distance loses */
1244 if (alternate->distance < current->distance)
1245 return alternate;
1246 if (current->distance < alternate->distance)
1247 return current;
1248
1249 /* metric tie-breaks equal distance */
1250 if (alternate->metric <= current->metric)
1251 return alternate;
1252
1253 return current;
1254}
1255
paul718e3742002-12-13 20:15:29 +00001256/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001257static void
1258rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001259{
1260 struct rib *rib;
1261 struct rib *next;
Timo Teräs0abf6792016-01-15 17:36:29 +02001262 struct rib *old_fib = NULL;
1263 struct rib *new_fib = NULL;
pauld753e9e2003-01-22 19:45:50 +00001264 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001265 struct nexthop *nexthop = NULL, *tnexthop;
1266 int recursing;
Balaji95116332014-10-23 15:25:25 +00001267 rib_table_info_t *info;
1268
paul4d38fdb2005-04-28 17:35:14 +00001269 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001270
1271 info = rn->table->info;
1272
Timo Teräs0abf6792016-01-15 17:36:29 +02001273 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001274 {
paul718e3742002-12-13 20:15:29 +00001275 /* Currently installed rib. */
1276 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001277 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001278 assert (old_fib == NULL);
1279 old_fib = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001280 }
Timo Teräs0abf6792016-01-15 17:36:29 +02001281
1282 /* Skip deleted entries from selection */
Paul Jakma6d691122006-07-27 21:49:00 +00001283 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
Timo Teräs0abf6792016-01-15 17:36:29 +02001284 continue;
paul4d38fdb2005-04-28 17:35:14 +00001285
paul718e3742002-12-13 20:15:29 +00001286 /* Skip unreachable nexthop. */
1287 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001288 continue;
paul718e3742002-12-13 20:15:29 +00001289
1290 /* Infinit distance. */
1291 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001292 continue;
paul718e3742002-12-13 20:15:29 +00001293
Timo Teräs0abf6792016-01-15 17:36:29 +02001294 new_fib = rib_choose_best(new_fib, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001295 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001296
1297 /* After the cycle is finished, the following pointers will be set:
Timo Teräs0abf6792016-01-15 17:36:29 +02001298 * old_fib --- RIB entry currently having SELECTED
1299 * new_fib --- RIB entry that is newly SELECTED
Denis Ovsienkodc958242007-08-13 16:03:06 +00001300 */
1301
Timo Teräs0abf6792016-01-15 17:36:29 +02001302 /* Set real nexthops. */
1303 if (new_fib)
1304 nexthop_active_update (rn, new_fib, 1);
1305
1306 /* Update kernel if FIB entry has changed */
1307 if (old_fib != new_fib
1308 || (new_fib && CHECK_FLAG (new_fib->status, RIB_ENTRY_CHANGED)))
paul718e3742002-12-13 20:15:29 +00001309 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001310 if (old_fib && old_fib != new_fib)
1311 {
1312 if (! new_fib)
1313 redistribute_delete (&rn->p, old_fib);
1314
1315 if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
1316 rib_update_kernel (rn, old_fib, NULL);
1317 UNSET_FLAG (old_fib->flags, ZEBRA_FLAG_SELECTED);
1318 }
1319
1320 if (new_fib)
1321 {
1322 /* Install new or replace existing FIB entry */
1323 SET_FLAG (new_fib->flags, ZEBRA_FLAG_SELECTED);
1324 redistribute_add (&rn->p, new_fib);
1325
1326 if (! RIB_SYSTEM_ROUTE (new_fib))
1327 rib_update_kernel (rn, old_fib, new_fib);
1328 }
1329
1330 if (info->safi == SAFI_UNICAST)
1331 zfpm_trigger_update (rn, "updating existing route");
1332 }
1333 else if (old_fib == new_fib && new_fib && ! RIB_SYSTEM_ROUTE (new_fib))
1334 {
1335 /* Housekeeping code to deal with race conditions in kernel with
1336 * linux netlink reporting interface up before IPv4 or IPv6 protocol
1337 * is ready to add routes. This makes sure routes are IN the kernel.
1338 */
1339 for (ALL_NEXTHOPS_RO(new_fib->nexthop, nexthop, tnexthop, recursing))
1340 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1341 {
1342 installed = 1;
1343 break;
1344 }
1345 if (! installed)
1346 rib_update_kernel (rn, NULL, new_fib);
1347 }
1348
1349 /* Remove all RIB entries queued for removal */
1350 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1351 {
1352 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
paul4d38fdb2005-04-28 17:35:14 +00001353 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001354 if (IS_ZEBRA_DEBUG_RIB)
1355 rnode_debug (rn, "rn %p, removing rib %p",
1356 (void *)rn, (void *)rib);
1357 rib_unlink (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001358 }
paul718e3742002-12-13 20:15:29 +00001359 }
1360
Paul Jakma6d691122006-07-27 21:49:00 +00001361 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001362 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001363
1364 /*
1365 * Check if the dest can be deleted now.
1366 */
1367 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001368}
1369
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001370/* Take a list of route_node structs and return 1, if there was a record
1371 * picked from it and processed by rib_process(). Don't process more,
1372 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001373 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001374static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001375process_subq (struct list * subq, u_char qindex)
1376{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001377 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001378 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001379
1380 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001381 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001382
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001383 rnode = listgetdata (lnode);
1384 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001385
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001386 if (rnode->info)
1387 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1388
Chris Caputo67b94672009-07-18 04:02:26 +00001389#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001390 else
1391 {
1392 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1393 __func__, rnode, rnode->lock);
1394 zlog_backtrace(LOG_DEBUG);
1395 }
Chris Caputo67b94672009-07-18 04:02:26 +00001396#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001397 route_unlock_node (rnode);
1398 list_delete_node (subq, lnode);
1399 return 1;
1400}
1401
1402/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1403 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1404 * is pointed to the meta queue structure.
1405 */
1406static wq_item_status
1407meta_queue_process (struct work_queue *dummy, void *data)
1408{
1409 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001410 unsigned i;
1411
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001412 for (i = 0; i < MQ_SIZE; i++)
1413 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001414 {
1415 mq->size--;
1416 break;
1417 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001418 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1419}
1420
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001421/*
1422 * Map from rib types to queue type (priority) in meta queue
1423 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001424static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1425 [ZEBRA_ROUTE_SYSTEM] = 4,
1426 [ZEBRA_ROUTE_KERNEL] = 0,
1427 [ZEBRA_ROUTE_CONNECT] = 0,
1428 [ZEBRA_ROUTE_STATIC] = 1,
1429 [ZEBRA_ROUTE_RIP] = 2,
1430 [ZEBRA_ROUTE_RIPNG] = 2,
1431 [ZEBRA_ROUTE_OSPF] = 2,
1432 [ZEBRA_ROUTE_OSPF6] = 2,
1433 [ZEBRA_ROUTE_ISIS] = 2,
1434 [ZEBRA_ROUTE_BGP] = 3,
1435 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001436 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001437};
1438
1439/* Look into the RN and queue it into one or more priority queues,
1440 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001441 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001442static void
1443rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001444{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001445 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001446
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001447 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001448 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001449 u_char qindex = meta_queue_map[rib->type];
1450
1451 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001452 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1453 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001454 {
1455 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001456 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001457 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001458 continue;
1459 }
1460
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001461 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001462 listnode_add (mq->subq[qindex], rn);
1463 route_lock_node (rn);
1464 mq->size++;
1465
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001466 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001467 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001468 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001469 }
paul4d38fdb2005-04-28 17:35:14 +00001470}
1471
Paul Jakma6d691122006-07-27 21:49:00 +00001472/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001473static void
Paul Jakma6d691122006-07-27 21:49:00 +00001474rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001475{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001476 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001477
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001478 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001479 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001480 {
1481 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001482 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001483 zlog_backtrace(LOG_DEBUG);
1484 return;
1485 }
1486
1487 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001488 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001489
1490 assert (zebra);
1491
1492 if (zebra->ribq == NULL)
1493 {
1494 zlog_err ("%s: work_queue does not exist!", __func__);
1495 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001496 }
paul4d38fdb2005-04-28 17:35:14 +00001497
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001498 /*
1499 * The RIB queue should normally be either empty or holding the only
1500 * work_queue_item element. In the latter case this element would
1501 * hold a pointer to the meta queue structure, which must be used to
1502 * actually queue the route nodes to process. So create the MQ
1503 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001504 * This semantics was introduced after 0.99.9 release.
1505 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001506 if (!zebra->ribq->items->count)
1507 work_queue_add (zebra->ribq, zebra->mq);
1508
1509 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001510
1511 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001512 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001513
1514 return;
paul4d38fdb2005-04-28 17:35:14 +00001515}
1516
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001517/* Create new meta queue.
1518 A destructor function doesn't seem to be necessary here.
1519 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001520static struct meta_queue *
1521meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001522{
1523 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001524 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001525
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001526 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1527 assert(new);
1528
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001529 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001530 {
1531 new->subq[i] = list_new ();
1532 assert(new->subq[i]);
1533 }
1534
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001535 return new;
1536}
1537
paul4d38fdb2005-04-28 17:35:14 +00001538/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001539static void
paul4d38fdb2005-04-28 17:35:14 +00001540rib_queue_init (struct zebra_t *zebra)
1541{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001542 assert (zebra);
1543
paul4d38fdb2005-04-28 17:35:14 +00001544 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001545 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001546 {
Paul Jakma6d691122006-07-27 21:49:00 +00001547 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001548 return;
1549 }
1550
1551 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001552 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001553 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001554 /* XXX: TODO: These should be runtime configurable via vty */
1555 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001556 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001557
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001558 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001559 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001560 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001561 return;
1562 }
1563 return;
paul718e3742002-12-13 20:15:29 +00001564}
1565
Paul Jakma6d691122006-07-27 21:49:00 +00001566/* RIB updates are processed via a queue of pointers to route_nodes.
1567 *
1568 * The queue length is bounded by the maximal size of the routing table,
1569 * as a route_node will not be requeued, if already queued.
1570 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001571 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05001572 * state, or static_install_route (when an existing RIB is updated)
Paul Jakma3c0755d2006-12-08 00:53:14 +00001573 * and then submit route_node to queue for best-path selection later.
1574 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001575 *
1576 * Deleted RIBs are reaped during best-path selection.
1577 *
1578 * rib_addnode
1579 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001580 * |-------->| | best RIB, if required
1581 * | |
1582 * static_install->|->rib_addqueue...... -> rib_process
1583 * | |
1584 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001585 * |-> set RIB_ENTRY_REMOVE |
1586 * rib_delnode (RIB freed)
1587 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001588 * The 'info' pointer of a route_node points to a rib_dest_t
1589 * ('dest'). Queueing state for a route_node is kept on the dest. The
1590 * dest is created on-demand by rib_link() and is kept around at least
1591 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001592 *
1593 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1594 *
1595 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001596 * - dest attached to route_node:
1597 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001598 * - route_node processing queue
1599 * - managed by: rib_addqueue, rib_process.
1600 *
1601 */
1602
paul718e3742002-12-13 20:15:29 +00001603/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001604static void
Paul Jakma6d691122006-07-27 21:49:00 +00001605rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001606{
1607 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001608 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001609
paul4d38fdb2005-04-28 17:35:14 +00001610 assert (rib && rn);
1611
Paul Jakma6d691122006-07-27 21:49:00 +00001612 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001613 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001614
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001615 dest = rib_dest_from_rnode (rn);
1616 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001617 {
1618 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001619 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001620
1621 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1622 route_lock_node (rn); /* rn route table reference */
1623 rn->info = dest;
1624 dest->rnode = rn;
1625 }
1626
1627 head = dest->routes;
1628 if (head)
1629 {
Paul Jakma6d691122006-07-27 21:49:00 +00001630 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001631 }
paul718e3742002-12-13 20:15:29 +00001632 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001633 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001634 rib_queue_add (&zebrad, rn);
1635}
1636
1637static void
1638rib_addnode (struct route_node *rn, struct rib *rib)
1639{
1640 /* RIB node has been un-removed before route-node is processed.
1641 * route_node must hence already be on the queue for processing..
1642 */
1643 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1644 {
1645 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001646 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001647
Paul Jakma6d691122006-07-27 21:49:00 +00001648 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1649 return;
1650 }
1651 rib_link (rn, rib);
1652}
1653
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001654/*
1655 * rib_unlink
1656 *
1657 * Detach a rib structure from a route_node.
1658 *
1659 * Note that a call to rib_unlink() should be followed by a call to
1660 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1661 * longer required to be deleted.
1662 */
Paul Jakma6d691122006-07-27 21:49:00 +00001663static void
1664rib_unlink (struct route_node *rn, struct rib *rib)
1665{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001666 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001667
1668 assert (rn && rib);
1669
1670 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001671 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001672
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001673 dest = rib_dest_from_rnode (rn);
1674
Paul Jakma6d691122006-07-27 21:49:00 +00001675 if (rib->next)
1676 rib->next->prev = rib->prev;
1677
1678 if (rib->prev)
1679 rib->prev->next = rib->next;
1680 else
1681 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001682 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001683 }
1684
1685 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001686 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001687 XFREE (MTYPE_RIB, rib);
1688
paul718e3742002-12-13 20:15:29 +00001689}
1690
paula1ac18c2005-06-28 17:17:12 +00001691static void
paul718e3742002-12-13 20:15:29 +00001692rib_delnode (struct route_node *rn, struct rib *rib)
1693{
Paul Jakma6d691122006-07-27 21:49:00 +00001694 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001695 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001696 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1697 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001698}
1699
1700int
1701rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001702 struct in_addr *gate, struct in_addr *src,
Feng Lu0d0686f2015-05-22 11:40:02 +02001703 unsigned int ifindex, vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001704 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001705{
1706 struct rib *rib;
1707 struct rib *same = NULL;
1708 struct route_table *table;
1709 struct route_node *rn;
1710 struct nexthop *nexthop;
1711
1712 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001713 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00001714 if (! table)
1715 return 0;
1716
1717 /* Make it sure prefixlen is applied to the prefix. */
1718 apply_mask_ipv4 (p);
1719
1720 /* Set default distance by route type. */
1721 if (distance == 0)
1722 {
Balaji.G837d16c2012-09-26 14:09:10 +05301723 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001724 distance = 150;
1725 else
1726 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001727
1728 /* iBGP distance is 200. */
1729 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1730 distance = 200;
1731 }
1732
1733 /* Lookup route node.*/
1734 rn = route_node_get (table, (struct prefix *) p);
1735
1736 /* If same type of route are installed, treat it as a implicit
1737 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001738 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001739 {
Paul Jakma6d691122006-07-27 21:49:00 +00001740 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1741 continue;
1742
hassoebf1ead2005-09-21 14:58:20 +00001743 if (rib->type != type)
1744 continue;
1745 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001746 {
1747 same = rib;
1748 break;
1749 }
hassoebf1ead2005-09-21 14:58:20 +00001750 /* Duplicate connected route comes in. */
1751 else if ((nexthop = rib->nexthop) &&
1752 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001753 nexthop->ifindex == ifindex &&
1754 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001755 {
1756 rib->refcnt++;
1757 return 0 ;
1758 }
paul718e3742002-12-13 20:15:29 +00001759 }
1760
1761 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001762 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001763 rib->type = type;
1764 rib->distance = distance;
1765 rib->flags = flags;
1766 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001767 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02001768 rib->vrf_id = vrf_id;
1769 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00001770 rib->nexthop_num = 0;
1771 rib->uptime = time (NULL);
1772
1773 /* Nexthop settings. */
1774 if (gate)
1775 {
1776 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001777 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001778 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001779 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001780 }
1781 else
1782 nexthop_ifindex_add (rib, ifindex);
1783
1784 /* If this route is kernel route, set FIB flag to the route. */
1785 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1786 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1787 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1788
1789 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001790 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001791 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1792 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001793 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001794
paul718e3742002-12-13 20:15:29 +00001795 /* Free implicit route.*/
1796 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001797 {
1798 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001799 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1800 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001801 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001802 }
paul4d38fdb2005-04-28 17:35:14 +00001803
1804 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001805 return 0;
1806}
1807
Denis Ovsienkodc958242007-08-13 16:03:06 +00001808/* This function dumps the contents of a given RIB entry into
1809 * standard debug log. Calling function name and IP prefix in
1810 * question are passed as 1st and 2nd arguments.
1811 */
1812
David Lamparterf7bf4152013-10-22 17:10:21 +00001813void _rib_dump (const char * func,
1814 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001815{
David Lamparterf7bf4152013-10-22 17:10:21 +00001816 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001817 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001818 struct nexthop *nexthop, *tnexthop;
1819 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001820
Feng Lu0d0686f2015-05-22 11:40:02 +02001821 zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
1822 prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001823 zlog_debug
1824 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001825 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001826 func,
1827 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001828 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001829 rib->type,
1830 rib->table
1831 );
1832 zlog_debug
1833 (
1834 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1835 func,
1836 rib->metric,
1837 rib->distance,
1838 rib->flags,
1839 rib->status
1840 );
1841 zlog_debug
1842 (
1843 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1844 func,
1845 rib->nexthop_num,
1846 rib->nexthop_active_num,
1847 rib->nexthop_fib_num
1848 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001849
Christian Frankefa713d92013-07-05 15:35:37 +00001850 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1851 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001852 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001853 zlog_debug
1854 (
1855 "%s: %s %s with flags %s%s%s",
1856 func,
1857 (recursing ? " NH" : "NH"),
1858 straddr,
1859 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1860 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1861 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1862 );
1863 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001864 zlog_debug ("%s: dump complete", func);
1865}
1866
1867/* This is an exported helper to rtm_read() to dump the strange
1868 * RIB entry found by rib_lookup_ipv4_route()
1869 */
1870
1871void rib_lookup_and_dump (struct prefix_ipv4 * p)
1872{
1873 struct route_table *table;
1874 struct route_node *rn;
1875 struct rib *rib;
1876 char prefix_buf[INET_ADDRSTRLEN];
1877
1878 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001879 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001880 if (! table)
1881 {
Feng Lu41f44a22015-05-22 11:39:56 +02001882 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001883 return;
1884 }
1885
Denis Ovsienkodc958242007-08-13 16:03:06 +00001886 /* Scan the RIB table for exactly matching RIB entry. */
1887 rn = route_node_lookup (table, (struct prefix *) p);
1888
1889 /* No route for this prefix. */
1890 if (! rn)
1891 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001892 zlog_debug ("%s: lookup failed for %s", __func__,
1893 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001894 return;
1895 }
1896
1897 /* Unlock node. */
1898 route_unlock_node (rn);
1899
1900 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001901 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001902 {
1903 zlog_debug
1904 (
1905 "%s: rn %p, rib %p: %s, %s",
1906 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01001907 (void *)rn,
1908 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001909 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1910 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1911 );
David Lamparterf7bf4152013-10-22 17:10:21 +00001912 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001913 }
1914}
1915
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001916/* Check if requested address assignment will fail due to another
1917 * route being installed by zebra in FIB already. Take necessary
1918 * actions, if needed: remove such a route from FIB and deSELECT
1919 * corresponding RIB entry. Then put affected RN into RIBQ head.
1920 */
1921void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1922{
1923 struct route_table *table;
1924 struct route_node *rn;
1925 struct rib *rib;
1926 unsigned changed = 0;
1927
Feng Lu41f44a22015-05-22 11:39:56 +02001928 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001929 {
Feng Lu41f44a22015-05-22 11:39:56 +02001930 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001931 return;
1932 }
1933
1934 /* No matches would be the simplest case. */
1935 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1936 return;
1937
1938 /* Unlock node. */
1939 route_unlock_node (rn);
1940
1941 /* Check all RIB entries. In case any changes have to be done, requeue
1942 * the RN into RIBQ head. If the routing message about the new connected
1943 * route (generated by the IP address we are going to assign very soon)
1944 * comes before the RIBQ is processed, the new RIB entry will join
1945 * RIBQ record already on head. This is necessary for proper revalidation
1946 * of the rest of the RIB.
1947 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001948 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001949 {
1950 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1951 ! RIB_SYSTEM_ROUTE (rib))
1952 {
1953 changed = 1;
1954 if (IS_ZEBRA_DEBUG_RIB)
1955 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001956 char buf[PREFIX_STRLEN];
1957 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
1958 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00001959 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001960 }
1961 rib_uninstall (rn, rib);
1962 }
1963 }
1964 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001965 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001966}
1967
paul718e3742002-12-13 20:15:29 +00001968int
G.Balajicddf3912011-11-26 21:59:32 +04001969rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001970{
1971 struct route_table *table;
1972 struct route_node *rn;
1973 struct rib *same;
1974 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001975
paul718e3742002-12-13 20:15:29 +00001976 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001977 table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +00001978 if (! table)
1979 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04001980
paul718e3742002-12-13 20:15:29 +00001981 /* Make it sure prefixlen is applied to the prefix. */
1982 apply_mask_ipv4 (p);
1983
1984 /* Set default distance by route type. */
1985 if (rib->distance == 0)
1986 {
1987 rib->distance = route_info[rib->type].distance;
1988
1989 /* iBGP distance is 200. */
1990 if (rib->type == ZEBRA_ROUTE_BGP
1991 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1992 rib->distance = 200;
1993 }
1994
1995 /* Lookup route node.*/
1996 rn = route_node_get (table, (struct prefix *) p);
1997
1998 /* If same type of route are installed, treat it as a implicit
1999 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002000 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002001 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002002 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002003 continue;
2004
paul718e3742002-12-13 20:15:29 +00002005 if (same->type == rib->type && same->table == rib->table
2006 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002007 break;
paul718e3742002-12-13 20:15:29 +00002008 }
paul4d38fdb2005-04-28 17:35:14 +00002009
paul718e3742002-12-13 20:15:29 +00002010 /* If this route is kernel route, set FIB flag to the route. */
2011 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2012 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2013 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2014
2015 /* Link new rib to node.*/
2016 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002017 if (IS_ZEBRA_DEBUG_RIB)
2018 {
2019 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002020 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002021 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002022 }
paul718e3742002-12-13 20:15:29 +00002023
paul718e3742002-12-13 20:15:29 +00002024 /* Free implicit route.*/
2025 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002026 {
2027 if (IS_ZEBRA_DEBUG_RIB)
2028 {
2029 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002030 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002031 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002032 }
paul4d38fdb2005-04-28 17:35:14 +00002033 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002034 }
paul4d38fdb2005-04-28 17:35:14 +00002035
2036 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002037 return 0;
2038}
2039
hassoebf1ead2005-09-21 14:58:20 +00002040/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002041int
2042rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002043 struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002044{
2045 struct route_table *table;
2046 struct route_node *rn;
2047 struct rib *rib;
2048 struct rib *fib = NULL;
2049 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002050 struct nexthop *nexthop, *tnexthop;
2051 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002052 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002053 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002054
2055 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002056 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002057 if (! table)
2058 return 0;
2059
2060 /* Apply mask. */
2061 apply_mask_ipv4 (p);
2062
Christian Frankeb52aef12013-11-27 17:06:15 +00002063 if (IS_ZEBRA_DEBUG_KERNEL)
2064 {
2065 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002066 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
2067 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002068 inet_ntoa (*gate),
2069 ifindex);
2070 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002071 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
2072 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002073 ifindex);
2074 }
paul5ec90d22003-06-19 01:41:37 +00002075
paul718e3742002-12-13 20:15:29 +00002076 /* Lookup route node. */
2077 rn = route_node_lookup (table, (struct prefix *) p);
2078 if (! rn)
2079 {
2080 if (IS_ZEBRA_DEBUG_KERNEL)
2081 {
2082 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002083 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2084 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002085 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002086 ifindex);
2087 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002088 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2089 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002090 ifindex);
2091 }
2092 return ZEBRA_ERR_RTNOEXIST;
2093 }
2094
2095 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002096 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002097 {
Paul Jakma6d691122006-07-27 21:49:00 +00002098 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2099 continue;
2100
paul718e3742002-12-13 20:15:29 +00002101 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2102 fib = rib;
2103
hassoebf1ead2005-09-21 14:58:20 +00002104 if (rib->type != type)
2105 continue;
2106 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002107 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002108 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002109 if (nexthop->ifindex != ifindex)
2110 continue;
hassoebf1ead2005-09-21 14:58:20 +00002111 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002112 {
hassoebf1ead2005-09-21 14:58:20 +00002113 rib->refcnt--;
2114 route_unlock_node (rn);
2115 route_unlock_node (rn);
2116 return 0;
paul718e3742002-12-13 20:15:29 +00002117 }
hassoebf1ead2005-09-21 14:58:20 +00002118 same = rib;
2119 break;
paul718e3742002-12-13 20:15:29 +00002120 }
hassoebf1ead2005-09-21 14:58:20 +00002121 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002122 else
paul5ec90d22003-06-19 01:41:37 +00002123 {
Christian Frankefa713d92013-07-05 15:35:37 +00002124 if (gate == NULL)
2125 {
2126 same = rib;
2127 break;
2128 }
2129 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2130 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2131 {
2132 same = rib;
2133 break;
2134 }
2135 if (same)
2136 break;
2137 }
paul718e3742002-12-13 20:15:29 +00002138 }
paul718e3742002-12-13 20:15:29 +00002139 /* If same type of route can't be found and this message is from
2140 kernel. */
2141 if (! same)
2142 {
2143 if (fib && type == ZEBRA_ROUTE_KERNEL)
2144 {
2145 /* Unset flags. */
2146 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2147 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2148
2149 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2150 }
2151 else
2152 {
2153 if (IS_ZEBRA_DEBUG_KERNEL)
2154 {
2155 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002156 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2157 "doesn't exist in rib",
2158 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002159 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002160 ifindex,
2161 type);
2162 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002163 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2164 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002165 ifindex,
2166 type);
2167 }
2168 route_unlock_node (rn);
2169 return ZEBRA_ERR_RTNOEXIST;
2170 }
2171 }
paul4d38fdb2005-04-28 17:35:14 +00002172
paul718e3742002-12-13 20:15:29 +00002173 if (same)
2174 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002175
paul718e3742002-12-13 20:15:29 +00002176 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002177 return 0;
2178}
David Lamparter6b0655a2014-06-04 06:53:35 +02002179
paul718e3742002-12-13 20:15:29 +00002180/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002181static void
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002182static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002183{
2184 struct rib *rib;
2185 struct route_node *rn;
2186 struct route_table *table;
2187
2188 /* Lookup table. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002189 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002190 if (! table)
2191 return;
2192
2193 /* Lookup existing route */
2194 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002195 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002196 {
2197 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2198 continue;
2199
2200 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2201 break;
2202 }
paul718e3742002-12-13 20:15:29 +00002203
2204 if (rib)
2205 {
2206 /* Same distance static route is there. Update it with new
2207 nexthop. */
paul718e3742002-12-13 20:15:29 +00002208 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002209 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002210 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002211 case STATIC_IPV4_GATEWAY:
2212 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2213 break;
2214 case STATIC_IPV4_IFNAME:
2215 nexthop_ifname_add (rib, si->ifname);
2216 break;
2217 case STATIC_IPV4_BLACKHOLE:
2218 nexthop_blackhole_add (rib);
2219 break;
2220 case STATIC_IPV6_GATEWAY:
2221 nexthop_ipv6_add (rib, &si->addr.ipv6);
2222 break;
2223 case STATIC_IPV6_IFNAME:
2224 nexthop_ifname_add (rib, si->ifname);
2225 break;
2226 case STATIC_IPV6_GATEWAY_IFNAME:
2227 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2228 break;
paul4d38fdb2005-04-28 17:35:14 +00002229 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002230 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002231 }
2232 else
2233 {
2234 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002235 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2236
paul718e3742002-12-13 20:15:29 +00002237 rib->type = ZEBRA_ROUTE_STATIC;
2238 rib->distance = si->distance;
2239 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002240 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002241 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002242 rib->nexthop_num = 0;
2243
2244 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002245 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002246 case STATIC_IPV4_GATEWAY:
2247 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2248 break;
2249 case STATIC_IPV4_IFNAME:
2250 nexthop_ifname_add (rib, si->ifname);
2251 break;
2252 case STATIC_IPV4_BLACKHOLE:
2253 nexthop_blackhole_add (rib);
2254 break;
2255 case STATIC_IPV6_GATEWAY:
2256 nexthop_ipv6_add (rib, &si->addr.ipv6);
2257 break;
2258 case STATIC_IPV6_IFNAME:
2259 nexthop_ifname_add (rib, si->ifname);
2260 break;
2261 case STATIC_IPV6_GATEWAY_IFNAME:
2262 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2263 break;
paul7021c422003-07-15 12:52:22 +00002264 }
paul718e3742002-12-13 20:15:29 +00002265
hasso81dfcaa2003-05-25 19:21:25 +00002266 /* Save the flags of this static routes (reject, blackhole) */
2267 rib->flags = si->flags;
2268
paul718e3742002-12-13 20:15:29 +00002269 /* Link this rib to the tree. */
2270 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002271 }
2272}
2273
paula1ac18c2005-06-28 17:17:12 +00002274static int
Donald Sharpa979ab72015-11-04 13:26:38 -05002275static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002276{
2277 if (nexthop->type == NEXTHOP_TYPE_IPV4
2278 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002279 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002280 return 1;
2281 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2282 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002283 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002284 return 1;
paul595db7f2003-05-25 21:35:06 +00002285 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2286 && si->type == STATIC_IPV4_BLACKHOLE)
2287 return 1;
Donald Sharpa979ab72015-11-04 13:26:38 -05002288 if (nexthop->type == NEXTHOP_TYPE_IPV6
2289 && si->type == STATIC_IPV6_GATEWAY
2290 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
2291 return 1;
2292 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2293 && si->type == STATIC_IPV6_IFNAME
2294 && strcmp (nexthop->ifname, si->ifname) == 0)
2295 return 1;
2296 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2297 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2298 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
2299 && strcmp (nexthop->ifname, si->ifname) == 0)
2300 return 1;
paule8e19462006-01-19 20:16:55 +00002301 return 0;
paul718e3742002-12-13 20:15:29 +00002302}
2303
2304/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002305static void
Donald Sharp949b7192015-11-04 13:26:39 -05002306static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002307{
2308 struct route_node *rn;
2309 struct rib *rib;
2310 struct nexthop *nexthop;
2311 struct route_table *table;
2312
2313 /* Lookup table. */
Donald Sharp949b7192015-11-04 13:26:39 -05002314 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002315 if (! table)
2316 return;
paul4d38fdb2005-04-28 17:35:14 +00002317
paul718e3742002-12-13 20:15:29 +00002318 /* Lookup existing route with type and distance. */
2319 rn = route_node_lookup (table, p);
2320 if (! rn)
2321 return;
2322
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002323 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002324 {
2325 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2326 continue;
2327
2328 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2329 break;
2330 }
paul718e3742002-12-13 20:15:29 +00002331
2332 if (! rib)
2333 {
2334 route_unlock_node (rn);
2335 return;
2336 }
2337
2338 /* Lookup nexthop. */
2339 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Donald Sharpa979ab72015-11-04 13:26:38 -05002340 if (static_nexthop_same (nexthop, si))
paul718e3742002-12-13 20:15:29 +00002341 break;
2342
2343 /* Can't find nexthop. */
2344 if (! nexthop)
2345 {
2346 route_unlock_node (rn);
2347 return;
2348 }
2349
2350 /* Check nexthop. */
2351 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002352 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002353 else
2354 {
paul6baeb982003-10-28 03:47:15 +00002355 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2356 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002357 nexthop_delete (rib, nexthop);
2358 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002359 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002360 }
paul718e3742002-12-13 20:15:29 +00002361 /* Unlock node. */
2362 route_unlock_node (rn);
2363}
2364
paul718e3742002-12-13 20:15:29 +00002365int
Everton Marques33d86db2014-07-14 11:19:00 -03002366static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2367 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002368 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002369{
2370 u_char type = 0;
2371 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002372 struct static_route *si;
2373 struct static_route *pp;
2374 struct static_route *cp;
2375 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002376 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2377 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002378
paul718e3742002-12-13 20:15:29 +00002379 if (! stable)
2380 return -1;
2381
2382 /* Lookup static route prefix. */
2383 rn = route_node_get (stable, p);
2384
2385 /* Make flags. */
2386 if (gate)
2387 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002388 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002389 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002390 else
2391 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002392
2393 /* Do nothing if there is a same static route. */
2394 for (si = rn->info; si; si = si->next)
2395 {
2396 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002397 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2398 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002399 {
2400 if (distance == si->distance)
2401 {
2402 route_unlock_node (rn);
2403 return 0;
2404 }
2405 else
2406 update = si;
2407 }
2408 }
2409
Paul Jakma3c0755d2006-12-08 00:53:14 +00002410 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002411 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002412 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002413
2414 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002415 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002416
2417 si->type = type;
2418 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002419 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002420 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002421
2422 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002423 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002424 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002425 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002426
2427 /* Add new static route information to the tree with sort by
2428 distance value and gateway address. */
2429 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2430 {
2431 if (si->distance < cp->distance)
2432 break;
2433 if (si->distance > cp->distance)
2434 continue;
2435 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2436 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002437 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002438 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002439 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002440 continue;
2441 }
2442 }
2443
2444 /* Make linked list. */
2445 if (pp)
2446 pp->next = si;
2447 else
2448 rn->info = si;
2449 if (cp)
2450 cp->prev = si;
2451 si->prev = pp;
2452 si->next = cp;
2453
2454 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002455 static_install_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002456
2457 return 1;
2458}
2459
paul718e3742002-12-13 20:15:29 +00002460int
Everton Marques33d86db2014-07-14 11:19:00 -03002461static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002462 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002463{
2464 u_char type = 0;
2465 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002466 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002467 struct route_table *stable;
2468
2469 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002470 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002471 if (! stable)
2472 return -1;
2473
2474 /* Lookup static route prefix. */
2475 rn = route_node_lookup (stable, p);
2476 if (! rn)
2477 return 0;
2478
2479 /* Make flags. */
2480 if (gate)
2481 type = STATIC_IPV4_GATEWAY;
2482 else if (ifname)
2483 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002484 else
2485 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002486
2487 /* Find same static route is the tree */
2488 for (si = rn->info; si; si = si->next)
2489 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002490 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2491 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002492 break;
2493
2494 /* Can't find static route. */
2495 if (! si)
2496 {
2497 route_unlock_node (rn);
2498 return 0;
2499 }
2500
2501 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002502 static_uninstall_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002503
2504 /* Unlink static route from linked list. */
2505 if (si->prev)
2506 si->prev->next = si->next;
2507 else
2508 rn->info = si->next;
2509 if (si->next)
2510 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002511 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002512
2513 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002514 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002515 XFREE (0, si->ifname);
2516 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002517
paul143a3852003-09-29 20:06:13 +00002518 route_unlock_node (rn);
2519
paul718e3742002-12-13 20:15:29 +00002520 return 1;
2521}
2522
paul718e3742002-12-13 20:15:29 +00002523int
2524rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002525 struct in6_addr *gate, unsigned int ifindex,
2526 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002527 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002528{
2529 struct rib *rib;
2530 struct rib *same = NULL;
2531 struct route_table *table;
2532 struct route_node *rn;
2533 struct nexthop *nexthop;
2534
paul718e3742002-12-13 20:15:29 +00002535 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002536 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002537 if (! table)
2538 return 0;
2539
2540 /* Make sure mask is applied. */
2541 apply_mask_ipv6 (p);
2542
2543 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002544 if (!distance)
2545 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002546
2547 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2548 distance = 200;
2549
paul718e3742002-12-13 20:15:29 +00002550 /* Lookup route node.*/
2551 rn = route_node_get (table, (struct prefix *) p);
2552
2553 /* If same type of route are installed, treat it as a implicit
2554 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002555 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002556 {
Paul Jakma6d691122006-07-27 21:49:00 +00002557 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2558 continue;
2559
hassoebf1ead2005-09-21 14:58:20 +00002560 if (rib->type != type)
2561 continue;
2562 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002563 {
2564 same = rib;
paul718e3742002-12-13 20:15:29 +00002565 break;
2566 }
hassoebf1ead2005-09-21 14:58:20 +00002567 else if ((nexthop = rib->nexthop) &&
2568 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2569 nexthop->ifindex == ifindex)
2570 {
2571 rib->refcnt++;
2572 return 0;
2573 }
paul718e3742002-12-13 20:15:29 +00002574 }
2575
2576 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002577 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2578
paul718e3742002-12-13 20:15:29 +00002579 rib->type = type;
2580 rib->distance = distance;
2581 rib->flags = flags;
2582 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002583 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002584 rib->vrf_id = vrf_id;
2585 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002586 rib->nexthop_num = 0;
2587 rib->uptime = time (NULL);
2588
2589 /* Nexthop settings. */
2590 if (gate)
2591 {
2592 if (ifindex)
2593 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2594 else
2595 nexthop_ipv6_add (rib, gate);
2596 }
2597 else
2598 nexthop_ifindex_add (rib, ifindex);
2599
2600 /* If this route is kernel route, set FIB flag to the route. */
2601 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2602 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2603 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2604
2605 /* Link new rib to node.*/
2606 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002607 if (IS_ZEBRA_DEBUG_RIB)
2608 {
2609 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002610 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002611 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002612 }
paul718e3742002-12-13 20:15:29 +00002613
paul718e3742002-12-13 20:15:29 +00002614 /* Free implicit route.*/
2615 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002616 {
2617 if (IS_ZEBRA_DEBUG_RIB)
2618 {
2619 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002620 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002621 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002622 }
paul4d38fdb2005-04-28 17:35:14 +00002623 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002624 }
paul4d38fdb2005-04-28 17:35:14 +00002625
2626 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002627 return 0;
2628}
2629
hassoebf1ead2005-09-21 14:58:20 +00002630/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002631int
2632rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002633 struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002634{
2635 struct route_table *table;
2636 struct route_node *rn;
2637 struct rib *rib;
2638 struct rib *fib = NULL;
2639 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002640 struct nexthop *nexthop, *tnexthop;
2641 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002642 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002643 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002644
2645 /* Apply mask. */
2646 apply_mask_ipv6 (p);
2647
2648 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002649 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002650 if (! table)
2651 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002652
paul718e3742002-12-13 20:15:29 +00002653 /* Lookup route node. */
2654 rn = route_node_lookup (table, (struct prefix *) p);
2655 if (! rn)
2656 {
2657 if (IS_ZEBRA_DEBUG_KERNEL)
2658 {
2659 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002660 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2661 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002662 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002663 ifindex);
2664 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002665 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2666 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002667 ifindex);
2668 }
2669 return ZEBRA_ERR_RTNOEXIST;
2670 }
2671
2672 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002673 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002674 {
Paul Jakma6d691122006-07-27 21:49:00 +00002675 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2676 continue;
2677
paul718e3742002-12-13 20:15:29 +00002678 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2679 fib = rib;
2680
hassoebf1ead2005-09-21 14:58:20 +00002681 if (rib->type != type)
2682 continue;
2683 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002684 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002685 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002686 if (nexthop->ifindex != ifindex)
2687 continue;
hassoebf1ead2005-09-21 14:58:20 +00002688 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002689 {
hassoebf1ead2005-09-21 14:58:20 +00002690 rib->refcnt--;
2691 route_unlock_node (rn);
2692 route_unlock_node (rn);
2693 return 0;
paul718e3742002-12-13 20:15:29 +00002694 }
hassoebf1ead2005-09-21 14:58:20 +00002695 same = rib;
2696 break;
paul718e3742002-12-13 20:15:29 +00002697 }
hassoebf1ead2005-09-21 14:58:20 +00002698 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002699 else
2700 {
2701 if (gate == NULL)
2702 {
2703 same = rib;
2704 break;
2705 }
2706 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2707 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2708 {
2709 same = rib;
2710 break;
2711 }
2712 if (same)
2713 break;
2714 }
paul718e3742002-12-13 20:15:29 +00002715 }
2716
2717 /* If same type of route can't be found and this message is from
2718 kernel. */
2719 if (! same)
2720 {
2721 if (fib && type == ZEBRA_ROUTE_KERNEL)
2722 {
2723 /* Unset flags. */
2724 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2725 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2726
2727 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2728 }
2729 else
2730 {
2731 if (IS_ZEBRA_DEBUG_KERNEL)
2732 {
2733 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002734 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2735 "doesn't exist in rib",
2736 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002737 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002738 ifindex,
2739 type);
2740 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002741 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2742 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002743 ifindex,
2744 type);
2745 }
2746 route_unlock_node (rn);
2747 return ZEBRA_ERR_RTNOEXIST;
2748 }
2749 }
2750
2751 if (same)
2752 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002753
paul718e3742002-12-13 20:15:29 +00002754 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002755 return 0;
2756}
David Lamparter6b0655a2014-06-04 06:53:35 +02002757
paul718e3742002-12-13 20:15:29 +00002758
2759/* Add static route into static route configuration. */
2760int
2761static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002762 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002763 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002764{
2765 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002766 struct static_route *si;
2767 struct static_route *pp;
2768 struct static_route *cp;
Donald Sharpc1900e02015-11-04 13:26:40 -05002769 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002770 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2771 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002772
paul718e3742002-12-13 20:15:29 +00002773 if (! stable)
2774 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002775
2776 if (!gate &&
2777 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2778 return -1;
2779
2780 if (!ifname &&
2781 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2782 return -1;
paul718e3742002-12-13 20:15:29 +00002783
2784 /* Lookup static route prefix. */
2785 rn = route_node_get (stable, p);
2786
2787 /* Do nothing if there is a same static route. */
2788 for (si = rn->info; si; si = si->next)
2789 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002790 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002791 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002792 && (! ifname || strcmp (ifname, si->ifname) == 0))
2793 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002794 if (distance == si->distance)
2795 {
2796 route_unlock_node (rn);
2797 return 0;
2798 }
2799 else
2800 update = si;
paul718e3742002-12-13 20:15:29 +00002801 }
2802 }
2803
Donald Sharpc1900e02015-11-04 13:26:40 -05002804 if (update)
2805 static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
2806
paul718e3742002-12-13 20:15:29 +00002807 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002808 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002809
2810 si->type = type;
2811 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002812 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002813 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002814
2815 switch (type)
2816 {
2817 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002818 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002819 break;
2820 case STATIC_IPV6_IFNAME:
2821 si->ifname = XSTRDUP (0, ifname);
2822 break;
2823 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002824 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002825 si->ifname = XSTRDUP (0, ifname);
2826 break;
2827 }
2828
2829 /* Add new static route information to the tree with sort by
2830 distance value and gateway address. */
2831 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2832 {
2833 if (si->distance < cp->distance)
2834 break;
2835 if (si->distance > cp->distance)
2836 continue;
2837 }
2838
2839 /* Make linked list. */
2840 if (pp)
2841 pp->next = si;
2842 else
2843 rn->info = si;
2844 if (cp)
2845 cp->prev = si;
2846 si->prev = pp;
2847 si->next = cp;
2848
2849 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002850 static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002851
2852 return 1;
2853}
2854
2855/* Delete static route from static route configuration. */
2856int
2857static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002858 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002859{
2860 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002861 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002862 struct route_table *stable;
2863
2864 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002865 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002866 if (! stable)
2867 return -1;
2868
2869 /* Lookup static route prefix. */
2870 rn = route_node_lookup (stable, p);
2871 if (! rn)
2872 return 0;
2873
2874 /* Find same static route is the tree */
2875 for (si = rn->info; si; si = si->next)
2876 if (distance == si->distance
2877 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002878 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002879 && (! ifname || strcmp (ifname, si->ifname) == 0))
2880 break;
2881
2882 /* Can't find static route. */
2883 if (! si)
2884 {
2885 route_unlock_node (rn);
2886 return 0;
2887 }
2888
2889 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002890 static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002891
2892 /* Unlink static route from linked list. */
2893 if (si->prev)
2894 si->prev->next = si->next;
2895 else
2896 rn->info = si->next;
2897 if (si->next)
2898 si->next->prev = si->prev;
2899
2900 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002901 if (ifname)
2902 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05002903 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002904
2905 return 1;
2906}
David Lamparter6b0655a2014-06-04 06:53:35 +02002907
paul718e3742002-12-13 20:15:29 +00002908/* RIB update function. */
2909void
Feng Lu0d0686f2015-05-22 11:40:02 +02002910rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002911{
2912 struct route_node *rn;
2913 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002914
Feng Lu0d0686f2015-05-22 11:40:02 +02002915 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002916 if (table)
2917 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002918 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002919 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002920
Feng Lu0d0686f2015-05-22 11:40:02 +02002921 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002922 if (table)
2923 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002924 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002925 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002926}
2927
David Lamparter6b0655a2014-06-04 06:53:35 +02002928
paul718e3742002-12-13 20:15:29 +00002929/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002930static void
paul718e3742002-12-13 20:15:29 +00002931rib_weed_table (struct route_table *table)
2932{
2933 struct route_node *rn;
2934 struct rib *rib;
2935 struct rib *next;
2936
2937 if (table)
2938 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002939 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002940 {
Paul Jakma6d691122006-07-27 21:49:00 +00002941 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2942 continue;
2943
paulb21b19c2003-06-15 01:28:29 +00002944 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002945 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002946 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002947 }
2948}
2949
2950/* Delete all routes from non main table. */
2951void
paula1ac18c2005-06-28 17:17:12 +00002952rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002953{
Feng Lu0d0686f2015-05-22 11:40:02 +02002954 vrf_iter_t iter;
2955 struct zebra_vrf *zvrf;
2956
2957 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
2958 if ((zvrf = vrf_iter2info (iter)) != NULL)
2959 {
2960 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
2961 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
2962 }
paul718e3742002-12-13 20:15:29 +00002963}
David Lamparter6b0655a2014-06-04 06:53:35 +02002964
Feng Lu0d0686f2015-05-22 11:40:02 +02002965#if 0
paul718e3742002-12-13 20:15:29 +00002966/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002967static void
paul718e3742002-12-13 20:15:29 +00002968rib_sweep_table (struct route_table *table)
2969{
2970 struct route_node *rn;
2971 struct rib *rib;
2972 struct rib *next;
2973 int ret = 0;
2974
2975 if (table)
2976 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002977 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002978 {
Paul Jakma6d691122006-07-27 21:49:00 +00002979 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2980 continue;
2981
paul718e3742002-12-13 20:15:29 +00002982 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2983 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2984 {
Timo Teräs0abf6792016-01-15 17:36:29 +02002985 ret = rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00002986 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002987 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002988 }
2989 }
2990}
Feng Lu0d0686f2015-05-22 11:40:02 +02002991#endif
paul718e3742002-12-13 20:15:29 +00002992
2993/* Sweep all RIB tables. */
2994void
paula1ac18c2005-06-28 17:17:12 +00002995rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002996{
Feng Lu0d0686f2015-05-22 11:40:02 +02002997 vrf_iter_t iter;
2998 struct zebra_vrf *zvrf;
2999
3000 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3001 if ((zvrf = vrf_iter2info (iter)) != NULL)
3002 {
3003 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3004 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3005 }
paul718e3742002-12-13 20:15:29 +00003006}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003007
3008/* Remove specific by protocol routes from 'table'. */
3009static unsigned long
3010rib_score_proto_table (u_char proto, struct route_table *table)
3011{
3012 struct route_node *rn;
3013 struct rib *rib;
3014 struct rib *next;
3015 unsigned long n = 0;
3016
3017 if (table)
3018 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003019 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003020 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003021 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3022 continue;
3023 if (rib->type == proto)
3024 {
3025 rib_delnode (rn, rib);
3026 n++;
3027 }
3028 }
3029
3030 return n;
3031}
3032
3033/* Remove specific by protocol routes. */
3034unsigned long
3035rib_score_proto (u_char proto)
3036{
Feng Lu0d0686f2015-05-22 11:40:02 +02003037 vrf_iter_t iter;
3038 struct zebra_vrf *zvrf;
3039 unsigned long cnt = 0;
3040
3041 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3042 if ((zvrf = vrf_iter2info (iter)) != NULL)
3043 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3044 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3045
3046 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003047}
3048
paul718e3742002-12-13 20:15:29 +00003049/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003050void
paul718e3742002-12-13 20:15:29 +00003051rib_close_table (struct route_table *table)
3052{
3053 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003054 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003055 struct rib *rib;
3056
3057 if (table)
3058 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003059 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003060 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003061 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3062 continue;
3063
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003064 if (info->safi == SAFI_UNICAST)
3065 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003066
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003067 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02003068 rib_update_kernel (rn, rib, NULL);
Paul Jakma6d691122006-07-27 21:49:00 +00003069 }
paul718e3742002-12-13 20:15:29 +00003070}
3071
3072/* Close all RIB tables. */
3073void
paula1ac18c2005-06-28 17:17:12 +00003074rib_close (void)
paul718e3742002-12-13 20:15:29 +00003075{
Feng Lu0d0686f2015-05-22 11:40:02 +02003076 vrf_iter_t iter;
3077 struct zebra_vrf *zvrf;
3078
3079 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3080 if ((zvrf = vrf_iter2info (iter)) != NULL)
3081 {
3082 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3083 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3084 }
paul718e3742002-12-13 20:15:29 +00003085}
David Lamparter6b0655a2014-06-04 06:53:35 +02003086
paul718e3742002-12-13 20:15:29 +00003087/* Routing information base initialize. */
3088void
paula1ac18c2005-06-28 17:17:12 +00003089rib_init (void)
paul718e3742002-12-13 20:15:29 +00003090{
paul4d38fdb2005-04-28 17:35:14 +00003091 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003092}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003093
3094/*
3095 * vrf_id_get_next
3096 *
3097 * Get the first vrf id that is greater than the given vrf id if any.
3098 *
3099 * Returns TRUE if a vrf id was found, FALSE otherwise.
3100 */
3101static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003102vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003103{
Feng Lu41f44a22015-05-22 11:39:56 +02003104 vrf_iter_t iter = vrf_iterator (vrf_id);
3105 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3106
3107 /* The same one ? Then find out the next. */
3108 if (zvrf && (zvrf->vrf_id == vrf_id))
3109 zvrf = vrf_iter2info (vrf_next (iter));
3110
3111 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003112 {
Feng Lu41f44a22015-05-22 11:39:56 +02003113 *next_id_p = zvrf->vrf_id;
3114 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003115 }
3116
3117 return 0;
3118}
3119
3120/*
3121 * rib_tables_iter_next
3122 *
3123 * Returns the next table in the iteration.
3124 */
3125struct route_table *
3126rib_tables_iter_next (rib_tables_iter_t *iter)
3127{
3128 struct route_table *table;
3129
3130 /*
3131 * Array that helps us go over all AFI/SAFI combinations via one
3132 * index.
3133 */
3134 static struct {
3135 afi_t afi;
3136 safi_t safi;
3137 } afi_safis[] = {
3138 { AFI_IP, SAFI_UNICAST },
3139 { AFI_IP, SAFI_MULTICAST },
3140 { AFI_IP6, SAFI_UNICAST },
3141 { AFI_IP6, SAFI_MULTICAST },
3142 };
3143
3144 table = NULL;
3145
3146 switch (iter->state)
3147 {
3148
3149 case RIB_TABLES_ITER_S_INIT:
Donald Sharp0d271292015-11-19 07:21:30 -05003150 iter->vrf_id = VRF_DEFAULT;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003151 iter->afi_safi_ix = -1;
3152
3153 /* Fall through */
3154
3155 case RIB_TABLES_ITER_S_ITERATING:
3156 iter->afi_safi_ix++;
3157 while (1)
3158 {
3159
3160 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3161 {
Feng Lu41f44a22015-05-22 11:39:56 +02003162 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003163 afi_safis[iter->afi_safi_ix].safi,
3164 iter->vrf_id);
3165 if (table)
3166 break;
3167
3168 iter->afi_safi_ix++;
3169 }
3170
3171 /*
3172 * Found another table in this vrf.
3173 */
3174 if (table)
3175 break;
3176
3177 /*
3178 * Done with all tables in the current vrf, go to the next
3179 * one.
3180 */
3181 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3182 break;
3183
3184 iter->afi_safi_ix = 0;
3185 }
3186
3187 break;
3188
3189 case RIB_TABLES_ITER_S_DONE:
3190 return NULL;
3191 }
3192
3193 if (table)
3194 iter->state = RIB_TABLES_ITER_S_ITERATING;
3195 else
3196 iter->state = RIB_TABLES_ITER_S_DONE;
3197
3198 return table;
3199}
Feng Lu41f44a22015-05-22 11:39:56 +02003200
3201/*
3202 * Create a routing table for the specific AFI/SAFI in the given VRF.
3203 */
3204static void
3205zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3206{
3207 rib_table_info_t *info;
3208 struct route_table *table;
3209
3210 assert (!zvrf->table[afi][safi]);
3211
3212 table = route_table_init ();
3213 zvrf->table[afi][safi] = table;
3214
3215 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3216 info->zvrf = zvrf;
3217 info->afi = afi;
3218 info->safi = safi;
3219 table->info = info;
3220}
3221
3222/* Allocate new zebra VRF. */
3223struct zebra_vrf *
3224zebra_vrf_alloc (vrf_id_t vrf_id)
3225{
3226 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003227#ifdef HAVE_NETLINK
3228 char nl_name[64];
3229#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003230
3231 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3232
3233 /* Allocate routing table and static table. */
3234 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3235 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3236 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3237 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3238 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3239 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3240 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3241 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3242
3243 /* Set VRF ID */
3244 zvrf->vrf_id = vrf_id;
3245
Feng Lu758fb8f2014-07-03 18:23:09 +08003246#ifdef HAVE_NETLINK
3247 /* Initialize netlink sockets */
3248 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3249 zvrf->netlink.sock = -1;
3250 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3251
3252 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3253 zvrf->netlink_cmd.sock = -1;
3254 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3255#endif
3256
Feng Lu41f44a22015-05-22 11:39:56 +02003257 return zvrf;
3258}
3259
3260/* Lookup the routing table in an enabled VRF. */
3261struct route_table *
3262zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3263{
3264 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3265
3266 if (!zvrf)
3267 return NULL;
3268
3269 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3270 return NULL;
3271
3272 return zvrf->table[afi][safi];
3273}
3274
3275/* Lookup the static routing table in a VRF. */
3276struct route_table *
3277zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3278{
3279 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3280
3281 if (!zvrf)
3282 return NULL;
3283
3284 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3285 return NULL;
3286
3287 return zvrf->stable[afi][safi];
3288}
3289