blob: f206205b080bcfdd7274677b3930eeb754f55652 [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{
Timo Teräsbe6335d2015-05-23 11:08:41 +030083 char buf[PREFIX_STRLEN + 8];
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
Timo Teräsbe6335d2015-05-23 11:08:41 +030095 prefix2str(&rn->p, buf, sizeof(buf));
96 if (info->safi == SAFI_MULTICAST)
97 strcat(buf, " (MRIB)");
David Lamparter94813742014-04-24 20:22:53 +020098 }
99 else
100 {
101 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
102 }
103
104 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
105}
106
107#define rnode_debug(node, ...) \
108 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
109#define rnode_info(node, ...) \
110 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
111
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000112/*
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000113 * nexthop_type_to_str
114 */
115const char *
116nexthop_type_to_str (enum nexthop_types_t nh_type)
117{
118 static const char *desc[] = {
119 "none",
120 "Directly connected",
121 "Interface route",
122 "IPv4 nexthop",
123 "IPv4 nexthop with ifindex",
124 "IPv4 nexthop with ifname",
125 "IPv6 nexthop",
126 "IPv6 nexthop with ifindex",
127 "IPv6 nexthop with ifname",
128 "Null0 nexthop",
129 };
130
131 if (nh_type >= ZEBRA_NUM_OF (desc))
132 return "<Invalid nh type>";
133
134 return desc[nh_type];
135}
136
Christian Frankefa713d92013-07-05 15:35:37 +0000137/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000138static void
Christian Frankefa713d92013-07-05 15:35:37 +0000139_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000140{
141 struct nexthop *last;
142
Christian Frankefa713d92013-07-05 15:35:37 +0000143 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000144 ;
145 if (last)
146 last->next = nexthop;
147 else
Christian Frankefa713d92013-07-05 15:35:37 +0000148 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000149 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000150}
paul718e3742002-12-13 20:15:29 +0000151
Christian Frankefa713d92013-07-05 15:35:37 +0000152/* Add nexthop to the end of a rib node's nexthop list */
153static void
154nexthop_add (struct rib *rib, struct nexthop *nexthop)
155{
156 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000157 rib->nexthop_num++;
158}
159
160/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000161static void
paul718e3742002-12-13 20:15:29 +0000162nexthop_delete (struct rib *rib, struct nexthop *nexthop)
163{
164 if (nexthop->next)
165 nexthop->next->prev = nexthop->prev;
166 if (nexthop->prev)
167 nexthop->prev->next = nexthop->next;
168 else
169 rib->nexthop = nexthop->next;
170 rib->nexthop_num--;
171}
172
Christian Frankefa713d92013-07-05 15:35:37 +0000173static void nexthops_free(struct nexthop *nexthop);
174
paul718e3742002-12-13 20:15:29 +0000175/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000176static void
paul718e3742002-12-13 20:15:29 +0000177nexthop_free (struct nexthop *nexthop)
178{
paula4b70762003-05-16 17:19:48 +0000179 if (nexthop->ifname)
180 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000181 if (nexthop->resolved)
182 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000183 XFREE (MTYPE_NEXTHOP, nexthop);
184}
185
Christian Frankefa713d92013-07-05 15:35:37 +0000186/* Frees a list of nexthops */
187static void
188nexthops_free (struct nexthop *nexthop)
189{
190 struct nexthop *nh, *next;
191
192 for (nh = nexthop; nh; nh = next)
193 {
194 next = nh->next;
195 nexthop_free (nh);
196 }
197}
198
paul718e3742002-12-13 20:15:29 +0000199struct nexthop *
200nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
201{
202 struct nexthop *nexthop;
203
Stephen Hemminger393deb92008-08-18 14:13:29 -0700204 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000205 nexthop->type = NEXTHOP_TYPE_IFINDEX;
206 nexthop->ifindex = ifindex;
207
208 nexthop_add (rib, nexthop);
209
210 return nexthop;
211}
212
213struct nexthop *
214nexthop_ifname_add (struct rib *rib, char *ifname)
215{
216 struct nexthop *nexthop;
217
Stephen Hemminger393deb92008-08-18 14:13:29 -0700218 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000219 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000220 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000221
222 nexthop_add (rib, nexthop);
223
224 return nexthop;
225}
226
227struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000228nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000229{
230 struct nexthop *nexthop;
231
Stephen Hemminger393deb92008-08-18 14:13:29 -0700232 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000233 nexthop->type = NEXTHOP_TYPE_IPV4;
234 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000235 if (src)
236 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000237
238 nexthop_add (rib, nexthop);
239
240 return nexthop;
241}
242
Josh Bailey26e2ae32012-03-22 01:09:21 -0700243struct nexthop *
paul718e3742002-12-13 20:15:29 +0000244nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000245 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000246{
247 struct nexthop *nexthop;
248
Stephen Hemminger393deb92008-08-18 14:13:29 -0700249 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000250 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
251 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000252 if (src)
253 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000254 nexthop->ifindex = ifindex;
255
256 nexthop_add (rib, nexthop);
257
258 return nexthop;
259}
260
261#ifdef HAVE_IPV6
262struct 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}
307#endif /* HAVE_IPV6 */
308
paul595db7f2003-05-25 21:35:06 +0000309struct nexthop *
310nexthop_blackhole_add (struct rib *rib)
311{
312 struct nexthop *nexthop;
313
Stephen Hemminger393deb92008-08-18 14:13:29 -0700314 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000315 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
316 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
317
318 nexthop_add (rib, nexthop);
319
320 return nexthop;
321}
322
Christian Frankefa713d92013-07-05 15:35:37 +0000323/* This method checks whether a recursive nexthop has at
324 * least one resolved nexthop in the fib.
325 */
326int
327nexthop_has_fib_child(struct nexthop *nexthop)
328{
329 struct nexthop *nh;
330
331 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
332 return 0;
333
334 for (nh = nexthop->resolved; nh; nh = nh->next)
335 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
336 return 1;
337
338 return 0;
339}
340
paul718e3742002-12-13 20:15:29 +0000341/* If force flag is not set, do not modify falgs at all for uninstall
342 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000343static int
paul718e3742002-12-13 20:15:29 +0000344nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
345 struct route_node *top)
346{
347 struct prefix_ipv4 p;
348 struct route_table *table;
349 struct route_node *rn;
350 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000351 int resolved;
paul718e3742002-12-13 20:15:29 +0000352 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000353 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000354
355 if (nexthop->type == NEXTHOP_TYPE_IPV4)
356 nexthop->ifindex = 0;
357
358 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000359 {
360 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
361 nexthops_free(nexthop->resolved);
362 nexthop->resolved = NULL;
363 }
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 Lu41f44a22015-05-22 11:39:56 +0200372 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000373 if (! table)
374 return 0;
375
376 rn = route_node_match (table, (struct prefix *) &p);
377 while (rn)
378 {
379 route_unlock_node (rn);
380
David Warda50c1072009-12-03 15:34:39 +0300381 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000382 if (rn == top)
383 return 0;
384
385 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000386 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100387 {
388 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
389 continue;
390 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
391 break;
392 }
paul718e3742002-12-13 20:15:29 +0000393
394 /* If there is no selected route or matched route is EGP, go up
395 tree. */
396 if (! match
397 || match->type == ZEBRA_ROUTE_BGP)
398 {
399 do {
400 rn = rn->parent;
401 } while (rn && rn->info == NULL);
402 if (rn)
403 route_lock_node (rn);
404 }
405 else
406 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000407 /* If the longest prefix match for the nexthop yields
408 * a blackhole, mark it as inactive. */
409 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
410 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
411 return 0;
412
paul718e3742002-12-13 20:15:29 +0000413 if (match->type == ZEBRA_ROUTE_CONNECT)
414 {
415 /* Directly point connected route. */
416 newhop = match->nexthop;
417 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
418 nexthop->ifindex = newhop->ifindex;
419
420 return 1;
421 }
422 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
423 {
Christian Frankefa713d92013-07-05 15:35:37 +0000424 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000425 for (newhop = match->nexthop; newhop; newhop = newhop->next)
426 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
427 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
428 {
429 if (set)
430 {
431 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000432
433 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
434 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000435 /* If the resolving route specifies a gateway, use it */
436 if (newhop->type == NEXTHOP_TYPE_IPV4
437 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
438 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
439 {
440 resolved_hop->type = newhop->type;
441 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000442
Christian Frankec3e6b592013-07-05 15:35:40 +0000443 if (newhop->ifindex)
444 {
445 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
446 resolved_hop->ifindex = newhop->ifindex;
447 }
448 }
Christian Frankefa713d92013-07-05 15:35:37 +0000449
Christian Frankec3e6b592013-07-05 15:35:40 +0000450 /* If the resolving route is an interface route,
451 * it means the gateway we are looking up is connected
452 * to that interface. (The actual network is _not_ onlink).
453 * Therefore, the resolved route should have the original
454 * gateway as nexthop as it is directly connected.
455 *
456 * On Linux, we have to set the onlink netlink flag because
457 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000458 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000459 || newhop->type == NEXTHOP_TYPE_IFNAME)
460 {
461 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
462 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
463 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
464 resolved_hop->ifindex = newhop->ifindex;
465 }
Christian Frankefa713d92013-07-05 15:35:37 +0000466
467 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000468 }
Christian Frankefa713d92013-07-05 15:35:37 +0000469 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000470 }
Christian Frankefa713d92013-07-05 15:35:37 +0000471 return resolved;
paul718e3742002-12-13 20:15:29 +0000472 }
473 else
474 {
475 return 0;
476 }
477 }
478 }
479 return 0;
480}
481
482#ifdef HAVE_IPV6
483/* If force flag is not set, do not modify falgs at all for uninstall
484 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000485static int
paul718e3742002-12-13 20:15:29 +0000486nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
487 struct route_node *top)
488{
489 struct prefix_ipv6 p;
490 struct route_table *table;
491 struct route_node *rn;
492 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000493 int resolved;
paul718e3742002-12-13 20:15:29 +0000494 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000495 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000496
497 if (nexthop->type == NEXTHOP_TYPE_IPV6)
498 nexthop->ifindex = 0;
499
500 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000501 {
502 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
503 nexthops_free(nexthop->resolved);
504 nexthop->resolved = NULL;
505 }
paul718e3742002-12-13 20:15:29 +0000506
507 /* Make lookup prefix. */
508 memset (&p, 0, sizeof (struct prefix_ipv6));
509 p.family = AF_INET6;
510 p.prefixlen = IPV6_MAX_PREFIXLEN;
511 p.prefix = nexthop->gate.ipv6;
512
513 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +0200514 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000515 if (! table)
516 return 0;
517
518 rn = route_node_match (table, (struct prefix *) &p);
519 while (rn)
520 {
521 route_unlock_node (rn);
522
David Warda50c1072009-12-03 15:34:39 +0300523 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000524 if (rn == top)
525 return 0;
526
527 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000528 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100529 {
530 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
531 continue;
532 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
533 break;
534 }
paul718e3742002-12-13 20:15:29 +0000535
536 /* If there is no selected route or matched route is EGP, go up
537 tree. */
538 if (! match
539 || match->type == ZEBRA_ROUTE_BGP)
540 {
541 do {
542 rn = rn->parent;
543 } while (rn && rn->info == NULL);
544 if (rn)
545 route_lock_node (rn);
546 }
547 else
548 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000549 /* If the longest prefix match for the nexthop yields
550 * a blackhole, mark it as inactive. */
551 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
552 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
553 return 0;
554
paul718e3742002-12-13 20:15:29 +0000555 if (match->type == ZEBRA_ROUTE_CONNECT)
556 {
557 /* Directly point connected route. */
558 newhop = match->nexthop;
559
560 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
561 nexthop->ifindex = newhop->ifindex;
562
563 return 1;
564 }
565 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
566 {
Christian Frankefa713d92013-07-05 15:35:37 +0000567 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000568 for (newhop = match->nexthop; newhop; newhop = newhop->next)
569 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
570 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
571 {
572 if (set)
573 {
574 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000575
576 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
577 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000578 /* See nexthop_active_ipv4 for a description how the
579 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000580 if (newhop->type == NEXTHOP_TYPE_IPV6
581 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
582 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000583 {
584 resolved_hop->type = newhop->type;
585 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
586
587 if (newhop->ifindex)
588 {
589 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
590 resolved_hop->ifindex = newhop->ifindex;
591 }
592 }
Christian Frankefa713d92013-07-05 15:35:37 +0000593
paul718e3742002-12-13 20:15:29 +0000594 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000595 || newhop->type == NEXTHOP_TYPE_IFNAME)
596 {
597 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
598 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
599 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
600 resolved_hop->ifindex = newhop->ifindex;
601 }
Christian Frankefa713d92013-07-05 15:35:37 +0000602
603 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000604 }
Christian Frankefa713d92013-07-05 15:35:37 +0000605 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000606 }
Christian Frankefa713d92013-07-05 15:35:37 +0000607 return resolved;
paul718e3742002-12-13 20:15:29 +0000608 }
609 else
610 {
611 return 0;
612 }
613 }
614 }
615 return 0;
616}
617#endif /* HAVE_IPV6 */
618
619struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100620rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
621 struct route_node **rn_out)
Everton Marques3dea1782014-09-22 19:35:51 -0300622{
623 struct route_table *table;
624 struct route_node *rn;
625 struct rib *match;
626 struct nexthop *newhop, *tnewhop;
627 int recursing;
628
629 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +0200630 table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
Everton Marques3dea1782014-09-22 19:35:51 -0300631 if (! table)
632 return 0;
633
634 rn = route_node_match_ipv4 (table, &addr);
635
636 while (rn)
637 {
638 route_unlock_node (rn);
639
640 /* Pick up selected route. */
641 RNODE_FOREACH_RIB (rn, match)
642 {
643 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
644 continue;
645 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
646 break;
647 }
648
649 /* If there is no selected route or matched route is EGP, go up
650 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300651 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300652 {
653 do {
654 rn = rn->parent;
655 } while (rn && rn->info == NULL);
656 if (rn)
657 route_lock_node (rn);
658 }
659 else
660 {
David Lamparter24480d42015-01-22 19:09:36 +0100661 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300662 {
David Lamparter24480d42015-01-22 19:09:36 +0100663 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300664 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
665 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100666 {
667 found = 1;
668 break;
669 }
670 if (!found)
671 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300672 }
David Lamparter24480d42015-01-22 19:09:36 +0100673
674 if (rn_out)
675 *rn_out = rn;
676 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300677 }
678 }
679 return NULL;
680}
681
682struct rib *
David Lamparterbd078122015-01-06 19:53:24 +0100683rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
684{
685 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
686 struct route_node *m_rn = NULL, *u_rn = NULL;
687 int skip_bgp = 0; /* bool */
688
689 switch (ipv4_multicast_mode)
690 {
691 case MCAST_MRIB_ONLY:
692 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
693 case MCAST_URIB_ONLY:
694 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
695 case MCAST_NO_CONFIG:
696 case MCAST_MIX_MRIB_FIRST:
697 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
698 if (!mrib)
699 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
700 break;
701 case MCAST_MIX_DISTANCE:
702 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
703 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
704 if (mrib && urib)
705 rib = urib->distance < mrib->distance ? urib : mrib;
706 else if (mrib)
707 rib = mrib;
708 else if (urib)
709 rib = urib;
710 break;
711 case MCAST_MIX_PFXLEN:
712 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
713 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
714 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
731 zlog_debug("%s: %s: found %s, using %s",
732 __func__, buf,
733 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 *
paul718e3742002-12-13 20:15:29 +0000755rib_lookup_ipv4 (struct prefix_ipv4 *p)
756{
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 Lu41f44a22015-05-22 11:39:56 +0200764 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000765 if (! table)
766 return 0;
767
768 rn = route_node_lookup (table, (struct prefix *) p);
769
770 /* No route for this prefix. */
771 if (! rn)
772 return NULL;
773
774 /* Unlock node. */
775 route_unlock_node (rn);
776
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000777 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100778 {
779 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
780 continue;
781 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
782 break;
783 }
paul718e3742002-12-13 20:15:29 +0000784
785 if (! match || match->type == ZEBRA_ROUTE_BGP)
786 return NULL;
787
788 if (match->type == ZEBRA_ROUTE_CONNECT)
789 return match;
790
Christian Frankefa713d92013-07-05 15:35:37 +0000791 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000792 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
793 return match;
794
795 return NULL;
796}
797
Denis Ovsienkodc958242007-08-13 16:03:06 +0000798/*
799 * This clone function, unlike its original rib_lookup_ipv4(), checks
800 * if specified IPv4 route record (prefix/mask -> gate) exists in
801 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
802 *
803 * Return values:
804 * -1: error
805 * 0: exact match found
806 * 1: a match was found with a different gate
807 * 2: connected route found
808 * 3: no matches found
809 */
810int
811rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
812{
813 struct route_table *table;
814 struct route_node *rn;
815 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000816 struct nexthop *nexthop, *tnexthop;
817 int recursing;
818 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000819
820 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +0200821 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000822 if (! table)
823 return ZEBRA_RIB_LOOKUP_ERROR;
824
825 /* Scan the RIB table for exactly matching RIB entry. */
826 rn = route_node_lookup (table, (struct prefix *) p);
827
828 /* No route for this prefix. */
829 if (! rn)
830 return ZEBRA_RIB_NOTFOUND;
831
832 /* Unlock node. */
833 route_unlock_node (rn);
834
835 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000836 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100837 {
838 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
839 continue;
840 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
841 break;
842 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000843
844 /* None such found :( */
845 if (!match)
846 return ZEBRA_RIB_NOTFOUND;
847
848 if (match->type == ZEBRA_ROUTE_CONNECT)
849 return ZEBRA_RIB_FOUND_CONNECTED;
850
851 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000852 nexthops_active = 0;
853 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000854 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000855 {
Christian Frankefa713d92013-07-05 15:35:37 +0000856 nexthops_active = 1;
857 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
858 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000859 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000860 {
861 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
862 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
863 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
864 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
865 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
866 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000867 }
Christian Frankefa713d92013-07-05 15:35:37 +0000868
869 if (nexthops_active)
870 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000871
872 return ZEBRA_RIB_NOTFOUND;
873}
874
paul718e3742002-12-13 20:15:29 +0000875#ifdef HAVE_IPV6
876struct rib *
877rib_match_ipv6 (struct in6_addr *addr)
878{
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 Lu41f44a22015-05-22 11:39:56 +0200887 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000888 if (! table)
889 return 0;
890
891 memset (&p, 0, sizeof (struct prefix_ipv6));
892 p.family = AF_INET6;
893 p.prefixlen = IPV6_MAX_PREFIXLEN;
894 IPV6_ADDR_COPY (&p.prefix, addr);
895
896 rn = route_node_match (table, (struct prefix *) &p);
897
898 while (rn)
899 {
900 route_unlock_node (rn);
901
902 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000903 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100904 {
905 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
906 continue;
907 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
908 break;
909 }
paul718e3742002-12-13 20:15:29 +0000910
911 /* If there is no selected route or matched route is EGP, go up
912 tree. */
913 if (! match
914 || match->type == ZEBRA_ROUTE_BGP)
915 {
916 do {
917 rn = rn->parent;
918 } while (rn && rn->info == NULL);
919 if (rn)
920 route_lock_node (rn);
921 }
922 else
923 {
924 if (match->type == ZEBRA_ROUTE_CONNECT)
925 /* Directly point connected route. */
926 return match;
927 else
928 {
Christian Frankefa713d92013-07-05 15:35:37 +0000929 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000930 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
931 return match;
932 return NULL;
933 }
934 }
935 }
936 return NULL;
937}
938#endif /* HAVE_IPV6 */
939
Paul Jakma7514fb72007-05-02 16:05:35 +0000940#define RIB_SYSTEM_ROUTE(R) \
941 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
942
Denis Ovsienkodc958242007-08-13 16:03:06 +0000943/* This function verifies reachability of one given nexthop, which can be
944 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
945 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
946 * nexthop->ifindex will be updated appropriately as well.
947 * An existing route map can turn (otherwise active) nexthop into inactive, but
948 * not vice versa.
949 *
950 * The return value is the final value of 'ACTIVE' flag.
951 */
952
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300953static unsigned
paul718e3742002-12-13 20:15:29 +0000954nexthop_active_check (struct route_node *rn, struct rib *rib,
955 struct nexthop *nexthop, int set)
956{
Christian Frankef3a17322013-07-05 15:35:41 +0000957 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +0000958 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000959 route_map_result_t ret = RMAP_MATCH;
960 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
961 struct route_map *rmap;
962 int family;
paul718e3742002-12-13 20:15:29 +0000963
Paul Jakma7514fb72007-05-02 16:05:35 +0000964 family = 0;
paul718e3742002-12-13 20:15:29 +0000965 switch (nexthop->type)
966 {
967 case NEXTHOP_TYPE_IFINDEX:
968 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000969 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000970 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
971 else
972 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
973 break;
paul718e3742002-12-13 20:15:29 +0000974 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000975 family = AFI_IP6;
976 case NEXTHOP_TYPE_IFNAME:
paul718e3742002-12-13 20:15:29 +0000977 ifp = if_lookup_by_name (nexthop->ifname);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000978 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000979 {
980 if (set)
981 nexthop->ifindex = ifp->ifindex;
982 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
983 }
984 else
985 {
986 if (set)
987 nexthop->ifindex = 0;
988 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
989 }
990 break;
991 case NEXTHOP_TYPE_IPV4:
992 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +0000993 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +0000994 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
995 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
996 else
997 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
998 break;
999#ifdef HAVE_IPV6
1000 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001001 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001002 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1003 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1004 else
1005 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1006 break;
1007 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001008 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001009 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1010 {
1011 ifp = if_lookup_by_index (nexthop->ifindex);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001012 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001013 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1014 else
1015 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1016 }
1017 else
1018 {
1019 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1020 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1021 else
1022 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1023 }
1024 break;
1025#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +00001026 case NEXTHOP_TYPE_BLACKHOLE:
1027 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1028 break;
paul718e3742002-12-13 20:15:29 +00001029 default:
1030 break;
1031 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001032 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1033 return 0;
1034
Christian Frankef3a17322013-07-05 15:35:41 +00001035 /* XXX: What exactly do those checks do? Do we support
1036 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001037 if (RIB_SYSTEM_ROUTE(rib) ||
1038 (family == AFI_IP && rn->p.family != AF_INET) ||
1039 (family == AFI_IP6 && rn->p.family != AF_INET6))
1040 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1041
Christian Frankef3a17322013-07-05 15:35:41 +00001042 /* The original code didn't determine the family correctly
1043 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1044 * from the rib_table_info in those cases.
1045 * Possibly it may be better to use only the rib_table_info
1046 * in every case.
1047 */
1048 if (!family)
1049 family = info->afi;
1050
Paul Jakma7514fb72007-05-02 16:05:35 +00001051 rmap = 0;
1052 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1053 proto_rm[family][rib->type])
1054 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1055 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1056 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1057 if (rmap) {
1058 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
1059 }
1060
1061 if (ret == RMAP_DENYMATCH)
1062 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001063 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1064}
1065
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001066/* Iterate over all nexthops of the given RIB entry and refresh their
1067 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1068 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1069 * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
1070 * transparently passed to nexthop_active_check().
1071 *
1072 * Return value is the new number of active nexthops.
1073 */
1074
paula1ac18c2005-06-28 17:17:12 +00001075static int
paul718e3742002-12-13 20:15:29 +00001076nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1077{
1078 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001079 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001080
1081 rib->nexthop_active_num = 0;
1082 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1083
1084 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001085 {
1086 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001087 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001088 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1089 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001090 if (prev_active != new_active ||
1091 prev_index != nexthop->ifindex)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001092 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
1093 }
paul718e3742002-12-13 20:15:29 +00001094 return rib->nexthop_active_num;
1095}
paul6baeb982003-10-28 03:47:15 +00001096
David Lamparter6b0655a2014-06-04 06:53:35 +02001097
paul718e3742002-12-13 20:15:29 +00001098
paula1ac18c2005-06-28 17:17:12 +00001099static void
paul718e3742002-12-13 20:15:29 +00001100rib_install_kernel (struct route_node *rn, struct rib *rib)
1101{
1102 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001103 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001104 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001105 int recursing;
paul718e3742002-12-13 20:15:29 +00001106
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001107 if (info->safi != SAFI_UNICAST)
1108 {
1109 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1110 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1111 return;
1112 }
1113
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001114 /*
1115 * Make sure we update the FPM any time we send new information to
1116 * the kernel.
1117 */
1118 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001119 switch (PREFIX_FAMILY (&rn->p))
1120 {
1121 case AF_INET:
1122 ret = kernel_add_ipv4 (&rn->p, rib);
1123 break;
1124#ifdef HAVE_IPV6
1125 case AF_INET6:
1126 ret = kernel_add_ipv6 (&rn->p, rib);
1127 break;
1128#endif /* HAVE_IPV6 */
1129 }
1130
Denis Ovsienkodc958242007-08-13 16:03:06 +00001131 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001132 if (ret < 0)
1133 {
Christian Frankefa713d92013-07-05 15:35:37 +00001134 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001135 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1136 }
1137}
1138
1139/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001140static int
paul718e3742002-12-13 20:15:29 +00001141rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1142{
1143 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001144 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001145 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001146 int recursing;
paul718e3742002-12-13 20:15:29 +00001147
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001148 if (info->safi != SAFI_UNICAST)
1149 {
1150 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1151 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1152 return ret;
1153 }
1154
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001155 /*
1156 * Make sure we update the FPM any time we send new information to
1157 * the kernel.
1158 */
1159 zfpm_trigger_update (rn, "uninstalling from kernel");
1160
paul718e3742002-12-13 20:15:29 +00001161 switch (PREFIX_FAMILY (&rn->p))
1162 {
1163 case AF_INET:
1164 ret = kernel_delete_ipv4 (&rn->p, rib);
1165 break;
1166#ifdef HAVE_IPV6
1167 case AF_INET6:
1168 ret = kernel_delete_ipv6 (&rn->p, rib);
1169 break;
1170#endif /* HAVE_IPV6 */
1171 }
1172
Christian Frankefa713d92013-07-05 15:35:37 +00001173 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001174 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1175
1176 return ret;
1177}
1178
1179/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001180static void
paul718e3742002-12-13 20:15:29 +00001181rib_uninstall (struct route_node *rn, struct rib *rib)
1182{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001183 rib_table_info_t *info = rn->table->info;
1184
paul718e3742002-12-13 20:15:29 +00001185 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1186 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001187 if (info->safi == SAFI_UNICAST)
1188 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001189
paul718e3742002-12-13 20:15:29 +00001190 redistribute_delete (&rn->p, rib);
1191 if (! RIB_SYSTEM_ROUTE (rib))
1192 rib_uninstall_kernel (rn, rib);
1193 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1194 }
1195}
1196
Paul Jakma6d691122006-07-27 21:49:00 +00001197static void rib_unlink (struct route_node *, struct rib *);
1198
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001199/*
1200 * rib_can_delete_dest
1201 *
1202 * Returns TRUE if the given dest can be deleted from the table.
1203 */
1204static int
1205rib_can_delete_dest (rib_dest_t *dest)
1206{
1207 if (dest->routes)
1208 {
1209 return 0;
1210 }
1211
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001212 /*
1213 * Don't delete the dest if we have to update the FPM about this
1214 * prefix.
1215 */
1216 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1217 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1218 return 0;
1219
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001220 return 1;
1221}
1222
1223/*
1224 * rib_gc_dest
1225 *
1226 * Garbage collect the rib dest corresponding to the given route node
1227 * if appropriate.
1228 *
1229 * Returns TRUE if the dest was deleted, FALSE otherwise.
1230 */
1231int
1232rib_gc_dest (struct route_node *rn)
1233{
1234 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001235
1236 dest = rib_dest_from_rnode (rn);
1237 if (!dest)
1238 return 0;
1239
1240 if (!rib_can_delete_dest (dest))
1241 return 0;
1242
1243 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001244 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001245
1246 dest->rnode = NULL;
1247 XFREE (MTYPE_RIB_DEST, dest);
1248 rn->info = NULL;
1249
1250 /*
1251 * Release the one reference that we keep on the route node.
1252 */
1253 route_unlock_node (rn);
1254 return 1;
1255}
1256
paul718e3742002-12-13 20:15:29 +00001257/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001258static void
1259rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001260{
1261 struct rib *rib;
1262 struct rib *next;
1263 struct rib *fib = NULL;
1264 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001265 struct rib *del = 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
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001275 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
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 {
1280 assert (fib == NULL);
1281 fib = rib;
1282 }
1283
1284 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1285 * which we need to do do further work with below.
1286 */
1287 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1288 {
1289 if (rib != fib)
1290 {
1291 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001292 rnode_debug (rn, "rn %p, removing rib %p",
1293 (void *)rn, (void *)rib);
1294 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001295 }
1296 else
1297 del = rib;
1298
1299 continue;
1300 }
paul4d38fdb2005-04-28 17:35:14 +00001301
paul718e3742002-12-13 20:15:29 +00001302 /* Skip unreachable nexthop. */
1303 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001304 continue;
paul718e3742002-12-13 20:15:29 +00001305
1306 /* Infinit distance. */
1307 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001308 continue;
paul718e3742002-12-13 20:15:29 +00001309
paulaf887b52006-01-18 14:52:52 +00001310 /* Newly selected rib, the common case. */
1311 if (!select)
1312 {
1313 select = rib;
1314 continue;
1315 }
1316
1317 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001318 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001319 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001320 * - lower metric beats higher for equal distance
1321 * - last, hence oldest, route wins tie break.
1322 */
paula1038a12006-01-30 14:08:51 +00001323
1324 /* Connected routes. Pick the last connected
1325 * route of the set of lowest metric connected routes.
1326 */
paula8d9c1f2006-01-25 06:31:04 +00001327 if (rib->type == ZEBRA_ROUTE_CONNECT)
1328 {
paula1038a12006-01-30 14:08:51 +00001329 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001330 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001331 select = rib;
1332 continue;
paula8d9c1f2006-01-25 06:31:04 +00001333 }
1334 else if (select->type == ZEBRA_ROUTE_CONNECT)
1335 continue;
1336
1337 /* higher distance loses */
1338 if (rib->distance > select->distance)
1339 continue;
1340
1341 /* lower wins */
1342 if (rib->distance < select->distance)
1343 {
paulaf887b52006-01-18 14:52:52 +00001344 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001345 continue;
1346 }
1347
1348 /* metric tie-breaks equal distance */
1349 if (rib->metric <= select->metric)
1350 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001351 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001352
1353 /* After the cycle is finished, the following pointers will be set:
1354 * select --- the winner RIB entry, if any was found, otherwise NULL
1355 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1356 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1357 * rib --- NULL
1358 */
1359
1360 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001361 if (select && select == fib)
1362 {
Paul Jakma6d691122006-07-27 21:49:00 +00001363 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001364 rnode_debug (rn, "Updating existing route, select %p, fib %p",
David Lampartereed3c482015-03-03 08:51:53 +01001365 (void *)select, (void *)fib);
paul718e3742002-12-13 20:15:29 +00001366 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001367 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001368 if (info->safi == SAFI_UNICAST)
1369 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001370
paul4d38fdb2005-04-28 17:35:14 +00001371 redistribute_delete (&rn->p, select);
1372 if (! RIB_SYSTEM_ROUTE (select))
1373 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001374
paul4d38fdb2005-04-28 17:35:14 +00001375 /* Set real nexthop. */
1376 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001377
paul4d38fdb2005-04-28 17:35:14 +00001378 if (! RIB_SYSTEM_ROUTE (select))
1379 rib_install_kernel (rn, select);
1380 redistribute_add (&rn->p, select);
1381 }
pauld753e9e2003-01-22 19:45:50 +00001382 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001383 {
1384 /* Housekeeping code to deal with
1385 race conditions in kernel with linux
1386 netlink reporting interface up before IPv4 or IPv6 protocol
1387 is ready to add routes.
1388 This makes sure the routes are IN the kernel.
1389 */
pauld753e9e2003-01-22 19:45:50 +00001390
Christian Frankefa713d92013-07-05 15:35:37 +00001391 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001392 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001393 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001394 installed = 1;
1395 break;
paul4d38fdb2005-04-28 17:35:14 +00001396 }
1397 if (! installed)
1398 rib_install_kernel (rn, select);
1399 }
Paul Jakma6d691122006-07-27 21:49:00 +00001400 goto end;
paul718e3742002-12-13 20:15:29 +00001401 }
1402
Denis Ovsienkodc958242007-08-13 16:03:06 +00001403 /* At this point we either haven't found the best RIB entry or it is
1404 * different from what we currently intend to flag with SELECTED. In both
1405 * cases, if a RIB block is present in FIB, it should be withdrawn.
1406 */
paul718e3742002-12-13 20:15:29 +00001407 if (fib)
1408 {
Paul Jakma6d691122006-07-27 21:49:00 +00001409 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001410 rnode_debug (rn, "Removing existing route, fib %p", (void *)fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001411
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001412 if (info->safi == SAFI_UNICAST)
1413 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001414
paul718e3742002-12-13 20:15:29 +00001415 redistribute_delete (&rn->p, fib);
1416 if (! RIB_SYSTEM_ROUTE (fib))
1417 rib_uninstall_kernel (rn, fib);
1418 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1419
1420 /* Set real nexthop. */
1421 nexthop_active_update (rn, fib, 1);
1422 }
1423
Denis Ovsienkodc958242007-08-13 16:03:06 +00001424 /* Regardless of some RIB entry being SELECTED or not before, now we can
1425 * tell, that if a new winner exists, FIB is still not updated with this
1426 * data, but ready to be.
1427 */
paul718e3742002-12-13 20:15:29 +00001428 if (select)
1429 {
Paul Jakma6d691122006-07-27 21:49:00 +00001430 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001431 rnode_debug (rn, "Adding route, select %p", (void *)select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001432
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001433 if (info->safi == SAFI_UNICAST)
1434 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001435
paul718e3742002-12-13 20:15:29 +00001436 /* Set real nexthop. */
1437 nexthop_active_update (rn, select, 1);
1438
1439 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001440 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001441 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1442 redistribute_add (&rn->p, select);
1443 }
paul4d38fdb2005-04-28 17:35:14 +00001444
Paul Jakma6d691122006-07-27 21:49:00 +00001445 /* FIB route was removed, should be deleted */
1446 if (del)
1447 {
1448 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001449 rnode_debug (rn, "Deleting fib %p, rn %p", (void *)del, (void *)rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001450 rib_unlink (rn, del);
1451 }
paul4d38fdb2005-04-28 17:35:14 +00001452
Paul Jakma6d691122006-07-27 21:49:00 +00001453end:
1454 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001455 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001456
1457 /*
1458 * Check if the dest can be deleted now.
1459 */
1460 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001461}
1462
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001463/* Take a list of route_node structs and return 1, if there was a record
1464 * picked from it and processed by rib_process(). Don't process more,
1465 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001466 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001467static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001468process_subq (struct list * subq, u_char qindex)
1469{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001470 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001471 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001472
1473 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001474 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001475
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001476 rnode = listgetdata (lnode);
1477 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001478
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001479 if (rnode->info)
1480 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1481
Chris Caputo67b94672009-07-18 04:02:26 +00001482#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001483 else
1484 {
1485 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1486 __func__, rnode, rnode->lock);
1487 zlog_backtrace(LOG_DEBUG);
1488 }
Chris Caputo67b94672009-07-18 04:02:26 +00001489#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001490 route_unlock_node (rnode);
1491 list_delete_node (subq, lnode);
1492 return 1;
1493}
1494
1495/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1496 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1497 * is pointed to the meta queue structure.
1498 */
1499static wq_item_status
1500meta_queue_process (struct work_queue *dummy, void *data)
1501{
1502 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001503 unsigned i;
1504
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001505 for (i = 0; i < MQ_SIZE; i++)
1506 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001507 {
1508 mq->size--;
1509 break;
1510 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001511 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1512}
1513
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001514/*
1515 * Map from rib types to queue type (priority) in meta queue
1516 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001517static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1518 [ZEBRA_ROUTE_SYSTEM] = 4,
1519 [ZEBRA_ROUTE_KERNEL] = 0,
1520 [ZEBRA_ROUTE_CONNECT] = 0,
1521 [ZEBRA_ROUTE_STATIC] = 1,
1522 [ZEBRA_ROUTE_RIP] = 2,
1523 [ZEBRA_ROUTE_RIPNG] = 2,
1524 [ZEBRA_ROUTE_OSPF] = 2,
1525 [ZEBRA_ROUTE_OSPF6] = 2,
1526 [ZEBRA_ROUTE_ISIS] = 2,
1527 [ZEBRA_ROUTE_BGP] = 3,
1528 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001529 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001530};
1531
1532/* Look into the RN and queue it into one or more priority queues,
1533 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001534 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001535static void
1536rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001537{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001538 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001539
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001540 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001541 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001542 u_char qindex = meta_queue_map[rib->type];
1543
1544 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001545 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1546 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001547 {
1548 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001549 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001550 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001551 continue;
1552 }
1553
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001554 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001555 listnode_add (mq->subq[qindex], rn);
1556 route_lock_node (rn);
1557 mq->size++;
1558
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001559 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001560 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001561 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001562 }
paul4d38fdb2005-04-28 17:35:14 +00001563}
1564
Paul Jakma6d691122006-07-27 21:49:00 +00001565/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001566static void
Paul Jakma6d691122006-07-27 21:49:00 +00001567rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001568{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001569 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001570
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001571 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001572 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001573 {
1574 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001575 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001576 zlog_backtrace(LOG_DEBUG);
1577 return;
1578 }
1579
1580 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001581 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001582
1583 assert (zebra);
1584
1585 if (zebra->ribq == NULL)
1586 {
1587 zlog_err ("%s: work_queue does not exist!", __func__);
1588 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001589 }
paul4d38fdb2005-04-28 17:35:14 +00001590
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001591 /*
1592 * The RIB queue should normally be either empty or holding the only
1593 * work_queue_item element. In the latter case this element would
1594 * hold a pointer to the meta queue structure, which must be used to
1595 * actually queue the route nodes to process. So create the MQ
1596 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001597 * This semantics was introduced after 0.99.9 release.
1598 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001599 if (!zebra->ribq->items->count)
1600 work_queue_add (zebra->ribq, zebra->mq);
1601
1602 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001603
1604 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001605 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001606
1607 return;
paul4d38fdb2005-04-28 17:35:14 +00001608}
1609
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001610/* Create new meta queue.
1611 A destructor function doesn't seem to be necessary here.
1612 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001613static struct meta_queue *
1614meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001615{
1616 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001617 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001618
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001619 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1620 assert(new);
1621
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001622 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001623 {
1624 new->subq[i] = list_new ();
1625 assert(new->subq[i]);
1626 }
1627
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001628 return new;
1629}
1630
paul4d38fdb2005-04-28 17:35:14 +00001631/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001632static void
paul4d38fdb2005-04-28 17:35:14 +00001633rib_queue_init (struct zebra_t *zebra)
1634{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001635 assert (zebra);
1636
paul4d38fdb2005-04-28 17:35:14 +00001637 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001638 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001639 {
Paul Jakma6d691122006-07-27 21:49:00 +00001640 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001641 return;
1642 }
1643
1644 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001645 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001646 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001647 /* XXX: TODO: These should be runtime configurable via vty */
1648 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001649 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001650
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001651 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001652 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001653 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001654 return;
1655 }
1656 return;
paul718e3742002-12-13 20:15:29 +00001657}
1658
Paul Jakma6d691122006-07-27 21:49:00 +00001659/* RIB updates are processed via a queue of pointers to route_nodes.
1660 *
1661 * The queue length is bounded by the maximal size of the routing table,
1662 * as a route_node will not be requeued, if already queued.
1663 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001664 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1665 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1666 * and then submit route_node to queue for best-path selection later.
1667 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001668 *
1669 * Deleted RIBs are reaped during best-path selection.
1670 *
1671 * rib_addnode
1672 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001673 * |-------->| | best RIB, if required
1674 * | |
1675 * static_install->|->rib_addqueue...... -> rib_process
1676 * | |
1677 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001678 * |-> set RIB_ENTRY_REMOVE |
1679 * rib_delnode (RIB freed)
1680 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001681 * The 'info' pointer of a route_node points to a rib_dest_t
1682 * ('dest'). Queueing state for a route_node is kept on the dest. The
1683 * dest is created on-demand by rib_link() and is kept around at least
1684 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001685 *
1686 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1687 *
1688 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001689 * - dest attached to route_node:
1690 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001691 * - route_node processing queue
1692 * - managed by: rib_addqueue, rib_process.
1693 *
1694 */
1695
paul718e3742002-12-13 20:15:29 +00001696/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001697static void
Paul Jakma6d691122006-07-27 21:49:00 +00001698rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001699{
1700 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001701 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001702
paul4d38fdb2005-04-28 17:35:14 +00001703 assert (rib && rn);
1704
Paul Jakma6d691122006-07-27 21:49:00 +00001705 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001706 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001707
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001708 dest = rib_dest_from_rnode (rn);
1709 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001710 {
1711 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001712 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001713
1714 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1715 route_lock_node (rn); /* rn route table reference */
1716 rn->info = dest;
1717 dest->rnode = rn;
1718 }
1719
1720 head = dest->routes;
1721 if (head)
1722 {
Paul Jakma6d691122006-07-27 21:49:00 +00001723 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001724 }
paul718e3742002-12-13 20:15:29 +00001725 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001726 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001727 rib_queue_add (&zebrad, rn);
1728}
1729
1730static void
1731rib_addnode (struct route_node *rn, struct rib *rib)
1732{
1733 /* RIB node has been un-removed before route-node is processed.
1734 * route_node must hence already be on the queue for processing..
1735 */
1736 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1737 {
1738 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001739 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001740
Paul Jakma6d691122006-07-27 21:49:00 +00001741 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1742 return;
1743 }
1744 rib_link (rn, rib);
1745}
1746
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001747/*
1748 * rib_unlink
1749 *
1750 * Detach a rib structure from a route_node.
1751 *
1752 * Note that a call to rib_unlink() should be followed by a call to
1753 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1754 * longer required to be deleted.
1755 */
Paul Jakma6d691122006-07-27 21:49:00 +00001756static void
1757rib_unlink (struct route_node *rn, struct rib *rib)
1758{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001759 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001760
1761 assert (rn && rib);
1762
1763 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001764 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001765
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001766 dest = rib_dest_from_rnode (rn);
1767
Paul Jakma6d691122006-07-27 21:49:00 +00001768 if (rib->next)
1769 rib->next->prev = rib->prev;
1770
1771 if (rib->prev)
1772 rib->prev->next = rib->next;
1773 else
1774 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001775 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001776 }
1777
1778 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001779 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001780 XFREE (MTYPE_RIB, rib);
1781
paul718e3742002-12-13 20:15:29 +00001782}
1783
paula1ac18c2005-06-28 17:17:12 +00001784static void
paul718e3742002-12-13 20:15:29 +00001785rib_delnode (struct route_node *rn, struct rib *rib)
1786{
Paul Jakma6d691122006-07-27 21:49:00 +00001787 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001788 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001789 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1790 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001791}
1792
1793int
1794rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001795 struct in_addr *gate, struct in_addr *src,
1796 unsigned int ifindex, u_int32_t vrf_id,
G.Balajicddf3912011-11-26 21:59:32 +04001797 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001798{
1799 struct rib *rib;
1800 struct rib *same = NULL;
1801 struct route_table *table;
1802 struct route_node *rn;
1803 struct nexthop *nexthop;
1804
1805 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001806 table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001807 if (! table)
1808 return 0;
1809
1810 /* Make it sure prefixlen is applied to the prefix. */
1811 apply_mask_ipv4 (p);
1812
1813 /* Set default distance by route type. */
1814 if (distance == 0)
1815 {
Balaji.G837d16c2012-09-26 14:09:10 +05301816 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001817 distance = 150;
1818 else
1819 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001820
1821 /* iBGP distance is 200. */
1822 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1823 distance = 200;
1824 }
1825
1826 /* Lookup route node.*/
1827 rn = route_node_get (table, (struct prefix *) p);
1828
1829 /* If same type of route are installed, treat it as a implicit
1830 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001831 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001832 {
Paul Jakma6d691122006-07-27 21:49:00 +00001833 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1834 continue;
1835
hassoebf1ead2005-09-21 14:58:20 +00001836 if (rib->type != type)
1837 continue;
1838 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001839 {
1840 same = rib;
1841 break;
1842 }
hassoebf1ead2005-09-21 14:58:20 +00001843 /* Duplicate connected route comes in. */
1844 else if ((nexthop = rib->nexthop) &&
1845 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001846 nexthop->ifindex == ifindex &&
1847 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001848 {
1849 rib->refcnt++;
1850 return 0 ;
1851 }
paul718e3742002-12-13 20:15:29 +00001852 }
1853
1854 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001855 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001856 rib->type = type;
1857 rib->distance = distance;
1858 rib->flags = flags;
1859 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001860 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001861 rib->nexthop_num = 0;
1862 rib->uptime = time (NULL);
1863
1864 /* Nexthop settings. */
1865 if (gate)
1866 {
1867 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001868 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001869 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001870 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001871 }
1872 else
1873 nexthop_ifindex_add (rib, ifindex);
1874
1875 /* If this route is kernel route, set FIB flag to the route. */
1876 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1877 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1878 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1879
1880 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001881 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001882 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1883 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001884 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001885
paul718e3742002-12-13 20:15:29 +00001886 /* Free implicit route.*/
1887 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001888 {
1889 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001890 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1891 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001892 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001893 }
paul4d38fdb2005-04-28 17:35:14 +00001894
1895 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001896 return 0;
1897}
1898
Denis Ovsienkodc958242007-08-13 16:03:06 +00001899/* This function dumps the contents of a given RIB entry into
1900 * standard debug log. Calling function name and IP prefix in
1901 * question are passed as 1st and 2nd arguments.
1902 */
1903
David Lamparterf7bf4152013-10-22 17:10:21 +00001904void _rib_dump (const char * func,
1905 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001906{
David Lamparterf7bf4152013-10-22 17:10:21 +00001907 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001908 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001909 struct nexthop *nexthop, *tnexthop;
1910 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001911
Timo Teräsbe6335d2015-05-23 11:08:41 +03001912 zlog_debug ("%s: dumping RIB entry %p for %s", func, (void *)rib,
1913 prefix2str(p, straddr, sizeof(straddr)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001914 zlog_debug
1915 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001916 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001917 func,
1918 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001919 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001920 rib->type,
1921 rib->table
1922 );
1923 zlog_debug
1924 (
1925 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1926 func,
1927 rib->metric,
1928 rib->distance,
1929 rib->flags,
1930 rib->status
1931 );
1932 zlog_debug
1933 (
1934 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1935 func,
1936 rib->nexthop_num,
1937 rib->nexthop_active_num,
1938 rib->nexthop_fib_num
1939 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001940
Christian Frankefa713d92013-07-05 15:35:37 +00001941 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1942 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001943 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001944 zlog_debug
1945 (
1946 "%s: %s %s with flags %s%s%s",
1947 func,
1948 (recursing ? " NH" : "NH"),
1949 straddr,
1950 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1951 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1952 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1953 );
1954 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001955 zlog_debug ("%s: dump complete", func);
1956}
1957
1958/* This is an exported helper to rtm_read() to dump the strange
1959 * RIB entry found by rib_lookup_ipv4_route()
1960 */
1961
1962void rib_lookup_and_dump (struct prefix_ipv4 * p)
1963{
1964 struct route_table *table;
1965 struct route_node *rn;
1966 struct rib *rib;
1967 char prefix_buf[INET_ADDRSTRLEN];
1968
1969 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001970 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001971 if (! table)
1972 {
Feng Lu41f44a22015-05-22 11:39:56 +02001973 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001974 return;
1975 }
1976
Denis Ovsienkodc958242007-08-13 16:03:06 +00001977 /* Scan the RIB table for exactly matching RIB entry. */
1978 rn = route_node_lookup (table, (struct prefix *) p);
1979
1980 /* No route for this prefix. */
1981 if (! rn)
1982 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001983 zlog_debug ("%s: lookup failed for %s", __func__,
1984 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001985 return;
1986 }
1987
1988 /* Unlock node. */
1989 route_unlock_node (rn);
1990
1991 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001992 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001993 {
1994 zlog_debug
1995 (
1996 "%s: rn %p, rib %p: %s, %s",
1997 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01001998 (void *)rn,
1999 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002000 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2001 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2002 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002003 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002004 }
2005}
2006
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002007/* Check if requested address assignment will fail due to another
2008 * route being installed by zebra in FIB already. Take necessary
2009 * actions, if needed: remove such a route from FIB and deSELECT
2010 * corresponding RIB entry. Then put affected RN into RIBQ head.
2011 */
2012void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2013{
2014 struct route_table *table;
2015 struct route_node *rn;
2016 struct rib *rib;
2017 unsigned changed = 0;
2018
Feng Lu41f44a22015-05-22 11:39:56 +02002019 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002020 {
Feng Lu41f44a22015-05-22 11:39:56 +02002021 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002022 return;
2023 }
2024
2025 /* No matches would be the simplest case. */
2026 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2027 return;
2028
2029 /* Unlock node. */
2030 route_unlock_node (rn);
2031
2032 /* Check all RIB entries. In case any changes have to be done, requeue
2033 * the RN into RIBQ head. If the routing message about the new connected
2034 * route (generated by the IP address we are going to assign very soon)
2035 * comes before the RIBQ is processed, the new RIB entry will join
2036 * RIBQ record already on head. This is necessary for proper revalidation
2037 * of the rest of the RIB.
2038 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002039 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002040 {
2041 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2042 ! RIB_SYSTEM_ROUTE (rib))
2043 {
2044 changed = 1;
2045 if (IS_ZEBRA_DEBUG_RIB)
2046 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03002047 char buf[PREFIX_STRLEN];
2048 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
2049 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00002050 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002051 }
2052 rib_uninstall (rn, rib);
2053 }
2054 }
2055 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002056 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002057}
2058
paul718e3742002-12-13 20:15:29 +00002059int
G.Balajicddf3912011-11-26 21:59:32 +04002060rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002061{
2062 struct route_table *table;
2063 struct route_node *rn;
2064 struct rib *same;
2065 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002066
paul718e3742002-12-13 20:15:29 +00002067 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002068 table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002069 if (! table)
2070 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002071
paul718e3742002-12-13 20:15:29 +00002072 /* Make it sure prefixlen is applied to the prefix. */
2073 apply_mask_ipv4 (p);
2074
2075 /* Set default distance by route type. */
2076 if (rib->distance == 0)
2077 {
2078 rib->distance = route_info[rib->type].distance;
2079
2080 /* iBGP distance is 200. */
2081 if (rib->type == ZEBRA_ROUTE_BGP
2082 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2083 rib->distance = 200;
2084 }
2085
2086 /* Lookup route node.*/
2087 rn = route_node_get (table, (struct prefix *) p);
2088
2089 /* If same type of route are installed, treat it as a implicit
2090 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002091 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002092 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002093 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002094 continue;
2095
paul718e3742002-12-13 20:15:29 +00002096 if (same->type == rib->type && same->table == rib->table
2097 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002098 break;
paul718e3742002-12-13 20:15:29 +00002099 }
paul4d38fdb2005-04-28 17:35:14 +00002100
paul718e3742002-12-13 20:15:29 +00002101 /* If this route is kernel route, set FIB flag to the route. */
2102 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2103 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2104 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2105
2106 /* Link new rib to node.*/
2107 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002108 if (IS_ZEBRA_DEBUG_RIB)
2109 {
2110 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002111 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002112 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002113 }
paul718e3742002-12-13 20:15:29 +00002114
paul718e3742002-12-13 20:15:29 +00002115 /* Free implicit route.*/
2116 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002117 {
2118 if (IS_ZEBRA_DEBUG_RIB)
2119 {
2120 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002121 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002122 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002123 }
paul4d38fdb2005-04-28 17:35:14 +00002124 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002125 }
paul4d38fdb2005-04-28 17:35:14 +00002126
2127 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002128 return 0;
2129}
2130
hassoebf1ead2005-09-21 14:58:20 +00002131/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002132int
2133rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
G.Balajicddf3912011-11-26 21:59:32 +04002134 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002135{
2136 struct route_table *table;
2137 struct route_node *rn;
2138 struct rib *rib;
2139 struct rib *fib = NULL;
2140 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002141 struct nexthop *nexthop, *tnexthop;
2142 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002143 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002144 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002145
2146 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002147 table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002148 if (! table)
2149 return 0;
2150
2151 /* Apply mask. */
2152 apply_mask_ipv4 (p);
2153
Christian Frankeb52aef12013-11-27 17:06:15 +00002154 if (IS_ZEBRA_DEBUG_KERNEL)
2155 {
2156 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002157 zlog_debug ("rib_delete_ipv4(): route delete %s via %s ifindex %d",
2158 prefix2str (p, buf1, sizeof(buf1)),
Christian Frankeb52aef12013-11-27 17:06:15 +00002159 inet_ntoa (*gate),
2160 ifindex);
2161 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002162 zlog_debug ("rib_delete_ipv4(): route delete %s ifindex %d",
2163 prefix2str (p, buf1, sizeof(buf1)),
Christian Frankeb52aef12013-11-27 17:06:15 +00002164 ifindex);
2165 }
paul5ec90d22003-06-19 01:41:37 +00002166
paul718e3742002-12-13 20:15:29 +00002167 /* Lookup route node. */
2168 rn = route_node_lookup (table, (struct prefix *) p);
2169 if (! rn)
2170 {
2171 if (IS_ZEBRA_DEBUG_KERNEL)
2172 {
2173 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002174 zlog_debug ("route %s via %s ifindex %d doesn't exist in rib",
2175 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002176 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002177 ifindex);
2178 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002179 zlog_debug ("route %s ifindex %d doesn't exist in rib",
2180 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002181 ifindex);
2182 }
2183 return ZEBRA_ERR_RTNOEXIST;
2184 }
2185
2186 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002187 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002188 {
Paul Jakma6d691122006-07-27 21:49:00 +00002189 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2190 continue;
2191
paul718e3742002-12-13 20:15:29 +00002192 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2193 fib = rib;
2194
hassoebf1ead2005-09-21 14:58:20 +00002195 if (rib->type != type)
2196 continue;
2197 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002198 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002199 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002200 if (nexthop->ifindex != ifindex)
2201 continue;
hassoebf1ead2005-09-21 14:58:20 +00002202 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002203 {
hassoebf1ead2005-09-21 14:58:20 +00002204 rib->refcnt--;
2205 route_unlock_node (rn);
2206 route_unlock_node (rn);
2207 return 0;
paul718e3742002-12-13 20:15:29 +00002208 }
hassoebf1ead2005-09-21 14:58:20 +00002209 same = rib;
2210 break;
paul718e3742002-12-13 20:15:29 +00002211 }
hassoebf1ead2005-09-21 14:58:20 +00002212 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002213 else
paul5ec90d22003-06-19 01:41:37 +00002214 {
Christian Frankefa713d92013-07-05 15:35:37 +00002215 if (gate == NULL)
2216 {
2217 same = rib;
2218 break;
2219 }
2220 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2221 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2222 {
2223 same = rib;
2224 break;
2225 }
2226 if (same)
2227 break;
2228 }
paul718e3742002-12-13 20:15:29 +00002229 }
paul718e3742002-12-13 20:15:29 +00002230 /* If same type of route can't be found and this message is from
2231 kernel. */
2232 if (! same)
2233 {
2234 if (fib && type == ZEBRA_ROUTE_KERNEL)
2235 {
2236 /* Unset flags. */
2237 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2238 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2239
2240 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2241 }
2242 else
2243 {
2244 if (IS_ZEBRA_DEBUG_KERNEL)
2245 {
2246 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002247 zlog_debug ("route %s via %s ifindex %d type %d doesn't exist in rib",
2248 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002249 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002250 ifindex,
2251 type);
2252 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002253 zlog_debug ("route %s ifindex %d type %d doesn't exist in rib",
2254 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002255 ifindex,
2256 type);
2257 }
2258 route_unlock_node (rn);
2259 return ZEBRA_ERR_RTNOEXIST;
2260 }
2261 }
paul4d38fdb2005-04-28 17:35:14 +00002262
paul718e3742002-12-13 20:15:29 +00002263 if (same)
2264 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002265
paul718e3742002-12-13 20:15:29 +00002266 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002267 return 0;
2268}
David Lamparter6b0655a2014-06-04 06:53:35 +02002269
paul718e3742002-12-13 20:15:29 +00002270/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002271static void
Everton Marques33d86db2014-07-14 11:19:00 -03002272static_install_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002273{
2274 struct rib *rib;
2275 struct route_node *rn;
2276 struct route_table *table;
2277
2278 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002279 table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002280 if (! table)
2281 return;
2282
2283 /* Lookup existing route */
2284 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002285 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002286 {
2287 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2288 continue;
2289
2290 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2291 break;
2292 }
paul718e3742002-12-13 20:15:29 +00002293
2294 if (rib)
2295 {
2296 /* Same distance static route is there. Update it with new
2297 nexthop. */
paul718e3742002-12-13 20:15:29 +00002298 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002299 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002300 {
2301 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002302 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002303 break;
2304 case STATIC_IPV4_IFNAME:
2305 nexthop_ifname_add (rib, si->gate.ifname);
2306 break;
2307 case STATIC_IPV4_BLACKHOLE:
2308 nexthop_blackhole_add (rib);
2309 break;
paul4d38fdb2005-04-28 17:35:14 +00002310 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002311 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002312 }
2313 else
2314 {
2315 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002316 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2317
paul718e3742002-12-13 20:15:29 +00002318 rib->type = ZEBRA_ROUTE_STATIC;
2319 rib->distance = si->distance;
2320 rib->metric = 0;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002321 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002322 rib->nexthop_num = 0;
2323
2324 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002325 {
2326 case STATIC_IPV4_GATEWAY:
Paul Jakma7514fb72007-05-02 16:05:35 +00002327 nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002328 break;
2329 case STATIC_IPV4_IFNAME:
2330 nexthop_ifname_add (rib, si->gate.ifname);
2331 break;
2332 case STATIC_IPV4_BLACKHOLE:
2333 nexthop_blackhole_add (rib);
2334 break;
2335 }
paul718e3742002-12-13 20:15:29 +00002336
hasso81dfcaa2003-05-25 19:21:25 +00002337 /* Save the flags of this static routes (reject, blackhole) */
2338 rib->flags = si->flags;
2339
paul718e3742002-12-13 20:15:29 +00002340 /* Link this rib to the tree. */
2341 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002342 }
2343}
2344
paula1ac18c2005-06-28 17:17:12 +00002345static int
paul718e3742002-12-13 20:15:29 +00002346static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
2347{
2348 if (nexthop->type == NEXTHOP_TYPE_IPV4
2349 && si->type == STATIC_IPV4_GATEWAY
2350 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
2351 return 1;
2352 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2353 && si->type == STATIC_IPV4_IFNAME
2354 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
2355 return 1;
paul595db7f2003-05-25 21:35:06 +00002356 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2357 && si->type == STATIC_IPV4_BLACKHOLE)
2358 return 1;
paule8e19462006-01-19 20:16:55 +00002359 return 0;
paul718e3742002-12-13 20:15:29 +00002360}
2361
2362/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002363static void
Everton Marques33d86db2014-07-14 11:19:00 -03002364static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_ipv4 *si)
paul718e3742002-12-13 20:15:29 +00002365{
2366 struct route_node *rn;
2367 struct rib *rib;
2368 struct nexthop *nexthop;
2369 struct route_table *table;
2370
2371 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002372 table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002373 if (! table)
2374 return;
paul4d38fdb2005-04-28 17:35:14 +00002375
paul718e3742002-12-13 20:15:29 +00002376 /* Lookup existing route with type and distance. */
2377 rn = route_node_lookup (table, p);
2378 if (! rn)
2379 return;
2380
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002381 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002382 {
2383 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2384 continue;
2385
2386 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2387 break;
2388 }
paul718e3742002-12-13 20:15:29 +00002389
2390 if (! rib)
2391 {
2392 route_unlock_node (rn);
2393 return;
2394 }
2395
2396 /* Lookup nexthop. */
2397 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2398 if (static_ipv4_nexthop_same (nexthop, si))
2399 break;
2400
2401 /* Can't find nexthop. */
2402 if (! nexthop)
2403 {
2404 route_unlock_node (rn);
2405 return;
2406 }
2407
2408 /* Check nexthop. */
2409 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002410 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002411 else
2412 {
paul6baeb982003-10-28 03:47:15 +00002413 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2414 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002415 nexthop_delete (rib, nexthop);
2416 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002417 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002418 }
paul718e3742002-12-13 20:15:29 +00002419 /* Unlock node. */
2420 route_unlock_node (rn);
2421}
2422
paul718e3742002-12-13 20:15:29 +00002423int
Everton Marques33d86db2014-07-14 11:19:00 -03002424static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2425 const char *ifname, u_char flags, u_char distance,
2426 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002427{
2428 u_char type = 0;
2429 struct route_node *rn;
2430 struct static_ipv4 *si;
2431 struct static_ipv4 *pp;
2432 struct static_ipv4 *cp;
2433 struct static_ipv4 *update = NULL;
2434 struct route_table *stable;
2435
2436 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002437 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002438 if (! stable)
2439 return -1;
2440
2441 /* Lookup static route prefix. */
2442 rn = route_node_get (stable, p);
2443
2444 /* Make flags. */
2445 if (gate)
2446 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002447 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002448 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002449 else
2450 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002451
2452 /* Do nothing if there is a same static route. */
2453 for (si = rn->info; si; si = si->next)
2454 {
2455 if (type == si->type
2456 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2457 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2458 {
2459 if (distance == si->distance)
2460 {
2461 route_unlock_node (rn);
2462 return 0;
2463 }
2464 else
2465 update = si;
2466 }
2467 }
2468
Paul Jakma3c0755d2006-12-08 00:53:14 +00002469 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002470 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002471 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002472
2473 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07002474 si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
paul718e3742002-12-13 20:15:29 +00002475
2476 si->type = type;
2477 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002478 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002479
2480 if (gate)
2481 si->gate.ipv4 = *gate;
2482 if (ifname)
2483 si->gate.ifname = XSTRDUP (0, ifname);
2484
2485 /* Add new static route information to the tree with sort by
2486 distance value and gateway address. */
2487 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2488 {
2489 if (si->distance < cp->distance)
2490 break;
2491 if (si->distance > cp->distance)
2492 continue;
2493 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2494 {
2495 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
2496 break;
2497 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
2498 continue;
2499 }
2500 }
2501
2502 /* Make linked list. */
2503 if (pp)
2504 pp->next = si;
2505 else
2506 rn->info = si;
2507 if (cp)
2508 cp->prev = si;
2509 si->prev = pp;
2510 si->next = cp;
2511
2512 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002513 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002514
2515 return 1;
2516}
2517
paul718e3742002-12-13 20:15:29 +00002518int
Everton Marques33d86db2014-07-14 11:19:00 -03002519static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2520 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002521{
2522 u_char type = 0;
2523 struct route_node *rn;
2524 struct static_ipv4 *si;
2525 struct route_table *stable;
2526
2527 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002528 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002529 if (! stable)
2530 return -1;
2531
2532 /* Lookup static route prefix. */
2533 rn = route_node_lookup (stable, p);
2534 if (! rn)
2535 return 0;
2536
2537 /* Make flags. */
2538 if (gate)
2539 type = STATIC_IPV4_GATEWAY;
2540 else if (ifname)
2541 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002542 else
2543 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002544
2545 /* Find same static route is the tree */
2546 for (si = rn->info; si; si = si->next)
2547 if (type == si->type
2548 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
2549 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
2550 break;
2551
2552 /* Can't find static route. */
2553 if (! si)
2554 {
2555 route_unlock_node (rn);
2556 return 0;
2557 }
2558
2559 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002560 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002561
2562 /* Unlink static route from linked list. */
2563 if (si->prev)
2564 si->prev->next = si->next;
2565 else
2566 rn->info = si->next;
2567 if (si->next)
2568 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002569 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002570
2571 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002572 if (ifname)
2573 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00002574 XFREE (MTYPE_STATIC_IPV4, si);
2575
paul143a3852003-09-29 20:06:13 +00002576 route_unlock_node (rn);
2577
paul718e3742002-12-13 20:15:29 +00002578 return 1;
2579}
2580
paul718e3742002-12-13 20:15:29 +00002581#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00002582int
2583rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00002584 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
G.Balajif768f362011-11-26 22:10:39 +04002585 u_int32_t metric, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002586{
2587 struct rib *rib;
2588 struct rib *same = NULL;
2589 struct route_table *table;
2590 struct route_node *rn;
2591 struct nexthop *nexthop;
2592
paul718e3742002-12-13 20:15:29 +00002593 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002594 table = zebra_vrf_table (AFI_IP6, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002595 if (! table)
2596 return 0;
2597
2598 /* Make sure mask is applied. */
2599 apply_mask_ipv6 (p);
2600
2601 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002602 if (!distance)
2603 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002604
2605 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2606 distance = 200;
2607
paul718e3742002-12-13 20:15:29 +00002608 /* Lookup route node.*/
2609 rn = route_node_get (table, (struct prefix *) p);
2610
2611 /* If same type of route are installed, treat it as a implicit
2612 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002613 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002614 {
Paul Jakma6d691122006-07-27 21:49:00 +00002615 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2616 continue;
2617
hassoebf1ead2005-09-21 14:58:20 +00002618 if (rib->type != type)
2619 continue;
2620 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002621 {
2622 same = rib;
paul718e3742002-12-13 20:15:29 +00002623 break;
2624 }
hassoebf1ead2005-09-21 14:58:20 +00002625 else if ((nexthop = rib->nexthop) &&
2626 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2627 nexthop->ifindex == ifindex)
2628 {
2629 rib->refcnt++;
2630 return 0;
2631 }
paul718e3742002-12-13 20:15:29 +00002632 }
2633
2634 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002635 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2636
paul718e3742002-12-13 20:15:29 +00002637 rib->type = type;
2638 rib->distance = distance;
2639 rib->flags = flags;
2640 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00002641 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00002642 rib->nexthop_num = 0;
2643 rib->uptime = time (NULL);
2644
2645 /* Nexthop settings. */
2646 if (gate)
2647 {
2648 if (ifindex)
2649 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2650 else
2651 nexthop_ipv6_add (rib, gate);
2652 }
2653 else
2654 nexthop_ifindex_add (rib, ifindex);
2655
2656 /* If this route is kernel route, set FIB flag to the route. */
2657 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2658 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2659 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2660
2661 /* Link new rib to node.*/
2662 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002663 if (IS_ZEBRA_DEBUG_RIB)
2664 {
2665 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002666 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002667 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002668 }
paul718e3742002-12-13 20:15:29 +00002669
paul718e3742002-12-13 20:15:29 +00002670 /* Free implicit route.*/
2671 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002672 {
2673 if (IS_ZEBRA_DEBUG_RIB)
2674 {
2675 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002676 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002677 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002678 }
paul4d38fdb2005-04-28 17:35:14 +00002679 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002680 }
paul4d38fdb2005-04-28 17:35:14 +00002681
2682 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002683 return 0;
2684}
2685
hassoebf1ead2005-09-21 14:58:20 +00002686/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002687int
2688rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
G.Balajif768f362011-11-26 22:10:39 +04002689 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002690{
2691 struct route_table *table;
2692 struct route_node *rn;
2693 struct rib *rib;
2694 struct rib *fib = NULL;
2695 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002696 struct nexthop *nexthop, *tnexthop;
2697 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002698 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002699 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002700
2701 /* Apply mask. */
2702 apply_mask_ipv6 (p);
2703
2704 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002705 table = zebra_vrf_table (AFI_IP6, safi, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002706 if (! table)
2707 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002708
paul718e3742002-12-13 20:15:29 +00002709 /* Lookup route node. */
2710 rn = route_node_lookup (table, (struct prefix *) p);
2711 if (! rn)
2712 {
2713 if (IS_ZEBRA_DEBUG_KERNEL)
2714 {
2715 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002716 zlog_debug ("route %s via %s ifindex %d doesn't exist in rib",
2717 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002718 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002719 ifindex);
2720 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002721 zlog_debug ("route %s ifindex %d doesn't exist in rib",
2722 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002723 ifindex);
2724 }
2725 return ZEBRA_ERR_RTNOEXIST;
2726 }
2727
2728 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002729 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002730 {
Paul Jakma6d691122006-07-27 21:49:00 +00002731 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2732 continue;
2733
paul718e3742002-12-13 20:15:29 +00002734 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2735 fib = rib;
2736
hassoebf1ead2005-09-21 14:58:20 +00002737 if (rib->type != type)
2738 continue;
2739 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002740 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002741 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002742 if (nexthop->ifindex != ifindex)
2743 continue;
hassoebf1ead2005-09-21 14:58:20 +00002744 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002745 {
hassoebf1ead2005-09-21 14:58:20 +00002746 rib->refcnt--;
2747 route_unlock_node (rn);
2748 route_unlock_node (rn);
2749 return 0;
paul718e3742002-12-13 20:15:29 +00002750 }
hassoebf1ead2005-09-21 14:58:20 +00002751 same = rib;
2752 break;
paul718e3742002-12-13 20:15:29 +00002753 }
hassoebf1ead2005-09-21 14:58:20 +00002754 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002755 else
2756 {
2757 if (gate == NULL)
2758 {
2759 same = rib;
2760 break;
2761 }
2762 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2763 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2764 {
2765 same = rib;
2766 break;
2767 }
2768 if (same)
2769 break;
2770 }
paul718e3742002-12-13 20:15:29 +00002771 }
2772
2773 /* If same type of route can't be found and this message is from
2774 kernel. */
2775 if (! same)
2776 {
2777 if (fib && type == ZEBRA_ROUTE_KERNEL)
2778 {
2779 /* Unset flags. */
2780 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2781 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2782
2783 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2784 }
2785 else
2786 {
2787 if (IS_ZEBRA_DEBUG_KERNEL)
2788 {
2789 if (gate)
Timo Teräsbe6335d2015-05-23 11:08:41 +03002790 zlog_debug ("route %s via %s ifindex %d type %d doesn't exist in rib",
2791 prefix2str (p, buf1, sizeof(buf1)),
Stephen Hemminger81cce012009-04-28 14:28:00 -07002792 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002793 ifindex,
2794 type);
2795 else
Timo Teräsbe6335d2015-05-23 11:08:41 +03002796 zlog_debug ("route %s ifindex %d type %d doesn't exist in rib",
2797 prefix2str (p, buf1, sizeof(buf1)),
paul718e3742002-12-13 20:15:29 +00002798 ifindex,
2799 type);
2800 }
2801 route_unlock_node (rn);
2802 return ZEBRA_ERR_RTNOEXIST;
2803 }
2804 }
2805
2806 if (same)
2807 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002808
paul718e3742002-12-13 20:15:29 +00002809 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002810 return 0;
2811}
David Lamparter6b0655a2014-06-04 06:53:35 +02002812
paul718e3742002-12-13 20:15:29 +00002813/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002814static void
paul718e3742002-12-13 20:15:29 +00002815static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
2816{
2817 struct rib *rib;
2818 struct route_table *table;
2819 struct route_node *rn;
2820
2821 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002822 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002823 if (! table)
2824 return;
2825
2826 /* Lookup existing route */
2827 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002828 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002829 {
2830 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2831 continue;
2832
2833 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2834 break;
2835 }
paul718e3742002-12-13 20:15:29 +00002836
2837 if (rib)
2838 {
2839 /* Same distance static route is there. Update it with new
2840 nexthop. */
paul718e3742002-12-13 20:15:29 +00002841 route_unlock_node (rn);
2842
2843 switch (si->type)
2844 {
2845 case STATIC_IPV6_GATEWAY:
2846 nexthop_ipv6_add (rib, &si->ipv6);
2847 break;
2848 case STATIC_IPV6_IFNAME:
2849 nexthop_ifname_add (rib, si->ifname);
2850 break;
2851 case STATIC_IPV6_GATEWAY_IFNAME:
2852 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2853 break;
2854 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002855 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002856 }
2857 else
2858 {
2859 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002860 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2861
paul718e3742002-12-13 20:15:29 +00002862 rib->type = ZEBRA_ROUTE_STATIC;
2863 rib->distance = si->distance;
2864 rib->metric = 0;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002865 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002866 rib->nexthop_num = 0;
2867
2868 switch (si->type)
2869 {
2870 case STATIC_IPV6_GATEWAY:
2871 nexthop_ipv6_add (rib, &si->ipv6);
2872 break;
2873 case STATIC_IPV6_IFNAME:
2874 nexthop_ifname_add (rib, si->ifname);
2875 break;
2876 case STATIC_IPV6_GATEWAY_IFNAME:
2877 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2878 break;
2879 }
2880
hasso81dfcaa2003-05-25 19:21:25 +00002881 /* Save the flags of this static routes (reject, blackhole) */
2882 rib->flags = si->flags;
2883
paul718e3742002-12-13 20:15:29 +00002884 /* Link this rib to the tree. */
2885 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002886 }
2887}
2888
paula1ac18c2005-06-28 17:17:12 +00002889static int
paul718e3742002-12-13 20:15:29 +00002890static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2891{
2892 if (nexthop->type == NEXTHOP_TYPE_IPV6
2893 && si->type == STATIC_IPV6_GATEWAY
2894 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2895 return 1;
2896 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2897 && si->type == STATIC_IPV6_IFNAME
2898 && strcmp (nexthop->ifname, si->ifname) == 0)
2899 return 1;
2900 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2901 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2902 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2903 && strcmp (nexthop->ifname, si->ifname) == 0)
2904 return 1;
paule8e19462006-01-19 20:16:55 +00002905 return 0;
paul718e3742002-12-13 20:15:29 +00002906}
2907
paula1ac18c2005-06-28 17:17:12 +00002908static void
paul718e3742002-12-13 20:15:29 +00002909static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2910{
2911 struct route_table *table;
2912 struct route_node *rn;
2913 struct rib *rib;
2914 struct nexthop *nexthop;
2915
2916 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002917 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002918 if (! table)
2919 return;
2920
2921 /* Lookup existing route with type and distance. */
2922 rn = route_node_lookup (table, (struct prefix *) p);
2923 if (! rn)
2924 return;
2925
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002926 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002927 {
2928 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2929 continue;
2930
2931 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2932 break;
2933 }
2934
paul718e3742002-12-13 20:15:29 +00002935 if (! rib)
2936 {
2937 route_unlock_node (rn);
2938 return;
2939 }
2940
2941 /* Lookup nexthop. */
2942 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2943 if (static_ipv6_nexthop_same (nexthop, si))
2944 break;
2945
2946 /* Can't find nexthop. */
2947 if (! nexthop)
2948 {
2949 route_unlock_node (rn);
2950 return;
2951 }
2952
2953 /* Check nexthop. */
2954 if (rib->nexthop_num == 1)
2955 {
2956 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002957 }
2958 else
2959 {
paul6baeb982003-10-28 03:47:15 +00002960 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2961 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002962 nexthop_delete (rib, nexthop);
2963 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002964 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002965 }
paul718e3742002-12-13 20:15:29 +00002966 /* Unlock node. */
2967 route_unlock_node (rn);
2968}
2969
2970/* Add static route into static route configuration. */
2971int
2972static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002973 const char *ifname, u_char flags, u_char distance,
2974 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002975{
2976 struct route_node *rn;
2977 struct static_ipv6 *si;
2978 struct static_ipv6 *pp;
2979 struct static_ipv6 *cp;
2980 struct route_table *stable;
2981
2982 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002983 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00002984 if (! stable)
2985 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002986
2987 if (!gate &&
2988 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2989 return -1;
2990
2991 if (!ifname &&
2992 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2993 return -1;
paul718e3742002-12-13 20:15:29 +00002994
2995 /* Lookup static route prefix. */
2996 rn = route_node_get (stable, p);
2997
2998 /* Do nothing if there is a same static route. */
2999 for (si = rn->info; si; si = si->next)
3000 {
3001 if (distance == si->distance
3002 && type == si->type
3003 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3004 && (! ifname || strcmp (ifname, si->ifname) == 0))
3005 {
3006 route_unlock_node (rn);
3007 return 0;
3008 }
3009 }
3010
3011 /* Make new static route structure. */
Stephen Hemminger393deb92008-08-18 14:13:29 -07003012 si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
paul718e3742002-12-13 20:15:29 +00003013
3014 si->type = type;
3015 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003016 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00003017
3018 switch (type)
3019 {
3020 case STATIC_IPV6_GATEWAY:
3021 si->ipv6 = *gate;
3022 break;
3023 case STATIC_IPV6_IFNAME:
3024 si->ifname = XSTRDUP (0, ifname);
3025 break;
3026 case STATIC_IPV6_GATEWAY_IFNAME:
3027 si->ipv6 = *gate;
3028 si->ifname = XSTRDUP (0, ifname);
3029 break;
3030 }
3031
3032 /* Add new static route information to the tree with sort by
3033 distance value and gateway address. */
3034 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3035 {
3036 if (si->distance < cp->distance)
3037 break;
3038 if (si->distance > cp->distance)
3039 continue;
3040 }
3041
3042 /* Make linked list. */
3043 if (pp)
3044 pp->next = si;
3045 else
3046 rn->info = si;
3047 if (cp)
3048 cp->prev = si;
3049 si->prev = pp;
3050 si->next = cp;
3051
3052 /* Install into rib. */
3053 static_install_ipv6 (p, si);
3054
3055 return 1;
3056}
3057
3058/* Delete static route from static route configuration. */
3059int
3060static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00003061 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003062{
3063 struct route_node *rn;
3064 struct static_ipv6 *si;
3065 struct route_table *stable;
3066
3067 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02003068 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003069 if (! stable)
3070 return -1;
3071
3072 /* Lookup static route prefix. */
3073 rn = route_node_lookup (stable, p);
3074 if (! rn)
3075 return 0;
3076
3077 /* Find same static route is the tree */
3078 for (si = rn->info; si; si = si->next)
3079 if (distance == si->distance
3080 && type == si->type
3081 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
3082 && (! ifname || strcmp (ifname, si->ifname) == 0))
3083 break;
3084
3085 /* Can't find static route. */
3086 if (! si)
3087 {
3088 route_unlock_node (rn);
3089 return 0;
3090 }
3091
3092 /* Install into rib. */
3093 static_uninstall_ipv6 (p, si);
3094
3095 /* Unlink static route from linked list. */
3096 if (si->prev)
3097 si->prev->next = si->next;
3098 else
3099 rn->info = si->next;
3100 if (si->next)
3101 si->next->prev = si->prev;
3102
3103 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003104 if (ifname)
3105 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00003106 XFREE (MTYPE_STATIC_IPV6, si);
3107
3108 return 1;
3109}
3110#endif /* HAVE_IPV6 */
David Lamparter6b0655a2014-06-04 06:53:35 +02003111
paul718e3742002-12-13 20:15:29 +00003112/* RIB update function. */
3113void
paula1ac18c2005-06-28 17:17:12 +00003114rib_update (void)
paul718e3742002-12-13 20:15:29 +00003115{
3116 struct route_node *rn;
3117 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003118
Feng Lu41f44a22015-05-22 11:39:56 +02003119 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00003120 if (table)
3121 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003122 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003123 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003124
Feng Lu41f44a22015-05-22 11:39:56 +02003125 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00003126 if (table)
3127 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003128 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003129 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003130}
3131
David Lamparter6b0655a2014-06-04 06:53:35 +02003132
paul718e3742002-12-13 20:15:29 +00003133/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003134static void
paul718e3742002-12-13 20:15:29 +00003135rib_weed_table (struct route_table *table)
3136{
3137 struct route_node *rn;
3138 struct rib *rib;
3139 struct rib *next;
3140
3141 if (table)
3142 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003143 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003144 {
Paul Jakma6d691122006-07-27 21:49:00 +00003145 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3146 continue;
3147
paulb21b19c2003-06-15 01:28:29 +00003148 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003149 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003150 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003151 }
3152}
3153
3154/* Delete all routes from non main table. */
3155void
paula1ac18c2005-06-28 17:17:12 +00003156rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003157{
Feng Lu41f44a22015-05-22 11:39:56 +02003158 rib_weed_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT));
3159 rib_weed_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT));
paul718e3742002-12-13 20:15:29 +00003160}
David Lamparter6b0655a2014-06-04 06:53:35 +02003161
paul718e3742002-12-13 20:15:29 +00003162/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003163static void
paul718e3742002-12-13 20:15:29 +00003164rib_sweep_table (struct route_table *table)
3165{
3166 struct route_node *rn;
3167 struct rib *rib;
3168 struct rib *next;
3169 int ret = 0;
3170
3171 if (table)
3172 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003173 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003174 {
Paul Jakma6d691122006-07-27 21:49:00 +00003175 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3176 continue;
3177
paul718e3742002-12-13 20:15:29 +00003178 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3179 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3180 {
3181 ret = rib_uninstall_kernel (rn, rib);
3182 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003183 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003184 }
3185 }
3186}
3187
3188/* Sweep all RIB tables. */
3189void
paula1ac18c2005-06-28 17:17:12 +00003190rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003191{
Feng Lu41f44a22015-05-22 11:39:56 +02003192 rib_sweep_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT));
3193 rib_sweep_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT));
paul718e3742002-12-13 20:15:29 +00003194}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003195
3196/* Remove specific by protocol routes from 'table'. */
3197static unsigned long
3198rib_score_proto_table (u_char proto, struct route_table *table)
3199{
3200 struct route_node *rn;
3201 struct rib *rib;
3202 struct rib *next;
3203 unsigned long n = 0;
3204
3205 if (table)
3206 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003207 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003208 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003209 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3210 continue;
3211 if (rib->type == proto)
3212 {
3213 rib_delnode (rn, rib);
3214 n++;
3215 }
3216 }
3217
3218 return n;
3219}
3220
3221/* Remove specific by protocol routes. */
3222unsigned long
3223rib_score_proto (u_char proto)
3224{
Feng Lu41f44a22015-05-22 11:39:56 +02003225 return rib_score_proto_table (proto, zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT))
3226 +rib_score_proto_table (proto, zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT));
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003227}
3228
paul718e3742002-12-13 20:15:29 +00003229/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00003230static void
paul718e3742002-12-13 20:15:29 +00003231rib_close_table (struct route_table *table)
3232{
3233 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003234 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003235 struct rib *rib;
3236
3237 if (table)
3238 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003239 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003240 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003241 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3242 continue;
3243
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003244 if (info->safi == SAFI_UNICAST)
3245 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003246
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003247 if (! RIB_SYSTEM_ROUTE (rib))
3248 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003249 }
paul718e3742002-12-13 20:15:29 +00003250}
3251
3252/* Close all RIB tables. */
3253void
paula1ac18c2005-06-28 17:17:12 +00003254rib_close (void)
paul718e3742002-12-13 20:15:29 +00003255{
Feng Lu41f44a22015-05-22 11:39:56 +02003256 rib_close_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT));
3257 rib_close_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT));
paul718e3742002-12-13 20:15:29 +00003258}
David Lamparter6b0655a2014-06-04 06:53:35 +02003259
paul718e3742002-12-13 20:15:29 +00003260/* Routing information base initialize. */
3261void
paula1ac18c2005-06-28 17:17:12 +00003262rib_init (void)
paul718e3742002-12-13 20:15:29 +00003263{
paul4d38fdb2005-04-28 17:35:14 +00003264 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003265}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003266
3267/*
3268 * vrf_id_get_next
3269 *
3270 * Get the first vrf id that is greater than the given vrf id if any.
3271 *
3272 * Returns TRUE if a vrf id was found, FALSE otherwise.
3273 */
3274static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003275vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003276{
Feng Lu41f44a22015-05-22 11:39:56 +02003277 vrf_iter_t iter = vrf_iterator (vrf_id);
3278 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3279
3280 /* The same one ? Then find out the next. */
3281 if (zvrf && (zvrf->vrf_id == vrf_id))
3282 zvrf = vrf_iter2info (vrf_next (iter));
3283
3284 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003285 {
Feng Lu41f44a22015-05-22 11:39:56 +02003286 *next_id_p = zvrf->vrf_id;
3287 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003288 }
3289
3290 return 0;
3291}
3292
3293/*
3294 * rib_tables_iter_next
3295 *
3296 * Returns the next table in the iteration.
3297 */
3298struct route_table *
3299rib_tables_iter_next (rib_tables_iter_t *iter)
3300{
3301 struct route_table *table;
3302
3303 /*
3304 * Array that helps us go over all AFI/SAFI combinations via one
3305 * index.
3306 */
3307 static struct {
3308 afi_t afi;
3309 safi_t safi;
3310 } afi_safis[] = {
3311 { AFI_IP, SAFI_UNICAST },
3312 { AFI_IP, SAFI_MULTICAST },
3313 { AFI_IP6, SAFI_UNICAST },
3314 { AFI_IP6, SAFI_MULTICAST },
3315 };
3316
3317 table = NULL;
3318
3319 switch (iter->state)
3320 {
3321
3322 case RIB_TABLES_ITER_S_INIT:
3323 iter->vrf_id = 0;
3324 iter->afi_safi_ix = -1;
3325
3326 /* Fall through */
3327
3328 case RIB_TABLES_ITER_S_ITERATING:
3329 iter->afi_safi_ix++;
3330 while (1)
3331 {
3332
3333 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3334 {
Feng Lu41f44a22015-05-22 11:39:56 +02003335 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003336 afi_safis[iter->afi_safi_ix].safi,
3337 iter->vrf_id);
3338 if (table)
3339 break;
3340
3341 iter->afi_safi_ix++;
3342 }
3343
3344 /*
3345 * Found another table in this vrf.
3346 */
3347 if (table)
3348 break;
3349
3350 /*
3351 * Done with all tables in the current vrf, go to the next
3352 * one.
3353 */
3354 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3355 break;
3356
3357 iter->afi_safi_ix = 0;
3358 }
3359
3360 break;
3361
3362 case RIB_TABLES_ITER_S_DONE:
3363 return NULL;
3364 }
3365
3366 if (table)
3367 iter->state = RIB_TABLES_ITER_S_ITERATING;
3368 else
3369 iter->state = RIB_TABLES_ITER_S_DONE;
3370
3371 return table;
3372}
Feng Lu41f44a22015-05-22 11:39:56 +02003373
3374/*
3375 * Create a routing table for the specific AFI/SAFI in the given VRF.
3376 */
3377static void
3378zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3379{
3380 rib_table_info_t *info;
3381 struct route_table *table;
3382
3383 assert (!zvrf->table[afi][safi]);
3384
3385 table = route_table_init ();
3386 zvrf->table[afi][safi] = table;
3387
3388 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3389 info->zvrf = zvrf;
3390 info->afi = afi;
3391 info->safi = safi;
3392 table->info = info;
3393}
3394
3395/* Allocate new zebra VRF. */
3396struct zebra_vrf *
3397zebra_vrf_alloc (vrf_id_t vrf_id)
3398{
3399 struct zebra_vrf *zvrf;
3400
3401 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3402
3403 /* Allocate routing table and static table. */
3404 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3405 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3406 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3407 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3408 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3409 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3410 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3411 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3412
3413 /* Set VRF ID */
3414 zvrf->vrf_id = vrf_id;
3415
3416 return zvrf;
3417}
3418
3419/* Lookup the routing table in an enabled VRF. */
3420struct route_table *
3421zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3422{
3423 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3424
3425 if (!zvrf)
3426 return NULL;
3427
3428 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3429 return NULL;
3430
3431 return zvrf->table[afi][safi];
3432}
3433
3434/* Lookup the static routing table in a VRF. */
3435struct route_table *
3436zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3437{
3438 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3439
3440 if (!zvrf)
3441 return NULL;
3442
3443 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3444 return NULL;
3445
3446 return zvrf->stable[afi][safi];
3447}
3448