blob: 7cce13fe4ea9a09672ff329a1e66869607c3a0e3 [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;
Christian Frankefa713d92013-07-05 15:35:37 +0000442
Christian Frankec3e6b592013-07-05 15:35:40 +0000443 if (newhop->ifindex)
444 {
445 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
446 resolved_hop->ifindex = newhop->ifindex;
447 }
448 }
Christian Frankefa713d92013-07-05 15:35:37 +0000449
Christian Frankec3e6b592013-07-05 15:35:40 +0000450 /* If the resolving route is an interface route,
451 * it means the gateway we are looking up is connected
452 * to that interface. (The actual network is _not_ onlink).
453 * Therefore, the resolved route should have the original
454 * gateway as nexthop as it is directly connected.
455 *
456 * On Linux, we have to set the onlink netlink flag because
457 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000458 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000459 || newhop->type == NEXTHOP_TYPE_IFNAME)
460 {
461 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
462 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
463 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
464 resolved_hop->ifindex = newhop->ifindex;
465 }
Christian Frankefa713d92013-07-05 15:35:37 +0000466
467 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000468 }
Christian Frankefa713d92013-07-05 15:35:37 +0000469 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000470 }
Timo Teräsb11f3b52015-11-02 16:50:07 +0200471 if (resolved && set)
472 rib->nexthop_mtu = match->mtu;
Christian Frankefa713d92013-07-05 15:35:37 +0000473 return resolved;
paul718e3742002-12-13 20:15:29 +0000474 }
475 else
476 {
477 return 0;
478 }
479 }
480 }
481 return 0;
482}
483
paul718e3742002-12-13 20:15:29 +0000484/* If force flag is not set, do not modify falgs at all for uninstall
485 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000486static int
paul718e3742002-12-13 20:15:29 +0000487nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
488 struct route_node *top)
489{
490 struct prefix_ipv6 p;
491 struct route_table *table;
492 struct route_node *rn;
493 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000494 int resolved;
paul718e3742002-12-13 20:15:29 +0000495 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000496 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000497
498 if (nexthop->type == NEXTHOP_TYPE_IPV6)
499 nexthop->ifindex = 0;
500
501 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000502 {
503 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
504 nexthops_free(nexthop->resolved);
505 nexthop->resolved = NULL;
506 }
paul718e3742002-12-13 20:15:29 +0000507
508 /* Make lookup prefix. */
509 memset (&p, 0, sizeof (struct prefix_ipv6));
510 p.family = AF_INET6;
511 p.prefixlen = IPV6_MAX_PREFIXLEN;
512 p.prefix = nexthop->gate.ipv6;
513
514 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200515 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +0000516 if (! table)
517 return 0;
518
519 rn = route_node_match (table, (struct prefix *) &p);
520 while (rn)
521 {
522 route_unlock_node (rn);
523
David Warda50c1072009-12-03 15:34:39 +0300524 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000525 if (rn == top)
526 return 0;
527
528 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000529 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100530 {
531 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
532 continue;
533 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
534 break;
535 }
paul718e3742002-12-13 20:15:29 +0000536
537 /* If there is no selected route or matched route is EGP, go up
538 tree. */
539 if (! match
540 || match->type == ZEBRA_ROUTE_BGP)
541 {
542 do {
543 rn = rn->parent;
544 } while (rn && rn->info == NULL);
545 if (rn)
546 route_lock_node (rn);
547 }
548 else
549 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000550 /* If the longest prefix match for the nexthop yields
551 * a blackhole, mark it as inactive. */
552 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
553 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
554 return 0;
555
paul718e3742002-12-13 20:15:29 +0000556 if (match->type == ZEBRA_ROUTE_CONNECT)
557 {
558 /* Directly point connected route. */
559 newhop = match->nexthop;
560
561 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
562 nexthop->ifindex = newhop->ifindex;
563
564 return 1;
565 }
566 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
567 {
Christian Frankefa713d92013-07-05 15:35:37 +0000568 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000569 for (newhop = match->nexthop; newhop; newhop = newhop->next)
570 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
571 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
572 {
573 if (set)
574 {
575 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000576
577 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
578 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000579 /* See nexthop_active_ipv4 for a description how the
580 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000581 if (newhop->type == NEXTHOP_TYPE_IPV6
582 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
583 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000584 {
585 resolved_hop->type = newhop->type;
586 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
587
588 if (newhop->ifindex)
589 {
590 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
591 resolved_hop->ifindex = newhop->ifindex;
592 }
593 }
Christian Frankefa713d92013-07-05 15:35:37 +0000594
paul718e3742002-12-13 20:15:29 +0000595 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000596 || newhop->type == NEXTHOP_TYPE_IFNAME)
597 {
598 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
599 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
600 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
601 resolved_hop->ifindex = newhop->ifindex;
602 }
Christian Frankefa713d92013-07-05 15:35:37 +0000603
604 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000605 }
Christian Frankefa713d92013-07-05 15:35:37 +0000606 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000607 }
Christian Frankefa713d92013-07-05 15:35:37 +0000608 return resolved;
paul718e3742002-12-13 20:15:29 +0000609 }
610 else
611 {
612 return 0;
613 }
614 }
615 }
616 return 0;
617}
paul718e3742002-12-13 20:15:29 +0000618
619struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100620rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
Feng Lu0d0686f2015-05-22 11:40:02 +0200621 struct route_node **rn_out, vrf_id_t vrf_id)
Everton Marques3dea1782014-09-22 19:35:51 -0300622{
623 struct route_table *table;
624 struct route_node *rn;
625 struct rib *match;
626 struct nexthop *newhop, *tnewhop;
627 int recursing;
628
629 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200630 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
Everton Marques3dea1782014-09-22 19:35:51 -0300631 if (! table)
632 return 0;
633
634 rn = route_node_match_ipv4 (table, &addr);
635
636 while (rn)
637 {
638 route_unlock_node (rn);
639
640 /* Pick up selected route. */
641 RNODE_FOREACH_RIB (rn, match)
642 {
643 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
644 continue;
645 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
646 break;
647 }
648
649 /* If there is no selected route or matched route is EGP, go up
650 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300651 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300652 {
653 do {
654 rn = rn->parent;
655 } while (rn && rn->info == NULL);
656 if (rn)
657 route_lock_node (rn);
658 }
659 else
660 {
David Lamparter24480d42015-01-22 19:09:36 +0100661 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300662 {
David Lamparter24480d42015-01-22 19:09:36 +0100663 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300664 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
665 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100666 {
667 found = 1;
668 break;
669 }
670 if (!found)
671 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300672 }
David Lamparter24480d42015-01-22 19:09:36 +0100673
674 if (rn_out)
675 *rn_out = rn;
676 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300677 }
678 }
679 return NULL;
680}
681
682struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200683rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out,
684 vrf_id_t vrf_id)
David Lamparterbd078122015-01-06 19:53:24 +0100685{
686 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
687 struct route_node *m_rn = NULL, *u_rn = NULL;
688 int skip_bgp = 0; /* bool */
689
690 switch (ipv4_multicast_mode)
691 {
692 case MCAST_MRIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200693 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out,
694 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100695 case MCAST_URIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200696 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out,
697 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100698 case MCAST_NO_CONFIG:
699 case MCAST_MIX_MRIB_FIRST:
Feng Lu0d0686f2015-05-22 11:40:02 +0200700 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
701 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100702 if (!mrib)
Feng Lu0d0686f2015-05-22 11:40:02 +0200703 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
704 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100705 break;
706 case MCAST_MIX_DISTANCE:
Feng Lu0d0686f2015-05-22 11:40:02 +0200707 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
708 vrf_id);
709 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
710 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100711 if (mrib && urib)
712 rib = urib->distance < mrib->distance ? urib : mrib;
713 else if (mrib)
714 rib = mrib;
715 else if (urib)
716 rib = urib;
717 break;
718 case MCAST_MIX_PFXLEN:
Feng Lu0d0686f2015-05-22 11:40:02 +0200719 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
720 vrf_id);
721 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
722 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100723 if (mrib && urib)
724 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
725 else if (mrib)
726 rib = mrib;
727 else if (urib)
728 rib = urib;
729 break;
730 }
731
732 if (rn_out)
733 *rn_out = (rib == mrib) ? m_rn : u_rn;
734
735 if (IS_ZEBRA_DEBUG_RIB)
736 {
737 char buf[BUFSIZ];
738 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
739
Feng Lu0d0686f2015-05-22 11:40:02 +0200740 zlog_debug("%s: %s vrf %u: found %s, using %s",
741 __func__, buf, vrf_id,
David Lamparterbd078122015-01-06 19:53:24 +0100742 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
743 urib ? "URIB" : "nothing",
744 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
745 }
746 return rib;
747}
748
749void
750multicast_mode_ipv4_set (enum multicast_mode mode)
751{
752 if (IS_ZEBRA_DEBUG_RIB)
753 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
754 ipv4_multicast_mode = mode;
755}
756
757enum multicast_mode
758multicast_mode_ipv4_get (void)
759{
760 return ipv4_multicast_mode;
761}
762
763struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200764rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000765{
766 struct route_table *table;
767 struct route_node *rn;
768 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000769 struct nexthop *nexthop, *tnexthop;
770 int recursing;
paul718e3742002-12-13 20:15:29 +0000771
772 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200773 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000774 if (! table)
775 return 0;
776
777 rn = route_node_lookup (table, (struct prefix *) p);
778
779 /* No route for this prefix. */
780 if (! rn)
781 return NULL;
782
783 /* Unlock node. */
784 route_unlock_node (rn);
785
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000786 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100787 {
788 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
789 continue;
790 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
791 break;
792 }
paul718e3742002-12-13 20:15:29 +0000793
794 if (! match || match->type == ZEBRA_ROUTE_BGP)
795 return NULL;
796
797 if (match->type == ZEBRA_ROUTE_CONNECT)
798 return match;
799
Christian Frankefa713d92013-07-05 15:35:37 +0000800 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000801 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
802 return match;
803
804 return NULL;
805}
806
Denis Ovsienkodc958242007-08-13 16:03:06 +0000807/*
808 * This clone function, unlike its original rib_lookup_ipv4(), checks
809 * if specified IPv4 route record (prefix/mask -> gate) exists in
810 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
811 *
812 * Return values:
813 * -1: error
814 * 0: exact match found
815 * 1: a match was found with a different gate
816 * 2: connected route found
817 * 3: no matches found
818 */
819int
Feng Lu0d0686f2015-05-22 11:40:02 +0200820rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
821 vrf_id_t vrf_id)
Denis Ovsienkodc958242007-08-13 16:03:06 +0000822{
823 struct route_table *table;
824 struct route_node *rn;
825 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000826 struct nexthop *nexthop, *tnexthop;
827 int recursing;
828 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000829
830 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200831 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000832 if (! table)
833 return ZEBRA_RIB_LOOKUP_ERROR;
834
835 /* Scan the RIB table for exactly matching RIB entry. */
836 rn = route_node_lookup (table, (struct prefix *) p);
837
838 /* No route for this prefix. */
839 if (! rn)
840 return ZEBRA_RIB_NOTFOUND;
841
842 /* Unlock node. */
843 route_unlock_node (rn);
844
845 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000846 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100847 {
848 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
849 continue;
850 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
851 break;
852 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000853
854 /* None such found :( */
855 if (!match)
856 return ZEBRA_RIB_NOTFOUND;
857
858 if (match->type == ZEBRA_ROUTE_CONNECT)
859 return ZEBRA_RIB_FOUND_CONNECTED;
860
861 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000862 nexthops_active = 0;
863 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000864 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000865 {
Christian Frankefa713d92013-07-05 15:35:37 +0000866 nexthops_active = 1;
867 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
868 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000869 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000870 {
871 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
872 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
873 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
874 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
875 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
876 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000877 }
Christian Frankefa713d92013-07-05 15:35:37 +0000878
879 if (nexthops_active)
880 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000881
882 return ZEBRA_RIB_NOTFOUND;
883}
884
paul718e3742002-12-13 20:15:29 +0000885struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200886rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000887{
888 struct prefix_ipv6 p;
889 struct route_table *table;
890 struct route_node *rn;
891 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000892 struct nexthop *newhop, *tnewhop;
893 int recursing;
paul718e3742002-12-13 20:15:29 +0000894
895 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200896 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000897 if (! table)
898 return 0;
899
900 memset (&p, 0, sizeof (struct prefix_ipv6));
901 p.family = AF_INET6;
902 p.prefixlen = IPV6_MAX_PREFIXLEN;
903 IPV6_ADDR_COPY (&p.prefix, addr);
904
905 rn = route_node_match (table, (struct prefix *) &p);
906
907 while (rn)
908 {
909 route_unlock_node (rn);
910
911 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000912 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100913 {
914 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
915 continue;
916 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
917 break;
918 }
paul718e3742002-12-13 20:15:29 +0000919
920 /* If there is no selected route or matched route is EGP, go up
921 tree. */
922 if (! match
923 || match->type == ZEBRA_ROUTE_BGP)
924 {
925 do {
926 rn = rn->parent;
927 } while (rn && rn->info == NULL);
928 if (rn)
929 route_lock_node (rn);
930 }
931 else
932 {
933 if (match->type == ZEBRA_ROUTE_CONNECT)
934 /* Directly point connected route. */
935 return match;
936 else
937 {
Christian Frankefa713d92013-07-05 15:35:37 +0000938 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000939 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
940 return match;
941 return NULL;
942 }
943 }
944 }
945 return NULL;
946}
paul718e3742002-12-13 20:15:29 +0000947
Paul Jakma7514fb72007-05-02 16:05:35 +0000948#define RIB_SYSTEM_ROUTE(R) \
949 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
950
Denis Ovsienkodc958242007-08-13 16:03:06 +0000951/* This function verifies reachability of one given nexthop, which can be
952 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
953 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
954 * nexthop->ifindex will be updated appropriately as well.
955 * An existing route map can turn (otherwise active) nexthop into inactive, but
956 * not vice versa.
957 *
958 * The return value is the final value of 'ACTIVE' flag.
959 */
960
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300961static unsigned
paul718e3742002-12-13 20:15:29 +0000962nexthop_active_check (struct route_node *rn, struct rib *rib,
963 struct nexthop *nexthop, int set)
964{
Christian Frankef3a17322013-07-05 15:35:41 +0000965 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +0000966 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000967 route_map_result_t ret = RMAP_MATCH;
968 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
969 struct route_map *rmap;
970 int family;
paul718e3742002-12-13 20:15:29 +0000971
Paul Jakma7514fb72007-05-02 16:05:35 +0000972 family = 0;
paul718e3742002-12-13 20:15:29 +0000973 switch (nexthop->type)
974 {
975 case NEXTHOP_TYPE_IFINDEX:
Feng Lu0d0686f2015-05-22 11:40:02 +0200976 ifp = if_lookup_by_index_vrf (nexthop->ifindex, 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 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
979 else
980 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
981 break;
paul718e3742002-12-13 20:15:29 +0000982 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000983 family = AFI_IP6;
984 case NEXTHOP_TYPE_IFNAME:
Feng Lu0d0686f2015-05-22 11:40:02 +0200985 ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000986 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000987 {
988 if (set)
989 nexthop->ifindex = ifp->ifindex;
990 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
991 }
992 else
993 {
994 if (set)
995 nexthop->ifindex = 0;
996 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
997 }
998 break;
999 case NEXTHOP_TYPE_IPV4:
1000 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001001 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001002 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1003 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1004 else
1005 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1006 break;
paul718e3742002-12-13 20:15:29 +00001007 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001008 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001009 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1010 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1011 else
1012 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1013 break;
1014 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001015 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001016 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1017 {
Feng Lu0d0686f2015-05-22 11:40:02 +02001018 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001019 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001020 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1021 else
1022 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1023 }
1024 else
1025 {
1026 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1027 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1028 else
1029 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1030 }
1031 break;
paul595db7f2003-05-25 21:35:06 +00001032 case NEXTHOP_TYPE_BLACKHOLE:
1033 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1034 break;
paul718e3742002-12-13 20:15:29 +00001035 default:
1036 break;
1037 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001038 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1039 return 0;
1040
Christian Frankef3a17322013-07-05 15:35:41 +00001041 /* XXX: What exactly do those checks do? Do we support
1042 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001043 if (RIB_SYSTEM_ROUTE(rib) ||
1044 (family == AFI_IP && rn->p.family != AF_INET) ||
1045 (family == AFI_IP6 && rn->p.family != AF_INET6))
1046 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1047
Christian Frankef3a17322013-07-05 15:35:41 +00001048 /* The original code didn't determine the family correctly
1049 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1050 * from the rib_table_info in those cases.
1051 * Possibly it may be better to use only the rib_table_info
1052 * in every case.
1053 */
1054 if (!family)
1055 family = info->afi;
1056
Paul Jakma7514fb72007-05-02 16:05:35 +00001057 rmap = 0;
1058 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1059 proto_rm[family][rib->type])
1060 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1061 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1062 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1063 if (rmap) {
Feng Lu1885d0a2015-05-22 11:40:04 +02001064 struct nexthop_vrfid nh_vrf = {nexthop, rib->vrf_id};
1065 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, &nh_vrf);
Paul Jakma7514fb72007-05-02 16:05:35 +00001066 }
1067
1068 if (ret == RMAP_DENYMATCH)
1069 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001070 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1071}
1072
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001073/* Iterate over all nexthops of the given RIB entry and refresh their
1074 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1075 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
Timo Teräs7eb61362015-11-02 16:50:05 +02001076 * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001077 * transparently passed to nexthop_active_check().
1078 *
1079 * Return value is the new number of active nexthops.
1080 */
1081
paula1ac18c2005-06-28 17:17:12 +00001082static int
paul718e3742002-12-13 20:15:29 +00001083nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1084{
1085 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001086 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001087
1088 rib->nexthop_active_num = 0;
Timo Teräs7eb61362015-11-02 16:50:05 +02001089 UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
paul718e3742002-12-13 20:15:29 +00001090
1091 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001092 {
1093 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001094 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001095 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1096 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001097 if (prev_active != new_active ||
1098 prev_index != nexthop->ifindex)
Timo Teräs7eb61362015-11-02 16:50:05 +02001099 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001100 }
paul718e3742002-12-13 20:15:29 +00001101 return rib->nexthop_active_num;
1102}
paul6baeb982003-10-28 03:47:15 +00001103
David Lamparter6b0655a2014-06-04 06:53:35 +02001104
paul718e3742002-12-13 20:15:29 +00001105
Timo Teräs0abf6792016-01-15 17:36:29 +02001106static int
1107rib_update_kernel (struct route_node *rn, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001108{
1109 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001110 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001111 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001112 int recursing;
paul718e3742002-12-13 20:15:29 +00001113
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001114 if (info->safi != SAFI_UNICAST)
1115 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001116 if (new)
1117 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1118 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1119 if (old)
1120 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1121 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1122 return 0;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001123 }
1124
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001125 /*
1126 * Make sure we update the FPM any time we send new information to
1127 * the kernel.
1128 */
Timo Teräs0abf6792016-01-15 17:36:29 +02001129 zfpm_trigger_update (rn, "updating in kernel");
1130
1131 ret = kernel_route_rib (&rn->p, old, new);
paul718e3742002-12-13 20:15:29 +00001132
Denis Ovsienkodc958242007-08-13 16:03:06 +00001133 /* This condition is never met, if we are using rt_socket.c */
Timo Teräs0abf6792016-01-15 17:36:29 +02001134 if (ret < 0 && new)
1135 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1136 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001137
Timo Teräs0abf6792016-01-15 17:36:29 +02001138 if (old)
1139 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1140 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001141
1142 return ret;
1143}
1144
1145/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001146static void
paul718e3742002-12-13 20:15:29 +00001147rib_uninstall (struct route_node *rn, struct rib *rib)
1148{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001149 rib_table_info_t *info = rn->table->info;
1150
paul718e3742002-12-13 20:15:29 +00001151 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1152 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001153 if (info->safi == SAFI_UNICAST)
1154 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001155
paul718e3742002-12-13 20:15:29 +00001156 redistribute_delete (&rn->p, rib);
1157 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02001158 rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00001159 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1160 }
1161}
1162
Paul Jakma6d691122006-07-27 21:49:00 +00001163static void rib_unlink (struct route_node *, struct rib *);
1164
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001165/*
1166 * rib_can_delete_dest
1167 *
1168 * Returns TRUE if the given dest can be deleted from the table.
1169 */
1170static int
1171rib_can_delete_dest (rib_dest_t *dest)
1172{
1173 if (dest->routes)
1174 {
1175 return 0;
1176 }
1177
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001178 /*
1179 * Don't delete the dest if we have to update the FPM about this
1180 * prefix.
1181 */
1182 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1183 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1184 return 0;
1185
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001186 return 1;
1187}
1188
1189/*
1190 * rib_gc_dest
1191 *
1192 * Garbage collect the rib dest corresponding to the given route node
1193 * if appropriate.
1194 *
1195 * Returns TRUE if the dest was deleted, FALSE otherwise.
1196 */
1197int
1198rib_gc_dest (struct route_node *rn)
1199{
1200 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001201
1202 dest = rib_dest_from_rnode (rn);
1203 if (!dest)
1204 return 0;
1205
1206 if (!rib_can_delete_dest (dest))
1207 return 0;
1208
1209 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001210 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001211
1212 dest->rnode = NULL;
1213 XFREE (MTYPE_RIB_DEST, dest);
1214 rn->info = NULL;
1215
1216 /*
1217 * Release the one reference that we keep on the route node.
1218 */
1219 route_unlock_node (rn);
1220 return 1;
1221}
1222
Timo Teräs0abf6792016-01-15 17:36:29 +02001223/* Check if 'alternate' RIB entry is better than 'current'. */
1224static struct rib *
1225rib_choose_best (struct rib *current, struct rib *alternate)
1226{
1227 if (current == NULL)
1228 return alternate;
1229
1230 /* filter route selection in following order:
1231 * - connected beats other types
1232 * - lower distance beats higher
1233 * - lower metric beats higher for equal distance
1234 * - last, hence oldest, route wins tie break.
1235 */
1236
1237 /* Connected routes. Pick the last connected
1238 * route of the set of lowest metric connected routes.
1239 */
1240 if (alternate->type == ZEBRA_ROUTE_CONNECT)
1241 {
1242 if (current->type != ZEBRA_ROUTE_CONNECT
1243 || alternate->metric <= current->metric)
1244 return alternate;
1245
1246 return current;
1247 }
1248
1249 if (current->type == ZEBRA_ROUTE_CONNECT)
1250 return current;
1251
1252 /* higher distance loses */
1253 if (alternate->distance < current->distance)
1254 return alternate;
1255 if (current->distance < alternate->distance)
1256 return current;
1257
1258 /* metric tie-breaks equal distance */
1259 if (alternate->metric <= current->metric)
1260 return alternate;
1261
1262 return current;
1263}
1264
paul718e3742002-12-13 20:15:29 +00001265/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001266static void
1267rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001268{
1269 struct rib *rib;
1270 struct rib *next;
Timo Teräs0abf6792016-01-15 17:36:29 +02001271 struct rib *old_fib = NULL;
1272 struct rib *new_fib = NULL;
pauld753e9e2003-01-22 19:45:50 +00001273 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001274 struct nexthop *nexthop = NULL, *tnexthop;
1275 int recursing;
Balaji95116332014-10-23 15:25:25 +00001276 rib_table_info_t *info;
1277
paul4d38fdb2005-04-28 17:35:14 +00001278 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001279
1280 info = rn->table->info;
1281
Timo Teräs0abf6792016-01-15 17:36:29 +02001282 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001283 {
paul718e3742002-12-13 20:15:29 +00001284 /* Currently installed rib. */
1285 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001286 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001287 assert (old_fib == NULL);
1288 old_fib = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001289 }
Timo Teräs0abf6792016-01-15 17:36:29 +02001290
1291 /* Skip deleted entries from selection */
Paul Jakma6d691122006-07-27 21:49:00 +00001292 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
Timo Teräs0abf6792016-01-15 17:36:29 +02001293 continue;
paul4d38fdb2005-04-28 17:35:14 +00001294
paul718e3742002-12-13 20:15:29 +00001295 /* Skip unreachable nexthop. */
1296 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001297 continue;
paul718e3742002-12-13 20:15:29 +00001298
1299 /* Infinit distance. */
1300 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001301 continue;
paul718e3742002-12-13 20:15:29 +00001302
Timo Teräs0abf6792016-01-15 17:36:29 +02001303 new_fib = rib_choose_best(new_fib, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001304 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001305
1306 /* After the cycle is finished, the following pointers will be set:
Timo Teräs0abf6792016-01-15 17:36:29 +02001307 * old_fib --- RIB entry currently having SELECTED
1308 * new_fib --- RIB entry that is newly SELECTED
Denis Ovsienkodc958242007-08-13 16:03:06 +00001309 */
1310
Timo Teräs0abf6792016-01-15 17:36:29 +02001311 /* Set real nexthops. */
1312 if (new_fib)
1313 nexthop_active_update (rn, new_fib, 1);
1314
1315 /* Update kernel if FIB entry has changed */
1316 if (old_fib != new_fib
1317 || (new_fib && CHECK_FLAG (new_fib->status, RIB_ENTRY_CHANGED)))
paul718e3742002-12-13 20:15:29 +00001318 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001319 if (old_fib && old_fib != new_fib)
1320 {
1321 if (! new_fib)
1322 redistribute_delete (&rn->p, old_fib);
1323
1324 if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
1325 rib_update_kernel (rn, old_fib, NULL);
1326 UNSET_FLAG (old_fib->flags, ZEBRA_FLAG_SELECTED);
1327 }
1328
1329 if (new_fib)
1330 {
1331 /* Install new or replace existing FIB entry */
1332 SET_FLAG (new_fib->flags, ZEBRA_FLAG_SELECTED);
1333 redistribute_add (&rn->p, new_fib);
1334
1335 if (! RIB_SYSTEM_ROUTE (new_fib))
1336 rib_update_kernel (rn, old_fib, new_fib);
1337 }
1338
1339 if (info->safi == SAFI_UNICAST)
1340 zfpm_trigger_update (rn, "updating existing route");
1341 }
1342 else if (old_fib == new_fib && new_fib && ! RIB_SYSTEM_ROUTE (new_fib))
1343 {
1344 /* Housekeeping code to deal with race conditions in kernel with
1345 * linux netlink reporting interface up before IPv4 or IPv6 protocol
1346 * is ready to add routes. This makes sure routes are IN the kernel.
1347 */
1348 for (ALL_NEXTHOPS_RO(new_fib->nexthop, nexthop, tnexthop, recursing))
1349 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1350 {
1351 installed = 1;
1352 break;
1353 }
1354 if (! installed)
1355 rib_update_kernel (rn, NULL, new_fib);
1356 }
1357
1358 /* Remove all RIB entries queued for removal */
1359 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1360 {
1361 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
paul4d38fdb2005-04-28 17:35:14 +00001362 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001363 if (IS_ZEBRA_DEBUG_RIB)
1364 rnode_debug (rn, "rn %p, removing rib %p",
1365 (void *)rn, (void *)rib);
1366 rib_unlink (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001367 }
paul718e3742002-12-13 20:15:29 +00001368 }
1369
Paul Jakma6d691122006-07-27 21:49:00 +00001370 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001371 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001372
1373 /*
1374 * Check if the dest can be deleted now.
1375 */
1376 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001377}
1378
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001379/* Take a list of route_node structs and return 1, if there was a record
1380 * picked from it and processed by rib_process(). Don't process more,
1381 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001382 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001383static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001384process_subq (struct list * subq, u_char qindex)
1385{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001386 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001387 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001388
1389 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001390 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001391
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001392 rnode = listgetdata (lnode);
1393 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001394
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001395 if (rnode->info)
1396 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1397
Chris Caputo67b94672009-07-18 04:02:26 +00001398#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001399 else
1400 {
1401 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1402 __func__, rnode, rnode->lock);
1403 zlog_backtrace(LOG_DEBUG);
1404 }
Chris Caputo67b94672009-07-18 04:02:26 +00001405#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001406 route_unlock_node (rnode);
1407 list_delete_node (subq, lnode);
1408 return 1;
1409}
1410
1411/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1412 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1413 * is pointed to the meta queue structure.
1414 */
1415static wq_item_status
1416meta_queue_process (struct work_queue *dummy, void *data)
1417{
1418 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001419 unsigned i;
1420
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001421 for (i = 0; i < MQ_SIZE; i++)
1422 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001423 {
1424 mq->size--;
1425 break;
1426 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001427 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1428}
1429
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001430/*
1431 * Map from rib types to queue type (priority) in meta queue
1432 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001433static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1434 [ZEBRA_ROUTE_SYSTEM] = 4,
1435 [ZEBRA_ROUTE_KERNEL] = 0,
1436 [ZEBRA_ROUTE_CONNECT] = 0,
1437 [ZEBRA_ROUTE_STATIC] = 1,
1438 [ZEBRA_ROUTE_RIP] = 2,
1439 [ZEBRA_ROUTE_RIPNG] = 2,
1440 [ZEBRA_ROUTE_OSPF] = 2,
1441 [ZEBRA_ROUTE_OSPF6] = 2,
1442 [ZEBRA_ROUTE_ISIS] = 2,
1443 [ZEBRA_ROUTE_BGP] = 3,
1444 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001445 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001446};
1447
1448/* Look into the RN and queue it into one or more priority queues,
1449 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001450 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001451static void
1452rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001453{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001454 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001455
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001456 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001457 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001458 u_char qindex = meta_queue_map[rib->type];
1459
1460 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001461 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1462 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001463 {
1464 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001465 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001466 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001467 continue;
1468 }
1469
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001470 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001471 listnode_add (mq->subq[qindex], rn);
1472 route_lock_node (rn);
1473 mq->size++;
1474
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001475 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001476 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001477 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001478 }
paul4d38fdb2005-04-28 17:35:14 +00001479}
1480
Paul Jakma6d691122006-07-27 21:49:00 +00001481/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001482static void
Paul Jakma6d691122006-07-27 21:49:00 +00001483rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001484{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001485 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001486
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001487 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001488 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001489 {
1490 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001491 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001492 zlog_backtrace(LOG_DEBUG);
1493 return;
1494 }
1495
1496 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001497 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001498
1499 assert (zebra);
1500
1501 if (zebra->ribq == NULL)
1502 {
1503 zlog_err ("%s: work_queue does not exist!", __func__);
1504 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001505 }
paul4d38fdb2005-04-28 17:35:14 +00001506
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001507 /*
1508 * The RIB queue should normally be either empty or holding the only
1509 * work_queue_item element. In the latter case this element would
1510 * hold a pointer to the meta queue structure, which must be used to
1511 * actually queue the route nodes to process. So create the MQ
1512 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001513 * This semantics was introduced after 0.99.9 release.
1514 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001515 if (!zebra->ribq->items->count)
1516 work_queue_add (zebra->ribq, zebra->mq);
1517
1518 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001519
1520 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001521 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001522
1523 return;
paul4d38fdb2005-04-28 17:35:14 +00001524}
1525
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001526/* Create new meta queue.
1527 A destructor function doesn't seem to be necessary here.
1528 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001529static struct meta_queue *
1530meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001531{
1532 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001533 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001534
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001535 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1536 assert(new);
1537
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001538 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001539 {
1540 new->subq[i] = list_new ();
1541 assert(new->subq[i]);
1542 }
1543
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001544 return new;
1545}
1546
paul4d38fdb2005-04-28 17:35:14 +00001547/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001548static void
paul4d38fdb2005-04-28 17:35:14 +00001549rib_queue_init (struct zebra_t *zebra)
1550{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001551 assert (zebra);
1552
paul4d38fdb2005-04-28 17:35:14 +00001553 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001554 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001555 {
Paul Jakma6d691122006-07-27 21:49:00 +00001556 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001557 return;
1558 }
1559
1560 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001561 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001562 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001563 /* XXX: TODO: These should be runtime configurable via vty */
1564 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001565 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001566
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001567 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001568 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001569 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001570 return;
1571 }
1572 return;
paul718e3742002-12-13 20:15:29 +00001573}
1574
Paul Jakma6d691122006-07-27 21:49:00 +00001575/* RIB updates are processed via a queue of pointers to route_nodes.
1576 *
1577 * The queue length is bounded by the maximal size of the routing table,
1578 * as a route_node will not be requeued, if already queued.
1579 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001580 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05001581 * state, or static_install_route (when an existing RIB is updated)
Paul Jakma3c0755d2006-12-08 00:53:14 +00001582 * and then submit route_node to queue for best-path selection later.
1583 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001584 *
1585 * Deleted RIBs are reaped during best-path selection.
1586 *
1587 * rib_addnode
1588 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001589 * |-------->| | best RIB, if required
1590 * | |
1591 * static_install->|->rib_addqueue...... -> rib_process
1592 * | |
1593 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001594 * |-> set RIB_ENTRY_REMOVE |
1595 * rib_delnode (RIB freed)
1596 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001597 * The 'info' pointer of a route_node points to a rib_dest_t
1598 * ('dest'). Queueing state for a route_node is kept on the dest. The
1599 * dest is created on-demand by rib_link() and is kept around at least
1600 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001601 *
1602 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1603 *
1604 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001605 * - dest attached to route_node:
1606 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001607 * - route_node processing queue
1608 * - managed by: rib_addqueue, rib_process.
1609 *
1610 */
1611
paul718e3742002-12-13 20:15:29 +00001612/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001613static void
Paul Jakma6d691122006-07-27 21:49:00 +00001614rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001615{
1616 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001617 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001618
paul4d38fdb2005-04-28 17:35:14 +00001619 assert (rib && rn);
1620
Paul Jakma6d691122006-07-27 21:49:00 +00001621 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001622 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001623
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001624 dest = rib_dest_from_rnode (rn);
1625 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001626 {
1627 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001628 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001629
1630 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1631 route_lock_node (rn); /* rn route table reference */
1632 rn->info = dest;
1633 dest->rnode = rn;
1634 }
1635
1636 head = dest->routes;
1637 if (head)
1638 {
Paul Jakma6d691122006-07-27 21:49:00 +00001639 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001640 }
paul718e3742002-12-13 20:15:29 +00001641 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001642 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001643 rib_queue_add (&zebrad, rn);
1644}
1645
1646static void
1647rib_addnode (struct route_node *rn, struct rib *rib)
1648{
1649 /* RIB node has been un-removed before route-node is processed.
1650 * route_node must hence already be on the queue for processing..
1651 */
1652 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1653 {
1654 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001655 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001656
Paul Jakma6d691122006-07-27 21:49:00 +00001657 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1658 return;
1659 }
1660 rib_link (rn, rib);
1661}
1662
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001663/*
1664 * rib_unlink
1665 *
1666 * Detach a rib structure from a route_node.
1667 *
1668 * Note that a call to rib_unlink() should be followed by a call to
1669 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1670 * longer required to be deleted.
1671 */
Paul Jakma6d691122006-07-27 21:49:00 +00001672static void
1673rib_unlink (struct route_node *rn, struct rib *rib)
1674{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001675 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001676
1677 assert (rn && rib);
1678
1679 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001680 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001681
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001682 dest = rib_dest_from_rnode (rn);
1683
Paul Jakma6d691122006-07-27 21:49:00 +00001684 if (rib->next)
1685 rib->next->prev = rib->prev;
1686
1687 if (rib->prev)
1688 rib->prev->next = rib->next;
1689 else
1690 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001691 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001692 }
1693
1694 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001695 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001696 XFREE (MTYPE_RIB, rib);
1697
paul718e3742002-12-13 20:15:29 +00001698}
1699
paula1ac18c2005-06-28 17:17:12 +00001700static void
paul718e3742002-12-13 20:15:29 +00001701rib_delnode (struct route_node *rn, struct rib *rib)
1702{
Paul Jakma6d691122006-07-27 21:49:00 +00001703 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001704 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001705 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1706 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001707}
1708
1709int
1710rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001711 struct in_addr *gate, struct in_addr *src,
Feng Lu0d0686f2015-05-22 11:40:02 +02001712 unsigned int ifindex, vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001713 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001714{
1715 struct rib *rib;
1716 struct rib *same = NULL;
1717 struct route_table *table;
1718 struct route_node *rn;
1719 struct nexthop *nexthop;
1720
1721 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001722 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00001723 if (! table)
1724 return 0;
1725
1726 /* Make it sure prefixlen is applied to the prefix. */
1727 apply_mask_ipv4 (p);
1728
1729 /* Set default distance by route type. */
1730 if (distance == 0)
1731 {
Balaji.G837d16c2012-09-26 14:09:10 +05301732 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001733 distance = 150;
1734 else
1735 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001736
1737 /* iBGP distance is 200. */
1738 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1739 distance = 200;
1740 }
1741
1742 /* Lookup route node.*/
1743 rn = route_node_get (table, (struct prefix *) p);
1744
1745 /* If same type of route are installed, treat it as a implicit
1746 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001747 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001748 {
Paul Jakma6d691122006-07-27 21:49:00 +00001749 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1750 continue;
1751
hassoebf1ead2005-09-21 14:58:20 +00001752 if (rib->type != type)
1753 continue;
1754 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001755 {
1756 same = rib;
1757 break;
1758 }
hassoebf1ead2005-09-21 14:58:20 +00001759 /* Duplicate connected route comes in. */
1760 else if ((nexthop = rib->nexthop) &&
1761 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001762 nexthop->ifindex == ifindex &&
1763 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001764 {
1765 rib->refcnt++;
1766 return 0 ;
1767 }
paul718e3742002-12-13 20:15:29 +00001768 }
1769
1770 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001771 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001772 rib->type = type;
1773 rib->distance = distance;
1774 rib->flags = flags;
1775 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001776 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02001777 rib->vrf_id = vrf_id;
1778 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00001779 rib->nexthop_num = 0;
1780 rib->uptime = time (NULL);
1781
1782 /* Nexthop settings. */
1783 if (gate)
1784 {
1785 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001786 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001787 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001788 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001789 }
1790 else
1791 nexthop_ifindex_add (rib, ifindex);
1792
1793 /* If this route is kernel route, set FIB flag to the route. */
1794 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1795 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1796 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1797
1798 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001799 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001800 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1801 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001802 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001803
paul718e3742002-12-13 20:15:29 +00001804 /* Free implicit route.*/
1805 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001806 {
1807 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001808 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1809 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001810 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001811 }
paul4d38fdb2005-04-28 17:35:14 +00001812
1813 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001814 return 0;
1815}
1816
Denis Ovsienkodc958242007-08-13 16:03:06 +00001817/* This function dumps the contents of a given RIB entry into
1818 * standard debug log. Calling function name and IP prefix in
1819 * question are passed as 1st and 2nd arguments.
1820 */
1821
David Lamparterf7bf4152013-10-22 17:10:21 +00001822void _rib_dump (const char * func,
1823 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001824{
David Lamparterf7bf4152013-10-22 17:10:21 +00001825 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001826 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001827 struct nexthop *nexthop, *tnexthop;
1828 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001829
Feng Lu0d0686f2015-05-22 11:40:02 +02001830 zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
1831 prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001832 zlog_debug
1833 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001834 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001835 func,
1836 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001837 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001838 rib->type,
1839 rib->table
1840 );
1841 zlog_debug
1842 (
1843 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1844 func,
1845 rib->metric,
1846 rib->distance,
1847 rib->flags,
1848 rib->status
1849 );
1850 zlog_debug
1851 (
1852 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1853 func,
1854 rib->nexthop_num,
1855 rib->nexthop_active_num,
1856 rib->nexthop_fib_num
1857 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001858
Christian Frankefa713d92013-07-05 15:35:37 +00001859 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1860 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001861 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001862 zlog_debug
1863 (
1864 "%s: %s %s with flags %s%s%s",
1865 func,
1866 (recursing ? " NH" : "NH"),
1867 straddr,
1868 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1869 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1870 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1871 );
1872 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001873 zlog_debug ("%s: dump complete", func);
1874}
1875
1876/* This is an exported helper to rtm_read() to dump the strange
1877 * RIB entry found by rib_lookup_ipv4_route()
1878 */
1879
1880void rib_lookup_and_dump (struct prefix_ipv4 * p)
1881{
1882 struct route_table *table;
1883 struct route_node *rn;
1884 struct rib *rib;
1885 char prefix_buf[INET_ADDRSTRLEN];
1886
1887 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001888 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001889 if (! table)
1890 {
Feng Lu41f44a22015-05-22 11:39:56 +02001891 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001892 return;
1893 }
1894
Denis Ovsienkodc958242007-08-13 16:03:06 +00001895 /* Scan the RIB table for exactly matching RIB entry. */
1896 rn = route_node_lookup (table, (struct prefix *) p);
1897
1898 /* No route for this prefix. */
1899 if (! rn)
1900 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001901 zlog_debug ("%s: lookup failed for %s", __func__,
1902 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001903 return;
1904 }
1905
1906 /* Unlock node. */
1907 route_unlock_node (rn);
1908
1909 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001910 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001911 {
1912 zlog_debug
1913 (
1914 "%s: rn %p, rib %p: %s, %s",
1915 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01001916 (void *)rn,
1917 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001918 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1919 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1920 );
David Lamparterf7bf4152013-10-22 17:10:21 +00001921 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001922 }
1923}
1924
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001925/* Check if requested address assignment will fail due to another
1926 * route being installed by zebra in FIB already. Take necessary
1927 * actions, if needed: remove such a route from FIB and deSELECT
1928 * corresponding RIB entry. Then put affected RN into RIBQ head.
1929 */
1930void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1931{
1932 struct route_table *table;
1933 struct route_node *rn;
1934 struct rib *rib;
1935 unsigned changed = 0;
1936
Feng Lu41f44a22015-05-22 11:39:56 +02001937 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001938 {
Feng Lu41f44a22015-05-22 11:39:56 +02001939 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001940 return;
1941 }
1942
1943 /* No matches would be the simplest case. */
1944 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1945 return;
1946
1947 /* Unlock node. */
1948 route_unlock_node (rn);
1949
1950 /* Check all RIB entries. In case any changes have to be done, requeue
1951 * the RN into RIBQ head. If the routing message about the new connected
1952 * route (generated by the IP address we are going to assign very soon)
1953 * comes before the RIBQ is processed, the new RIB entry will join
1954 * RIBQ record already on head. This is necessary for proper revalidation
1955 * of the rest of the RIB.
1956 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001957 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001958 {
1959 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
1960 ! RIB_SYSTEM_ROUTE (rib))
1961 {
1962 changed = 1;
1963 if (IS_ZEBRA_DEBUG_RIB)
1964 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001965 char buf[PREFIX_STRLEN];
1966 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
1967 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00001968 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001969 }
1970 rib_uninstall (rn, rib);
1971 }
1972 }
1973 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001974 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001975}
1976
paul718e3742002-12-13 20:15:29 +00001977int
G.Balajicddf3912011-11-26 21:59:32 +04001978rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001979{
1980 struct route_table *table;
1981 struct route_node *rn;
1982 struct rib *same;
1983 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001984
paul718e3742002-12-13 20:15:29 +00001985 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001986 table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +00001987 if (! table)
1988 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04001989
paul718e3742002-12-13 20:15:29 +00001990 /* Make it sure prefixlen is applied to the prefix. */
1991 apply_mask_ipv4 (p);
1992
1993 /* Set default distance by route type. */
1994 if (rib->distance == 0)
1995 {
1996 rib->distance = route_info[rib->type].distance;
1997
1998 /* iBGP distance is 200. */
1999 if (rib->type == ZEBRA_ROUTE_BGP
2000 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2001 rib->distance = 200;
2002 }
2003
2004 /* Lookup route node.*/
2005 rn = route_node_get (table, (struct prefix *) p);
2006
2007 /* If same type of route are installed, treat it as a implicit
2008 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002009 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002010 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002011 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002012 continue;
2013
paul718e3742002-12-13 20:15:29 +00002014 if (same->type == rib->type && same->table == rib->table
2015 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002016 break;
paul718e3742002-12-13 20:15:29 +00002017 }
paul4d38fdb2005-04-28 17:35:14 +00002018
paul718e3742002-12-13 20:15:29 +00002019 /* If this route is kernel route, set FIB flag to the route. */
2020 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2021 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2022 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2023
2024 /* Link new rib to node.*/
2025 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002026 if (IS_ZEBRA_DEBUG_RIB)
2027 {
2028 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002029 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002030 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002031 }
paul718e3742002-12-13 20:15:29 +00002032
paul718e3742002-12-13 20:15:29 +00002033 /* Free implicit route.*/
2034 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002035 {
2036 if (IS_ZEBRA_DEBUG_RIB)
2037 {
2038 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002039 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002040 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002041 }
paul4d38fdb2005-04-28 17:35:14 +00002042 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002043 }
paul4d38fdb2005-04-28 17:35:14 +00002044
2045 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002046 return 0;
2047}
2048
hassoebf1ead2005-09-21 14:58:20 +00002049/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002050int
2051rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002052 struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002053{
2054 struct route_table *table;
2055 struct route_node *rn;
2056 struct rib *rib;
2057 struct rib *fib = NULL;
2058 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002059 struct nexthop *nexthop, *tnexthop;
2060 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002061 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002062 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002063
2064 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002065 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002066 if (! table)
2067 return 0;
2068
2069 /* Apply mask. */
2070 apply_mask_ipv4 (p);
2071
Christian Frankeb52aef12013-11-27 17:06:15 +00002072 if (IS_ZEBRA_DEBUG_KERNEL)
2073 {
2074 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002075 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
2076 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002077 inet_ntoa (*gate),
2078 ifindex);
2079 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002080 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
2081 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002082 ifindex);
2083 }
paul5ec90d22003-06-19 01:41:37 +00002084
paul718e3742002-12-13 20:15:29 +00002085 /* Lookup route node. */
2086 rn = route_node_lookup (table, (struct prefix *) p);
2087 if (! rn)
2088 {
2089 if (IS_ZEBRA_DEBUG_KERNEL)
2090 {
2091 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002092 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2093 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002094 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002095 ifindex);
2096 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002097 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2098 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002099 ifindex);
2100 }
2101 return ZEBRA_ERR_RTNOEXIST;
2102 }
2103
2104 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002105 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002106 {
Paul Jakma6d691122006-07-27 21:49:00 +00002107 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2108 continue;
2109
paul718e3742002-12-13 20:15:29 +00002110 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2111 fib = rib;
2112
hassoebf1ead2005-09-21 14:58:20 +00002113 if (rib->type != type)
2114 continue;
2115 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002116 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002117 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002118 if (nexthop->ifindex != ifindex)
2119 continue;
hassoebf1ead2005-09-21 14:58:20 +00002120 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002121 {
hassoebf1ead2005-09-21 14:58:20 +00002122 rib->refcnt--;
2123 route_unlock_node (rn);
2124 route_unlock_node (rn);
2125 return 0;
paul718e3742002-12-13 20:15:29 +00002126 }
hassoebf1ead2005-09-21 14:58:20 +00002127 same = rib;
2128 break;
paul718e3742002-12-13 20:15:29 +00002129 }
hassoebf1ead2005-09-21 14:58:20 +00002130 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002131 else
paul5ec90d22003-06-19 01:41:37 +00002132 {
Christian Frankefa713d92013-07-05 15:35:37 +00002133 if (gate == NULL)
2134 {
2135 same = rib;
2136 break;
2137 }
2138 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2139 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2140 {
2141 same = rib;
2142 break;
2143 }
2144 if (same)
2145 break;
2146 }
paul718e3742002-12-13 20:15:29 +00002147 }
paul718e3742002-12-13 20:15:29 +00002148 /* If same type of route can't be found and this message is from
2149 kernel. */
2150 if (! same)
2151 {
2152 if (fib && type == ZEBRA_ROUTE_KERNEL)
2153 {
2154 /* Unset flags. */
2155 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2156 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2157
2158 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2159 }
2160 else
2161 {
2162 if (IS_ZEBRA_DEBUG_KERNEL)
2163 {
2164 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002165 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2166 "doesn't exist in rib",
2167 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002168 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002169 ifindex,
2170 type);
2171 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002172 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2173 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002174 ifindex,
2175 type);
2176 }
2177 route_unlock_node (rn);
2178 return ZEBRA_ERR_RTNOEXIST;
2179 }
2180 }
paul4d38fdb2005-04-28 17:35:14 +00002181
paul718e3742002-12-13 20:15:29 +00002182 if (same)
2183 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002184
paul718e3742002-12-13 20:15:29 +00002185 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002186 return 0;
2187}
David Lamparter6b0655a2014-06-04 06:53:35 +02002188
paul718e3742002-12-13 20:15:29 +00002189/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002190static void
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002191static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002192{
2193 struct rib *rib;
2194 struct route_node *rn;
2195 struct route_table *table;
2196
2197 /* Lookup table. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002198 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002199 if (! table)
2200 return;
2201
2202 /* Lookup existing route */
2203 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002204 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002205 {
2206 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2207 continue;
2208
2209 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2210 break;
2211 }
paul718e3742002-12-13 20:15:29 +00002212
2213 if (rib)
2214 {
2215 /* Same distance static route is there. Update it with new
2216 nexthop. */
paul718e3742002-12-13 20:15:29 +00002217 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002218 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002219 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002220 case STATIC_IPV4_GATEWAY:
2221 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2222 break;
2223 case STATIC_IPV4_IFNAME:
2224 nexthop_ifname_add (rib, si->ifname);
2225 break;
2226 case STATIC_IPV4_BLACKHOLE:
2227 nexthop_blackhole_add (rib);
2228 break;
2229 case STATIC_IPV6_GATEWAY:
2230 nexthop_ipv6_add (rib, &si->addr.ipv6);
2231 break;
2232 case STATIC_IPV6_IFNAME:
2233 nexthop_ifname_add (rib, si->ifname);
2234 break;
2235 case STATIC_IPV6_GATEWAY_IFNAME:
2236 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2237 break;
paul4d38fdb2005-04-28 17:35:14 +00002238 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002239 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002240 }
2241 else
2242 {
2243 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002244 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2245
paul718e3742002-12-13 20:15:29 +00002246 rib->type = ZEBRA_ROUTE_STATIC;
2247 rib->distance = si->distance;
2248 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002249 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002250 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002251 rib->nexthop_num = 0;
2252
2253 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002254 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002255 case STATIC_IPV4_GATEWAY:
2256 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2257 break;
2258 case STATIC_IPV4_IFNAME:
2259 nexthop_ifname_add (rib, si->ifname);
2260 break;
2261 case STATIC_IPV4_BLACKHOLE:
2262 nexthop_blackhole_add (rib);
2263 break;
2264 case STATIC_IPV6_GATEWAY:
2265 nexthop_ipv6_add (rib, &si->addr.ipv6);
2266 break;
2267 case STATIC_IPV6_IFNAME:
2268 nexthop_ifname_add (rib, si->ifname);
2269 break;
2270 case STATIC_IPV6_GATEWAY_IFNAME:
2271 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2272 break;
paul7021c422003-07-15 12:52:22 +00002273 }
paul718e3742002-12-13 20:15:29 +00002274
hasso81dfcaa2003-05-25 19:21:25 +00002275 /* Save the flags of this static routes (reject, blackhole) */
2276 rib->flags = si->flags;
2277
paul718e3742002-12-13 20:15:29 +00002278 /* Link this rib to the tree. */
2279 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002280 }
2281}
2282
paula1ac18c2005-06-28 17:17:12 +00002283static int
Donald Sharpa979ab72015-11-04 13:26:38 -05002284static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002285{
2286 if (nexthop->type == NEXTHOP_TYPE_IPV4
2287 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002288 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002289 return 1;
2290 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2291 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002292 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002293 return 1;
paul595db7f2003-05-25 21:35:06 +00002294 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2295 && si->type == STATIC_IPV4_BLACKHOLE)
2296 return 1;
Donald Sharpa979ab72015-11-04 13:26:38 -05002297 if (nexthop->type == NEXTHOP_TYPE_IPV6
2298 && si->type == STATIC_IPV6_GATEWAY
2299 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
2300 return 1;
2301 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2302 && si->type == STATIC_IPV6_IFNAME
2303 && strcmp (nexthop->ifname, si->ifname) == 0)
2304 return 1;
2305 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2306 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2307 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
2308 && strcmp (nexthop->ifname, si->ifname) == 0)
2309 return 1;
paule8e19462006-01-19 20:16:55 +00002310 return 0;
paul718e3742002-12-13 20:15:29 +00002311}
2312
2313/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002314static void
Donald Sharp949b7192015-11-04 13:26:39 -05002315static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002316{
2317 struct route_node *rn;
2318 struct rib *rib;
2319 struct nexthop *nexthop;
2320 struct route_table *table;
2321
2322 /* Lookup table. */
Donald Sharp949b7192015-11-04 13:26:39 -05002323 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002324 if (! table)
2325 return;
paul4d38fdb2005-04-28 17:35:14 +00002326
paul718e3742002-12-13 20:15:29 +00002327 /* Lookup existing route with type and distance. */
2328 rn = route_node_lookup (table, p);
2329 if (! rn)
2330 return;
2331
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002332 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002333 {
2334 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2335 continue;
2336
2337 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2338 break;
2339 }
paul718e3742002-12-13 20:15:29 +00002340
2341 if (! rib)
2342 {
2343 route_unlock_node (rn);
2344 return;
2345 }
2346
2347 /* Lookup nexthop. */
2348 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Donald Sharpa979ab72015-11-04 13:26:38 -05002349 if (static_nexthop_same (nexthop, si))
paul718e3742002-12-13 20:15:29 +00002350 break;
2351
2352 /* Can't find nexthop. */
2353 if (! nexthop)
2354 {
2355 route_unlock_node (rn);
2356 return;
2357 }
2358
2359 /* Check nexthop. */
2360 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002361 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002362 else
2363 {
paul6baeb982003-10-28 03:47:15 +00002364 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2365 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002366 nexthop_delete (rib, nexthop);
2367 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002368 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002369 }
paul718e3742002-12-13 20:15:29 +00002370 /* Unlock node. */
2371 route_unlock_node (rn);
2372}
2373
paul718e3742002-12-13 20:15:29 +00002374int
Everton Marques33d86db2014-07-14 11:19:00 -03002375static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2376 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002377 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002378{
2379 u_char type = 0;
2380 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002381 struct static_route *si;
2382 struct static_route *pp;
2383 struct static_route *cp;
2384 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002385 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2386 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002387
paul718e3742002-12-13 20:15:29 +00002388 if (! stable)
2389 return -1;
2390
2391 /* Lookup static route prefix. */
2392 rn = route_node_get (stable, p);
2393
2394 /* Make flags. */
2395 if (gate)
2396 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002397 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002398 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002399 else
2400 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002401
2402 /* Do nothing if there is a same static route. */
2403 for (si = rn->info; si; si = si->next)
2404 {
2405 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002406 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2407 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002408 {
2409 if (distance == si->distance)
2410 {
2411 route_unlock_node (rn);
2412 return 0;
2413 }
2414 else
2415 update = si;
2416 }
2417 }
2418
Paul Jakma3c0755d2006-12-08 00:53:14 +00002419 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002420 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002421 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002422
2423 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002424 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002425
2426 si->type = type;
2427 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002428 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002429 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002430
2431 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002432 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002433 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002434 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002435
2436 /* Add new static route information to the tree with sort by
2437 distance value and gateway address. */
2438 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2439 {
2440 if (si->distance < cp->distance)
2441 break;
2442 if (si->distance > cp->distance)
2443 continue;
2444 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2445 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002446 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002447 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002448 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002449 continue;
2450 }
2451 }
2452
2453 /* Make linked list. */
2454 if (pp)
2455 pp->next = si;
2456 else
2457 rn->info = si;
2458 if (cp)
2459 cp->prev = si;
2460 si->prev = pp;
2461 si->next = cp;
2462
2463 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002464 static_install_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002465
2466 return 1;
2467}
2468
paul718e3742002-12-13 20:15:29 +00002469int
Everton Marques33d86db2014-07-14 11:19:00 -03002470static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002471 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002472{
2473 u_char type = 0;
2474 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002475 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002476 struct route_table *stable;
2477
2478 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002479 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002480 if (! stable)
2481 return -1;
2482
2483 /* Lookup static route prefix. */
2484 rn = route_node_lookup (stable, p);
2485 if (! rn)
2486 return 0;
2487
2488 /* Make flags. */
2489 if (gate)
2490 type = STATIC_IPV4_GATEWAY;
2491 else if (ifname)
2492 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002493 else
2494 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002495
2496 /* Find same static route is the tree */
2497 for (si = rn->info; si; si = si->next)
2498 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002499 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2500 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002501 break;
2502
2503 /* Can't find static route. */
2504 if (! si)
2505 {
2506 route_unlock_node (rn);
2507 return 0;
2508 }
2509
2510 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002511 static_uninstall_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002512
2513 /* Unlink static route from linked list. */
2514 if (si->prev)
2515 si->prev->next = si->next;
2516 else
2517 rn->info = si->next;
2518 if (si->next)
2519 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002520 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002521
2522 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002523 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002524 XFREE (0, si->ifname);
2525 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002526
paul143a3852003-09-29 20:06:13 +00002527 route_unlock_node (rn);
2528
paul718e3742002-12-13 20:15:29 +00002529 return 1;
2530}
2531
paul718e3742002-12-13 20:15:29 +00002532int
2533rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002534 struct in6_addr *gate, unsigned int ifindex,
2535 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002536 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002537{
2538 struct rib *rib;
2539 struct rib *same = NULL;
2540 struct route_table *table;
2541 struct route_node *rn;
2542 struct nexthop *nexthop;
2543
paul718e3742002-12-13 20:15:29 +00002544 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002545 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002546 if (! table)
2547 return 0;
2548
2549 /* Make sure mask is applied. */
2550 apply_mask_ipv6 (p);
2551
2552 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002553 if (!distance)
2554 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002555
2556 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2557 distance = 200;
2558
paul718e3742002-12-13 20:15:29 +00002559 /* Lookup route node.*/
2560 rn = route_node_get (table, (struct prefix *) p);
2561
2562 /* If same type of route are installed, treat it as a implicit
2563 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002564 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002565 {
Paul Jakma6d691122006-07-27 21:49:00 +00002566 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2567 continue;
2568
hassoebf1ead2005-09-21 14:58:20 +00002569 if (rib->type != type)
2570 continue;
2571 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002572 {
2573 same = rib;
paul718e3742002-12-13 20:15:29 +00002574 break;
2575 }
hassoebf1ead2005-09-21 14:58:20 +00002576 else if ((nexthop = rib->nexthop) &&
2577 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2578 nexthop->ifindex == ifindex)
2579 {
2580 rib->refcnt++;
2581 return 0;
2582 }
paul718e3742002-12-13 20:15:29 +00002583 }
2584
2585 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002586 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2587
paul718e3742002-12-13 20:15:29 +00002588 rib->type = type;
2589 rib->distance = distance;
2590 rib->flags = flags;
2591 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002592 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002593 rib->vrf_id = vrf_id;
2594 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002595 rib->nexthop_num = 0;
2596 rib->uptime = time (NULL);
2597
2598 /* Nexthop settings. */
2599 if (gate)
2600 {
2601 if (ifindex)
2602 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2603 else
2604 nexthop_ipv6_add (rib, gate);
2605 }
2606 else
2607 nexthop_ifindex_add (rib, ifindex);
2608
2609 /* If this route is kernel route, set FIB flag to the route. */
2610 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2611 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2612 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2613
2614 /* Link new rib to node.*/
2615 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002616 if (IS_ZEBRA_DEBUG_RIB)
2617 {
2618 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002619 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002620 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002621 }
paul718e3742002-12-13 20:15:29 +00002622
paul718e3742002-12-13 20:15:29 +00002623 /* Free implicit route.*/
2624 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002625 {
2626 if (IS_ZEBRA_DEBUG_RIB)
2627 {
2628 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002629 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002630 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002631 }
paul4d38fdb2005-04-28 17:35:14 +00002632 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002633 }
paul4d38fdb2005-04-28 17:35:14 +00002634
2635 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002636 return 0;
2637}
2638
hassoebf1ead2005-09-21 14:58:20 +00002639/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002640int
2641rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002642 struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002643{
2644 struct route_table *table;
2645 struct route_node *rn;
2646 struct rib *rib;
2647 struct rib *fib = NULL;
2648 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002649 struct nexthop *nexthop, *tnexthop;
2650 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002651 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002652 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002653
2654 /* Apply mask. */
2655 apply_mask_ipv6 (p);
2656
2657 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002658 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002659 if (! table)
2660 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002661
paul718e3742002-12-13 20:15:29 +00002662 /* Lookup route node. */
2663 rn = route_node_lookup (table, (struct prefix *) p);
2664 if (! rn)
2665 {
2666 if (IS_ZEBRA_DEBUG_KERNEL)
2667 {
2668 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002669 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2670 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002671 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002672 ifindex);
2673 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002674 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2675 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002676 ifindex);
2677 }
2678 return ZEBRA_ERR_RTNOEXIST;
2679 }
2680
2681 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002682 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002683 {
Paul Jakma6d691122006-07-27 21:49:00 +00002684 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2685 continue;
2686
paul718e3742002-12-13 20:15:29 +00002687 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2688 fib = rib;
2689
hassoebf1ead2005-09-21 14:58:20 +00002690 if (rib->type != type)
2691 continue;
2692 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002693 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002694 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002695 if (nexthop->ifindex != ifindex)
2696 continue;
hassoebf1ead2005-09-21 14:58:20 +00002697 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002698 {
hassoebf1ead2005-09-21 14:58:20 +00002699 rib->refcnt--;
2700 route_unlock_node (rn);
2701 route_unlock_node (rn);
2702 return 0;
paul718e3742002-12-13 20:15:29 +00002703 }
hassoebf1ead2005-09-21 14:58:20 +00002704 same = rib;
2705 break;
paul718e3742002-12-13 20:15:29 +00002706 }
hassoebf1ead2005-09-21 14:58:20 +00002707 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002708 else
2709 {
2710 if (gate == NULL)
2711 {
2712 same = rib;
2713 break;
2714 }
2715 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2716 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2717 {
2718 same = rib;
2719 break;
2720 }
2721 if (same)
2722 break;
2723 }
paul718e3742002-12-13 20:15:29 +00002724 }
2725
2726 /* If same type of route can't be found and this message is from
2727 kernel. */
2728 if (! same)
2729 {
2730 if (fib && type == ZEBRA_ROUTE_KERNEL)
2731 {
2732 /* Unset flags. */
2733 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2734 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2735
2736 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2737 }
2738 else
2739 {
2740 if (IS_ZEBRA_DEBUG_KERNEL)
2741 {
2742 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002743 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2744 "doesn't exist in rib",
2745 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002746 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002747 ifindex,
2748 type);
2749 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002750 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2751 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002752 ifindex,
2753 type);
2754 }
2755 route_unlock_node (rn);
2756 return ZEBRA_ERR_RTNOEXIST;
2757 }
2758 }
2759
2760 if (same)
2761 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002762
paul718e3742002-12-13 20:15:29 +00002763 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002764 return 0;
2765}
David Lamparter6b0655a2014-06-04 06:53:35 +02002766
paul718e3742002-12-13 20:15:29 +00002767
2768/* Add static route into static route configuration. */
2769int
2770static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002771 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002772 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002773{
2774 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002775 struct static_route *si;
2776 struct static_route *pp;
2777 struct static_route *cp;
Donald Sharpc1900e02015-11-04 13:26:40 -05002778 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002779 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2780 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002781
paul718e3742002-12-13 20:15:29 +00002782 if (! stable)
2783 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002784
2785 if (!gate &&
2786 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2787 return -1;
2788
2789 if (!ifname &&
2790 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2791 return -1;
paul718e3742002-12-13 20:15:29 +00002792
2793 /* Lookup static route prefix. */
2794 rn = route_node_get (stable, p);
2795
2796 /* Do nothing if there is a same static route. */
2797 for (si = rn->info; si; si = si->next)
2798 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002799 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002800 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002801 && (! ifname || strcmp (ifname, si->ifname) == 0))
2802 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002803 if (distance == si->distance)
2804 {
2805 route_unlock_node (rn);
2806 return 0;
2807 }
2808 else
2809 update = si;
paul718e3742002-12-13 20:15:29 +00002810 }
2811 }
2812
Donald Sharpc1900e02015-11-04 13:26:40 -05002813 if (update)
2814 static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
2815
paul718e3742002-12-13 20:15:29 +00002816 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002817 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002818
2819 si->type = type;
2820 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002821 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002822 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002823
2824 switch (type)
2825 {
2826 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002827 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002828 break;
2829 case STATIC_IPV6_IFNAME:
2830 si->ifname = XSTRDUP (0, ifname);
2831 break;
2832 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002833 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002834 si->ifname = XSTRDUP (0, ifname);
2835 break;
2836 }
2837
2838 /* Add new static route information to the tree with sort by
2839 distance value and gateway address. */
2840 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2841 {
2842 if (si->distance < cp->distance)
2843 break;
2844 if (si->distance > cp->distance)
2845 continue;
2846 }
2847
2848 /* Make linked list. */
2849 if (pp)
2850 pp->next = si;
2851 else
2852 rn->info = si;
2853 if (cp)
2854 cp->prev = si;
2855 si->prev = pp;
2856 si->next = cp;
2857
2858 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002859 static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002860
2861 return 1;
2862}
2863
2864/* Delete static route from static route configuration. */
2865int
2866static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002867 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002868{
2869 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002870 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002871 struct route_table *stable;
2872
2873 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002874 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002875 if (! stable)
2876 return -1;
2877
2878 /* Lookup static route prefix. */
2879 rn = route_node_lookup (stable, p);
2880 if (! rn)
2881 return 0;
2882
2883 /* Find same static route is the tree */
2884 for (si = rn->info; si; si = si->next)
2885 if (distance == si->distance
2886 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002887 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002888 && (! ifname || strcmp (ifname, si->ifname) == 0))
2889 break;
2890
2891 /* Can't find static route. */
2892 if (! si)
2893 {
2894 route_unlock_node (rn);
2895 return 0;
2896 }
2897
2898 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002899 static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002900
2901 /* Unlink static route from linked list. */
2902 if (si->prev)
2903 si->prev->next = si->next;
2904 else
2905 rn->info = si->next;
2906 if (si->next)
2907 si->next->prev = si->prev;
2908
2909 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002910 if (ifname)
2911 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05002912 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002913
2914 return 1;
2915}
David Lamparter6b0655a2014-06-04 06:53:35 +02002916
paul718e3742002-12-13 20:15:29 +00002917/* RIB update function. */
2918void
Feng Lu0d0686f2015-05-22 11:40:02 +02002919rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002920{
2921 struct route_node *rn;
2922 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002923
Feng Lu0d0686f2015-05-22 11:40:02 +02002924 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002925 if (table)
2926 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002927 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002928 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002929
Feng Lu0d0686f2015-05-22 11:40:02 +02002930 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002931 if (table)
2932 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002933 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002934 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002935}
2936
David Lamparter6b0655a2014-06-04 06:53:35 +02002937
paul718e3742002-12-13 20:15:29 +00002938/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002939static void
paul718e3742002-12-13 20:15:29 +00002940rib_weed_table (struct route_table *table)
2941{
2942 struct route_node *rn;
2943 struct rib *rib;
2944 struct rib *next;
2945
2946 if (table)
2947 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002948 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002949 {
Paul Jakma6d691122006-07-27 21:49:00 +00002950 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2951 continue;
2952
paulb21b19c2003-06-15 01:28:29 +00002953 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002954 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002955 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002956 }
2957}
2958
2959/* Delete all routes from non main table. */
2960void
paula1ac18c2005-06-28 17:17:12 +00002961rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002962{
Feng Lu0d0686f2015-05-22 11:40:02 +02002963 vrf_iter_t iter;
2964 struct zebra_vrf *zvrf;
2965
2966 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
2967 if ((zvrf = vrf_iter2info (iter)) != NULL)
2968 {
2969 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
2970 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
2971 }
paul718e3742002-12-13 20:15:29 +00002972}
David Lamparter6b0655a2014-06-04 06:53:35 +02002973
Feng Lu0d0686f2015-05-22 11:40:02 +02002974#if 0
paul718e3742002-12-13 20:15:29 +00002975/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002976static void
paul718e3742002-12-13 20:15:29 +00002977rib_sweep_table (struct route_table *table)
2978{
2979 struct route_node *rn;
2980 struct rib *rib;
2981 struct rib *next;
2982 int ret = 0;
2983
2984 if (table)
2985 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002986 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002987 {
Paul Jakma6d691122006-07-27 21:49:00 +00002988 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2989 continue;
2990
paul718e3742002-12-13 20:15:29 +00002991 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2992 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2993 {
Timo Teräs0abf6792016-01-15 17:36:29 +02002994 ret = rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00002995 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002996 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002997 }
2998 }
2999}
Feng Lu0d0686f2015-05-22 11:40:02 +02003000#endif
paul718e3742002-12-13 20:15:29 +00003001
3002/* Sweep all RIB tables. */
3003void
paula1ac18c2005-06-28 17:17:12 +00003004rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003005{
Feng Lu0d0686f2015-05-22 11:40:02 +02003006 vrf_iter_t iter;
3007 struct zebra_vrf *zvrf;
3008
3009 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3010 if ((zvrf = vrf_iter2info (iter)) != NULL)
3011 {
3012 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3013 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3014 }
paul718e3742002-12-13 20:15:29 +00003015}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003016
3017/* Remove specific by protocol routes from 'table'. */
3018static unsigned long
3019rib_score_proto_table (u_char proto, struct route_table *table)
3020{
3021 struct route_node *rn;
3022 struct rib *rib;
3023 struct rib *next;
3024 unsigned long n = 0;
3025
3026 if (table)
3027 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003028 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003029 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003030 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3031 continue;
3032 if (rib->type == proto)
3033 {
3034 rib_delnode (rn, rib);
3035 n++;
3036 }
3037 }
3038
3039 return n;
3040}
3041
3042/* Remove specific by protocol routes. */
3043unsigned long
3044rib_score_proto (u_char proto)
3045{
Feng Lu0d0686f2015-05-22 11:40:02 +02003046 vrf_iter_t iter;
3047 struct zebra_vrf *zvrf;
3048 unsigned long cnt = 0;
3049
3050 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3051 if ((zvrf = vrf_iter2info (iter)) != NULL)
3052 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3053 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3054
3055 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003056}
3057
paul718e3742002-12-13 20:15:29 +00003058/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003059void
paul718e3742002-12-13 20:15:29 +00003060rib_close_table (struct route_table *table)
3061{
3062 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003063 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003064 struct rib *rib;
3065
3066 if (table)
3067 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003068 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003069 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003070 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3071 continue;
3072
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003073 if (info->safi == SAFI_UNICAST)
3074 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003075
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003076 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02003077 rib_update_kernel (rn, rib, NULL);
Paul Jakma6d691122006-07-27 21:49:00 +00003078 }
paul718e3742002-12-13 20:15:29 +00003079}
3080
3081/* Close all RIB tables. */
3082void
paula1ac18c2005-06-28 17:17:12 +00003083rib_close (void)
paul718e3742002-12-13 20:15:29 +00003084{
Feng Lu0d0686f2015-05-22 11:40:02 +02003085 vrf_iter_t iter;
3086 struct zebra_vrf *zvrf;
3087
3088 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3089 if ((zvrf = vrf_iter2info (iter)) != NULL)
3090 {
3091 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3092 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3093 }
paul718e3742002-12-13 20:15:29 +00003094}
David Lamparter6b0655a2014-06-04 06:53:35 +02003095
paul718e3742002-12-13 20:15:29 +00003096/* Routing information base initialize. */
3097void
paula1ac18c2005-06-28 17:17:12 +00003098rib_init (void)
paul718e3742002-12-13 20:15:29 +00003099{
paul4d38fdb2005-04-28 17:35:14 +00003100 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003101}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003102
3103/*
3104 * vrf_id_get_next
3105 *
3106 * Get the first vrf id that is greater than the given vrf id if any.
3107 *
3108 * Returns TRUE if a vrf id was found, FALSE otherwise.
3109 */
3110static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003111vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003112{
Feng Lu41f44a22015-05-22 11:39:56 +02003113 vrf_iter_t iter = vrf_iterator (vrf_id);
3114 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3115
3116 /* The same one ? Then find out the next. */
3117 if (zvrf && (zvrf->vrf_id == vrf_id))
3118 zvrf = vrf_iter2info (vrf_next (iter));
3119
3120 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003121 {
Feng Lu41f44a22015-05-22 11:39:56 +02003122 *next_id_p = zvrf->vrf_id;
3123 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003124 }
3125
3126 return 0;
3127}
3128
3129/*
3130 * rib_tables_iter_next
3131 *
3132 * Returns the next table in the iteration.
3133 */
3134struct route_table *
3135rib_tables_iter_next (rib_tables_iter_t *iter)
3136{
3137 struct route_table *table;
3138
3139 /*
3140 * Array that helps us go over all AFI/SAFI combinations via one
3141 * index.
3142 */
3143 static struct {
3144 afi_t afi;
3145 safi_t safi;
3146 } afi_safis[] = {
3147 { AFI_IP, SAFI_UNICAST },
3148 { AFI_IP, SAFI_MULTICAST },
3149 { AFI_IP6, SAFI_UNICAST },
3150 { AFI_IP6, SAFI_MULTICAST },
3151 };
3152
3153 table = NULL;
3154
3155 switch (iter->state)
3156 {
3157
3158 case RIB_TABLES_ITER_S_INIT:
Donald Sharp0d271292015-11-19 07:21:30 -05003159 iter->vrf_id = VRF_DEFAULT;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003160 iter->afi_safi_ix = -1;
3161
3162 /* Fall through */
3163
3164 case RIB_TABLES_ITER_S_ITERATING:
3165 iter->afi_safi_ix++;
3166 while (1)
3167 {
3168
3169 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3170 {
Feng Lu41f44a22015-05-22 11:39:56 +02003171 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003172 afi_safis[iter->afi_safi_ix].safi,
3173 iter->vrf_id);
3174 if (table)
3175 break;
3176
3177 iter->afi_safi_ix++;
3178 }
3179
3180 /*
3181 * Found another table in this vrf.
3182 */
3183 if (table)
3184 break;
3185
3186 /*
3187 * Done with all tables in the current vrf, go to the next
3188 * one.
3189 */
3190 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3191 break;
3192
3193 iter->afi_safi_ix = 0;
3194 }
3195
3196 break;
3197
3198 case RIB_TABLES_ITER_S_DONE:
3199 return NULL;
3200 }
3201
3202 if (table)
3203 iter->state = RIB_TABLES_ITER_S_ITERATING;
3204 else
3205 iter->state = RIB_TABLES_ITER_S_DONE;
3206
3207 return table;
3208}
Feng Lu41f44a22015-05-22 11:39:56 +02003209
3210/*
3211 * Create a routing table for the specific AFI/SAFI in the given VRF.
3212 */
3213static void
3214zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3215{
3216 rib_table_info_t *info;
3217 struct route_table *table;
3218
3219 assert (!zvrf->table[afi][safi]);
3220
3221 table = route_table_init ();
3222 zvrf->table[afi][safi] = table;
3223
3224 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3225 info->zvrf = zvrf;
3226 info->afi = afi;
3227 info->safi = safi;
3228 table->info = info;
3229}
3230
3231/* Allocate new zebra VRF. */
3232struct zebra_vrf *
3233zebra_vrf_alloc (vrf_id_t vrf_id)
3234{
3235 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003236#ifdef HAVE_NETLINK
3237 char nl_name[64];
3238#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003239
3240 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3241
3242 /* Allocate routing table and static table. */
3243 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3244 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3245 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3246 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3247 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3248 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3249 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3250 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3251
3252 /* Set VRF ID */
3253 zvrf->vrf_id = vrf_id;
3254
Feng Lu758fb8f2014-07-03 18:23:09 +08003255#ifdef HAVE_NETLINK
3256 /* Initialize netlink sockets */
3257 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3258 zvrf->netlink.sock = -1;
3259 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3260
3261 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3262 zvrf->netlink_cmd.sock = -1;
3263 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3264#endif
3265
Feng Lu41f44a22015-05-22 11:39:56 +02003266 return zvrf;
3267}
3268
3269/* Lookup the routing table in an enabled VRF. */
3270struct route_table *
3271zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3272{
3273 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3274
3275 if (!zvrf)
3276 return NULL;
3277
3278 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3279 return NULL;
3280
3281 return zvrf->table[afi][safi];
3282}
3283
3284/* Lookup the static routing table in a VRF. */
3285struct route_table *
3286zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3287{
3288 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3289
3290 if (!zvrf)
3291 return NULL;
3292
3293 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3294 return NULL;
3295
3296 return zvrf->stable[afi][safi];
3297}
3298