blob: d06382c3fba5f682f21fd74c0ff55c4f5896737f [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;
Timo Teräs325823a2016-01-15 17:36:31 +0200390 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100391 break;
392 }
paul718e3742002-12-13 20:15:29 +0000393
394 /* If there is no selected route or matched route is EGP, go up
395 tree. */
396 if (! match
397 || match->type == ZEBRA_ROUTE_BGP)
398 {
399 do {
400 rn = rn->parent;
401 } while (rn && rn->info == NULL);
402 if (rn)
403 route_lock_node (rn);
404 }
405 else
406 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000407 /* If the longest prefix match for the nexthop yields
408 * a blackhole, mark it as inactive. */
409 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
410 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
411 return 0;
412
paul718e3742002-12-13 20:15:29 +0000413 if (match->type == ZEBRA_ROUTE_CONNECT)
414 {
415 /* Directly point connected route. */
416 newhop = match->nexthop;
417 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
418 nexthop->ifindex = newhop->ifindex;
419
420 return 1;
421 }
422 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
423 {
Christian Frankefa713d92013-07-05 15:35:37 +0000424 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000425 for (newhop = match->nexthop; newhop; newhop = newhop->next)
426 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
427 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
428 {
429 if (set)
430 {
431 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000432
433 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
434 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000435 /* If the resolving route specifies a gateway, use it */
436 if (newhop->type == NEXTHOP_TYPE_IPV4
437 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
438 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
439 {
440 resolved_hop->type = newhop->type;
441 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Timo Teräs82a66352016-01-15 17:36:30 +0200442 resolved_hop->ifindex = newhop->ifindex;
Christian Frankec3e6b592013-07-05 15:35:40 +0000443 }
Christian Frankefa713d92013-07-05 15:35:37 +0000444
Timo Teräs82a66352016-01-15 17:36:30 +0200445 /* If the resolving route is an interface route, it
446 * means the gateway we are looking up is connected
447 * to that interface. Therefore, the resolved route
448 * should have the original gateway as nexthop as it
449 * is directly connected. */
paul718e3742002-12-13 20:15:29 +0000450 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000451 || newhop->type == NEXTHOP_TYPE_IFNAME)
452 {
Christian Frankec3e6b592013-07-05 15:35:40 +0000453 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
454 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
455 resolved_hop->ifindex = newhop->ifindex;
456 }
Christian Frankefa713d92013-07-05 15:35:37 +0000457
458 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000459 }
Christian Frankefa713d92013-07-05 15:35:37 +0000460 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000461 }
Timo Teräsb11f3b52015-11-02 16:50:07 +0200462 if (resolved && set)
463 rib->nexthop_mtu = match->mtu;
Christian Frankefa713d92013-07-05 15:35:37 +0000464 return resolved;
paul718e3742002-12-13 20:15:29 +0000465 }
466 else
467 {
468 return 0;
469 }
470 }
471 }
472 return 0;
473}
474
paul718e3742002-12-13 20:15:29 +0000475/* If force flag is not set, do not modify falgs at all for uninstall
476 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000477static int
paul718e3742002-12-13 20:15:29 +0000478nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
479 struct route_node *top)
480{
481 struct prefix_ipv6 p;
482 struct route_table *table;
483 struct route_node *rn;
484 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000485 int resolved;
paul718e3742002-12-13 20:15:29 +0000486 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000487 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000488
489 if (nexthop->type == NEXTHOP_TYPE_IPV6)
490 nexthop->ifindex = 0;
491
492 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000493 {
494 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
495 nexthops_free(nexthop->resolved);
496 nexthop->resolved = NULL;
497 }
paul718e3742002-12-13 20:15:29 +0000498
499 /* Make lookup prefix. */
500 memset (&p, 0, sizeof (struct prefix_ipv6));
501 p.family = AF_INET6;
502 p.prefixlen = IPV6_MAX_PREFIXLEN;
503 p.prefix = nexthop->gate.ipv6;
504
505 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200506 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +0000507 if (! table)
508 return 0;
509
510 rn = route_node_match (table, (struct prefix *) &p);
511 while (rn)
512 {
513 route_unlock_node (rn);
514
David Warda50c1072009-12-03 15:34:39 +0300515 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000516 if (rn == top)
517 return 0;
518
519 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000520 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100521 {
522 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
523 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200524 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100525 break;
526 }
paul718e3742002-12-13 20:15:29 +0000527
528 /* If there is no selected route or matched route is EGP, go up
529 tree. */
530 if (! match
531 || match->type == ZEBRA_ROUTE_BGP)
532 {
533 do {
534 rn = rn->parent;
535 } while (rn && rn->info == NULL);
536 if (rn)
537 route_lock_node (rn);
538 }
539 else
540 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000541 /* If the longest prefix match for the nexthop yields
542 * a blackhole, mark it as inactive. */
543 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
544 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
545 return 0;
546
paul718e3742002-12-13 20:15:29 +0000547 if (match->type == ZEBRA_ROUTE_CONNECT)
548 {
549 /* Directly point connected route. */
550 newhop = match->nexthop;
551
552 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
553 nexthop->ifindex = newhop->ifindex;
554
555 return 1;
556 }
557 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
558 {
Christian Frankefa713d92013-07-05 15:35:37 +0000559 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000560 for (newhop = match->nexthop; newhop; newhop = newhop->next)
561 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
562 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
563 {
564 if (set)
565 {
566 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000567
568 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
569 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000570 /* See nexthop_active_ipv4 for a description how the
571 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000572 if (newhop->type == NEXTHOP_TYPE_IPV6
573 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
574 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000575 {
576 resolved_hop->type = newhop->type;
577 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
578
579 if (newhop->ifindex)
580 {
581 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
582 resolved_hop->ifindex = newhop->ifindex;
583 }
584 }
Christian Frankefa713d92013-07-05 15:35:37 +0000585
paul718e3742002-12-13 20:15:29 +0000586 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000587 || newhop->type == NEXTHOP_TYPE_IFNAME)
588 {
589 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
590 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
591 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
592 resolved_hop->ifindex = newhop->ifindex;
593 }
Christian Frankefa713d92013-07-05 15:35:37 +0000594
595 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000596 }
Christian Frankefa713d92013-07-05 15:35:37 +0000597 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000598 }
Christian Frankefa713d92013-07-05 15:35:37 +0000599 return resolved;
paul718e3742002-12-13 20:15:29 +0000600 }
601 else
602 {
603 return 0;
604 }
605 }
606 }
607 return 0;
608}
paul718e3742002-12-13 20:15:29 +0000609
610struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100611rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
Feng Lu0d0686f2015-05-22 11:40:02 +0200612 struct route_node **rn_out, vrf_id_t vrf_id)
Everton Marques3dea1782014-09-22 19:35:51 -0300613{
614 struct route_table *table;
615 struct route_node *rn;
616 struct rib *match;
617 struct nexthop *newhop, *tnewhop;
618 int recursing;
619
620 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200621 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
Everton Marques3dea1782014-09-22 19:35:51 -0300622 if (! table)
623 return 0;
624
625 rn = route_node_match_ipv4 (table, &addr);
626
627 while (rn)
628 {
629 route_unlock_node (rn);
630
631 /* Pick up selected route. */
632 RNODE_FOREACH_RIB (rn, match)
633 {
634 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
635 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200636 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Everton Marques3dea1782014-09-22 19:35:51 -0300637 break;
638 }
639
640 /* If there is no selected route or matched route is EGP, go up
641 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300642 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300643 {
644 do {
645 rn = rn->parent;
646 } while (rn && rn->info == NULL);
647 if (rn)
648 route_lock_node (rn);
649 }
650 else
651 {
David Lamparter24480d42015-01-22 19:09:36 +0100652 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300653 {
David Lamparter24480d42015-01-22 19:09:36 +0100654 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300655 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
656 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100657 {
658 found = 1;
659 break;
660 }
661 if (!found)
662 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300663 }
David Lamparter24480d42015-01-22 19:09:36 +0100664
665 if (rn_out)
666 *rn_out = rn;
667 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300668 }
669 }
670 return NULL;
671}
672
673struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200674rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out,
675 vrf_id_t vrf_id)
David Lamparterbd078122015-01-06 19:53:24 +0100676{
677 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
678 struct route_node *m_rn = NULL, *u_rn = NULL;
679 int skip_bgp = 0; /* bool */
680
681 switch (ipv4_multicast_mode)
682 {
683 case MCAST_MRIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200684 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out,
685 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100686 case MCAST_URIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200687 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out,
688 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100689 case MCAST_NO_CONFIG:
690 case MCAST_MIX_MRIB_FIRST:
Feng Lu0d0686f2015-05-22 11:40:02 +0200691 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
692 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100693 if (!mrib)
Feng Lu0d0686f2015-05-22 11:40:02 +0200694 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
695 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100696 break;
697 case MCAST_MIX_DISTANCE:
Feng Lu0d0686f2015-05-22 11:40:02 +0200698 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
699 vrf_id);
700 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
701 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100702 if (mrib && urib)
703 rib = urib->distance < mrib->distance ? urib : mrib;
704 else if (mrib)
705 rib = mrib;
706 else if (urib)
707 rib = urib;
708 break;
709 case MCAST_MIX_PFXLEN:
Feng Lu0d0686f2015-05-22 11:40:02 +0200710 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
711 vrf_id);
712 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
713 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100714 if (mrib && urib)
715 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
716 else if (mrib)
717 rib = mrib;
718 else if (urib)
719 rib = urib;
720 break;
721 }
722
723 if (rn_out)
724 *rn_out = (rib == mrib) ? m_rn : u_rn;
725
726 if (IS_ZEBRA_DEBUG_RIB)
727 {
728 char buf[BUFSIZ];
729 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
730
Feng Lu0d0686f2015-05-22 11:40:02 +0200731 zlog_debug("%s: %s vrf %u: found %s, using %s",
732 __func__, buf, vrf_id,
David Lamparterbd078122015-01-06 19:53:24 +0100733 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
734 urib ? "URIB" : "nothing",
735 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
736 }
737 return rib;
738}
739
740void
741multicast_mode_ipv4_set (enum multicast_mode mode)
742{
743 if (IS_ZEBRA_DEBUG_RIB)
744 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
745 ipv4_multicast_mode = mode;
746}
747
748enum multicast_mode
749multicast_mode_ipv4_get (void)
750{
751 return ipv4_multicast_mode;
752}
753
754struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200755rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000756{
757 struct route_table *table;
758 struct route_node *rn;
759 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000760 struct nexthop *nexthop, *tnexthop;
761 int recursing;
paul718e3742002-12-13 20:15:29 +0000762
763 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200764 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000765 if (! table)
766 return 0;
767
768 rn = route_node_lookup (table, (struct prefix *) p);
769
770 /* No route for this prefix. */
771 if (! rn)
772 return NULL;
773
774 /* Unlock node. */
775 route_unlock_node (rn);
776
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000777 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100778 {
779 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
780 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200781 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100782 break;
783 }
paul718e3742002-12-13 20:15:29 +0000784
785 if (! match || match->type == ZEBRA_ROUTE_BGP)
786 return NULL;
787
788 if (match->type == ZEBRA_ROUTE_CONNECT)
789 return match;
790
Christian Frankefa713d92013-07-05 15:35:37 +0000791 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000792 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
793 return match;
794
795 return NULL;
796}
797
Denis Ovsienkodc958242007-08-13 16:03:06 +0000798/*
799 * This clone function, unlike its original rib_lookup_ipv4(), checks
800 * if specified IPv4 route record (prefix/mask -> gate) exists in
801 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
802 *
803 * Return values:
804 * -1: error
805 * 0: exact match found
806 * 1: a match was found with a different gate
807 * 2: connected route found
808 * 3: no matches found
809 */
810int
Feng Lu0d0686f2015-05-22 11:40:02 +0200811rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
812 vrf_id_t vrf_id)
Denis Ovsienkodc958242007-08-13 16:03:06 +0000813{
814 struct route_table *table;
815 struct route_node *rn;
816 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000817 struct nexthop *nexthop, *tnexthop;
818 int recursing;
819 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000820
821 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200822 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000823 if (! table)
824 return ZEBRA_RIB_LOOKUP_ERROR;
825
826 /* Scan the RIB table for exactly matching RIB entry. */
827 rn = route_node_lookup (table, (struct prefix *) p);
828
829 /* No route for this prefix. */
830 if (! rn)
831 return ZEBRA_RIB_NOTFOUND;
832
833 /* Unlock node. */
834 route_unlock_node (rn);
835
836 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000837 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100838 {
839 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
840 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200841 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100842 break;
843 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000844
845 /* None such found :( */
846 if (!match)
847 return ZEBRA_RIB_NOTFOUND;
848
849 if (match->type == ZEBRA_ROUTE_CONNECT)
850 return ZEBRA_RIB_FOUND_CONNECTED;
851
852 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000853 nexthops_active = 0;
854 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000855 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000856 {
Christian Frankefa713d92013-07-05 15:35:37 +0000857 nexthops_active = 1;
858 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
859 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000860 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000861 {
862 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
863 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
864 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
865 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
866 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
867 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000868 }
Christian Frankefa713d92013-07-05 15:35:37 +0000869
870 if (nexthops_active)
871 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000872
873 return ZEBRA_RIB_NOTFOUND;
874}
875
paul718e3742002-12-13 20:15:29 +0000876struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200877rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000878{
879 struct prefix_ipv6 p;
880 struct route_table *table;
881 struct route_node *rn;
882 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000883 struct nexthop *newhop, *tnewhop;
884 int recursing;
paul718e3742002-12-13 20:15:29 +0000885
886 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200887 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000888 if (! table)
889 return 0;
890
891 memset (&p, 0, sizeof (struct prefix_ipv6));
892 p.family = AF_INET6;
893 p.prefixlen = IPV6_MAX_PREFIXLEN;
894 IPV6_ADDR_COPY (&p.prefix, addr);
895
896 rn = route_node_match (table, (struct prefix *) &p);
897
898 while (rn)
899 {
900 route_unlock_node (rn);
901
902 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000903 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100904 {
905 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
906 continue;
Timo Teräs325823a2016-01-15 17:36:31 +0200907 if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
Stephen Hemminger16814f92008-08-17 17:39:31 +0100908 break;
909 }
paul718e3742002-12-13 20:15:29 +0000910
911 /* If there is no selected route or matched route is EGP, go up
912 tree. */
913 if (! match
914 || match->type == ZEBRA_ROUTE_BGP)
915 {
916 do {
917 rn = rn->parent;
918 } while (rn && rn->info == NULL);
919 if (rn)
920 route_lock_node (rn);
921 }
922 else
923 {
924 if (match->type == ZEBRA_ROUTE_CONNECT)
925 /* Directly point connected route. */
926 return match;
927 else
928 {
Christian Frankefa713d92013-07-05 15:35:37 +0000929 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000930 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
931 return match;
932 return NULL;
933 }
934 }
935 }
936 return NULL;
937}
paul718e3742002-12-13 20:15:29 +0000938
Paul Jakma7514fb72007-05-02 16:05:35 +0000939#define RIB_SYSTEM_ROUTE(R) \
940 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
941
Denis Ovsienkodc958242007-08-13 16:03:06 +0000942/* This function verifies reachability of one given nexthop, which can be
943 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
944 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
945 * nexthop->ifindex will be updated appropriately as well.
946 * An existing route map can turn (otherwise active) nexthop into inactive, but
947 * not vice versa.
948 *
949 * The return value is the final value of 'ACTIVE' flag.
950 */
951
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300952static unsigned
paul718e3742002-12-13 20:15:29 +0000953nexthop_active_check (struct route_node *rn, struct rib *rib,
954 struct nexthop *nexthop, int set)
955{
Christian Frankef3a17322013-07-05 15:35:41 +0000956 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +0000957 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000958 route_map_result_t ret = RMAP_MATCH;
959 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
960 struct route_map *rmap;
961 int family;
paul718e3742002-12-13 20:15:29 +0000962
Paul Jakma7514fb72007-05-02 16:05:35 +0000963 family = 0;
paul718e3742002-12-13 20:15:29 +0000964 switch (nexthop->type)
965 {
966 case NEXTHOP_TYPE_IFINDEX:
Feng Lu0d0686f2015-05-22 11:40:02 +0200967 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000968 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000969 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
970 else
971 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
972 break;
paul718e3742002-12-13 20:15:29 +0000973 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000974 family = AFI_IP6;
975 case NEXTHOP_TYPE_IFNAME:
Feng Lu0d0686f2015-05-22 11:40:02 +0200976 ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000977 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000978 {
979 if (set)
980 nexthop->ifindex = ifp->ifindex;
981 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
982 }
983 else
984 {
985 if (set)
986 nexthop->ifindex = 0;
987 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
988 }
989 break;
990 case NEXTHOP_TYPE_IPV4:
991 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000992 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000993 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
994 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
995 else
996 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
997 break;
paul718e3742002-12-13 20:15:29 +0000998 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +0000999 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001000 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1001 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1002 else
1003 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1004 break;
1005 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001006 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001007 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1008 {
Feng Lu0d0686f2015-05-22 11:40:02 +02001009 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001010 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001011 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1012 else
1013 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1014 }
1015 else
1016 {
1017 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1018 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1019 else
1020 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1021 }
1022 break;
paul595db7f2003-05-25 21:35:06 +00001023 case NEXTHOP_TYPE_BLACKHOLE:
1024 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1025 break;
paul718e3742002-12-13 20:15:29 +00001026 default:
1027 break;
1028 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001029 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1030 return 0;
1031
Christian Frankef3a17322013-07-05 15:35:41 +00001032 /* XXX: What exactly do those checks do? Do we support
1033 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001034 if (RIB_SYSTEM_ROUTE(rib) ||
1035 (family == AFI_IP && rn->p.family != AF_INET) ||
1036 (family == AFI_IP6 && rn->p.family != AF_INET6))
1037 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1038
Christian Frankef3a17322013-07-05 15:35:41 +00001039 /* The original code didn't determine the family correctly
1040 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1041 * from the rib_table_info in those cases.
1042 * Possibly it may be better to use only the rib_table_info
1043 * in every case.
1044 */
1045 if (!family)
1046 family = info->afi;
1047
Paul Jakma7514fb72007-05-02 16:05:35 +00001048 rmap = 0;
1049 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1050 proto_rm[family][rib->type])
1051 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1052 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1053 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1054 if (rmap) {
Feng Lu1885d0a2015-05-22 11:40:04 +02001055 struct nexthop_vrfid nh_vrf = {nexthop, rib->vrf_id};
1056 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, &nh_vrf);
Paul Jakma7514fb72007-05-02 16:05:35 +00001057 }
1058
1059 if (ret == RMAP_DENYMATCH)
1060 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001061 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1062}
1063
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001064/* Iterate over all nexthops of the given RIB entry and refresh their
1065 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1066 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
Timo Teräs7eb61362015-11-02 16:50:05 +02001067 * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001068 * transparently passed to nexthop_active_check().
1069 *
1070 * Return value is the new number of active nexthops.
1071 */
1072
paula1ac18c2005-06-28 17:17:12 +00001073static int
paul718e3742002-12-13 20:15:29 +00001074nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1075{
1076 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001077 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001078
1079 rib->nexthop_active_num = 0;
Timo Teräs7eb61362015-11-02 16:50:05 +02001080 UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
paul718e3742002-12-13 20:15:29 +00001081
1082 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001083 {
1084 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001085 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001086 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1087 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001088 if (prev_active != new_active ||
1089 prev_index != nexthop->ifindex)
Timo Teräs7eb61362015-11-02 16:50:05 +02001090 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001091 }
paul718e3742002-12-13 20:15:29 +00001092 return rib->nexthop_active_num;
1093}
paul6baeb982003-10-28 03:47:15 +00001094
David Lamparter6b0655a2014-06-04 06:53:35 +02001095
paul718e3742002-12-13 20:15:29 +00001096
Timo Teräs0abf6792016-01-15 17:36:29 +02001097static int
1098rib_update_kernel (struct route_node *rn, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001099{
1100 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001101 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001102 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001103 int recursing;
paul718e3742002-12-13 20:15:29 +00001104
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001105 if (info->safi != SAFI_UNICAST)
1106 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001107 if (new)
1108 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1109 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1110 if (old)
1111 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1112 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1113 return 0;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001114 }
1115
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001116 /*
1117 * Make sure we update the FPM any time we send new information to
1118 * the kernel.
1119 */
Timo Teräs0abf6792016-01-15 17:36:29 +02001120 zfpm_trigger_update (rn, "updating in kernel");
1121
1122 ret = kernel_route_rib (&rn->p, old, new);
paul718e3742002-12-13 20:15:29 +00001123
Denis Ovsienkodc958242007-08-13 16:03:06 +00001124 /* This condition is never met, if we are using rt_socket.c */
Timo Teräs0abf6792016-01-15 17:36:29 +02001125 if (ret < 0 && new)
1126 for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
1127 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001128
Timo Teräs0abf6792016-01-15 17:36:29 +02001129 if (old)
1130 for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
1131 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001132
1133 return ret;
1134}
1135
1136/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001137static void
paul718e3742002-12-13 20:15:29 +00001138rib_uninstall (struct route_node *rn, struct rib *rib)
1139{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001140 rib_table_info_t *info = rn->table->info;
1141
Timo Teräs325823a2016-01-15 17:36:31 +02001142 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00001143 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001144 if (info->safi == SAFI_UNICAST)
1145 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001146
paul718e3742002-12-13 20:15:29 +00001147 redistribute_delete (&rn->p, rib);
1148 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02001149 rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00001150 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1151 }
1152}
1153
Paul Jakma6d691122006-07-27 21:49:00 +00001154static void rib_unlink (struct route_node *, struct rib *);
1155
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001156/*
1157 * rib_can_delete_dest
1158 *
1159 * Returns TRUE if the given dest can be deleted from the table.
1160 */
1161static int
1162rib_can_delete_dest (rib_dest_t *dest)
1163{
1164 if (dest->routes)
1165 {
1166 return 0;
1167 }
1168
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001169 /*
1170 * Don't delete the dest if we have to update the FPM about this
1171 * prefix.
1172 */
1173 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1174 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1175 return 0;
1176
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001177 return 1;
1178}
1179
1180/*
1181 * rib_gc_dest
1182 *
1183 * Garbage collect the rib dest corresponding to the given route node
1184 * if appropriate.
1185 *
1186 * Returns TRUE if the dest was deleted, FALSE otherwise.
1187 */
1188int
1189rib_gc_dest (struct route_node *rn)
1190{
1191 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001192
1193 dest = rib_dest_from_rnode (rn);
1194 if (!dest)
1195 return 0;
1196
1197 if (!rib_can_delete_dest (dest))
1198 return 0;
1199
1200 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001201 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001202
1203 dest->rnode = NULL;
1204 XFREE (MTYPE_RIB_DEST, dest);
1205 rn->info = NULL;
1206
1207 /*
1208 * Release the one reference that we keep on the route node.
1209 */
1210 route_unlock_node (rn);
1211 return 1;
1212}
1213
Timo Teräs0abf6792016-01-15 17:36:29 +02001214/* Check if 'alternate' RIB entry is better than 'current'. */
1215static struct rib *
1216rib_choose_best (struct rib *current, struct rib *alternate)
1217{
1218 if (current == NULL)
1219 return alternate;
1220
1221 /* filter route selection in following order:
1222 * - connected beats other types
1223 * - lower distance beats higher
1224 * - lower metric beats higher for equal distance
1225 * - last, hence oldest, route wins tie break.
1226 */
1227
1228 /* Connected routes. Pick the last connected
1229 * route of the set of lowest metric connected routes.
1230 */
1231 if (alternate->type == ZEBRA_ROUTE_CONNECT)
1232 {
1233 if (current->type != ZEBRA_ROUTE_CONNECT
1234 || alternate->metric <= current->metric)
1235 return alternate;
1236
1237 return current;
1238 }
1239
1240 if (current->type == ZEBRA_ROUTE_CONNECT)
1241 return current;
1242
1243 /* higher distance loses */
1244 if (alternate->distance < current->distance)
1245 return alternate;
1246 if (current->distance < alternate->distance)
1247 return current;
1248
1249 /* metric tie-breaks equal distance */
1250 if (alternate->metric <= current->metric)
1251 return alternate;
1252
1253 return current;
1254}
1255
paul718e3742002-12-13 20:15:29 +00001256/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001257static void
1258rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001259{
1260 struct rib *rib;
1261 struct rib *next;
Timo Teräs325823a2016-01-15 17:36:31 +02001262 struct rib *old_selected = NULL;
1263 struct rib *new_selected = NULL;
Timo Teräs0abf6792016-01-15 17:36:29 +02001264 struct rib *old_fib = NULL;
1265 struct rib *new_fib = NULL;
pauld753e9e2003-01-22 19:45:50 +00001266 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001267 struct nexthop *nexthop = NULL, *tnexthop;
1268 int recursing;
Balaji95116332014-10-23 15:25:25 +00001269 rib_table_info_t *info;
1270
paul4d38fdb2005-04-28 17:35:14 +00001271 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001272
1273 info = rn->table->info;
1274
Timo Teräs0abf6792016-01-15 17:36:29 +02001275 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001276 {
paul718e3742002-12-13 20:15:29 +00001277 /* Currently installed rib. */
1278 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001279 {
Timo Teräs325823a2016-01-15 17:36:31 +02001280 assert (old_selected == NULL);
1281 old_selected = rib;
1282 }
1283 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1284 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001285 assert (old_fib == NULL);
1286 old_fib = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001287 }
Timo Teräs0abf6792016-01-15 17:36:29 +02001288
1289 /* Skip deleted entries from selection */
Paul Jakma6d691122006-07-27 21:49:00 +00001290 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
Timo Teräs0abf6792016-01-15 17:36:29 +02001291 continue;
paul4d38fdb2005-04-28 17:35:14 +00001292
paul718e3742002-12-13 20:15:29 +00001293 /* Skip unreachable nexthop. */
1294 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001295 continue;
paul718e3742002-12-13 20:15:29 +00001296
1297 /* Infinit distance. */
1298 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001299 continue;
paul718e3742002-12-13 20:15:29 +00001300
Timo Teräs325823a2016-01-15 17:36:31 +02001301 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
1302 new_fib = rib_choose_best(new_fib, rib);
1303 else
1304 new_selected = rib_choose_best(new_selected, rib);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001305 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001306
Timo Teräs325823a2016-01-15 17:36:31 +02001307 /* If no FIB override route, use the selected route also for FIB */
1308 if (new_fib == NULL)
1309 new_fib = new_selected;
1310
Denis Ovsienkodc958242007-08-13 16:03:06 +00001311 /* After the cycle is finished, the following pointers will be set:
Timo Teräs325823a2016-01-15 17:36:31 +02001312 * old_selected --- RIB entry currently having SELECTED
1313 * new_selected --- RIB entry that is newly SELECTED
1314 * old_fib --- RIB entry currently in kernel FIB
1315 * new_fib --- RIB entry that is newly to be in kernel FIB
1316 *
1317 * new_selected will get SELECTED flag, and is going to be redistributed
1318 * the zclients. new_fib (which can be new_selected) will be installed in kernel.
Denis Ovsienkodc958242007-08-13 16:03:06 +00001319 */
1320
Timo Teräs0abf6792016-01-15 17:36:29 +02001321 /* Set real nexthops. */
1322 if (new_fib)
1323 nexthop_active_update (rn, new_fib, 1);
Timo Teräs325823a2016-01-15 17:36:31 +02001324 if (new_selected && new_selected != new_fib)
1325 nexthop_active_update (rn, new_selected, 1);
Timo Teräs0abf6792016-01-15 17:36:29 +02001326
1327 /* Update kernel if FIB entry has changed */
1328 if (old_fib != new_fib
1329 || (new_fib && CHECK_FLAG (new_fib->status, RIB_ENTRY_CHANGED)))
paul718e3742002-12-13 20:15:29 +00001330 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001331 if (old_fib && old_fib != new_fib)
1332 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001333 if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
1334 rib_update_kernel (rn, old_fib, NULL);
Timo Teräs325823a2016-01-15 17:36:31 +02001335 UNSET_FLAG (old_fib->status, RIB_ENTRY_SELECTED_FIB);
Timo Teräs0abf6792016-01-15 17:36:29 +02001336 }
1337
1338 if (new_fib)
1339 {
1340 /* Install new or replace existing FIB entry */
Timo Teräs325823a2016-01-15 17:36:31 +02001341 SET_FLAG (new_fib->status, RIB_ENTRY_SELECTED_FIB);
Timo Teräs0abf6792016-01-15 17:36:29 +02001342 if (! RIB_SYSTEM_ROUTE (new_fib))
1343 rib_update_kernel (rn, old_fib, new_fib);
1344 }
1345
1346 if (info->safi == SAFI_UNICAST)
1347 zfpm_trigger_update (rn, "updating existing route");
1348 }
1349 else if (old_fib == new_fib && new_fib && ! RIB_SYSTEM_ROUTE (new_fib))
1350 {
1351 /* Housekeeping code to deal with race conditions in kernel with
1352 * linux netlink reporting interface up before IPv4 or IPv6 protocol
1353 * is ready to add routes. This makes sure routes are IN the kernel.
1354 */
1355 for (ALL_NEXTHOPS_RO(new_fib->nexthop, nexthop, tnexthop, recursing))
1356 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1357 {
1358 installed = 1;
1359 break;
1360 }
1361 if (! installed)
1362 rib_update_kernel (rn, NULL, new_fib);
1363 }
1364
Timo Teräs325823a2016-01-15 17:36:31 +02001365 /* Redistribute SELECTED entry */
1366 if (old_selected != new_selected
1367 || (new_selected && CHECK_FLAG (new_selected->status, RIB_ENTRY_CHANGED)))
1368 {
1369 if (old_selected)
1370 {
1371 if (! new_selected)
1372 redistribute_delete (&rn->p, old_selected);
1373 if (old_selected != new_selected)
1374 UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED);
1375 }
1376
1377 if (new_selected)
1378 {
1379 /* Install new or replace existing redistributed entry */
1380 SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED);
1381 redistribute_add (&rn->p, new_selected);
1382 }
1383 }
1384
Timo Teräs0abf6792016-01-15 17:36:29 +02001385 /* Remove all RIB entries queued for removal */
1386 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1387 {
1388 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
paul4d38fdb2005-04-28 17:35:14 +00001389 {
Timo Teräs0abf6792016-01-15 17:36:29 +02001390 if (IS_ZEBRA_DEBUG_RIB)
1391 rnode_debug (rn, "rn %p, removing rib %p",
1392 (void *)rn, (void *)rib);
1393 rib_unlink (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001394 }
paul718e3742002-12-13 20:15:29 +00001395 }
1396
Paul Jakma6d691122006-07-27 21:49:00 +00001397 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001398 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001399
1400 /*
1401 * Check if the dest can be deleted now.
1402 */
1403 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001404}
1405
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001406/* Take a list of route_node structs and return 1, if there was a record
1407 * picked from it and processed by rib_process(). Don't process more,
1408 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001409 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001410static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001411process_subq (struct list * subq, u_char qindex)
1412{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001413 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001414 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001415
1416 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001417 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001418
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001419 rnode = listgetdata (lnode);
1420 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001421
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001422 if (rnode->info)
1423 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1424
Chris Caputo67b94672009-07-18 04:02:26 +00001425#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001426 else
1427 {
1428 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1429 __func__, rnode, rnode->lock);
1430 zlog_backtrace(LOG_DEBUG);
1431 }
Chris Caputo67b94672009-07-18 04:02:26 +00001432#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001433 route_unlock_node (rnode);
1434 list_delete_node (subq, lnode);
1435 return 1;
1436}
1437
1438/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1439 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1440 * is pointed to the meta queue structure.
1441 */
1442static wq_item_status
1443meta_queue_process (struct work_queue *dummy, void *data)
1444{
1445 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001446 unsigned i;
1447
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001448 for (i = 0; i < MQ_SIZE; i++)
1449 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001450 {
1451 mq->size--;
1452 break;
1453 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001454 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1455}
1456
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001457/*
1458 * Map from rib types to queue type (priority) in meta queue
1459 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001460static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1461 [ZEBRA_ROUTE_SYSTEM] = 4,
1462 [ZEBRA_ROUTE_KERNEL] = 0,
1463 [ZEBRA_ROUTE_CONNECT] = 0,
1464 [ZEBRA_ROUTE_STATIC] = 1,
1465 [ZEBRA_ROUTE_RIP] = 2,
1466 [ZEBRA_ROUTE_RIPNG] = 2,
1467 [ZEBRA_ROUTE_OSPF] = 2,
1468 [ZEBRA_ROUTE_OSPF6] = 2,
1469 [ZEBRA_ROUTE_ISIS] = 2,
1470 [ZEBRA_ROUTE_BGP] = 3,
1471 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001472 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001473};
1474
1475/* Look into the RN and queue it into one or more priority queues,
1476 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001477 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001478static void
1479rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001480{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001481 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001482
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001483 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001484 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001485 u_char qindex = meta_queue_map[rib->type];
1486
1487 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001488 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1489 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001490 {
1491 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001492 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001493 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001494 continue;
1495 }
1496
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001497 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001498 listnode_add (mq->subq[qindex], rn);
1499 route_lock_node (rn);
1500 mq->size++;
1501
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001502 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001503 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001504 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001505 }
paul4d38fdb2005-04-28 17:35:14 +00001506}
1507
Paul Jakma6d691122006-07-27 21:49:00 +00001508/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001509static void
Paul Jakma6d691122006-07-27 21:49:00 +00001510rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001511{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001512 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001513
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001514 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001515 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001516 {
1517 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001518 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001519 zlog_backtrace(LOG_DEBUG);
1520 return;
1521 }
1522
1523 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001524 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001525
1526 assert (zebra);
1527
1528 if (zebra->ribq == NULL)
1529 {
1530 zlog_err ("%s: work_queue does not exist!", __func__);
1531 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001532 }
paul4d38fdb2005-04-28 17:35:14 +00001533
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001534 /*
1535 * The RIB queue should normally be either empty or holding the only
1536 * work_queue_item element. In the latter case this element would
1537 * hold a pointer to the meta queue structure, which must be used to
1538 * actually queue the route nodes to process. So create the MQ
1539 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001540 * This semantics was introduced after 0.99.9 release.
1541 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001542 if (!zebra->ribq->items->count)
1543 work_queue_add (zebra->ribq, zebra->mq);
1544
1545 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001546
1547 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001548 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001549
1550 return;
paul4d38fdb2005-04-28 17:35:14 +00001551}
1552
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001553/* Create new meta queue.
1554 A destructor function doesn't seem to be necessary here.
1555 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001556static struct meta_queue *
1557meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001558{
1559 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001560 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001561
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001562 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1563 assert(new);
1564
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001565 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001566 {
1567 new->subq[i] = list_new ();
1568 assert(new->subq[i]);
1569 }
1570
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001571 return new;
1572}
1573
paul4d38fdb2005-04-28 17:35:14 +00001574/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001575static void
paul4d38fdb2005-04-28 17:35:14 +00001576rib_queue_init (struct zebra_t *zebra)
1577{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001578 assert (zebra);
1579
paul4d38fdb2005-04-28 17:35:14 +00001580 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001581 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001582 {
Paul Jakma6d691122006-07-27 21:49:00 +00001583 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001584 return;
1585 }
1586
1587 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001588 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001589 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001590 /* XXX: TODO: These should be runtime configurable via vty */
1591 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001592 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001593
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001594 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001595 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001596 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001597 return;
1598 }
1599 return;
paul718e3742002-12-13 20:15:29 +00001600}
1601
Paul Jakma6d691122006-07-27 21:49:00 +00001602/* RIB updates are processed via a queue of pointers to route_nodes.
1603 *
1604 * The queue length is bounded by the maximal size of the routing table,
1605 * as a route_node will not be requeued, if already queued.
1606 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001607 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05001608 * state, or static_install_route (when an existing RIB is updated)
Paul Jakma3c0755d2006-12-08 00:53:14 +00001609 * and then submit route_node to queue for best-path selection later.
1610 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001611 *
1612 * Deleted RIBs are reaped during best-path selection.
1613 *
1614 * rib_addnode
1615 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001616 * |-------->| | best RIB, if required
1617 * | |
1618 * static_install->|->rib_addqueue...... -> rib_process
1619 * | |
1620 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001621 * |-> set RIB_ENTRY_REMOVE |
1622 * rib_delnode (RIB freed)
1623 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001624 * The 'info' pointer of a route_node points to a rib_dest_t
1625 * ('dest'). Queueing state for a route_node is kept on the dest. The
1626 * dest is created on-demand by rib_link() and is kept around at least
1627 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001628 *
1629 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1630 *
1631 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001632 * - dest attached to route_node:
1633 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001634 * - route_node processing queue
1635 * - managed by: rib_addqueue, rib_process.
1636 *
1637 */
1638
paul718e3742002-12-13 20:15:29 +00001639/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001640static void
Paul Jakma6d691122006-07-27 21:49:00 +00001641rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001642{
1643 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001644 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001645
paul4d38fdb2005-04-28 17:35:14 +00001646 assert (rib && rn);
1647
Paul Jakma6d691122006-07-27 21:49:00 +00001648 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001649 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001650
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001651 dest = rib_dest_from_rnode (rn);
1652 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001653 {
1654 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001655 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001656
1657 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1658 route_lock_node (rn); /* rn route table reference */
1659 rn->info = dest;
1660 dest->rnode = rn;
1661 }
1662
1663 head = dest->routes;
1664 if (head)
1665 {
Paul Jakma6d691122006-07-27 21:49:00 +00001666 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001667 }
paul718e3742002-12-13 20:15:29 +00001668 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001669 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001670 rib_queue_add (&zebrad, rn);
1671}
1672
1673static void
1674rib_addnode (struct route_node *rn, struct rib *rib)
1675{
1676 /* RIB node has been un-removed before route-node is processed.
1677 * route_node must hence already be on the queue for processing..
1678 */
1679 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1680 {
1681 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001682 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001683
Paul Jakma6d691122006-07-27 21:49:00 +00001684 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1685 return;
1686 }
1687 rib_link (rn, rib);
1688}
1689
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001690/*
1691 * rib_unlink
1692 *
1693 * Detach a rib structure from a route_node.
1694 *
1695 * Note that a call to rib_unlink() should be followed by a call to
1696 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1697 * longer required to be deleted.
1698 */
Paul Jakma6d691122006-07-27 21:49:00 +00001699static void
1700rib_unlink (struct route_node *rn, struct rib *rib)
1701{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001702 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001703
1704 assert (rn && rib);
1705
1706 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001707 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001708
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001709 dest = rib_dest_from_rnode (rn);
1710
Paul Jakma6d691122006-07-27 21:49:00 +00001711 if (rib->next)
1712 rib->next->prev = rib->prev;
1713
1714 if (rib->prev)
1715 rib->prev->next = rib->next;
1716 else
1717 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001718 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001719 }
1720
1721 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001722 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001723 XFREE (MTYPE_RIB, rib);
1724
paul718e3742002-12-13 20:15:29 +00001725}
1726
paula1ac18c2005-06-28 17:17:12 +00001727static void
paul718e3742002-12-13 20:15:29 +00001728rib_delnode (struct route_node *rn, struct rib *rib)
1729{
Paul Jakma6d691122006-07-27 21:49:00 +00001730 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001731 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001732 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1733 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001734}
1735
1736int
1737rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001738 struct in_addr *gate, struct in_addr *src,
Feng Lu0d0686f2015-05-22 11:40:02 +02001739 unsigned int ifindex, vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001740 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001741{
1742 struct rib *rib;
1743 struct rib *same = NULL;
1744 struct route_table *table;
1745 struct route_node *rn;
1746 struct nexthop *nexthop;
1747
1748 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001749 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00001750 if (! table)
1751 return 0;
1752
1753 /* Make it sure prefixlen is applied to the prefix. */
1754 apply_mask_ipv4 (p);
1755
1756 /* Set default distance by route type. */
1757 if (distance == 0)
1758 {
Balaji.G837d16c2012-09-26 14:09:10 +05301759 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001760 distance = 150;
1761 else
1762 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001763
1764 /* iBGP distance is 200. */
1765 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1766 distance = 200;
1767 }
1768
1769 /* Lookup route node.*/
1770 rn = route_node_get (table, (struct prefix *) p);
1771
1772 /* If same type of route are installed, treat it as a implicit
1773 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001774 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001775 {
Paul Jakma6d691122006-07-27 21:49:00 +00001776 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1777 continue;
1778
hassoebf1ead2005-09-21 14:58:20 +00001779 if (rib->type != type)
1780 continue;
1781 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001782 {
1783 same = rib;
1784 break;
1785 }
hassoebf1ead2005-09-21 14:58:20 +00001786 /* Duplicate connected route comes in. */
1787 else if ((nexthop = rib->nexthop) &&
1788 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001789 nexthop->ifindex == ifindex &&
1790 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001791 {
1792 rib->refcnt++;
1793 return 0 ;
1794 }
paul718e3742002-12-13 20:15:29 +00001795 }
1796
1797 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001798 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001799 rib->type = type;
1800 rib->distance = distance;
1801 rib->flags = flags;
1802 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001803 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02001804 rib->vrf_id = vrf_id;
1805 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00001806 rib->nexthop_num = 0;
1807 rib->uptime = time (NULL);
1808
1809 /* Nexthop settings. */
1810 if (gate)
1811 {
1812 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001813 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001814 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001815 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001816 }
1817 else
1818 nexthop_ifindex_add (rib, ifindex);
1819
1820 /* If this route is kernel route, set FIB flag to the route. */
1821 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1822 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1823 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1824
1825 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001826 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001827 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1828 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001829 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001830
paul718e3742002-12-13 20:15:29 +00001831 /* Free implicit route.*/
1832 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001833 {
1834 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001835 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1836 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001837 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001838 }
paul4d38fdb2005-04-28 17:35:14 +00001839
1840 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001841 return 0;
1842}
1843
Denis Ovsienkodc958242007-08-13 16:03:06 +00001844/* This function dumps the contents of a given RIB entry into
1845 * standard debug log. Calling function name and IP prefix in
1846 * question are passed as 1st and 2nd arguments.
1847 */
1848
David Lamparterf7bf4152013-10-22 17:10:21 +00001849void _rib_dump (const char * func,
1850 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001851{
David Lamparterf7bf4152013-10-22 17:10:21 +00001852 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001853 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001854 struct nexthop *nexthop, *tnexthop;
1855 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001856
Feng Lu0d0686f2015-05-22 11:40:02 +02001857 zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
1858 prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001859 zlog_debug
1860 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001861 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001862 func,
1863 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001864 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001865 rib->type,
1866 rib->table
1867 );
1868 zlog_debug
1869 (
1870 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1871 func,
1872 rib->metric,
1873 rib->distance,
1874 rib->flags,
1875 rib->status
1876 );
1877 zlog_debug
1878 (
1879 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1880 func,
1881 rib->nexthop_num,
1882 rib->nexthop_active_num,
1883 rib->nexthop_fib_num
1884 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001885
Christian Frankefa713d92013-07-05 15:35:37 +00001886 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1887 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001888 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001889 zlog_debug
1890 (
1891 "%s: %s %s with flags %s%s%s",
1892 func,
1893 (recursing ? " NH" : "NH"),
1894 straddr,
1895 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1896 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1897 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1898 );
1899 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001900 zlog_debug ("%s: dump complete", func);
1901}
1902
1903/* This is an exported helper to rtm_read() to dump the strange
1904 * RIB entry found by rib_lookup_ipv4_route()
1905 */
1906
1907void rib_lookup_and_dump (struct prefix_ipv4 * p)
1908{
1909 struct route_table *table;
1910 struct route_node *rn;
1911 struct rib *rib;
1912 char prefix_buf[INET_ADDRSTRLEN];
1913
1914 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001915 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001916 if (! table)
1917 {
Feng Lu41f44a22015-05-22 11:39:56 +02001918 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001919 return;
1920 }
1921
Denis Ovsienkodc958242007-08-13 16:03:06 +00001922 /* Scan the RIB table for exactly matching RIB entry. */
1923 rn = route_node_lookup (table, (struct prefix *) p);
1924
1925 /* No route for this prefix. */
1926 if (! rn)
1927 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001928 zlog_debug ("%s: lookup failed for %s", __func__,
1929 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001930 return;
1931 }
1932
1933 /* Unlock node. */
1934 route_unlock_node (rn);
1935
1936 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001937 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001938 {
1939 zlog_debug
1940 (
1941 "%s: rn %p, rib %p: %s, %s",
1942 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01001943 (void *)rn,
1944 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001945 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1946 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1947 );
David Lamparterf7bf4152013-10-22 17:10:21 +00001948 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001949 }
1950}
1951
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001952/* Check if requested address assignment will fail due to another
1953 * route being installed by zebra in FIB already. Take necessary
1954 * actions, if needed: remove such a route from FIB and deSELECT
1955 * corresponding RIB entry. Then put affected RN into RIBQ head.
1956 */
1957void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1958{
1959 struct route_table *table;
1960 struct route_node *rn;
1961 struct rib *rib;
1962 unsigned changed = 0;
1963
Feng Lu41f44a22015-05-22 11:39:56 +02001964 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001965 {
Feng Lu41f44a22015-05-22 11:39:56 +02001966 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001967 return;
1968 }
1969
1970 /* No matches would be the simplest case. */
1971 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1972 return;
1973
1974 /* Unlock node. */
1975 route_unlock_node (rn);
1976
1977 /* Check all RIB entries. In case any changes have to be done, requeue
1978 * the RN into RIBQ head. If the routing message about the new connected
1979 * route (generated by the IP address we are going to assign very soon)
1980 * comes before the RIBQ is processed, the new RIB entry will join
1981 * RIBQ record already on head. This is necessary for proper revalidation
1982 * of the rest of the RIB.
1983 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001984 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001985 {
Timo Teräs325823a2016-01-15 17:36:31 +02001986 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB) &&
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001987 ! RIB_SYSTEM_ROUTE (rib))
1988 {
1989 changed = 1;
1990 if (IS_ZEBRA_DEBUG_RIB)
1991 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001992 char buf[PREFIX_STRLEN];
1993 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
1994 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00001995 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00001996 }
1997 rib_uninstall (rn, rib);
1998 }
1999 }
2000 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002001 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002002}
2003
paul718e3742002-12-13 20:15:29 +00002004int
G.Balajicddf3912011-11-26 21:59:32 +04002005rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002006{
2007 struct route_table *table;
2008 struct route_node *rn;
2009 struct rib *same;
2010 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002011
paul718e3742002-12-13 20:15:29 +00002012 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002013 table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +00002014 if (! table)
2015 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002016
paul718e3742002-12-13 20:15:29 +00002017 /* Make it sure prefixlen is applied to the prefix. */
2018 apply_mask_ipv4 (p);
2019
2020 /* Set default distance by route type. */
2021 if (rib->distance == 0)
2022 {
2023 rib->distance = route_info[rib->type].distance;
2024
2025 /* iBGP distance is 200. */
2026 if (rib->type == ZEBRA_ROUTE_BGP
2027 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2028 rib->distance = 200;
2029 }
2030
2031 /* Lookup route node.*/
2032 rn = route_node_get (table, (struct prefix *) p);
2033
2034 /* If same type of route are installed, treat it as a implicit
2035 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002036 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002037 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002038 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002039 continue;
2040
paul718e3742002-12-13 20:15:29 +00002041 if (same->type == rib->type && same->table == rib->table
2042 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002043 break;
paul718e3742002-12-13 20:15:29 +00002044 }
paul4d38fdb2005-04-28 17:35:14 +00002045
paul718e3742002-12-13 20:15:29 +00002046 /* If this route is kernel route, set FIB flag to the route. */
2047 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2048 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2049 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2050
2051 /* Link new rib to node.*/
2052 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002053 if (IS_ZEBRA_DEBUG_RIB)
2054 {
2055 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002056 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002057 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002058 }
paul718e3742002-12-13 20:15:29 +00002059
paul718e3742002-12-13 20:15:29 +00002060 /* Free implicit route.*/
2061 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002062 {
2063 if (IS_ZEBRA_DEBUG_RIB)
2064 {
2065 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002066 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002067 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002068 }
paul4d38fdb2005-04-28 17:35:14 +00002069 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002070 }
paul4d38fdb2005-04-28 17:35:14 +00002071
2072 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002073 return 0;
2074}
2075
hassoebf1ead2005-09-21 14:58:20 +00002076/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002077int
2078rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002079 struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002080{
2081 struct route_table *table;
2082 struct route_node *rn;
2083 struct rib *rib;
2084 struct rib *fib = NULL;
2085 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002086 struct nexthop *nexthop, *tnexthop;
2087 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002088 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002089 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002090
2091 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002092 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002093 if (! table)
2094 return 0;
2095
2096 /* Apply mask. */
2097 apply_mask_ipv4 (p);
2098
Christian Frankeb52aef12013-11-27 17:06:15 +00002099 if (IS_ZEBRA_DEBUG_KERNEL)
2100 {
2101 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002102 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
2103 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002104 inet_ntoa (*gate),
2105 ifindex);
2106 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002107 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
2108 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002109 ifindex);
2110 }
paul5ec90d22003-06-19 01:41:37 +00002111
paul718e3742002-12-13 20:15:29 +00002112 /* Lookup route node. */
2113 rn = route_node_lookup (table, (struct prefix *) p);
2114 if (! rn)
2115 {
2116 if (IS_ZEBRA_DEBUG_KERNEL)
2117 {
2118 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002119 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2120 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002121 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002122 ifindex);
2123 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002124 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2125 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002126 ifindex);
2127 }
2128 return ZEBRA_ERR_RTNOEXIST;
2129 }
2130
2131 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002132 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002133 {
Paul Jakma6d691122006-07-27 21:49:00 +00002134 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2135 continue;
2136
Timo Teräs325823a2016-01-15 17:36:31 +02002137 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00002138 fib = rib;
2139
hassoebf1ead2005-09-21 14:58:20 +00002140 if (rib->type != type)
2141 continue;
2142 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002143 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002144 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002145 if (nexthop->ifindex != ifindex)
2146 continue;
hassoebf1ead2005-09-21 14:58:20 +00002147 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002148 {
hassoebf1ead2005-09-21 14:58:20 +00002149 rib->refcnt--;
2150 route_unlock_node (rn);
2151 route_unlock_node (rn);
2152 return 0;
paul718e3742002-12-13 20:15:29 +00002153 }
hassoebf1ead2005-09-21 14:58:20 +00002154 same = rib;
2155 break;
paul718e3742002-12-13 20:15:29 +00002156 }
hassoebf1ead2005-09-21 14:58:20 +00002157 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002158 else
paul5ec90d22003-06-19 01:41:37 +00002159 {
Christian Frankefa713d92013-07-05 15:35:37 +00002160 if (gate == NULL)
2161 {
2162 same = rib;
2163 break;
2164 }
2165 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2166 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2167 {
2168 same = rib;
2169 break;
2170 }
2171 if (same)
2172 break;
2173 }
paul718e3742002-12-13 20:15:29 +00002174 }
paul718e3742002-12-13 20:15:29 +00002175 /* If same type of route can't be found and this message is from
2176 kernel. */
2177 if (! same)
2178 {
2179 if (fib && type == ZEBRA_ROUTE_KERNEL)
2180 {
2181 /* Unset flags. */
2182 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2183 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2184
Timo Teräs325823a2016-01-15 17:36:31 +02002185 UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
paul718e3742002-12-13 20:15:29 +00002186 }
2187 else
2188 {
2189 if (IS_ZEBRA_DEBUG_KERNEL)
2190 {
2191 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002192 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2193 "doesn't exist in rib",
2194 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002195 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002196 ifindex,
2197 type);
2198 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002199 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2200 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002201 ifindex,
2202 type);
2203 }
2204 route_unlock_node (rn);
2205 return ZEBRA_ERR_RTNOEXIST;
2206 }
2207 }
paul4d38fdb2005-04-28 17:35:14 +00002208
paul718e3742002-12-13 20:15:29 +00002209 if (same)
2210 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002211
paul718e3742002-12-13 20:15:29 +00002212 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002213 return 0;
2214}
David Lamparter6b0655a2014-06-04 06:53:35 +02002215
paul718e3742002-12-13 20:15:29 +00002216/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002217static void
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002218static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002219{
2220 struct rib *rib;
2221 struct route_node *rn;
2222 struct route_table *table;
2223
2224 /* Lookup table. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002225 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002226 if (! table)
2227 return;
2228
2229 /* Lookup existing route */
2230 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002231 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002232 {
2233 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2234 continue;
2235
2236 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2237 break;
2238 }
paul718e3742002-12-13 20:15:29 +00002239
2240 if (rib)
2241 {
2242 /* Same distance static route is there. Update it with new
2243 nexthop. */
paul718e3742002-12-13 20:15:29 +00002244 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002245 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002246 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002247 case STATIC_IPV4_GATEWAY:
2248 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2249 break;
2250 case STATIC_IPV4_IFNAME:
2251 nexthop_ifname_add (rib, si->ifname);
2252 break;
2253 case STATIC_IPV4_BLACKHOLE:
2254 nexthop_blackhole_add (rib);
2255 break;
2256 case STATIC_IPV6_GATEWAY:
2257 nexthop_ipv6_add (rib, &si->addr.ipv6);
2258 break;
2259 case STATIC_IPV6_IFNAME:
2260 nexthop_ifname_add (rib, si->ifname);
2261 break;
2262 case STATIC_IPV6_GATEWAY_IFNAME:
2263 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2264 break;
paul4d38fdb2005-04-28 17:35:14 +00002265 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002266 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002267 }
2268 else
2269 {
2270 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002271 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2272
paul718e3742002-12-13 20:15:29 +00002273 rib->type = ZEBRA_ROUTE_STATIC;
2274 rib->distance = si->distance;
2275 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002276 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002277 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002278 rib->nexthop_num = 0;
2279
2280 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002281 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002282 case STATIC_IPV4_GATEWAY:
2283 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2284 break;
2285 case STATIC_IPV4_IFNAME:
2286 nexthop_ifname_add (rib, si->ifname);
2287 break;
2288 case STATIC_IPV4_BLACKHOLE:
2289 nexthop_blackhole_add (rib);
2290 break;
2291 case STATIC_IPV6_GATEWAY:
2292 nexthop_ipv6_add (rib, &si->addr.ipv6);
2293 break;
2294 case STATIC_IPV6_IFNAME:
2295 nexthop_ifname_add (rib, si->ifname);
2296 break;
2297 case STATIC_IPV6_GATEWAY_IFNAME:
2298 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2299 break;
paul7021c422003-07-15 12:52:22 +00002300 }
paul718e3742002-12-13 20:15:29 +00002301
hasso81dfcaa2003-05-25 19:21:25 +00002302 /* Save the flags of this static routes (reject, blackhole) */
2303 rib->flags = si->flags;
2304
paul718e3742002-12-13 20:15:29 +00002305 /* Link this rib to the tree. */
2306 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002307 }
2308}
2309
paula1ac18c2005-06-28 17:17:12 +00002310static int
Donald Sharpa979ab72015-11-04 13:26:38 -05002311static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002312{
2313 if (nexthop->type == NEXTHOP_TYPE_IPV4
2314 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002315 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002316 return 1;
2317 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2318 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002319 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002320 return 1;
paul595db7f2003-05-25 21:35:06 +00002321 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2322 && si->type == STATIC_IPV4_BLACKHOLE)
2323 return 1;
Donald Sharpa979ab72015-11-04 13:26:38 -05002324 if (nexthop->type == NEXTHOP_TYPE_IPV6
2325 && si->type == STATIC_IPV6_GATEWAY
2326 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
2327 return 1;
2328 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2329 && si->type == STATIC_IPV6_IFNAME
2330 && strcmp (nexthop->ifname, si->ifname) == 0)
2331 return 1;
2332 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2333 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2334 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
2335 && strcmp (nexthop->ifname, si->ifname) == 0)
2336 return 1;
paule8e19462006-01-19 20:16:55 +00002337 return 0;
paul718e3742002-12-13 20:15:29 +00002338}
2339
2340/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002341static void
Donald Sharp949b7192015-11-04 13:26:39 -05002342static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002343{
2344 struct route_node *rn;
2345 struct rib *rib;
2346 struct nexthop *nexthop;
2347 struct route_table *table;
2348
2349 /* Lookup table. */
Donald Sharp949b7192015-11-04 13:26:39 -05002350 table = zebra_vrf_table (afi, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002351 if (! table)
2352 return;
paul4d38fdb2005-04-28 17:35:14 +00002353
paul718e3742002-12-13 20:15:29 +00002354 /* Lookup existing route with type and distance. */
2355 rn = route_node_lookup (table, p);
2356 if (! rn)
2357 return;
2358
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002359 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002360 {
2361 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2362 continue;
2363
2364 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2365 break;
2366 }
paul718e3742002-12-13 20:15:29 +00002367
2368 if (! rib)
2369 {
2370 route_unlock_node (rn);
2371 return;
2372 }
2373
2374 /* Lookup nexthop. */
2375 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Donald Sharpa979ab72015-11-04 13:26:38 -05002376 if (static_nexthop_same (nexthop, si))
paul718e3742002-12-13 20:15:29 +00002377 break;
2378
2379 /* Can't find nexthop. */
2380 if (! nexthop)
2381 {
2382 route_unlock_node (rn);
2383 return;
2384 }
2385
2386 /* Check nexthop. */
2387 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002388 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002389 else
2390 {
paul6baeb982003-10-28 03:47:15 +00002391 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2392 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002393 nexthop_delete (rib, nexthop);
2394 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002395 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002396 }
paul718e3742002-12-13 20:15:29 +00002397 /* Unlock node. */
2398 route_unlock_node (rn);
2399}
2400
paul718e3742002-12-13 20:15:29 +00002401int
Everton Marques33d86db2014-07-14 11:19:00 -03002402static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2403 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002404 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002405{
2406 u_char type = 0;
2407 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002408 struct static_route *si;
2409 struct static_route *pp;
2410 struct static_route *cp;
2411 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002412 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2413 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002414
paul718e3742002-12-13 20:15:29 +00002415 if (! stable)
2416 return -1;
2417
2418 /* Lookup static route prefix. */
2419 rn = route_node_get (stable, p);
2420
2421 /* Make flags. */
2422 if (gate)
2423 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002424 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002425 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002426 else
2427 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002428
2429 /* Do nothing if there is a same static route. */
2430 for (si = rn->info; si; si = si->next)
2431 {
2432 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002433 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2434 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002435 {
2436 if (distance == si->distance)
2437 {
2438 route_unlock_node (rn);
2439 return 0;
2440 }
2441 else
2442 update = si;
2443 }
2444 }
2445
Paul Jakma3c0755d2006-12-08 00:53:14 +00002446 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002447 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002448 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002449
2450 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002451 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002452
2453 si->type = type;
2454 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002455 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002456 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002457
2458 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002459 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002460 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002461 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002462
2463 /* Add new static route information to the tree with sort by
2464 distance value and gateway address. */
2465 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2466 {
2467 if (si->distance < cp->distance)
2468 break;
2469 if (si->distance > cp->distance)
2470 continue;
2471 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2472 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002473 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002474 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002475 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002476 continue;
2477 }
2478 }
2479
2480 /* Make linked list. */
2481 if (pp)
2482 pp->next = si;
2483 else
2484 rn->info = si;
2485 if (cp)
2486 cp->prev = si;
2487 si->prev = pp;
2488 si->next = cp;
2489
2490 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002491 static_install_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002492
2493 return 1;
2494}
2495
paul718e3742002-12-13 20:15:29 +00002496int
Everton Marques33d86db2014-07-14 11:19:00 -03002497static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002498 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002499{
2500 u_char type = 0;
2501 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002502 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002503 struct route_table *stable;
2504
2505 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002506 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002507 if (! stable)
2508 return -1;
2509
2510 /* Lookup static route prefix. */
2511 rn = route_node_lookup (stable, p);
2512 if (! rn)
2513 return 0;
2514
2515 /* Make flags. */
2516 if (gate)
2517 type = STATIC_IPV4_GATEWAY;
2518 else if (ifname)
2519 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002520 else
2521 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002522
2523 /* Find same static route is the tree */
2524 for (si = rn->info; si; si = si->next)
2525 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002526 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2527 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002528 break;
2529
2530 /* Can't find static route. */
2531 if (! si)
2532 {
2533 route_unlock_node (rn);
2534 return 0;
2535 }
2536
2537 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002538 static_uninstall_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002539
2540 /* Unlink static route from linked list. */
2541 if (si->prev)
2542 si->prev->next = si->next;
2543 else
2544 rn->info = si->next;
2545 if (si->next)
2546 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002547 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002548
2549 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002550 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002551 XFREE (0, si->ifname);
2552 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002553
paul143a3852003-09-29 20:06:13 +00002554 route_unlock_node (rn);
2555
paul718e3742002-12-13 20:15:29 +00002556 return 1;
2557}
2558
paul718e3742002-12-13 20:15:29 +00002559int
2560rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002561 struct in6_addr *gate, unsigned int ifindex,
2562 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002563 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002564{
2565 struct rib *rib;
2566 struct rib *same = NULL;
2567 struct route_table *table;
2568 struct route_node *rn;
2569 struct nexthop *nexthop;
2570
paul718e3742002-12-13 20:15:29 +00002571 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002572 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002573 if (! table)
2574 return 0;
2575
2576 /* Make sure mask is applied. */
2577 apply_mask_ipv6 (p);
2578
2579 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002580 if (!distance)
2581 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002582
2583 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2584 distance = 200;
2585
paul718e3742002-12-13 20:15:29 +00002586 /* Lookup route node.*/
2587 rn = route_node_get (table, (struct prefix *) p);
2588
2589 /* If same type of route are installed, treat it as a implicit
2590 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002591 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002592 {
Paul Jakma6d691122006-07-27 21:49:00 +00002593 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2594 continue;
2595
hassoebf1ead2005-09-21 14:58:20 +00002596 if (rib->type != type)
2597 continue;
2598 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002599 {
2600 same = rib;
paul718e3742002-12-13 20:15:29 +00002601 break;
2602 }
hassoebf1ead2005-09-21 14:58:20 +00002603 else if ((nexthop = rib->nexthop) &&
2604 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2605 nexthop->ifindex == ifindex)
2606 {
2607 rib->refcnt++;
2608 return 0;
2609 }
paul718e3742002-12-13 20:15:29 +00002610 }
2611
2612 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002613 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2614
paul718e3742002-12-13 20:15:29 +00002615 rib->type = type;
2616 rib->distance = distance;
2617 rib->flags = flags;
2618 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002619 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002620 rib->vrf_id = vrf_id;
2621 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002622 rib->nexthop_num = 0;
2623 rib->uptime = time (NULL);
2624
2625 /* Nexthop settings. */
2626 if (gate)
2627 {
2628 if (ifindex)
2629 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2630 else
2631 nexthop_ipv6_add (rib, gate);
2632 }
2633 else
2634 nexthop_ifindex_add (rib, ifindex);
2635
2636 /* If this route is kernel route, set FIB flag to the route. */
2637 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2638 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2639 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2640
2641 /* Link new rib to node.*/
2642 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002643 if (IS_ZEBRA_DEBUG_RIB)
2644 {
2645 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002646 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002647 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002648 }
paul718e3742002-12-13 20:15:29 +00002649
paul718e3742002-12-13 20:15:29 +00002650 /* Free implicit route.*/
2651 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002652 {
2653 if (IS_ZEBRA_DEBUG_RIB)
2654 {
2655 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002656 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002657 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002658 }
paul4d38fdb2005-04-28 17:35:14 +00002659 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002660 }
paul4d38fdb2005-04-28 17:35:14 +00002661
2662 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002663 return 0;
2664}
2665
hassoebf1ead2005-09-21 14:58:20 +00002666/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002667int
2668rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002669 struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002670{
2671 struct route_table *table;
2672 struct route_node *rn;
2673 struct rib *rib;
2674 struct rib *fib = NULL;
2675 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002676 struct nexthop *nexthop, *tnexthop;
2677 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002678 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002679 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002680
2681 /* Apply mask. */
2682 apply_mask_ipv6 (p);
2683
2684 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002685 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002686 if (! table)
2687 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002688
paul718e3742002-12-13 20:15:29 +00002689 /* Lookup route node. */
2690 rn = route_node_lookup (table, (struct prefix *) p);
2691 if (! rn)
2692 {
2693 if (IS_ZEBRA_DEBUG_KERNEL)
2694 {
2695 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002696 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2697 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002698 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002699 ifindex);
2700 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002701 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2702 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002703 ifindex);
2704 }
2705 return ZEBRA_ERR_RTNOEXIST;
2706 }
2707
2708 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002709 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002710 {
Paul Jakma6d691122006-07-27 21:49:00 +00002711 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2712 continue;
2713
Timo Teräs325823a2016-01-15 17:36:31 +02002714 if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
paul718e3742002-12-13 20:15:29 +00002715 fib = rib;
2716
hassoebf1ead2005-09-21 14:58:20 +00002717 if (rib->type != type)
2718 continue;
2719 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002720 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002721 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002722 if (nexthop->ifindex != ifindex)
2723 continue;
hassoebf1ead2005-09-21 14:58:20 +00002724 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002725 {
hassoebf1ead2005-09-21 14:58:20 +00002726 rib->refcnt--;
2727 route_unlock_node (rn);
2728 route_unlock_node (rn);
2729 return 0;
paul718e3742002-12-13 20:15:29 +00002730 }
hassoebf1ead2005-09-21 14:58:20 +00002731 same = rib;
2732 break;
paul718e3742002-12-13 20:15:29 +00002733 }
hassoebf1ead2005-09-21 14:58:20 +00002734 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002735 else
2736 {
2737 if (gate == NULL)
2738 {
2739 same = rib;
2740 break;
2741 }
2742 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2743 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2744 {
2745 same = rib;
2746 break;
2747 }
2748 if (same)
2749 break;
2750 }
paul718e3742002-12-13 20:15:29 +00002751 }
2752
2753 /* If same type of route can't be found and this message is from
2754 kernel. */
2755 if (! same)
2756 {
2757 if (fib && type == ZEBRA_ROUTE_KERNEL)
2758 {
2759 /* Unset flags. */
2760 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2761 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2762
Timo Teräs325823a2016-01-15 17:36:31 +02002763 UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
paul718e3742002-12-13 20:15:29 +00002764 }
2765 else
2766 {
2767 if (IS_ZEBRA_DEBUG_KERNEL)
2768 {
2769 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002770 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2771 "doesn't exist in rib",
2772 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002773 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002774 ifindex,
2775 type);
2776 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002777 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2778 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002779 ifindex,
2780 type);
2781 }
2782 route_unlock_node (rn);
2783 return ZEBRA_ERR_RTNOEXIST;
2784 }
2785 }
2786
2787 if (same)
2788 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002789
paul718e3742002-12-13 20:15:29 +00002790 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002791 return 0;
2792}
David Lamparter6b0655a2014-06-04 06:53:35 +02002793
paul718e3742002-12-13 20:15:29 +00002794
2795/* Add static route into static route configuration. */
2796int
2797static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002798 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002799 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002800{
2801 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002802 struct static_route *si;
2803 struct static_route *pp;
2804 struct static_route *cp;
Donald Sharpc1900e02015-11-04 13:26:40 -05002805 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002806 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2807 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002808
paul718e3742002-12-13 20:15:29 +00002809 if (! stable)
2810 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002811
2812 if (!gate &&
2813 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2814 return -1;
2815
2816 if (!ifname &&
2817 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2818 return -1;
paul718e3742002-12-13 20:15:29 +00002819
2820 /* Lookup static route prefix. */
2821 rn = route_node_get (stable, p);
2822
2823 /* Do nothing if there is a same static route. */
2824 for (si = rn->info; si; si = si->next)
2825 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002826 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002827 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002828 && (! ifname || strcmp (ifname, si->ifname) == 0))
2829 {
Donald Sharpc1900e02015-11-04 13:26:40 -05002830 if (distance == si->distance)
2831 {
2832 route_unlock_node (rn);
2833 return 0;
2834 }
2835 else
2836 update = si;
paul718e3742002-12-13 20:15:29 +00002837 }
2838 }
2839
Donald Sharpc1900e02015-11-04 13:26:40 -05002840 if (update)
2841 static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
2842
paul718e3742002-12-13 20:15:29 +00002843 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002844 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002845
2846 si->type = type;
2847 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002848 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002849 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002850
2851 switch (type)
2852 {
2853 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002854 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002855 break;
2856 case STATIC_IPV6_IFNAME:
2857 si->ifname = XSTRDUP (0, ifname);
2858 break;
2859 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002860 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002861 si->ifname = XSTRDUP (0, ifname);
2862 break;
2863 }
2864
2865 /* Add new static route information to the tree with sort by
2866 distance value and gateway address. */
2867 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2868 {
2869 if (si->distance < cp->distance)
2870 break;
2871 if (si->distance > cp->distance)
2872 continue;
2873 }
2874
2875 /* Make linked list. */
2876 if (pp)
2877 pp->next = si;
2878 else
2879 rn->info = si;
2880 if (cp)
2881 cp->prev = si;
2882 si->prev = pp;
2883 si->next = cp;
2884
2885 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002886 static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002887
2888 return 1;
2889}
2890
2891/* Delete static route from static route configuration. */
2892int
2893static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002894 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002895{
2896 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002897 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002898 struct route_table *stable;
2899
2900 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002901 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002902 if (! stable)
2903 return -1;
2904
2905 /* Lookup static route prefix. */
2906 rn = route_node_lookup (stable, p);
2907 if (! rn)
2908 return 0;
2909
2910 /* Find same static route is the tree */
2911 for (si = rn->info; si; si = si->next)
2912 if (distance == si->distance
2913 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002914 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002915 && (! ifname || strcmp (ifname, si->ifname) == 0))
2916 break;
2917
2918 /* Can't find static route. */
2919 if (! si)
2920 {
2921 route_unlock_node (rn);
2922 return 0;
2923 }
2924
2925 /* Install into rib. */
Donald Sharp949b7192015-11-04 13:26:39 -05002926 static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00002927
2928 /* Unlink static route from linked list. */
2929 if (si->prev)
2930 si->prev->next = si->next;
2931 else
2932 rn->info = si->next;
2933 if (si->next)
2934 si->next->prev = si->prev;
2935
2936 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002937 if (ifname)
2938 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05002939 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002940
2941 return 1;
2942}
David Lamparter6b0655a2014-06-04 06:53:35 +02002943
paul718e3742002-12-13 20:15:29 +00002944/* RIB update function. */
2945void
Feng Lu0d0686f2015-05-22 11:40:02 +02002946rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002947{
2948 struct route_node *rn;
2949 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002950
Feng Lu0d0686f2015-05-22 11:40:02 +02002951 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002952 if (table)
2953 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002954 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002955 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002956
Feng Lu0d0686f2015-05-22 11:40:02 +02002957 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002958 if (table)
2959 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002960 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00002961 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002962}
2963
David Lamparter6b0655a2014-06-04 06:53:35 +02002964
paul718e3742002-12-13 20:15:29 +00002965/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002966static void
paul718e3742002-12-13 20:15:29 +00002967rib_weed_table (struct route_table *table)
2968{
2969 struct route_node *rn;
2970 struct rib *rib;
2971 struct rib *next;
2972
2973 if (table)
2974 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002975 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00002976 {
Paul Jakma6d691122006-07-27 21:49:00 +00002977 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2978 continue;
2979
paulb21b19c2003-06-15 01:28:29 +00002980 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002981 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002982 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002983 }
2984}
2985
2986/* Delete all routes from non main table. */
2987void
paula1ac18c2005-06-28 17:17:12 +00002988rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002989{
Feng Lu0d0686f2015-05-22 11:40:02 +02002990 vrf_iter_t iter;
2991 struct zebra_vrf *zvrf;
2992
2993 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
2994 if ((zvrf = vrf_iter2info (iter)) != NULL)
2995 {
2996 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
2997 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
2998 }
paul718e3742002-12-13 20:15:29 +00002999}
David Lamparter6b0655a2014-06-04 06:53:35 +02003000
Feng Lu0d0686f2015-05-22 11:40:02 +02003001#if 0
paul718e3742002-12-13 20:15:29 +00003002/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003003static void
paul718e3742002-12-13 20:15:29 +00003004rib_sweep_table (struct route_table *table)
3005{
3006 struct route_node *rn;
3007 struct rib *rib;
3008 struct rib *next;
3009 int ret = 0;
3010
3011 if (table)
3012 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003013 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003014 {
Paul Jakma6d691122006-07-27 21:49:00 +00003015 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3016 continue;
3017
paul718e3742002-12-13 20:15:29 +00003018 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3019 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3020 {
Timo Teräs0abf6792016-01-15 17:36:29 +02003021 ret = rib_update_kernel (rn, rib, NULL);
paul718e3742002-12-13 20:15:29 +00003022 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003023 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003024 }
3025 }
3026}
Feng Lu0d0686f2015-05-22 11:40:02 +02003027#endif
paul718e3742002-12-13 20:15:29 +00003028
3029/* Sweep all RIB tables. */
3030void
paula1ac18c2005-06-28 17:17:12 +00003031rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003032{
Feng Lu0d0686f2015-05-22 11:40:02 +02003033 vrf_iter_t iter;
3034 struct zebra_vrf *zvrf;
3035
3036 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3037 if ((zvrf = vrf_iter2info (iter)) != NULL)
3038 {
3039 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3040 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3041 }
paul718e3742002-12-13 20:15:29 +00003042}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003043
3044/* Remove specific by protocol routes from 'table'. */
3045static unsigned long
3046rib_score_proto_table (u_char proto, struct route_table *table)
3047{
3048 struct route_node *rn;
3049 struct rib *rib;
3050 struct rib *next;
3051 unsigned long n = 0;
3052
3053 if (table)
3054 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003055 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003056 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003057 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3058 continue;
3059 if (rib->type == proto)
3060 {
3061 rib_delnode (rn, rib);
3062 n++;
3063 }
3064 }
3065
3066 return n;
3067}
3068
3069/* Remove specific by protocol routes. */
3070unsigned long
3071rib_score_proto (u_char proto)
3072{
Feng Lu0d0686f2015-05-22 11:40:02 +02003073 vrf_iter_t iter;
3074 struct zebra_vrf *zvrf;
3075 unsigned long cnt = 0;
3076
3077 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3078 if ((zvrf = vrf_iter2info (iter)) != NULL)
3079 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3080 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3081
3082 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003083}
3084
paul718e3742002-12-13 20:15:29 +00003085/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003086void
paul718e3742002-12-13 20:15:29 +00003087rib_close_table (struct route_table *table)
3088{
3089 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003090 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003091 struct rib *rib;
3092
3093 if (table)
3094 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003095 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003096 {
Timo Teräs325823a2016-01-15 17:36:31 +02003097 if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003098 continue;
3099
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003100 if (info->safi == SAFI_UNICAST)
3101 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003102
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003103 if (! RIB_SYSTEM_ROUTE (rib))
Timo Teräs0abf6792016-01-15 17:36:29 +02003104 rib_update_kernel (rn, rib, NULL);
Paul Jakma6d691122006-07-27 21:49:00 +00003105 }
paul718e3742002-12-13 20:15:29 +00003106}
3107
3108/* Close all RIB tables. */
3109void
paula1ac18c2005-06-28 17:17:12 +00003110rib_close (void)
paul718e3742002-12-13 20:15:29 +00003111{
Feng Lu0d0686f2015-05-22 11:40:02 +02003112 vrf_iter_t iter;
3113 struct zebra_vrf *zvrf;
3114
3115 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3116 if ((zvrf = vrf_iter2info (iter)) != NULL)
3117 {
3118 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3119 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3120 }
paul718e3742002-12-13 20:15:29 +00003121}
David Lamparter6b0655a2014-06-04 06:53:35 +02003122
paul718e3742002-12-13 20:15:29 +00003123/* Routing information base initialize. */
3124void
paula1ac18c2005-06-28 17:17:12 +00003125rib_init (void)
paul718e3742002-12-13 20:15:29 +00003126{
paul4d38fdb2005-04-28 17:35:14 +00003127 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003128}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003129
3130/*
3131 * vrf_id_get_next
3132 *
3133 * Get the first vrf id that is greater than the given vrf id if any.
3134 *
3135 * Returns TRUE if a vrf id was found, FALSE otherwise.
3136 */
3137static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003138vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003139{
Feng Lu41f44a22015-05-22 11:39:56 +02003140 vrf_iter_t iter = vrf_iterator (vrf_id);
3141 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3142
3143 /* The same one ? Then find out the next. */
3144 if (zvrf && (zvrf->vrf_id == vrf_id))
3145 zvrf = vrf_iter2info (vrf_next (iter));
3146
3147 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003148 {
Feng Lu41f44a22015-05-22 11:39:56 +02003149 *next_id_p = zvrf->vrf_id;
3150 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003151 }
3152
3153 return 0;
3154}
3155
3156/*
3157 * rib_tables_iter_next
3158 *
3159 * Returns the next table in the iteration.
3160 */
3161struct route_table *
3162rib_tables_iter_next (rib_tables_iter_t *iter)
3163{
3164 struct route_table *table;
3165
3166 /*
3167 * Array that helps us go over all AFI/SAFI combinations via one
3168 * index.
3169 */
3170 static struct {
3171 afi_t afi;
3172 safi_t safi;
3173 } afi_safis[] = {
3174 { AFI_IP, SAFI_UNICAST },
3175 { AFI_IP, SAFI_MULTICAST },
3176 { AFI_IP6, SAFI_UNICAST },
3177 { AFI_IP6, SAFI_MULTICAST },
3178 };
3179
3180 table = NULL;
3181
3182 switch (iter->state)
3183 {
3184
3185 case RIB_TABLES_ITER_S_INIT:
Donald Sharp0d271292015-11-19 07:21:30 -05003186 iter->vrf_id = VRF_DEFAULT;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003187 iter->afi_safi_ix = -1;
3188
3189 /* Fall through */
3190
3191 case RIB_TABLES_ITER_S_ITERATING:
3192 iter->afi_safi_ix++;
3193 while (1)
3194 {
3195
3196 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3197 {
Feng Lu41f44a22015-05-22 11:39:56 +02003198 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003199 afi_safis[iter->afi_safi_ix].safi,
3200 iter->vrf_id);
3201 if (table)
3202 break;
3203
3204 iter->afi_safi_ix++;
3205 }
3206
3207 /*
3208 * Found another table in this vrf.
3209 */
3210 if (table)
3211 break;
3212
3213 /*
3214 * Done with all tables in the current vrf, go to the next
3215 * one.
3216 */
3217 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3218 break;
3219
3220 iter->afi_safi_ix = 0;
3221 }
3222
3223 break;
3224
3225 case RIB_TABLES_ITER_S_DONE:
3226 return NULL;
3227 }
3228
3229 if (table)
3230 iter->state = RIB_TABLES_ITER_S_ITERATING;
3231 else
3232 iter->state = RIB_TABLES_ITER_S_DONE;
3233
3234 return table;
3235}
Feng Lu41f44a22015-05-22 11:39:56 +02003236
3237/*
3238 * Create a routing table for the specific AFI/SAFI in the given VRF.
3239 */
3240static void
3241zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3242{
3243 rib_table_info_t *info;
3244 struct route_table *table;
3245
3246 assert (!zvrf->table[afi][safi]);
3247
3248 table = route_table_init ();
3249 zvrf->table[afi][safi] = table;
3250
3251 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3252 info->zvrf = zvrf;
3253 info->afi = afi;
3254 info->safi = safi;
3255 table->info = info;
3256}
3257
3258/* Allocate new zebra VRF. */
3259struct zebra_vrf *
3260zebra_vrf_alloc (vrf_id_t vrf_id)
3261{
3262 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003263#ifdef HAVE_NETLINK
3264 char nl_name[64];
3265#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003266
3267 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3268
3269 /* Allocate routing table and static table. */
3270 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3271 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3272 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3273 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3274 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3275 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3276 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3277 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3278
3279 /* Set VRF ID */
3280 zvrf->vrf_id = vrf_id;
3281
Feng Lu758fb8f2014-07-03 18:23:09 +08003282#ifdef HAVE_NETLINK
3283 /* Initialize netlink sockets */
3284 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3285 zvrf->netlink.sock = -1;
3286 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3287
3288 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3289 zvrf->netlink_cmd.sock = -1;
3290 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3291#endif
3292
Feng Lu41f44a22015-05-22 11:39:56 +02003293 return zvrf;
3294}
3295
3296/* Lookup the routing table in an enabled VRF. */
3297struct route_table *
3298zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3299{
3300 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3301
3302 if (!zvrf)
3303 return NULL;
3304
3305 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3306 return NULL;
3307
3308 return zvrf->table[afi][safi];
3309}
3310
3311/* Lookup the static routing table in a VRF. */
3312struct route_table *
3313zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3314{
3315 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3316
3317 if (!zvrf)
3318 return NULL;
3319
3320 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3321 return NULL;
3322
3323 return zvrf->stable[afi][safi];
3324}
3325