blob: 516d9d99c48349daa09ead81d46b9718b67e8d03 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "str.h"
28#include "command.h"
29#include "if.h"
30#include "log.h"
31#include "sockunion.h"
paul4d38fdb2005-04-28 17:35:14 +000032#include "linklist.h"
33#include "thread.h"
34#include "workqueue.h"
Paul Jakma7514fb72007-05-02 16:05:35 +000035#include "prefix.h"
36#include "routemap.h"
Feng Lu41f44a22015-05-22 11:39:56 +020037#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "zebra/rib.h"
40#include "zebra/rt.h"
41#include "zebra/zserv.h"
42#include "zebra/redistribute.h"
43#include "zebra/debug.h"
Avneesh Sachdev5adc2522012-11-13 22:48:59 +000044#include "zebra/zebra_fpm.h"
paul718e3742002-12-13 20:15:29 +000045
46/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000047extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000048
Paul Jakma457eb9a2006-07-27 19:59:58 +000049/* Hold time for RIB process, should be very minimal.
50 * it is useful to able to set it otherwise for testing, hence exported
51 * as global here for test-rig code.
52 */
53int rib_process_hold_time = 10;
54
paul718e3742002-12-13 20:15:29 +000055/* Each route type's string and default distance value. */
Stephen Hemmingerd145bc02008-08-17 17:41:37 +010056static const struct
paul718e3742002-12-13 20:15:29 +000057{
58 int key;
59 int distance;
Paul Jakma57345092011-12-25 17:52:09 +010060} route_info[ZEBRA_ROUTE_MAX] =
paul718e3742002-12-13 20:15:29 +000061{
Paul Jakma57345092011-12-25 17:52:09 +010062 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
63 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
64 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
65 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
66 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
67 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
68 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
69 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
70 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
71 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
72 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
David Lamparter7052f222009-08-27 00:28:28 +020073 /* no entry/default: 150 */
paul718e3742002-12-13 20:15:29 +000074};
David Lamparter6b0655a2014-06-04 06:53:35 +020075
David Lamparterbd078122015-01-06 19:53:24 +010076/* RPF lookup behaviour */
77static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
78
David Lampartereed3c482015-03-03 08:51:53 +010079static void __attribute__((format (printf, 4, 5)))
David Lamparter94813742014-04-24 20:22:53 +020080_rnode_zlog(const char *_func, struct route_node *rn, int priority,
81 const char *msgfmt, ...)
82{
Feng Lu0d0686f2015-05-22 11:40:02 +020083 char prefix[PREFIX_STRLEN], buf[256];
David Lamparter94813742014-04-24 20:22:53 +020084 char msgbuf[512];
85 va_list ap;
86
87 va_start(ap, msgfmt);
88 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
89 va_end(ap);
90
91 if (rn)
92 {
David Lamparterab2ba612015-01-22 19:02:13 +010093 rib_table_info_t *info = rn->table->info;
94
Feng Lu0d0686f2015-05-22 11:40:02 +020095 snprintf(buf, sizeof(buf), "%s%s vrf %u",
96 prefix2str(&rn->p, prefix, sizeof(prefix)),
97 info->safi == SAFI_MULTICAST ? " (MRIB)" : "",
98 info->zvrf->vrf_id);
David Lamparter94813742014-04-24 20:22:53 +020099 }
100 else
101 {
102 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
103 }
104
105 zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
106}
107
108#define rnode_debug(node, ...) \
109 _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
110#define rnode_info(node, ...) \
111 _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
112
Avneesh Sachdev1b5ed1b2012-11-13 22:48:54 +0000113/*
Avneesh Sachdev78deec42012-11-13 22:48:56 +0000114 * nexthop_type_to_str
115 */
116const char *
117nexthop_type_to_str (enum nexthop_types_t nh_type)
118{
119 static const char *desc[] = {
120 "none",
121 "Directly connected",
122 "Interface route",
123 "IPv4 nexthop",
124 "IPv4 nexthop with ifindex",
125 "IPv4 nexthop with ifname",
126 "IPv6 nexthop",
127 "IPv6 nexthop with ifindex",
128 "IPv6 nexthop with ifname",
129 "Null0 nexthop",
130 };
131
132 if (nh_type >= ZEBRA_NUM_OF (desc))
133 return "<Invalid nh type>";
134
135 return desc[nh_type];
136}
137
Christian Frankefa713d92013-07-05 15:35:37 +0000138/* Add nexthop to the end of a nexthop list. */
paula1ac18c2005-06-28 17:17:12 +0000139static void
Christian Frankefa713d92013-07-05 15:35:37 +0000140_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
paul718e3742002-12-13 20:15:29 +0000141{
142 struct nexthop *last;
143
Christian Frankefa713d92013-07-05 15:35:37 +0000144 for (last = *target; last && last->next; last = last->next)
paul718e3742002-12-13 20:15:29 +0000145 ;
146 if (last)
147 last->next = nexthop;
148 else
Christian Frankefa713d92013-07-05 15:35:37 +0000149 *target = nexthop;
paul718e3742002-12-13 20:15:29 +0000150 nexthop->prev = last;
Christian Frankefa713d92013-07-05 15:35:37 +0000151}
paul718e3742002-12-13 20:15:29 +0000152
Christian Frankefa713d92013-07-05 15:35:37 +0000153/* Add nexthop to the end of a rib node's nexthop list */
154static void
155nexthop_add (struct rib *rib, struct nexthop *nexthop)
156{
157 _nexthop_add(&rib->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000158 rib->nexthop_num++;
159}
160
161/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000162static void
paul718e3742002-12-13 20:15:29 +0000163nexthop_delete (struct rib *rib, struct nexthop *nexthop)
164{
165 if (nexthop->next)
166 nexthop->next->prev = nexthop->prev;
167 if (nexthop->prev)
168 nexthop->prev->next = nexthop->next;
169 else
170 rib->nexthop = nexthop->next;
171 rib->nexthop_num--;
172}
173
Christian Frankefa713d92013-07-05 15:35:37 +0000174static void nexthops_free(struct nexthop *nexthop);
175
paul718e3742002-12-13 20:15:29 +0000176/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000177static void
paul718e3742002-12-13 20:15:29 +0000178nexthop_free (struct nexthop *nexthop)
179{
paula4b70762003-05-16 17:19:48 +0000180 if (nexthop->ifname)
181 XFREE (0, nexthop->ifname);
Christian Frankefa713d92013-07-05 15:35:37 +0000182 if (nexthop->resolved)
183 nexthops_free(nexthop->resolved);
paul718e3742002-12-13 20:15:29 +0000184 XFREE (MTYPE_NEXTHOP, nexthop);
185}
186
Christian Frankefa713d92013-07-05 15:35:37 +0000187/* Frees a list of nexthops */
188static void
189nexthops_free (struct nexthop *nexthop)
190{
191 struct nexthop *nh, *next;
192
193 for (nh = nexthop; nh; nh = next)
194 {
195 next = nh->next;
196 nexthop_free (nh);
197 }
198}
199
paul718e3742002-12-13 20:15:29 +0000200struct nexthop *
201nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
202{
203 struct nexthop *nexthop;
204
Stephen Hemminger393deb92008-08-18 14:13:29 -0700205 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000206 nexthop->type = NEXTHOP_TYPE_IFINDEX;
207 nexthop->ifindex = ifindex;
208
209 nexthop_add (rib, nexthop);
210
211 return nexthop;
212}
213
214struct nexthop *
215nexthop_ifname_add (struct rib *rib, char *ifname)
216{
217 struct nexthop *nexthop;
218
Stephen Hemminger393deb92008-08-18 14:13:29 -0700219 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000220 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000221 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000222
223 nexthop_add (rib, nexthop);
224
225 return nexthop;
226}
227
228struct nexthop *
Paul Jakma7514fb72007-05-02 16:05:35 +0000229nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
paul718e3742002-12-13 20:15:29 +0000230{
231 struct nexthop *nexthop;
232
Stephen Hemminger393deb92008-08-18 14:13:29 -0700233 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000234 nexthop->type = NEXTHOP_TYPE_IPV4;
235 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000236 if (src)
237 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000238
239 nexthop_add (rib, nexthop);
240
241 return nexthop;
242}
243
Josh Bailey26e2ae32012-03-22 01:09:21 -0700244struct nexthop *
paul718e3742002-12-13 20:15:29 +0000245nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
Paul Jakma7514fb72007-05-02 16:05:35 +0000246 struct in_addr *src, unsigned int ifindex)
paul718e3742002-12-13 20:15:29 +0000247{
248 struct nexthop *nexthop;
249
Stephen Hemminger393deb92008-08-18 14:13:29 -0700250 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000251 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
252 nexthop->gate.ipv4 = *ipv4;
Paul Jakma7514fb72007-05-02 16:05:35 +0000253 if (src)
254 nexthop->src.ipv4 = *src;
paul718e3742002-12-13 20:15:29 +0000255 nexthop->ifindex = ifindex;
256
257 nexthop_add (rib, nexthop);
258
259 return nexthop;
260}
261
paul718e3742002-12-13 20:15:29 +0000262struct nexthop *
263nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
264{
265 struct nexthop *nexthop;
266
Stephen Hemminger393deb92008-08-18 14:13:29 -0700267 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000268 nexthop->type = NEXTHOP_TYPE_IPV6;
269 nexthop->gate.ipv6 = *ipv6;
270
271 nexthop_add (rib, nexthop);
272
273 return nexthop;
274}
275
paula1ac18c2005-06-28 17:17:12 +0000276static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000277nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
278 char *ifname)
279{
280 struct nexthop *nexthop;
281
Stephen Hemminger393deb92008-08-18 14:13:29 -0700282 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000283 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
284 nexthop->gate.ipv6 = *ipv6;
285 nexthop->ifname = XSTRDUP (0, ifname);
286
287 nexthop_add (rib, nexthop);
288
289 return nexthop;
290}
291
paula1ac18c2005-06-28 17:17:12 +0000292static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000293nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
294 unsigned int ifindex)
295{
296 struct nexthop *nexthop;
297
Stephen Hemminger393deb92008-08-18 14:13:29 -0700298 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul718e3742002-12-13 20:15:29 +0000299 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
300 nexthop->gate.ipv6 = *ipv6;
301 nexthop->ifindex = ifindex;
302
303 nexthop_add (rib, nexthop);
304
305 return nexthop;
306}
paul718e3742002-12-13 20:15:29 +0000307
paul595db7f2003-05-25 21:35:06 +0000308struct nexthop *
309nexthop_blackhole_add (struct rib *rib)
310{
311 struct nexthop *nexthop;
312
Stephen Hemminger393deb92008-08-18 14:13:29 -0700313 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
paul595db7f2003-05-25 21:35:06 +0000314 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
315 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
316
317 nexthop_add (rib, nexthop);
318
319 return nexthop;
320}
321
Christian Frankefa713d92013-07-05 15:35:37 +0000322/* This method checks whether a recursive nexthop has at
323 * least one resolved nexthop in the fib.
324 */
325int
326nexthop_has_fib_child(struct nexthop *nexthop)
327{
328 struct nexthop *nh;
329
330 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
331 return 0;
332
333 for (nh = nexthop->resolved; nh; nh = nh->next)
334 if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
335 return 1;
336
337 return 0;
338}
339
paul718e3742002-12-13 20:15:29 +0000340/* If force flag is not set, do not modify falgs at all for uninstall
341 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000342static int
paul718e3742002-12-13 20:15:29 +0000343nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
344 struct route_node *top)
345{
346 struct prefix_ipv4 p;
347 struct route_table *table;
348 struct route_node *rn;
349 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000350 int resolved;
paul718e3742002-12-13 20:15:29 +0000351 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000352 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000353
354 if (nexthop->type == NEXTHOP_TYPE_IPV4)
355 nexthop->ifindex = 0;
356
357 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000358 {
359 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
360 nexthops_free(nexthop->resolved);
361 nexthop->resolved = NULL;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200362 rib->nexthop_mtu = 0;
Christian Frankefa713d92013-07-05 15:35:37 +0000363 }
paul718e3742002-12-13 20:15:29 +0000364
365 /* Make lookup prefix. */
366 memset (&p, 0, sizeof (struct prefix_ipv4));
367 p.family = AF_INET;
368 p.prefixlen = IPV4_MAX_PREFIXLEN;
369 p.prefix = nexthop->gate.ipv4;
370
371 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200372 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +0000373 if (! table)
374 return 0;
375
376 rn = route_node_match (table, (struct prefix *) &p);
377 while (rn)
378 {
379 route_unlock_node (rn);
380
David Warda50c1072009-12-03 15:34:39 +0300381 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000382 if (rn == top)
383 return 0;
384
385 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000386 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100387 {
388 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
389 continue;
390 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
391 break;
392 }
paul718e3742002-12-13 20:15:29 +0000393
394 /* If there is no selected route or matched route is EGP, go up
395 tree. */
396 if (! match
397 || match->type == ZEBRA_ROUTE_BGP)
398 {
399 do {
400 rn = rn->parent;
401 } while (rn && rn->info == NULL);
402 if (rn)
403 route_lock_node (rn);
404 }
405 else
406 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000407 /* If the longest prefix match for the nexthop yields
408 * a blackhole, mark it as inactive. */
409 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
410 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
411 return 0;
412
paul718e3742002-12-13 20:15:29 +0000413 if (match->type == ZEBRA_ROUTE_CONNECT)
414 {
415 /* Directly point connected route. */
416 newhop = match->nexthop;
417 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
418 nexthop->ifindex = newhop->ifindex;
419
420 return 1;
421 }
422 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
423 {
Christian Frankefa713d92013-07-05 15:35:37 +0000424 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000425 for (newhop = match->nexthop; newhop; newhop = newhop->next)
426 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
427 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
428 {
429 if (set)
430 {
431 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000432
433 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
434 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000435 /* If the resolving route specifies a gateway, use it */
436 if (newhop->type == NEXTHOP_TYPE_IPV4
437 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
438 || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
439 {
440 resolved_hop->type = newhop->type;
441 resolved_hop->gate.ipv4 = newhop->gate.ipv4;
Christian Frankefa713d92013-07-05 15:35:37 +0000442
Christian Frankec3e6b592013-07-05 15:35:40 +0000443 if (newhop->ifindex)
444 {
445 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
446 resolved_hop->ifindex = newhop->ifindex;
447 }
448 }
Christian Frankefa713d92013-07-05 15:35:37 +0000449
Christian Frankec3e6b592013-07-05 15:35:40 +0000450 /* If the resolving route is an interface route,
451 * it means the gateway we are looking up is connected
452 * to that interface. (The actual network is _not_ onlink).
453 * Therefore, the resolved route should have the original
454 * gateway as nexthop as it is directly connected.
455 *
456 * On Linux, we have to set the onlink netlink flag because
457 * otherwise, the kernel won't accept the route. */
paul718e3742002-12-13 20:15:29 +0000458 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000459 || newhop->type == NEXTHOP_TYPE_IFNAME)
460 {
461 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
462 resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
463 resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
464 resolved_hop->ifindex = newhop->ifindex;
465 }
Christian Frankefa713d92013-07-05 15:35:37 +0000466
467 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000468 }
Christian Frankefa713d92013-07-05 15:35:37 +0000469 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000470 }
Timo Teräsb11f3b52015-11-02 16:50:07 +0200471 if (resolved && set)
472 rib->nexthop_mtu = match->mtu;
Christian Frankefa713d92013-07-05 15:35:37 +0000473 return resolved;
paul718e3742002-12-13 20:15:29 +0000474 }
475 else
476 {
477 return 0;
478 }
479 }
480 }
481 return 0;
482}
483
paul718e3742002-12-13 20:15:29 +0000484/* If force flag is not set, do not modify falgs at all for uninstall
485 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000486static int
paul718e3742002-12-13 20:15:29 +0000487nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
488 struct route_node *top)
489{
490 struct prefix_ipv6 p;
491 struct route_table *table;
492 struct route_node *rn;
493 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000494 int resolved;
paul718e3742002-12-13 20:15:29 +0000495 struct nexthop *newhop;
Christian Frankefa713d92013-07-05 15:35:37 +0000496 struct nexthop *resolved_hop;
paul718e3742002-12-13 20:15:29 +0000497
498 if (nexthop->type == NEXTHOP_TYPE_IPV6)
499 nexthop->ifindex = 0;
500
501 if (set)
Christian Frankefa713d92013-07-05 15:35:37 +0000502 {
503 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
504 nexthops_free(nexthop->resolved);
505 nexthop->resolved = NULL;
506 }
paul718e3742002-12-13 20:15:29 +0000507
508 /* Make lookup prefix. */
509 memset (&p, 0, sizeof (struct prefix_ipv6));
510 p.family = AF_INET6;
511 p.prefixlen = IPV6_MAX_PREFIXLEN;
512 p.prefix = nexthop->gate.ipv6;
513
514 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200515 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +0000516 if (! table)
517 return 0;
518
519 rn = route_node_match (table, (struct prefix *) &p);
520 while (rn)
521 {
522 route_unlock_node (rn);
523
David Warda50c1072009-12-03 15:34:39 +0300524 /* If lookup self prefix return immediately. */
paul718e3742002-12-13 20:15:29 +0000525 if (rn == top)
526 return 0;
527
528 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000529 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100530 {
531 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
532 continue;
533 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
534 break;
535 }
paul718e3742002-12-13 20:15:29 +0000536
537 /* If there is no selected route or matched route is EGP, go up
538 tree. */
539 if (! match
540 || match->type == ZEBRA_ROUTE_BGP)
541 {
542 do {
543 rn = rn->parent;
544 } while (rn && rn->info == NULL);
545 if (rn)
546 route_lock_node (rn);
547 }
548 else
549 {
Christian Franke48a53dc2013-07-05 15:35:38 +0000550 /* If the longest prefix match for the nexthop yields
551 * a blackhole, mark it as inactive. */
552 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
553 || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
554 return 0;
555
paul718e3742002-12-13 20:15:29 +0000556 if (match->type == ZEBRA_ROUTE_CONNECT)
557 {
558 /* Directly point connected route. */
559 newhop = match->nexthop;
560
561 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
562 nexthop->ifindex = newhop->ifindex;
563
564 return 1;
565 }
566 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
567 {
Christian Frankefa713d92013-07-05 15:35:37 +0000568 resolved = 0;
paul718e3742002-12-13 20:15:29 +0000569 for (newhop = match->nexthop; newhop; newhop = newhop->next)
570 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
571 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
572 {
573 if (set)
574 {
575 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
Christian Frankefa713d92013-07-05 15:35:37 +0000576
577 resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
578 SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
Christian Frankec3e6b592013-07-05 15:35:40 +0000579 /* See nexthop_active_ipv4 for a description how the
580 * resolved nexthop is constructed. */
paul718e3742002-12-13 20:15:29 +0000581 if (newhop->type == NEXTHOP_TYPE_IPV6
582 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
583 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
Christian Frankec3e6b592013-07-05 15:35:40 +0000584 {
585 resolved_hop->type = newhop->type;
586 resolved_hop->gate.ipv6 = newhop->gate.ipv6;
587
588 if (newhop->ifindex)
589 {
590 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
591 resolved_hop->ifindex = newhop->ifindex;
592 }
593 }
Christian Frankefa713d92013-07-05 15:35:37 +0000594
paul718e3742002-12-13 20:15:29 +0000595 if (newhop->type == NEXTHOP_TYPE_IFINDEX
Christian Frankec3e6b592013-07-05 15:35:40 +0000596 || newhop->type == NEXTHOP_TYPE_IFNAME)
597 {
598 resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
599 resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
600 resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
601 resolved_hop->ifindex = newhop->ifindex;
602 }
Christian Frankefa713d92013-07-05 15:35:37 +0000603
604 _nexthop_add(&nexthop->resolved, resolved_hop);
paul718e3742002-12-13 20:15:29 +0000605 }
Christian Frankefa713d92013-07-05 15:35:37 +0000606 resolved = 1;
paul718e3742002-12-13 20:15:29 +0000607 }
Christian Frankefa713d92013-07-05 15:35:37 +0000608 return resolved;
paul718e3742002-12-13 20:15:29 +0000609 }
610 else
611 {
612 return 0;
613 }
614 }
615 }
616 return 0;
617}
paul718e3742002-12-13 20:15:29 +0000618
619struct rib *
David Lamparter24480d42015-01-22 19:09:36 +0100620rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
Feng Lu0d0686f2015-05-22 11:40:02 +0200621 struct route_node **rn_out, vrf_id_t vrf_id)
Everton Marques3dea1782014-09-22 19:35:51 -0300622{
623 struct route_table *table;
624 struct route_node *rn;
625 struct rib *match;
626 struct nexthop *newhop, *tnewhop;
627 int recursing;
628
629 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200630 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
Everton Marques3dea1782014-09-22 19:35:51 -0300631 if (! table)
632 return 0;
633
634 rn = route_node_match_ipv4 (table, &addr);
635
636 while (rn)
637 {
638 route_unlock_node (rn);
639
640 /* Pick up selected route. */
641 RNODE_FOREACH_RIB (rn, match)
642 {
643 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
644 continue;
645 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
646 break;
647 }
648
649 /* If there is no selected route or matched route is EGP, go up
650 tree. */
Everton Marques83d71122014-09-19 16:39:34 -0300651 if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
Everton Marques3dea1782014-09-22 19:35:51 -0300652 {
653 do {
654 rn = rn->parent;
655 } while (rn && rn->info == NULL);
656 if (rn)
657 route_lock_node (rn);
658 }
659 else
660 {
David Lamparter24480d42015-01-22 19:09:36 +0100661 if (match->type != ZEBRA_ROUTE_CONNECT)
Everton Marques3dea1782014-09-22 19:35:51 -0300662 {
David Lamparter24480d42015-01-22 19:09:36 +0100663 int found = 0;
Everton Marques3dea1782014-09-22 19:35:51 -0300664 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
665 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
David Lamparter24480d42015-01-22 19:09:36 +0100666 {
667 found = 1;
668 break;
669 }
670 if (!found)
671 return NULL;
Everton Marques3dea1782014-09-22 19:35:51 -0300672 }
David Lamparter24480d42015-01-22 19:09:36 +0100673
674 if (rn_out)
675 *rn_out = rn;
676 return match;
Everton Marques3dea1782014-09-22 19:35:51 -0300677 }
678 }
679 return NULL;
680}
681
682struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200683rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out,
684 vrf_id_t vrf_id)
David Lamparterbd078122015-01-06 19:53:24 +0100685{
686 struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
687 struct route_node *m_rn = NULL, *u_rn = NULL;
688 int skip_bgp = 0; /* bool */
689
690 switch (ipv4_multicast_mode)
691 {
692 case MCAST_MRIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200693 return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out,
694 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100695 case MCAST_URIB_ONLY:
Feng Lu0d0686f2015-05-22 11:40:02 +0200696 return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out,
697 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100698 case MCAST_NO_CONFIG:
699 case MCAST_MIX_MRIB_FIRST:
Feng Lu0d0686f2015-05-22 11:40:02 +0200700 rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
701 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100702 if (!mrib)
Feng Lu0d0686f2015-05-22 11:40:02 +0200703 rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
704 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100705 break;
706 case MCAST_MIX_DISTANCE:
Feng Lu0d0686f2015-05-22 11:40:02 +0200707 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
708 vrf_id);
709 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
710 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100711 if (mrib && urib)
712 rib = urib->distance < mrib->distance ? urib : mrib;
713 else if (mrib)
714 rib = mrib;
715 else if (urib)
716 rib = urib;
717 break;
718 case MCAST_MIX_PFXLEN:
Feng Lu0d0686f2015-05-22 11:40:02 +0200719 mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
720 vrf_id);
721 urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
722 vrf_id);
David Lamparterbd078122015-01-06 19:53:24 +0100723 if (mrib && urib)
724 rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
725 else if (mrib)
726 rib = mrib;
727 else if (urib)
728 rib = urib;
729 break;
730 }
731
732 if (rn_out)
733 *rn_out = (rib == mrib) ? m_rn : u_rn;
734
735 if (IS_ZEBRA_DEBUG_RIB)
736 {
737 char buf[BUFSIZ];
738 inet_ntop (AF_INET, &addr, buf, BUFSIZ);
739
Feng Lu0d0686f2015-05-22 11:40:02 +0200740 zlog_debug("%s: %s vrf %u: found %s, using %s",
741 __func__, buf, vrf_id,
David Lamparterbd078122015-01-06 19:53:24 +0100742 mrib ? (urib ? "MRIB+URIB" : "MRIB") :
743 urib ? "URIB" : "nothing",
744 rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
745 }
746 return rib;
747}
748
749void
750multicast_mode_ipv4_set (enum multicast_mode mode)
751{
752 if (IS_ZEBRA_DEBUG_RIB)
753 zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
754 ipv4_multicast_mode = mode;
755}
756
757enum multicast_mode
758multicast_mode_ipv4_get (void)
759{
760 return ipv4_multicast_mode;
761}
762
763struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200764rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000765{
766 struct route_table *table;
767 struct route_node *rn;
768 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000769 struct nexthop *nexthop, *tnexthop;
770 int recursing;
paul718e3742002-12-13 20:15:29 +0000771
772 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200773 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000774 if (! table)
775 return 0;
776
777 rn = route_node_lookup (table, (struct prefix *) p);
778
779 /* No route for this prefix. */
780 if (! rn)
781 return NULL;
782
783 /* Unlock node. */
784 route_unlock_node (rn);
785
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000786 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100787 {
788 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
789 continue;
790 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
791 break;
792 }
paul718e3742002-12-13 20:15:29 +0000793
794 if (! match || match->type == ZEBRA_ROUTE_BGP)
795 return NULL;
796
797 if (match->type == ZEBRA_ROUTE_CONNECT)
798 return match;
799
Christian Frankefa713d92013-07-05 15:35:37 +0000800 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +0000801 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
802 return match;
803
804 return NULL;
805}
806
Denis Ovsienkodc958242007-08-13 16:03:06 +0000807/*
808 * This clone function, unlike its original rib_lookup_ipv4(), checks
809 * if specified IPv4 route record (prefix/mask -> gate) exists in
810 * the whole RIB and has ZEBRA_FLAG_SELECTED set.
811 *
812 * Return values:
813 * -1: error
814 * 0: exact match found
815 * 1: a match was found with a different gate
816 * 2: connected route found
817 * 3: no matches found
818 */
819int
Feng Lu0d0686f2015-05-22 11:40:02 +0200820rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
821 vrf_id_t vrf_id)
Denis Ovsienkodc958242007-08-13 16:03:06 +0000822{
823 struct route_table *table;
824 struct route_node *rn;
825 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000826 struct nexthop *nexthop, *tnexthop;
827 int recursing;
828 int nexthops_active;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000829
830 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200831 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000832 if (! table)
833 return ZEBRA_RIB_LOOKUP_ERROR;
834
835 /* Scan the RIB table for exactly matching RIB entry. */
836 rn = route_node_lookup (table, (struct prefix *) p);
837
838 /* No route for this prefix. */
839 if (! rn)
840 return ZEBRA_RIB_NOTFOUND;
841
842 /* Unlock node. */
843 route_unlock_node (rn);
844
845 /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000846 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100847 {
848 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
849 continue;
850 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
851 break;
852 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000853
854 /* None such found :( */
855 if (!match)
856 return ZEBRA_RIB_NOTFOUND;
857
858 if (match->type == ZEBRA_ROUTE_CONNECT)
859 return ZEBRA_RIB_FOUND_CONNECTED;
860
861 /* Ok, we have a cood candidate, let's check it's nexthop list... */
Christian Frankefa713d92013-07-05 15:35:37 +0000862 nexthops_active = 0;
863 for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000864 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
Denis Ovsienkodc958242007-08-13 16:03:06 +0000865 {
Christian Frankefa713d92013-07-05 15:35:37 +0000866 nexthops_active = 1;
867 if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
868 return ZEBRA_RIB_FOUND_EXACT;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000869 if (IS_ZEBRA_DEBUG_RIB)
Christian Frankefa713d92013-07-05 15:35:37 +0000870 {
871 char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
872 inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
873 inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
874 zlog_debug ("%s: qgate == %s, %s == %s", __func__,
875 qgate_buf, recursing ? "rgate" : "gate", gate_buf);
876 }
Denis Ovsienkodc958242007-08-13 16:03:06 +0000877 }
Christian Frankefa713d92013-07-05 15:35:37 +0000878
879 if (nexthops_active)
880 return ZEBRA_RIB_FOUND_NOGATE;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000881
882 return ZEBRA_RIB_NOTFOUND;
883}
884
paul718e3742002-12-13 20:15:29 +0000885struct rib *
Feng Lu0d0686f2015-05-22 11:40:02 +0200886rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000887{
888 struct prefix_ipv6 p;
889 struct route_table *table;
890 struct route_node *rn;
891 struct rib *match;
Christian Frankefa713d92013-07-05 15:35:37 +0000892 struct nexthop *newhop, *tnewhop;
893 int recursing;
paul718e3742002-12-13 20:15:29 +0000894
895 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200896 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +0000897 if (! table)
898 return 0;
899
900 memset (&p, 0, sizeof (struct prefix_ipv6));
901 p.family = AF_INET6;
902 p.prefixlen = IPV6_MAX_PREFIXLEN;
903 IPV6_ADDR_COPY (&p.prefix, addr);
904
905 rn = route_node_match (table, (struct prefix *) &p);
906
907 while (rn)
908 {
909 route_unlock_node (rn);
910
911 /* Pick up selected route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +0000912 RNODE_FOREACH_RIB (rn, match)
Stephen Hemminger16814f92008-08-17 17:39:31 +0100913 {
914 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
915 continue;
916 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
917 break;
918 }
paul718e3742002-12-13 20:15:29 +0000919
920 /* If there is no selected route or matched route is EGP, go up
921 tree. */
922 if (! match
923 || match->type == ZEBRA_ROUTE_BGP)
924 {
925 do {
926 rn = rn->parent;
927 } while (rn && rn->info == NULL);
928 if (rn)
929 route_lock_node (rn);
930 }
931 else
932 {
933 if (match->type == ZEBRA_ROUTE_CONNECT)
934 /* Directly point connected route. */
935 return match;
936 else
937 {
Christian Frankefa713d92013-07-05 15:35:37 +0000938 for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
paul718e3742002-12-13 20:15:29 +0000939 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
940 return match;
941 return NULL;
942 }
943 }
944 }
945 return NULL;
946}
paul718e3742002-12-13 20:15:29 +0000947
Paul Jakma7514fb72007-05-02 16:05:35 +0000948#define RIB_SYSTEM_ROUTE(R) \
949 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
950
Denis Ovsienkodc958242007-08-13 16:03:06 +0000951/* This function verifies reachability of one given nexthop, which can be
952 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
953 * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
954 * nexthop->ifindex will be updated appropriately as well.
955 * An existing route map can turn (otherwise active) nexthop into inactive, but
956 * not vice versa.
957 *
958 * The return value is the final value of 'ACTIVE' flag.
959 */
960
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +0300961static unsigned
paul718e3742002-12-13 20:15:29 +0000962nexthop_active_check (struct route_node *rn, struct rib *rib,
963 struct nexthop *nexthop, int set)
964{
Christian Frankef3a17322013-07-05 15:35:41 +0000965 rib_table_info_t *info = rn->table->info;
paul718e3742002-12-13 20:15:29 +0000966 struct interface *ifp;
Paul Jakma7514fb72007-05-02 16:05:35 +0000967 route_map_result_t ret = RMAP_MATCH;
968 extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
969 struct route_map *rmap;
970 int family;
paul718e3742002-12-13 20:15:29 +0000971
Paul Jakma7514fb72007-05-02 16:05:35 +0000972 family = 0;
paul718e3742002-12-13 20:15:29 +0000973 switch (nexthop->type)
974 {
975 case NEXTHOP_TYPE_IFINDEX:
Feng Lu0d0686f2015-05-22 11:40:02 +0200976 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000977 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000978 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
979 else
980 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
981 break;
paul718e3742002-12-13 20:15:29 +0000982 case NEXTHOP_TYPE_IPV6_IFNAME:
Paul Jakma7514fb72007-05-02 16:05:35 +0000983 family = AFI_IP6;
984 case NEXTHOP_TYPE_IFNAME:
Feng Lu0d0686f2015-05-22 11:40:02 +0200985 ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +0000986 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000987 {
988 if (set)
989 nexthop->ifindex = ifp->ifindex;
990 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
991 }
992 else
993 {
994 if (set)
995 nexthop->ifindex = 0;
996 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
997 }
998 break;
999 case NEXTHOP_TYPE_IPV4:
1000 case NEXTHOP_TYPE_IPV4_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001001 family = AFI_IP;
paul718e3742002-12-13 20:15:29 +00001002 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
1003 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1004 else
1005 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1006 break;
paul718e3742002-12-13 20:15:29 +00001007 case NEXTHOP_TYPE_IPV6:
Paul Jakma7514fb72007-05-02 16:05:35 +00001008 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001009 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1010 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1011 else
1012 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1013 break;
1014 case NEXTHOP_TYPE_IPV6_IFINDEX:
Paul Jakma7514fb72007-05-02 16:05:35 +00001015 family = AFI_IP6;
paul718e3742002-12-13 20:15:29 +00001016 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1017 {
Feng Lu0d0686f2015-05-22 11:40:02 +02001018 ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
Andrew J. Schorr3f087672008-01-08 20:12:46 +00001019 if (ifp && if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001020 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1021 else
1022 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1023 }
1024 else
1025 {
1026 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1027 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1028 else
1029 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1030 }
1031 break;
paul595db7f2003-05-25 21:35:06 +00001032 case NEXTHOP_TYPE_BLACKHOLE:
1033 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1034 break;
paul718e3742002-12-13 20:15:29 +00001035 default:
1036 break;
1037 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001038 if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1039 return 0;
1040
Christian Frankef3a17322013-07-05 15:35:41 +00001041 /* XXX: What exactly do those checks do? Do we support
1042 * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
Paul Jakma7514fb72007-05-02 16:05:35 +00001043 if (RIB_SYSTEM_ROUTE(rib) ||
1044 (family == AFI_IP && rn->p.family != AF_INET) ||
1045 (family == AFI_IP6 && rn->p.family != AF_INET6))
1046 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1047
Christian Frankef3a17322013-07-05 15:35:41 +00001048 /* The original code didn't determine the family correctly
1049 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
1050 * from the rib_table_info in those cases.
1051 * Possibly it may be better to use only the rib_table_info
1052 * in every case.
1053 */
1054 if (!family)
1055 family = info->afi;
1056
Paul Jakma7514fb72007-05-02 16:05:35 +00001057 rmap = 0;
1058 if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1059 proto_rm[family][rib->type])
1060 rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1061 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1062 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1063 if (rmap) {
Feng Lu1885d0a2015-05-22 11:40:04 +02001064 struct nexthop_vrfid nh_vrf = {nexthop, rib->vrf_id};
1065 ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, &nh_vrf);
Paul Jakma7514fb72007-05-02 16:05:35 +00001066 }
1067
1068 if (ret == RMAP_DENYMATCH)
1069 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul718e3742002-12-13 20:15:29 +00001070 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1071}
1072
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001073/* Iterate over all nexthops of the given RIB entry and refresh their
1074 * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1075 * nexthop is found to toggle the ACTIVE flag, the whole rib structure
Timo Teräs7eb61362015-11-02 16:50:05 +02001076 * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001077 * transparently passed to nexthop_active_check().
1078 *
1079 * Return value is the new number of active nexthops.
1080 */
1081
paula1ac18c2005-06-28 17:17:12 +00001082static int
paul718e3742002-12-13 20:15:29 +00001083nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1084{
1085 struct nexthop *nexthop;
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001086 unsigned int prev_active, prev_index, new_active;
paul718e3742002-12-13 20:15:29 +00001087
1088 rib->nexthop_active_num = 0;
Timo Teräs7eb61362015-11-02 16:50:05 +02001089 UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
paul718e3742002-12-13 20:15:29 +00001090
1091 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001092 {
1093 prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001094 prev_index = nexthop->ifindex;
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001095 if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1096 rib->nexthop_active_num++;
Joakim Tjernlundc3a56062009-06-24 19:15:36 +02001097 if (prev_active != new_active ||
1098 prev_index != nexthop->ifindex)
Timo Teräs7eb61362015-11-02 16:50:05 +02001099 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
Denis Ovsienko03e232a2007-08-14 09:46:48 +00001100 }
paul718e3742002-12-13 20:15:29 +00001101 return rib->nexthop_active_num;
1102}
paul6baeb982003-10-28 03:47:15 +00001103
David Lamparter6b0655a2014-06-04 06:53:35 +02001104
paul718e3742002-12-13 20:15:29 +00001105
paula1ac18c2005-06-28 17:17:12 +00001106static void
paul718e3742002-12-13 20:15:29 +00001107rib_install_kernel (struct route_node *rn, struct rib *rib)
1108{
1109 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001110 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001111 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001112 int recursing;
paul718e3742002-12-13 20:15:29 +00001113
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001114 if (info->safi != SAFI_UNICAST)
1115 {
1116 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1117 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1118 return;
1119 }
1120
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001121 /*
1122 * Make sure we update the FPM any time we send new information to
1123 * the kernel.
1124 */
1125 zfpm_trigger_update (rn, "installing in kernel");
paul718e3742002-12-13 20:15:29 +00001126 switch (PREFIX_FAMILY (&rn->p))
1127 {
1128 case AF_INET:
1129 ret = kernel_add_ipv4 (&rn->p, rib);
1130 break;
1131#ifdef HAVE_IPV6
1132 case AF_INET6:
1133 ret = kernel_add_ipv6 (&rn->p, rib);
1134 break;
1135#endif /* HAVE_IPV6 */
1136 }
1137
Denis Ovsienkodc958242007-08-13 16:03:06 +00001138 /* This condition is never met, if we are using rt_socket.c */
paul718e3742002-12-13 20:15:29 +00001139 if (ret < 0)
1140 {
Christian Frankefa713d92013-07-05 15:35:37 +00001141 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001142 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1143 }
1144}
1145
1146/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001147static int
paul718e3742002-12-13 20:15:29 +00001148rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
1149{
1150 int ret = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001151 struct nexthop *nexthop, *tnexthop;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001152 rib_table_info_t *info = rn->table->info;
Christian Frankefa713d92013-07-05 15:35:37 +00001153 int recursing;
paul718e3742002-12-13 20:15:29 +00001154
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001155 if (info->safi != SAFI_UNICAST)
1156 {
1157 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1158 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1159 return ret;
1160 }
1161
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001162 /*
1163 * Make sure we update the FPM any time we send new information to
1164 * the kernel.
1165 */
1166 zfpm_trigger_update (rn, "uninstalling from kernel");
1167
paul718e3742002-12-13 20:15:29 +00001168 switch (PREFIX_FAMILY (&rn->p))
1169 {
1170 case AF_INET:
1171 ret = kernel_delete_ipv4 (&rn->p, rib);
1172 break;
1173#ifdef HAVE_IPV6
1174 case AF_INET6:
1175 ret = kernel_delete_ipv6 (&rn->p, rib);
1176 break;
1177#endif /* HAVE_IPV6 */
1178 }
1179
Christian Frankefa713d92013-07-05 15:35:37 +00001180 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001181 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1182
1183 return ret;
1184}
1185
1186/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +00001187static void
paul718e3742002-12-13 20:15:29 +00001188rib_uninstall (struct route_node *rn, struct rib *rib)
1189{
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001190 rib_table_info_t *info = rn->table->info;
1191
paul718e3742002-12-13 20:15:29 +00001192 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1193 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001194 if (info->safi == SAFI_UNICAST)
1195 zfpm_trigger_update (rn, "rib_uninstall");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001196
paul718e3742002-12-13 20:15:29 +00001197 redistribute_delete (&rn->p, rib);
1198 if (! RIB_SYSTEM_ROUTE (rib))
1199 rib_uninstall_kernel (rn, rib);
1200 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1201 }
1202}
1203
Paul Jakma6d691122006-07-27 21:49:00 +00001204static void rib_unlink (struct route_node *, struct rib *);
1205
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001206/*
1207 * rib_can_delete_dest
1208 *
1209 * Returns TRUE if the given dest can be deleted from the table.
1210 */
1211static int
1212rib_can_delete_dest (rib_dest_t *dest)
1213{
1214 if (dest->routes)
1215 {
1216 return 0;
1217 }
1218
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001219 /*
1220 * Don't delete the dest if we have to update the FPM about this
1221 * prefix.
1222 */
1223 if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1224 CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1225 return 0;
1226
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001227 return 1;
1228}
1229
1230/*
1231 * rib_gc_dest
1232 *
1233 * Garbage collect the rib dest corresponding to the given route node
1234 * if appropriate.
1235 *
1236 * Returns TRUE if the dest was deleted, FALSE otherwise.
1237 */
1238int
1239rib_gc_dest (struct route_node *rn)
1240{
1241 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001242
1243 dest = rib_dest_from_rnode (rn);
1244 if (!dest)
1245 return 0;
1246
1247 if (!rib_can_delete_dest (dest))
1248 return 0;
1249
1250 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001251 rnode_debug (rn, "removing dest from table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001252
1253 dest->rnode = NULL;
1254 XFREE (MTYPE_RIB_DEST, dest);
1255 rn->info = NULL;
1256
1257 /*
1258 * Release the one reference that we keep on the route node.
1259 */
1260 route_unlock_node (rn);
1261 return 1;
1262}
1263
paul718e3742002-12-13 20:15:29 +00001264/* Core function for processing routing information base. */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001265static void
1266rib_process (struct route_node *rn)
paul718e3742002-12-13 20:15:29 +00001267{
1268 struct rib *rib;
1269 struct rib *next;
1270 struct rib *fib = NULL;
1271 struct rib *select = NULL;
Paul Jakma6d691122006-07-27 21:49:00 +00001272 struct rib *del = NULL;
pauld753e9e2003-01-22 19:45:50 +00001273 int installed = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001274 struct nexthop *nexthop = NULL, *tnexthop;
1275 int recursing;
Balaji95116332014-10-23 15:25:25 +00001276 rib_table_info_t *info;
1277
paul4d38fdb2005-04-28 17:35:14 +00001278 assert (rn);
Balaji95116332014-10-23 15:25:25 +00001279
1280 info = rn->table->info;
1281
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001282 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00001283 {
paul718e3742002-12-13 20:15:29 +00001284 /* Currently installed rib. */
1285 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
Paul Jakma6d691122006-07-27 21:49:00 +00001286 {
1287 assert (fib == NULL);
1288 fib = rib;
1289 }
1290
1291 /* Unlock removed routes, so they'll be freed, bar the FIB entry,
1292 * which we need to do do further work with below.
1293 */
1294 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1295 {
1296 if (rib != fib)
1297 {
1298 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001299 rnode_debug (rn, "rn %p, removing rib %p",
1300 (void *)rn, (void *)rib);
1301 rib_unlink (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001302 }
1303 else
1304 del = rib;
1305
1306 continue;
1307 }
paul4d38fdb2005-04-28 17:35:14 +00001308
paul718e3742002-12-13 20:15:29 +00001309 /* Skip unreachable nexthop. */
1310 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +00001311 continue;
paul718e3742002-12-13 20:15:29 +00001312
1313 /* Infinit distance. */
1314 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +00001315 continue;
paul718e3742002-12-13 20:15:29 +00001316
paulaf887b52006-01-18 14:52:52 +00001317 /* Newly selected rib, the common case. */
1318 if (!select)
1319 {
1320 select = rib;
1321 continue;
1322 }
1323
1324 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +00001325 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +00001326 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +00001327 * - lower metric beats higher for equal distance
1328 * - last, hence oldest, route wins tie break.
1329 */
paula1038a12006-01-30 14:08:51 +00001330
1331 /* Connected routes. Pick the last connected
1332 * route of the set of lowest metric connected routes.
1333 */
paula8d9c1f2006-01-25 06:31:04 +00001334 if (rib->type == ZEBRA_ROUTE_CONNECT)
1335 {
paula1038a12006-01-30 14:08:51 +00001336 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +00001337 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +00001338 select = rib;
1339 continue;
paula8d9c1f2006-01-25 06:31:04 +00001340 }
1341 else if (select->type == ZEBRA_ROUTE_CONNECT)
1342 continue;
1343
1344 /* higher distance loses */
1345 if (rib->distance > select->distance)
1346 continue;
1347
1348 /* lower wins */
1349 if (rib->distance < select->distance)
1350 {
paulaf887b52006-01-18 14:52:52 +00001351 select = rib;
paula8d9c1f2006-01-25 06:31:04 +00001352 continue;
1353 }
1354
1355 /* metric tie-breaks equal distance */
1356 if (rib->metric <= select->metric)
1357 select = rib;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001358 } /* RNODE_FOREACH_RIB_SAFE */
Denis Ovsienkodc958242007-08-13 16:03:06 +00001359
1360 /* After the cycle is finished, the following pointers will be set:
1361 * select --- the winner RIB entry, if any was found, otherwise NULL
1362 * fib --- the SELECTED RIB entry, if any, otherwise NULL
1363 * del --- equal to fib, if fib is queued for deletion, NULL otherwise
1364 * rib --- NULL
1365 */
1366
1367 /* Same RIB entry is selected. Update FIB and finish. */
paul718e3742002-12-13 20:15:29 +00001368 if (select && select == fib)
1369 {
Paul Jakma6d691122006-07-27 21:49:00 +00001370 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001371 rnode_debug (rn, "Updating existing route, select %p, fib %p",
David Lampartereed3c482015-03-03 08:51:53 +01001372 (void *)select, (void *)fib);
Timo Teräs7eb61362015-11-02 16:50:05 +02001373 if (CHECK_FLAG (select->status, RIB_ENTRY_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +00001374 {
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001375 if (info->safi == SAFI_UNICAST)
1376 zfpm_trigger_update (rn, "updating existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001377
paul4d38fdb2005-04-28 17:35:14 +00001378 redistribute_delete (&rn->p, select);
1379 if (! RIB_SYSTEM_ROUTE (select))
1380 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001381
paul4d38fdb2005-04-28 17:35:14 +00001382 /* Set real nexthop. */
1383 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +00001384
paul4d38fdb2005-04-28 17:35:14 +00001385 if (! RIB_SYSTEM_ROUTE (select))
1386 rib_install_kernel (rn, select);
1387 redistribute_add (&rn->p, select);
1388 }
pauld753e9e2003-01-22 19:45:50 +00001389 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001390 {
1391 /* Housekeeping code to deal with
1392 race conditions in kernel with linux
1393 netlink reporting interface up before IPv4 or IPv6 protocol
1394 is ready to add routes.
1395 This makes sure the routes are IN the kernel.
1396 */
pauld753e9e2003-01-22 19:45:50 +00001397
Christian Frankefa713d92013-07-05 15:35:37 +00001398 for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001399 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paul4d38fdb2005-04-28 17:35:14 +00001400 {
Denis Ovsienkoa3aaf5b2007-10-04 10:49:21 +00001401 installed = 1;
1402 break;
paul4d38fdb2005-04-28 17:35:14 +00001403 }
1404 if (! installed)
1405 rib_install_kernel (rn, select);
1406 }
Paul Jakma6d691122006-07-27 21:49:00 +00001407 goto end;
paul718e3742002-12-13 20:15:29 +00001408 }
1409
Denis Ovsienkodc958242007-08-13 16:03:06 +00001410 /* At this point we either haven't found the best RIB entry or it is
1411 * different from what we currently intend to flag with SELECTED. In both
1412 * cases, if a RIB block is present in FIB, it should be withdrawn.
1413 */
paul718e3742002-12-13 20:15:29 +00001414 if (fib)
1415 {
Paul Jakma6d691122006-07-27 21:49:00 +00001416 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001417 rnode_debug (rn, "Removing existing route, fib %p", (void *)fib);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001418
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001419 if (info->safi == SAFI_UNICAST)
1420 zfpm_trigger_update (rn, "removing existing route");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001421
paul718e3742002-12-13 20:15:29 +00001422 redistribute_delete (&rn->p, fib);
1423 if (! RIB_SYSTEM_ROUTE (fib))
1424 rib_uninstall_kernel (rn, fib);
1425 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1426
1427 /* Set real nexthop. */
1428 nexthop_active_update (rn, fib, 1);
1429 }
1430
Denis Ovsienkodc958242007-08-13 16:03:06 +00001431 /* Regardless of some RIB entry being SELECTED or not before, now we can
1432 * tell, that if a new winner exists, FIB is still not updated with this
1433 * data, but ready to be.
1434 */
paul718e3742002-12-13 20:15:29 +00001435 if (select)
1436 {
Paul Jakma6d691122006-07-27 21:49:00 +00001437 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001438 rnode_debug (rn, "Adding route, select %p", (void *)select);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001439
David Lamparter7ce9e6a2015-01-12 07:05:06 +01001440 if (info->safi == SAFI_UNICAST)
1441 zfpm_trigger_update (rn, "new route selected");
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00001442
paul718e3742002-12-13 20:15:29 +00001443 /* Set real nexthop. */
1444 nexthop_active_update (rn, select, 1);
1445
1446 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001447 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001448 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1449 redistribute_add (&rn->p, select);
1450 }
paul4d38fdb2005-04-28 17:35:14 +00001451
Paul Jakma6d691122006-07-27 21:49:00 +00001452 /* FIB route was removed, should be deleted */
1453 if (del)
1454 {
1455 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001456 rnode_debug (rn, "Deleting fib %p, rn %p", (void *)del, (void *)rn);
Paul Jakma6d691122006-07-27 21:49:00 +00001457 rib_unlink (rn, del);
1458 }
paul4d38fdb2005-04-28 17:35:14 +00001459
Paul Jakma6d691122006-07-27 21:49:00 +00001460end:
1461 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001462 rnode_debug (rn, "rn %p dequeued", (void *)rn);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001463
1464 /*
1465 * Check if the dest can be deleted now.
1466 */
1467 rib_gc_dest (rn);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001468}
1469
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001470/* Take a list of route_node structs and return 1, if there was a record
1471 * picked from it and processed by rib_process(). Don't process more,
1472 * than one RN record; operate only in the specified sub-queue.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001473 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001474static unsigned int
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001475process_subq (struct list * subq, u_char qindex)
1476{
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001477 struct listnode *lnode = listhead (subq);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001478 struct route_node *rnode;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001479
1480 if (!lnode)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001481 return 0;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001482
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001483 rnode = listgetdata (lnode);
1484 rib_process (rnode);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001485
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001486 if (rnode->info)
1487 UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1488
Chris Caputo67b94672009-07-18 04:02:26 +00001489#if 0
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001490 else
1491 {
1492 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1493 __func__, rnode, rnode->lock);
1494 zlog_backtrace(LOG_DEBUG);
1495 }
Chris Caputo67b94672009-07-18 04:02:26 +00001496#endif
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001497 route_unlock_node (rnode);
1498 list_delete_node (subq, lnode);
1499 return 1;
1500}
1501
1502/* Dispatch the meta queue by picking, processing and unlocking the next RN from
1503 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1504 * is pointed to the meta queue structure.
1505 */
1506static wq_item_status
1507meta_queue_process (struct work_queue *dummy, void *data)
1508{
1509 struct meta_queue * mq = data;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001510 unsigned i;
1511
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001512 for (i = 0; i < MQ_SIZE; i++)
1513 if (process_subq (mq->subq[i], i))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001514 {
1515 mq->size--;
1516 break;
1517 }
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001518 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1519}
1520
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001521/*
1522 * Map from rib types to queue type (priority) in meta queue
1523 */
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001524static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1525 [ZEBRA_ROUTE_SYSTEM] = 4,
1526 [ZEBRA_ROUTE_KERNEL] = 0,
1527 [ZEBRA_ROUTE_CONNECT] = 0,
1528 [ZEBRA_ROUTE_STATIC] = 1,
1529 [ZEBRA_ROUTE_RIP] = 2,
1530 [ZEBRA_ROUTE_RIPNG] = 2,
1531 [ZEBRA_ROUTE_OSPF] = 2,
1532 [ZEBRA_ROUTE_OSPF6] = 2,
1533 [ZEBRA_ROUTE_ISIS] = 2,
1534 [ZEBRA_ROUTE_BGP] = 3,
1535 [ZEBRA_ROUTE_HSLS] = 4,
Paul Jakma57345092011-12-25 17:52:09 +01001536 [ZEBRA_ROUTE_BABEL] = 2,
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001537};
1538
1539/* Look into the RN and queue it into one or more priority queues,
1540 * increasing the size for each data push done.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001541 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001542static void
1543rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001544{
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001545 struct rib *rib;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001546
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001547 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001548 {
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001549 u_char qindex = meta_queue_map[rib->type];
1550
1551 /* Invariant: at this point we always have rn->info set. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001552 if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1553 RIB_ROUTE_QUEUED (qindex)))
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001554 {
1555 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001556 rnode_debug (rn, "rn %p is already queued in sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001557 (void *)rn, qindex);
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001558 continue;
1559 }
1560
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001561 SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001562 listnode_add (mq->subq[qindex], rn);
1563 route_lock_node (rn);
1564 mq->size++;
1565
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001566 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001567 rnode_debug (rn, "queued rn %p into sub-queue %u",
David Lampartereed3c482015-03-03 08:51:53 +01001568 (void *)rn, qindex);
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001569 }
paul4d38fdb2005-04-28 17:35:14 +00001570}
1571
Paul Jakma6d691122006-07-27 21:49:00 +00001572/* Add route_node to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001573static void
Paul Jakma6d691122006-07-27 21:49:00 +00001574rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
paul4d38fdb2005-04-28 17:35:14 +00001575{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001576 assert (zebra && rn);
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001577
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001578 /* Pointless to queue a route_node with no RIB entries to add or remove */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001579 if (!rnode_to_ribs (rn))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001580 {
1581 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
David Lampartereed3c482015-03-03 08:51:53 +01001582 __func__, (void *)rn, rn->lock);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001583 zlog_backtrace(LOG_DEBUG);
1584 return;
1585 }
1586
1587 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lamparter94813742014-04-24 20:22:53 +02001588 rnode_info (rn, "work queue added");
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001589
1590 assert (zebra);
1591
1592 if (zebra->ribq == NULL)
1593 {
1594 zlog_err ("%s: work_queue does not exist!", __func__);
1595 return;
Paul Jakma6d691122006-07-27 21:49:00 +00001596 }
paul4d38fdb2005-04-28 17:35:14 +00001597
Stephen Hemmingercc2dd922009-12-09 17:54:49 +03001598 /*
1599 * The RIB queue should normally be either empty or holding the only
1600 * work_queue_item element. In the latter case this element would
1601 * hold a pointer to the meta queue structure, which must be used to
1602 * actually queue the route nodes to process. So create the MQ
1603 * holder, if necessary, then push the work into it in any case.
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001604 * This semantics was introduced after 0.99.9 release.
1605 */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001606 if (!zebra->ribq->items->count)
1607 work_queue_add (zebra->ribq, zebra->mq);
1608
1609 rib_meta_queue_add (zebra->mq, rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001610
1611 if (IS_ZEBRA_DEBUG_RIB_Q)
David Lampartereed3c482015-03-03 08:51:53 +01001612 rnode_debug (rn, "rn %p queued", (void *)rn);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001613
1614 return;
paul4d38fdb2005-04-28 17:35:14 +00001615}
1616
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001617/* Create new meta queue.
1618 A destructor function doesn't seem to be necessary here.
1619 */
Stephen Hemmingeref9b1132008-08-17 17:44:47 +01001620static struct meta_queue *
1621meta_queue_new (void)
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001622{
1623 struct meta_queue *new;
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001624 unsigned i;
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001625
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001626 new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1627 assert(new);
1628
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001629 for (i = 0; i < MQ_SIZE; i++)
Stephen Hemminger5110a0c2008-08-11 16:22:15 -07001630 {
1631 new->subq[i] = list_new ();
1632 assert(new->subq[i]);
1633 }
1634
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001635 return new;
1636}
1637
paul4d38fdb2005-04-28 17:35:14 +00001638/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001639static void
paul4d38fdb2005-04-28 17:35:14 +00001640rib_queue_init (struct zebra_t *zebra)
1641{
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001642 assert (zebra);
1643
paul4d38fdb2005-04-28 17:35:14 +00001644 if (! (zebra->ribq = work_queue_new (zebra->master,
Paul Jakma6d691122006-07-27 21:49:00 +00001645 "route_node processing")))
paul4d38fdb2005-04-28 17:35:14 +00001646 {
Paul Jakma6d691122006-07-27 21:49:00 +00001647 zlog_err ("%s: could not initialise work queue!", __func__);
paul4d38fdb2005-04-28 17:35:14 +00001648 return;
1649 }
1650
1651 /* fill in the work queue spec */
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001652 zebra->ribq->spec.workfunc = &meta_queue_process;
paul4d38fdb2005-04-28 17:35:14 +00001653 zebra->ribq->spec.errorfunc = NULL;
paul4d38fdb2005-04-28 17:35:14 +00001654 /* XXX: TODO: These should be runtime configurable via vty */
1655 zebra->ribq->spec.max_retries = 3;
Paul Jakma457eb9a2006-07-27 19:59:58 +00001656 zebra->ribq->spec.hold = rib_process_hold_time;
paul4d38fdb2005-04-28 17:35:14 +00001657
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001658 if (!(zebra->mq = meta_queue_new ()))
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001659 {
Denis Ovsienkoe96f9202008-06-02 12:03:22 +00001660 zlog_err ("%s: could not initialise meta queue!", __func__);
Subbaiah Venkatafc328ac2012-03-27 16:35:22 -07001661 return;
1662 }
1663 return;
paul718e3742002-12-13 20:15:29 +00001664}
1665
Paul Jakma6d691122006-07-27 21:49:00 +00001666/* RIB updates are processed via a queue of pointers to route_nodes.
1667 *
1668 * The queue length is bounded by the maximal size of the routing table,
1669 * as a route_node will not be requeued, if already queued.
1670 *
Paul Jakma3c0755d2006-12-08 00:53:14 +00001671 * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1672 * state, or static_install_ipv{4,6} (when an existing RIB is updated)
1673 * and then submit route_node to queue for best-path selection later.
1674 * Order of add/delete state changes are preserved for any given RIB.
Paul Jakma6d691122006-07-27 21:49:00 +00001675 *
1676 * Deleted RIBs are reaped during best-path selection.
1677 *
1678 * rib_addnode
1679 * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
Paul Jakma3c0755d2006-12-08 00:53:14 +00001680 * |-------->| | best RIB, if required
1681 * | |
1682 * static_install->|->rib_addqueue...... -> rib_process
1683 * | |
1684 * |-------->| |-> rib_unlink
Paul Jakma6d691122006-07-27 21:49:00 +00001685 * |-> set RIB_ENTRY_REMOVE |
1686 * rib_delnode (RIB freed)
1687 *
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001688 * The 'info' pointer of a route_node points to a rib_dest_t
1689 * ('dest'). Queueing state for a route_node is kept on the dest. The
1690 * dest is created on-demand by rib_link() and is kept around at least
1691 * as long as there are ribs hanging off it (@see rib_gc_dest()).
Paul Jakma6d691122006-07-27 21:49:00 +00001692 *
1693 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1694 *
1695 * - route_nodes: refcounted by:
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001696 * - dest attached to route_node:
1697 * - managed by: rib_link/rib_gc_dest
Paul Jakma6d691122006-07-27 21:49:00 +00001698 * - route_node processing queue
1699 * - managed by: rib_addqueue, rib_process.
1700 *
1701 */
1702
paul718e3742002-12-13 20:15:29 +00001703/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001704static void
Paul Jakma6d691122006-07-27 21:49:00 +00001705rib_link (struct route_node *rn, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001706{
1707 struct rib *head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001708 rib_dest_t *dest;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001709
paul4d38fdb2005-04-28 17:35:14 +00001710 assert (rib && rn);
1711
Paul Jakma6d691122006-07-27 21:49:00 +00001712 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001713 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001714
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001715 dest = rib_dest_from_rnode (rn);
1716 if (!dest)
Paul Jakma6d691122006-07-27 21:49:00 +00001717 {
1718 if (IS_ZEBRA_DEBUG_RIB)
David Lamparter94813742014-04-24 20:22:53 +02001719 rnode_debug (rn, "adding dest to table");
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001720
1721 dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1722 route_lock_node (rn); /* rn route table reference */
1723 rn->info = dest;
1724 dest->rnode = rn;
1725 }
1726
1727 head = dest->routes;
1728 if (head)
1729 {
Paul Jakma6d691122006-07-27 21:49:00 +00001730 head->prev = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001731 }
paul718e3742002-12-13 20:15:29 +00001732 rib->next = head;
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001733 dest->routes = rib;
Paul Jakma6d691122006-07-27 21:49:00 +00001734 rib_queue_add (&zebrad, rn);
1735}
1736
1737static void
1738rib_addnode (struct route_node *rn, struct rib *rib)
1739{
1740 /* RIB node has been un-removed before route-node is processed.
1741 * route_node must hence already be on the queue for processing..
1742 */
1743 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1744 {
1745 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001746 rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
David Lamparter94813742014-04-24 20:22:53 +02001747
Paul Jakma6d691122006-07-27 21:49:00 +00001748 UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1749 return;
1750 }
1751 rib_link (rn, rib);
1752}
1753
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001754/*
1755 * rib_unlink
1756 *
1757 * Detach a rib structure from a route_node.
1758 *
1759 * Note that a call to rib_unlink() should be followed by a call to
1760 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1761 * longer required to be deleted.
1762 */
Paul Jakma6d691122006-07-27 21:49:00 +00001763static void
1764rib_unlink (struct route_node *rn, struct rib *rib)
1765{
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001766 rib_dest_t *dest;
Paul Jakma6d691122006-07-27 21:49:00 +00001767
1768 assert (rn && rib);
1769
1770 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001771 rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001772
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001773 dest = rib_dest_from_rnode (rn);
1774
Paul Jakma6d691122006-07-27 21:49:00 +00001775 if (rib->next)
1776 rib->next->prev = rib->prev;
1777
1778 if (rib->prev)
1779 rib->prev->next = rib->next;
1780 else
1781 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001782 dest->routes = rib->next;
Paul Jakma6d691122006-07-27 21:49:00 +00001783 }
1784
1785 /* free RIB and nexthops */
Christian Frankefa713d92013-07-05 15:35:37 +00001786 nexthops_free(rib->nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00001787 XFREE (MTYPE_RIB, rib);
1788
paul718e3742002-12-13 20:15:29 +00001789}
1790
paula1ac18c2005-06-28 17:17:12 +00001791static void
paul718e3742002-12-13 20:15:29 +00001792rib_delnode (struct route_node *rn, struct rib *rib)
1793{
Paul Jakma6d691122006-07-27 21:49:00 +00001794 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001795 rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
Paul Jakma6d691122006-07-27 21:49:00 +00001796 SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1797 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00001798}
1799
1800int
1801rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Paul Jakma7514fb72007-05-02 16:05:35 +00001802 struct in_addr *gate, struct in_addr *src,
Feng Lu0d0686f2015-05-22 11:40:02 +02001803 unsigned int ifindex, vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001804 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00001805{
1806 struct rib *rib;
1807 struct rib *same = NULL;
1808 struct route_table *table;
1809 struct route_node *rn;
1810 struct nexthop *nexthop;
1811
1812 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02001813 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00001814 if (! table)
1815 return 0;
1816
1817 /* Make it sure prefixlen is applied to the prefix. */
1818 apply_mask_ipv4 (p);
1819
1820 /* Set default distance by route type. */
1821 if (distance == 0)
1822 {
Balaji.G837d16c2012-09-26 14:09:10 +05301823 if ((unsigned)type >= array_size(route_info))
David Lamparter7052f222009-08-27 00:28:28 +02001824 distance = 150;
1825 else
1826 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001827
1828 /* iBGP distance is 200. */
1829 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1830 distance = 200;
1831 }
1832
1833 /* Lookup route node.*/
1834 rn = route_node_get (table, (struct prefix *) p);
1835
1836 /* If same type of route are installed, treat it as a implicit
1837 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00001838 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00001839 {
Paul Jakma6d691122006-07-27 21:49:00 +00001840 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1841 continue;
1842
hassoebf1ead2005-09-21 14:58:20 +00001843 if (rib->type != type)
1844 continue;
1845 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001846 {
1847 same = rib;
1848 break;
1849 }
hassoebf1ead2005-09-21 14:58:20 +00001850 /* Duplicate connected route comes in. */
1851 else if ((nexthop = rib->nexthop) &&
1852 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
Paul Jakma6d691122006-07-27 21:49:00 +00001853 nexthop->ifindex == ifindex &&
1854 !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
hassoebf1ead2005-09-21 14:58:20 +00001855 {
1856 rib->refcnt++;
1857 return 0 ;
1858 }
paul718e3742002-12-13 20:15:29 +00001859 }
1860
1861 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001862 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001863 rib->type = type;
1864 rib->distance = distance;
1865 rib->flags = flags;
1866 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001867 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02001868 rib->vrf_id = vrf_id;
1869 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00001870 rib->nexthop_num = 0;
1871 rib->uptime = time (NULL);
1872
1873 /* Nexthop settings. */
1874 if (gate)
1875 {
1876 if (ifindex)
Paul Jakma7514fb72007-05-02 16:05:35 +00001877 nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
paul718e3742002-12-13 20:15:29 +00001878 else
Paul Jakma7514fb72007-05-02 16:05:35 +00001879 nexthop_ipv4_add (rib, gate, src);
paul718e3742002-12-13 20:15:29 +00001880 }
1881 else
1882 nexthop_ifindex_add (rib, ifindex);
1883
1884 /* If this route is kernel route, set FIB flag to the route. */
1885 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1886 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1887 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1888
1889 /* Link new rib to node.*/
Denis Ovsienkodc958242007-08-13 16:03:06 +00001890 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001891 zlog_debug ("%s: calling rib_addnode (%p, %p)",
1892 __func__, (void *)rn, (void *)rib);
paul718e3742002-12-13 20:15:29 +00001893 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001894
paul718e3742002-12-13 20:15:29 +00001895 /* Free implicit route.*/
1896 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001897 {
1898 if (IS_ZEBRA_DEBUG_RIB)
David Lampartereed3c482015-03-03 08:51:53 +01001899 zlog_debug ("%s: calling rib_delnode (%p, %p)",
1900 __func__, (void *)rn, (void *)rib);
paul4d38fdb2005-04-28 17:35:14 +00001901 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001902 }
paul4d38fdb2005-04-28 17:35:14 +00001903
1904 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001905 return 0;
1906}
1907
Denis Ovsienkodc958242007-08-13 16:03:06 +00001908/* This function dumps the contents of a given RIB entry into
1909 * standard debug log. Calling function name and IP prefix in
1910 * question are passed as 1st and 2nd arguments.
1911 */
1912
David Lamparterf7bf4152013-10-22 17:10:21 +00001913void _rib_dump (const char * func,
1914 union prefix46constptr pp, const struct rib * rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00001915{
David Lamparterf7bf4152013-10-22 17:10:21 +00001916 const struct prefix *p = pp.p;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001917 char straddr[PREFIX_STRLEN];
Christian Frankefa713d92013-07-05 15:35:37 +00001918 struct nexthop *nexthop, *tnexthop;
1919 int recursing;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001920
Feng Lu0d0686f2015-05-22 11:40:02 +02001921 zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
1922 prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001923 zlog_debug
1924 (
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001925 "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
Denis Ovsienkodc958242007-08-13 16:03:06 +00001926 func,
1927 rib->refcnt,
Stephen Hemmingerd02c56c2009-12-08 13:14:27 +03001928 (unsigned long) rib->uptime,
Denis Ovsienkodc958242007-08-13 16:03:06 +00001929 rib->type,
1930 rib->table
1931 );
1932 zlog_debug
1933 (
1934 "%s: metric == %u, distance == %u, flags == %u, status == %u",
1935 func,
1936 rib->metric,
1937 rib->distance,
1938 rib->flags,
1939 rib->status
1940 );
1941 zlog_debug
1942 (
1943 "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1944 func,
1945 rib->nexthop_num,
1946 rib->nexthop_active_num,
1947 rib->nexthop_fib_num
1948 );
Vincent Bernatfed643f2012-10-23 16:00:42 +00001949
Christian Frankefa713d92013-07-05 15:35:37 +00001950 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1951 {
Vincent Bernatfed643f2012-10-23 16:00:42 +00001952 inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
Christian Frankefa713d92013-07-05 15:35:37 +00001953 zlog_debug
1954 (
1955 "%s: %s %s with flags %s%s%s",
1956 func,
1957 (recursing ? " NH" : "NH"),
1958 straddr,
1959 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
1960 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
1961 (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
1962 );
1963 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001964 zlog_debug ("%s: dump complete", func);
1965}
1966
1967/* This is an exported helper to rtm_read() to dump the strange
1968 * RIB entry found by rib_lookup_ipv4_route()
1969 */
1970
1971void rib_lookup_and_dump (struct prefix_ipv4 * p)
1972{
1973 struct route_table *table;
1974 struct route_node *rn;
1975 struct rib *rib;
1976 char prefix_buf[INET_ADDRSTRLEN];
1977
1978 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02001979 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001980 if (! table)
1981 {
Feng Lu41f44a22015-05-22 11:39:56 +02001982 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienkodc958242007-08-13 16:03:06 +00001983 return;
1984 }
1985
Denis Ovsienkodc958242007-08-13 16:03:06 +00001986 /* Scan the RIB table for exactly matching RIB entry. */
1987 rn = route_node_lookup (table, (struct prefix *) p);
1988
1989 /* No route for this prefix. */
1990 if (! rn)
1991 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001992 zlog_debug ("%s: lookup failed for %s", __func__,
1993 prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
Denis Ovsienkodc958242007-08-13 16:03:06 +00001994 return;
1995 }
1996
1997 /* Unlock node. */
1998 route_unlock_node (rn);
1999
2000 /* let's go */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002001 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002002 {
2003 zlog_debug
2004 (
2005 "%s: rn %p, rib %p: %s, %s",
2006 __func__,
David Lampartereed3c482015-03-03 08:51:53 +01002007 (void *)rn,
2008 (void *)rib,
Denis Ovsienkodc958242007-08-13 16:03:06 +00002009 (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
2010 (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
2011 );
David Lamparterf7bf4152013-10-22 17:10:21 +00002012 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002013 }
2014}
2015
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002016/* Check if requested address assignment will fail due to another
2017 * route being installed by zebra in FIB already. Take necessary
2018 * actions, if needed: remove such a route from FIB and deSELECT
2019 * corresponding RIB entry. Then put affected RN into RIBQ head.
2020 */
2021void rib_lookup_and_pushup (struct prefix_ipv4 * p)
2022{
2023 struct route_table *table;
2024 struct route_node *rn;
2025 struct rib *rib;
2026 unsigned changed = 0;
2027
Feng Lu41f44a22015-05-22 11:39:56 +02002028 if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002029 {
Feng Lu41f44a22015-05-22 11:39:56 +02002030 zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002031 return;
2032 }
2033
2034 /* No matches would be the simplest case. */
2035 if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
2036 return;
2037
2038 /* Unlock node. */
2039 route_unlock_node (rn);
2040
2041 /* Check all RIB entries. In case any changes have to be done, requeue
2042 * the RN into RIBQ head. If the routing message about the new connected
2043 * route (generated by the IP address we are going to assign very soon)
2044 * comes before the RIBQ is processed, the new RIB entry will join
2045 * RIBQ record already on head. This is necessary for proper revalidation
2046 * of the rest of the RIB.
2047 */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002048 RNODE_FOREACH_RIB (rn, rib)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002049 {
2050 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
2051 ! RIB_SYSTEM_ROUTE (rib))
2052 {
2053 changed = 1;
2054 if (IS_ZEBRA_DEBUG_RIB)
2055 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03002056 char buf[PREFIX_STRLEN];
2057 zlog_debug ("%s: freeing way for connected prefix %s", __func__,
2058 prefix2str(&rn->p, buf, sizeof(buf)));
David Lamparterf7bf4152013-10-22 17:10:21 +00002059 rib_dump (&rn->p, rib);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002060 }
2061 rib_uninstall (rn, rib);
2062 }
2063 }
2064 if (changed)
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002065 rib_queue_add (&zebrad, rn);
Denis Ovsienko20e5ff02008-02-26 14:02:24 +00002066}
2067
paul718e3742002-12-13 20:15:29 +00002068int
G.Balajicddf3912011-11-26 21:59:32 +04002069rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002070{
2071 struct route_table *table;
2072 struct route_node *rn;
2073 struct rib *same;
2074 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00002075
paul718e3742002-12-13 20:15:29 +00002076 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002077 table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
paul718e3742002-12-13 20:15:29 +00002078 if (! table)
2079 return 0;
G.Balajicddf3912011-11-26 21:59:32 +04002080
paul718e3742002-12-13 20:15:29 +00002081 /* Make it sure prefixlen is applied to the prefix. */
2082 apply_mask_ipv4 (p);
2083
2084 /* Set default distance by route type. */
2085 if (rib->distance == 0)
2086 {
2087 rib->distance = route_info[rib->type].distance;
2088
2089 /* iBGP distance is 200. */
2090 if (rib->type == ZEBRA_ROUTE_BGP
2091 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2092 rib->distance = 200;
2093 }
2094
2095 /* Lookup route node.*/
2096 rn = route_node_get (table, (struct prefix *) p);
2097
2098 /* If same type of route are installed, treat it as a implicit
2099 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002100 RNODE_FOREACH_RIB (rn, same)
paul718e3742002-12-13 20:15:29 +00002101 {
Paul Jakma0b8c4f12007-06-27 11:12:38 +00002102 if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
Paul Jakma6d691122006-07-27 21:49:00 +00002103 continue;
2104
paul718e3742002-12-13 20:15:29 +00002105 if (same->type == rib->type && same->table == rib->table
2106 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00002107 break;
paul718e3742002-12-13 20:15:29 +00002108 }
paul4d38fdb2005-04-28 17:35:14 +00002109
paul718e3742002-12-13 20:15:29 +00002110 /* If this route is kernel route, set FIB flag to the route. */
2111 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2112 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2113 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2114
2115 /* Link new rib to node.*/
2116 rib_addnode (rn, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002117 if (IS_ZEBRA_DEBUG_RIB)
2118 {
2119 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002120 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002121 rib_dump (p, rib);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002122 }
paul718e3742002-12-13 20:15:29 +00002123
paul718e3742002-12-13 20:15:29 +00002124 /* Free implicit route.*/
2125 if (same)
Denis Ovsienkodc958242007-08-13 16:03:06 +00002126 {
2127 if (IS_ZEBRA_DEBUG_RIB)
2128 {
2129 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002130 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002131 rib_dump (p, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002132 }
paul4d38fdb2005-04-28 17:35:14 +00002133 rib_delnode (rn, same);
Denis Ovsienkodc958242007-08-13 16:03:06 +00002134 }
paul4d38fdb2005-04-28 17:35:14 +00002135
2136 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002137 return 0;
2138}
2139
hassoebf1ead2005-09-21 14:58:20 +00002140/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002141int
2142rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002143 struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002144{
2145 struct route_table *table;
2146 struct route_node *rn;
2147 struct rib *rib;
2148 struct rib *fib = NULL;
2149 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002150 struct nexthop *nexthop, *tnexthop;
2151 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002152 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002153 char buf2[INET_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002154
2155 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002156 table = zebra_vrf_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002157 if (! table)
2158 return 0;
2159
2160 /* Apply mask. */
2161 apply_mask_ipv4 (p);
2162
Christian Frankeb52aef12013-11-27 17:06:15 +00002163 if (IS_ZEBRA_DEBUG_KERNEL)
2164 {
2165 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002166 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
2167 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002168 inet_ntoa (*gate),
2169 ifindex);
2170 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002171 zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
2172 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Christian Frankeb52aef12013-11-27 17:06:15 +00002173 ifindex);
2174 }
paul5ec90d22003-06-19 01:41:37 +00002175
paul718e3742002-12-13 20:15:29 +00002176 /* Lookup route node. */
2177 rn = route_node_lookup (table, (struct prefix *) p);
2178 if (! rn)
2179 {
2180 if (IS_ZEBRA_DEBUG_KERNEL)
2181 {
2182 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002183 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2184 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002185 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002186 ifindex);
2187 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002188 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2189 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002190 ifindex);
2191 }
2192 return ZEBRA_ERR_RTNOEXIST;
2193 }
2194
2195 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002196 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002197 {
Paul Jakma6d691122006-07-27 21:49:00 +00002198 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2199 continue;
2200
paul718e3742002-12-13 20:15:29 +00002201 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2202 fib = rib;
2203
hassoebf1ead2005-09-21 14:58:20 +00002204 if (rib->type != type)
2205 continue;
2206 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002207 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002208 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002209 if (nexthop->ifindex != ifindex)
2210 continue;
hassoebf1ead2005-09-21 14:58:20 +00002211 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002212 {
hassoebf1ead2005-09-21 14:58:20 +00002213 rib->refcnt--;
2214 route_unlock_node (rn);
2215 route_unlock_node (rn);
2216 return 0;
paul718e3742002-12-13 20:15:29 +00002217 }
hassoebf1ead2005-09-21 14:58:20 +00002218 same = rib;
2219 break;
paul718e3742002-12-13 20:15:29 +00002220 }
hassoebf1ead2005-09-21 14:58:20 +00002221 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002222 else
paul5ec90d22003-06-19 01:41:37 +00002223 {
Christian Frankefa713d92013-07-05 15:35:37 +00002224 if (gate == NULL)
2225 {
2226 same = rib;
2227 break;
2228 }
2229 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2230 if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
2231 {
2232 same = rib;
2233 break;
2234 }
2235 if (same)
2236 break;
2237 }
paul718e3742002-12-13 20:15:29 +00002238 }
paul718e3742002-12-13 20:15:29 +00002239 /* If same type of route can't be found and this message is from
2240 kernel. */
2241 if (! same)
2242 {
2243 if (fib && type == ZEBRA_ROUTE_KERNEL)
2244 {
2245 /* Unset flags. */
2246 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2247 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2248
2249 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2250 }
2251 else
2252 {
2253 if (IS_ZEBRA_DEBUG_KERNEL)
2254 {
2255 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002256 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2257 "doesn't exist in rib",
2258 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002259 inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002260 ifindex,
2261 type);
2262 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002263 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2264 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002265 ifindex,
2266 type);
2267 }
2268 route_unlock_node (rn);
2269 return ZEBRA_ERR_RTNOEXIST;
2270 }
2271 }
paul4d38fdb2005-04-28 17:35:14 +00002272
paul718e3742002-12-13 20:15:29 +00002273 if (same)
2274 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002275
paul718e3742002-12-13 20:15:29 +00002276 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002277 return 0;
2278}
David Lamparter6b0655a2014-06-04 06:53:35 +02002279
paul718e3742002-12-13 20:15:29 +00002280/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002281static void
Donald Sharpd4c27d62015-11-04 13:26:35 -05002282static_install_ipv4 (safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002283{
2284 struct rib *rib;
2285 struct route_node *rn;
2286 struct route_table *table;
2287
2288 /* Lookup table. */
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002289 table = zebra_vrf_table (AFI_IP, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002290 if (! table)
2291 return;
2292
2293 /* Lookup existing route */
2294 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002295 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002296 {
2297 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2298 continue;
2299
2300 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2301 break;
2302 }
paul718e3742002-12-13 20:15:29 +00002303
2304 if (rib)
2305 {
2306 /* Same distance static route is there. Update it with new
2307 nexthop. */
paul718e3742002-12-13 20:15:29 +00002308 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002309 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002310 {
2311 case STATIC_IPV4_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002312 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002313 break;
2314 case STATIC_IPV4_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002315 nexthop_ifname_add (rib, si->ifname);
paul7021c422003-07-15 12:52:22 +00002316 break;
2317 case STATIC_IPV4_BLACKHOLE:
2318 nexthop_blackhole_add (rib);
2319 break;
paul4d38fdb2005-04-28 17:35:14 +00002320 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002321 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002322 }
2323 else
2324 {
2325 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002326 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2327
paul718e3742002-12-13 20:15:29 +00002328 rib->type = ZEBRA_ROUTE_STATIC;
2329 rib->distance = si->distance;
2330 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002331 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002332 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002333 rib->nexthop_num = 0;
2334
2335 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002336 {
2337 case STATIC_IPV4_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002338 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
paul7021c422003-07-15 12:52:22 +00002339 break;
2340 case STATIC_IPV4_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002341 nexthop_ifname_add (rib, si->ifname);
paul7021c422003-07-15 12:52:22 +00002342 break;
2343 case STATIC_IPV4_BLACKHOLE:
2344 nexthop_blackhole_add (rib);
2345 break;
2346 }
paul718e3742002-12-13 20:15:29 +00002347
hasso81dfcaa2003-05-25 19:21:25 +00002348 /* Save the flags of this static routes (reject, blackhole) */
2349 rib->flags = si->flags;
2350
paul718e3742002-12-13 20:15:29 +00002351 /* Link this rib to the tree. */
2352 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002353 }
2354}
2355
paula1ac18c2005-06-28 17:17:12 +00002356static int
Donald Sharpd4c27d62015-11-04 13:26:35 -05002357static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002358{
2359 if (nexthop->type == NEXTHOP_TYPE_IPV4
2360 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002361 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002362 return 1;
2363 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2364 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002365 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002366 return 1;
paul595db7f2003-05-25 21:35:06 +00002367 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2368 && si->type == STATIC_IPV4_BLACKHOLE)
2369 return 1;
paule8e19462006-01-19 20:16:55 +00002370 return 0;
paul718e3742002-12-13 20:15:29 +00002371}
2372
2373/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002374static void
Donald Sharpd4c27d62015-11-04 13:26:35 -05002375static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002376{
2377 struct route_node *rn;
2378 struct rib *rib;
2379 struct nexthop *nexthop;
2380 struct route_table *table;
2381
2382 /* Lookup table. */
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002383 table = zebra_vrf_table (AFI_IP, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002384 if (! table)
2385 return;
paul4d38fdb2005-04-28 17:35:14 +00002386
paul718e3742002-12-13 20:15:29 +00002387 /* Lookup existing route with type and distance. */
2388 rn = route_node_lookup (table, p);
2389 if (! rn)
2390 return;
2391
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002392 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002393 {
2394 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2395 continue;
2396
2397 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2398 break;
2399 }
paul718e3742002-12-13 20:15:29 +00002400
2401 if (! rib)
2402 {
2403 route_unlock_node (rn);
2404 return;
2405 }
2406
2407 /* Lookup nexthop. */
2408 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2409 if (static_ipv4_nexthop_same (nexthop, si))
2410 break;
2411
2412 /* Can't find nexthop. */
2413 if (! nexthop)
2414 {
2415 route_unlock_node (rn);
2416 return;
2417 }
2418
2419 /* Check nexthop. */
2420 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002421 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002422 else
2423 {
paul6baeb982003-10-28 03:47:15 +00002424 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2425 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002426 nexthop_delete (rib, nexthop);
2427 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002428 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002429 }
paul718e3742002-12-13 20:15:29 +00002430 /* Unlock node. */
2431 route_unlock_node (rn);
2432}
2433
paul718e3742002-12-13 20:15:29 +00002434int
Everton Marques33d86db2014-07-14 11:19:00 -03002435static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2436 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002437 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002438{
2439 u_char type = 0;
2440 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002441 struct static_route *si;
2442 struct static_route *pp;
2443 struct static_route *cp;
2444 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002445 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2446 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002447
paul718e3742002-12-13 20:15:29 +00002448 if (! stable)
2449 return -1;
2450
2451 /* Lookup static route prefix. */
2452 rn = route_node_get (stable, p);
2453
2454 /* Make flags. */
2455 if (gate)
2456 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002457 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002458 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002459 else
2460 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002461
2462 /* Do nothing if there is a same static route. */
2463 for (si = rn->info; si; si = si->next)
2464 {
2465 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002466 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2467 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002468 {
2469 if (distance == si->distance)
2470 {
2471 route_unlock_node (rn);
2472 return 0;
2473 }
2474 else
2475 update = si;
2476 }
2477 }
2478
Paul Jakma3c0755d2006-12-08 00:53:14 +00002479 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002480 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002481 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002482
2483 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002484 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002485
2486 si->type = type;
2487 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002488 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002489 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002490
2491 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002492 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002493 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002494 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002495
2496 /* Add new static route information to the tree with sort by
2497 distance value and gateway address. */
2498 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2499 {
2500 if (si->distance < cp->distance)
2501 break;
2502 if (si->distance > cp->distance)
2503 continue;
2504 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2505 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002506 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002507 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002508 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002509 continue;
2510 }
2511 }
2512
2513 /* Make linked list. */
2514 if (pp)
2515 pp->next = si;
2516 else
2517 rn->info = si;
2518 if (cp)
2519 cp->prev = si;
2520 si->prev = pp;
2521 si->next = cp;
2522
2523 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002524 static_install_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002525
2526 return 1;
2527}
2528
paul718e3742002-12-13 20:15:29 +00002529int
Everton Marques33d86db2014-07-14 11:19:00 -03002530static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002531 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002532{
2533 u_char type = 0;
2534 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002535 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002536 struct route_table *stable;
2537
2538 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002539 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002540 if (! stable)
2541 return -1;
2542
2543 /* Lookup static route prefix. */
2544 rn = route_node_lookup (stable, p);
2545 if (! rn)
2546 return 0;
2547
2548 /* Make flags. */
2549 if (gate)
2550 type = STATIC_IPV4_GATEWAY;
2551 else if (ifname)
2552 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002553 else
2554 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002555
2556 /* Find same static route is the tree */
2557 for (si = rn->info; si; si = si->next)
2558 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002559 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2560 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002561 break;
2562
2563 /* Can't find static route. */
2564 if (! si)
2565 {
2566 route_unlock_node (rn);
2567 return 0;
2568 }
2569
2570 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002571 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002572
2573 /* Unlink static route from linked list. */
2574 if (si->prev)
2575 si->prev->next = si->next;
2576 else
2577 rn->info = si->next;
2578 if (si->next)
2579 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002580 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002581
2582 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002583 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002584 XFREE (0, si->ifname);
2585 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002586
paul143a3852003-09-29 20:06:13 +00002587 route_unlock_node (rn);
2588
paul718e3742002-12-13 20:15:29 +00002589 return 1;
2590}
2591
paul718e3742002-12-13 20:15:29 +00002592int
2593rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002594 struct in6_addr *gate, unsigned int ifindex,
2595 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002596 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002597{
2598 struct rib *rib;
2599 struct rib *same = NULL;
2600 struct route_table *table;
2601 struct route_node *rn;
2602 struct nexthop *nexthop;
2603
paul718e3742002-12-13 20:15:29 +00002604 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002605 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002606 if (! table)
2607 return 0;
2608
2609 /* Make sure mask is applied. */
2610 apply_mask_ipv6 (p);
2611
2612 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002613 if (!distance)
2614 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002615
2616 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2617 distance = 200;
2618
paul718e3742002-12-13 20:15:29 +00002619 /* Lookup route node.*/
2620 rn = route_node_get (table, (struct prefix *) p);
2621
2622 /* If same type of route are installed, treat it as a implicit
2623 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002624 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002625 {
Paul Jakma6d691122006-07-27 21:49:00 +00002626 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2627 continue;
2628
hassoebf1ead2005-09-21 14:58:20 +00002629 if (rib->type != type)
2630 continue;
2631 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002632 {
2633 same = rib;
paul718e3742002-12-13 20:15:29 +00002634 break;
2635 }
hassoebf1ead2005-09-21 14:58:20 +00002636 else if ((nexthop = rib->nexthop) &&
2637 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2638 nexthop->ifindex == ifindex)
2639 {
2640 rib->refcnt++;
2641 return 0;
2642 }
paul718e3742002-12-13 20:15:29 +00002643 }
2644
2645 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002646 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2647
paul718e3742002-12-13 20:15:29 +00002648 rib->type = type;
2649 rib->distance = distance;
2650 rib->flags = flags;
2651 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002652 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002653 rib->vrf_id = vrf_id;
2654 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002655 rib->nexthop_num = 0;
2656 rib->uptime = time (NULL);
2657
2658 /* Nexthop settings. */
2659 if (gate)
2660 {
2661 if (ifindex)
2662 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2663 else
2664 nexthop_ipv6_add (rib, gate);
2665 }
2666 else
2667 nexthop_ifindex_add (rib, ifindex);
2668
2669 /* If this route is kernel route, set FIB flag to the route. */
2670 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2671 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2672 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2673
2674 /* Link new rib to node.*/
2675 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002676 if (IS_ZEBRA_DEBUG_RIB)
2677 {
2678 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002679 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002680 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002681 }
paul718e3742002-12-13 20:15:29 +00002682
paul718e3742002-12-13 20:15:29 +00002683 /* Free implicit route.*/
2684 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002685 {
2686 if (IS_ZEBRA_DEBUG_RIB)
2687 {
2688 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002689 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002690 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002691 }
paul4d38fdb2005-04-28 17:35:14 +00002692 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002693 }
paul4d38fdb2005-04-28 17:35:14 +00002694
2695 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002696 return 0;
2697}
2698
hassoebf1ead2005-09-21 14:58:20 +00002699/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002700int
2701rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002702 struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002703{
2704 struct route_table *table;
2705 struct route_node *rn;
2706 struct rib *rib;
2707 struct rib *fib = NULL;
2708 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002709 struct nexthop *nexthop, *tnexthop;
2710 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002711 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002712 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002713
2714 /* Apply mask. */
2715 apply_mask_ipv6 (p);
2716
2717 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002718 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002719 if (! table)
2720 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002721
paul718e3742002-12-13 20:15:29 +00002722 /* Lookup route node. */
2723 rn = route_node_lookup (table, (struct prefix *) p);
2724 if (! rn)
2725 {
2726 if (IS_ZEBRA_DEBUG_KERNEL)
2727 {
2728 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002729 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2730 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002731 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002732 ifindex);
2733 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002734 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2735 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002736 ifindex);
2737 }
2738 return ZEBRA_ERR_RTNOEXIST;
2739 }
2740
2741 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002742 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002743 {
Paul Jakma6d691122006-07-27 21:49:00 +00002744 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2745 continue;
2746
paul718e3742002-12-13 20:15:29 +00002747 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2748 fib = rib;
2749
hassoebf1ead2005-09-21 14:58:20 +00002750 if (rib->type != type)
2751 continue;
2752 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002753 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002754 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002755 if (nexthop->ifindex != ifindex)
2756 continue;
hassoebf1ead2005-09-21 14:58:20 +00002757 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002758 {
hassoebf1ead2005-09-21 14:58:20 +00002759 rib->refcnt--;
2760 route_unlock_node (rn);
2761 route_unlock_node (rn);
2762 return 0;
paul718e3742002-12-13 20:15:29 +00002763 }
hassoebf1ead2005-09-21 14:58:20 +00002764 same = rib;
2765 break;
paul718e3742002-12-13 20:15:29 +00002766 }
hassoebf1ead2005-09-21 14:58:20 +00002767 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002768 else
2769 {
2770 if (gate == NULL)
2771 {
2772 same = rib;
2773 break;
2774 }
2775 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2776 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2777 {
2778 same = rib;
2779 break;
2780 }
2781 if (same)
2782 break;
2783 }
paul718e3742002-12-13 20:15:29 +00002784 }
2785
2786 /* If same type of route can't be found and this message is from
2787 kernel. */
2788 if (! same)
2789 {
2790 if (fib && type == ZEBRA_ROUTE_KERNEL)
2791 {
2792 /* Unset flags. */
2793 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2794 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2795
2796 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2797 }
2798 else
2799 {
2800 if (IS_ZEBRA_DEBUG_KERNEL)
2801 {
2802 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002803 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2804 "doesn't exist in rib",
2805 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002806 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002807 ifindex,
2808 type);
2809 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002810 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2811 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002812 ifindex,
2813 type);
2814 }
2815 route_unlock_node (rn);
2816 return ZEBRA_ERR_RTNOEXIST;
2817 }
2818 }
2819
2820 if (same)
2821 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002822
paul718e3742002-12-13 20:15:29 +00002823 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002824 return 0;
2825}
David Lamparter6b0655a2014-06-04 06:53:35 +02002826
paul718e3742002-12-13 20:15:29 +00002827/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00002828static void
Donald Sharpd4c27d62015-11-04 13:26:35 -05002829static_install_ipv6 (struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002830{
2831 struct rib *rib;
2832 struct route_table *table;
2833 struct route_node *rn;
2834
2835 /* Lookup table. */
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002836 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002837 if (! table)
2838 return;
2839
2840 /* Lookup existing route */
2841 rn = route_node_get (table, p);
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002842 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002843 {
2844 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2845 continue;
2846
2847 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2848 break;
2849 }
paul718e3742002-12-13 20:15:29 +00002850
2851 if (rib)
2852 {
2853 /* Same distance static route is there. Update it with new
2854 nexthop. */
paul718e3742002-12-13 20:15:29 +00002855 route_unlock_node (rn);
2856
2857 switch (si->type)
2858 {
2859 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002860 nexthop_ipv6_add (rib, &si->addr.ipv6);
paul718e3742002-12-13 20:15:29 +00002861 break;
2862 case STATIC_IPV6_IFNAME:
2863 nexthop_ifname_add (rib, si->ifname);
2864 break;
2865 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002866 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
paul718e3742002-12-13 20:15:29 +00002867 break;
2868 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002869 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002870 }
2871 else
2872 {
2873 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002874 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2875
paul718e3742002-12-13 20:15:29 +00002876 rib->type = ZEBRA_ROUTE_STATIC;
2877 rib->distance = si->distance;
2878 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002879 rib->vrf_id = si->vrf_id;
Dinesh G Duttd1b09912014-09-30 12:54:13 -07002880 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002881 rib->nexthop_num = 0;
2882
2883 switch (si->type)
2884 {
2885 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002886 nexthop_ipv6_add (rib, &si->addr.ipv6);
paul718e3742002-12-13 20:15:29 +00002887 break;
2888 case STATIC_IPV6_IFNAME:
2889 nexthop_ifname_add (rib, si->ifname);
2890 break;
2891 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002892 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
paul718e3742002-12-13 20:15:29 +00002893 break;
2894 }
2895
hasso81dfcaa2003-05-25 19:21:25 +00002896 /* Save the flags of this static routes (reject, blackhole) */
2897 rib->flags = si->flags;
2898
paul718e3742002-12-13 20:15:29 +00002899 /* Link this rib to the tree. */
2900 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002901 }
2902}
2903
paula1ac18c2005-06-28 17:17:12 +00002904static int
Donald Sharpd4c27d62015-11-04 13:26:35 -05002905static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002906{
2907 if (nexthop->type == NEXTHOP_TYPE_IPV6
2908 && si->type == STATIC_IPV6_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002909 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002910 return 1;
2911 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2912 && si->type == STATIC_IPV6_IFNAME
2913 && strcmp (nexthop->ifname, si->ifname) == 0)
2914 return 1;
2915 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2916 && si->type == STATIC_IPV6_GATEWAY_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002917 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
paul718e3742002-12-13 20:15:29 +00002918 && strcmp (nexthop->ifname, si->ifname) == 0)
2919 return 1;
paule8e19462006-01-19 20:16:55 +00002920 return 0;
paul718e3742002-12-13 20:15:29 +00002921}
2922
paula1ac18c2005-06-28 17:17:12 +00002923static void
Donald Sharpd4c27d62015-11-04 13:26:35 -05002924static_uninstall_ipv6 (struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002925{
2926 struct route_table *table;
2927 struct route_node *rn;
2928 struct rib *rib;
2929 struct nexthop *nexthop;
2930
2931 /* Lookup table. */
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002932 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002933 if (! table)
2934 return;
2935
2936 /* Lookup existing route with type and distance. */
2937 rn = route_node_lookup (table, (struct prefix *) p);
2938 if (! rn)
2939 return;
2940
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002941 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002942 {
2943 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2944 continue;
2945
2946 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2947 break;
2948 }
2949
paul718e3742002-12-13 20:15:29 +00002950 if (! rib)
2951 {
2952 route_unlock_node (rn);
2953 return;
2954 }
2955
2956 /* Lookup nexthop. */
2957 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2958 if (static_ipv6_nexthop_same (nexthop, si))
2959 break;
2960
2961 /* Can't find nexthop. */
2962 if (! nexthop)
2963 {
2964 route_unlock_node (rn);
2965 return;
2966 }
2967
2968 /* Check nexthop. */
2969 if (rib->nexthop_num == 1)
2970 {
2971 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002972 }
2973 else
2974 {
paul6baeb982003-10-28 03:47:15 +00002975 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2976 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002977 nexthop_delete (rib, nexthop);
2978 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002979 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002980 }
paul718e3742002-12-13 20:15:29 +00002981 /* Unlock node. */
2982 route_unlock_node (rn);
2983}
2984
2985/* Add static route into static route configuration. */
2986int
2987static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002988 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002989 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002990{
2991 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002992 struct static_route *si;
2993 struct static_route *pp;
2994 struct static_route *cp;
Feng Lu0d0686f2015-05-22 11:40:02 +02002995 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2996 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002997
paul718e3742002-12-13 20:15:29 +00002998 if (! stable)
2999 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00003000
3001 if (!gate &&
3002 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
3003 return -1;
3004
3005 if (!ifname &&
3006 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
3007 return -1;
paul718e3742002-12-13 20:15:29 +00003008
3009 /* Lookup static route prefix. */
3010 rn = route_node_get (stable, p);
3011
3012 /* Do nothing if there is a same static route. */
3013 for (si = rn->info; si; si = si->next)
3014 {
3015 if (distance == si->distance
3016 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05003017 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00003018 && (! ifname || strcmp (ifname, si->ifname) == 0))
3019 {
3020 route_unlock_node (rn);
3021 return 0;
3022 }
3023 }
3024
3025 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05003026 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00003027
3028 si->type = type;
3029 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00003030 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02003031 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00003032
3033 switch (type)
3034 {
3035 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05003036 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00003037 break;
3038 case STATIC_IPV6_IFNAME:
3039 si->ifname = XSTRDUP (0, ifname);
3040 break;
3041 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05003042 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00003043 si->ifname = XSTRDUP (0, ifname);
3044 break;
3045 }
3046
3047 /* Add new static route information to the tree with sort by
3048 distance value and gateway address. */
3049 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
3050 {
3051 if (si->distance < cp->distance)
3052 break;
3053 if (si->distance > cp->distance)
3054 continue;
3055 }
3056
3057 /* Make linked list. */
3058 if (pp)
3059 pp->next = si;
3060 else
3061 rn->info = si;
3062 if (cp)
3063 cp->prev = si;
3064 si->prev = pp;
3065 si->next = cp;
3066
3067 /* Install into rib. */
3068 static_install_ipv6 (p, si);
3069
3070 return 1;
3071}
3072
3073/* Delete static route from static route configuration. */
3074int
3075static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02003076 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003077{
3078 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05003079 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00003080 struct route_table *stable;
3081
3082 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02003083 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003084 if (! stable)
3085 return -1;
3086
3087 /* Lookup static route prefix. */
3088 rn = route_node_lookup (stable, p);
3089 if (! rn)
3090 return 0;
3091
3092 /* Find same static route is the tree */
3093 for (si = rn->info; si; si = si->next)
3094 if (distance == si->distance
3095 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05003096 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00003097 && (! ifname || strcmp (ifname, si->ifname) == 0))
3098 break;
3099
3100 /* Can't find static route. */
3101 if (! si)
3102 {
3103 route_unlock_node (rn);
3104 return 0;
3105 }
3106
3107 /* Install into rib. */
3108 static_uninstall_ipv6 (p, si);
3109
3110 /* Unlink static route from linked list. */
3111 if (si->prev)
3112 si->prev->next = si->next;
3113 else
3114 rn->info = si->next;
3115 if (si->next)
3116 si->next->prev = si->prev;
3117
3118 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003119 if (ifname)
3120 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05003121 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00003122
3123 return 1;
3124}
David Lamparter6b0655a2014-06-04 06:53:35 +02003125
paul718e3742002-12-13 20:15:29 +00003126/* RIB update function. */
3127void
Feng Lu0d0686f2015-05-22 11:40:02 +02003128rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003129{
3130 struct route_node *rn;
3131 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003132
Feng Lu0d0686f2015-05-22 11:40:02 +02003133 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003134 if (table)
3135 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003136 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003137 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003138
Feng Lu0d0686f2015-05-22 11:40:02 +02003139 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003140 if (table)
3141 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003142 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003143 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003144}
3145
David Lamparter6b0655a2014-06-04 06:53:35 +02003146
paul718e3742002-12-13 20:15:29 +00003147/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003148static void
paul718e3742002-12-13 20:15:29 +00003149rib_weed_table (struct route_table *table)
3150{
3151 struct route_node *rn;
3152 struct rib *rib;
3153 struct rib *next;
3154
3155 if (table)
3156 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003157 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003158 {
Paul Jakma6d691122006-07-27 21:49:00 +00003159 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3160 continue;
3161
paulb21b19c2003-06-15 01:28:29 +00003162 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003163 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003164 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003165 }
3166}
3167
3168/* Delete all routes from non main table. */
3169void
paula1ac18c2005-06-28 17:17:12 +00003170rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003171{
Feng Lu0d0686f2015-05-22 11:40:02 +02003172 vrf_iter_t iter;
3173 struct zebra_vrf *zvrf;
3174
3175 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3176 if ((zvrf = vrf_iter2info (iter)) != NULL)
3177 {
3178 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3179 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3180 }
paul718e3742002-12-13 20:15:29 +00003181}
David Lamparter6b0655a2014-06-04 06:53:35 +02003182
Feng Lu0d0686f2015-05-22 11:40:02 +02003183#if 0
paul718e3742002-12-13 20:15:29 +00003184/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003185static void
paul718e3742002-12-13 20:15:29 +00003186rib_sweep_table (struct route_table *table)
3187{
3188 struct route_node *rn;
3189 struct rib *rib;
3190 struct rib *next;
3191 int ret = 0;
3192
3193 if (table)
3194 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003195 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003196 {
Paul Jakma6d691122006-07-27 21:49:00 +00003197 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3198 continue;
3199
paul718e3742002-12-13 20:15:29 +00003200 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3201 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3202 {
3203 ret = rib_uninstall_kernel (rn, rib);
3204 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003205 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003206 }
3207 }
3208}
Feng Lu0d0686f2015-05-22 11:40:02 +02003209#endif
paul718e3742002-12-13 20:15:29 +00003210
3211/* Sweep all RIB tables. */
3212void
paula1ac18c2005-06-28 17:17:12 +00003213rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003214{
Feng Lu0d0686f2015-05-22 11:40:02 +02003215 vrf_iter_t iter;
3216 struct zebra_vrf *zvrf;
3217
3218 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3219 if ((zvrf = vrf_iter2info (iter)) != NULL)
3220 {
3221 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3222 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3223 }
paul718e3742002-12-13 20:15:29 +00003224}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003225
3226/* Remove specific by protocol routes from 'table'. */
3227static unsigned long
3228rib_score_proto_table (u_char proto, struct route_table *table)
3229{
3230 struct route_node *rn;
3231 struct rib *rib;
3232 struct rib *next;
3233 unsigned long n = 0;
3234
3235 if (table)
3236 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003237 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003238 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003239 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3240 continue;
3241 if (rib->type == proto)
3242 {
3243 rib_delnode (rn, rib);
3244 n++;
3245 }
3246 }
3247
3248 return n;
3249}
3250
3251/* Remove specific by protocol routes. */
3252unsigned long
3253rib_score_proto (u_char proto)
3254{
Feng Lu0d0686f2015-05-22 11:40:02 +02003255 vrf_iter_t iter;
3256 struct zebra_vrf *zvrf;
3257 unsigned long cnt = 0;
3258
3259 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3260 if ((zvrf = vrf_iter2info (iter)) != NULL)
3261 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3262 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3263
3264 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003265}
3266
paul718e3742002-12-13 20:15:29 +00003267/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003268void
paul718e3742002-12-13 20:15:29 +00003269rib_close_table (struct route_table *table)
3270{
3271 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003272 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003273 struct rib *rib;
3274
3275 if (table)
3276 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003277 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003278 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003279 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3280 continue;
3281
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003282 if (info->safi == SAFI_UNICAST)
3283 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003284
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003285 if (! RIB_SYSTEM_ROUTE (rib))
3286 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003287 }
paul718e3742002-12-13 20:15:29 +00003288}
3289
3290/* Close all RIB tables. */
3291void
paula1ac18c2005-06-28 17:17:12 +00003292rib_close (void)
paul718e3742002-12-13 20:15:29 +00003293{
Feng Lu0d0686f2015-05-22 11:40:02 +02003294 vrf_iter_t iter;
3295 struct zebra_vrf *zvrf;
3296
3297 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3298 if ((zvrf = vrf_iter2info (iter)) != NULL)
3299 {
3300 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3301 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3302 }
paul718e3742002-12-13 20:15:29 +00003303}
David Lamparter6b0655a2014-06-04 06:53:35 +02003304
paul718e3742002-12-13 20:15:29 +00003305/* Routing information base initialize. */
3306void
paula1ac18c2005-06-28 17:17:12 +00003307rib_init (void)
paul718e3742002-12-13 20:15:29 +00003308{
paul4d38fdb2005-04-28 17:35:14 +00003309 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003310}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003311
3312/*
3313 * vrf_id_get_next
3314 *
3315 * Get the first vrf id that is greater than the given vrf id if any.
3316 *
3317 * Returns TRUE if a vrf id was found, FALSE otherwise.
3318 */
3319static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003320vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003321{
Feng Lu41f44a22015-05-22 11:39:56 +02003322 vrf_iter_t iter = vrf_iterator (vrf_id);
3323 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3324
3325 /* The same one ? Then find out the next. */
3326 if (zvrf && (zvrf->vrf_id == vrf_id))
3327 zvrf = vrf_iter2info (vrf_next (iter));
3328
3329 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003330 {
Feng Lu41f44a22015-05-22 11:39:56 +02003331 *next_id_p = zvrf->vrf_id;
3332 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003333 }
3334
3335 return 0;
3336}
3337
3338/*
3339 * rib_tables_iter_next
3340 *
3341 * Returns the next table in the iteration.
3342 */
3343struct route_table *
3344rib_tables_iter_next (rib_tables_iter_t *iter)
3345{
3346 struct route_table *table;
3347
3348 /*
3349 * Array that helps us go over all AFI/SAFI combinations via one
3350 * index.
3351 */
3352 static struct {
3353 afi_t afi;
3354 safi_t safi;
3355 } afi_safis[] = {
3356 { AFI_IP, SAFI_UNICAST },
3357 { AFI_IP, SAFI_MULTICAST },
3358 { AFI_IP6, SAFI_UNICAST },
3359 { AFI_IP6, SAFI_MULTICAST },
3360 };
3361
3362 table = NULL;
3363
3364 switch (iter->state)
3365 {
3366
3367 case RIB_TABLES_ITER_S_INIT:
3368 iter->vrf_id = 0;
3369 iter->afi_safi_ix = -1;
3370
3371 /* Fall through */
3372
3373 case RIB_TABLES_ITER_S_ITERATING:
3374 iter->afi_safi_ix++;
3375 while (1)
3376 {
3377
3378 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3379 {
Feng Lu41f44a22015-05-22 11:39:56 +02003380 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003381 afi_safis[iter->afi_safi_ix].safi,
3382 iter->vrf_id);
3383 if (table)
3384 break;
3385
3386 iter->afi_safi_ix++;
3387 }
3388
3389 /*
3390 * Found another table in this vrf.
3391 */
3392 if (table)
3393 break;
3394
3395 /*
3396 * Done with all tables in the current vrf, go to the next
3397 * one.
3398 */
3399 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3400 break;
3401
3402 iter->afi_safi_ix = 0;
3403 }
3404
3405 break;
3406
3407 case RIB_TABLES_ITER_S_DONE:
3408 return NULL;
3409 }
3410
3411 if (table)
3412 iter->state = RIB_TABLES_ITER_S_ITERATING;
3413 else
3414 iter->state = RIB_TABLES_ITER_S_DONE;
3415
3416 return table;
3417}
Feng Lu41f44a22015-05-22 11:39:56 +02003418
3419/*
3420 * Create a routing table for the specific AFI/SAFI in the given VRF.
3421 */
3422static void
3423zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3424{
3425 rib_table_info_t *info;
3426 struct route_table *table;
3427
3428 assert (!zvrf->table[afi][safi]);
3429
3430 table = route_table_init ();
3431 zvrf->table[afi][safi] = table;
3432
3433 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3434 info->zvrf = zvrf;
3435 info->afi = afi;
3436 info->safi = safi;
3437 table->info = info;
3438}
3439
3440/* Allocate new zebra VRF. */
3441struct zebra_vrf *
3442zebra_vrf_alloc (vrf_id_t vrf_id)
3443{
3444 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003445#ifdef HAVE_NETLINK
3446 char nl_name[64];
3447#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003448
3449 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3450
3451 /* Allocate routing table and static table. */
3452 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3453 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3454 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3455 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3456 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3457 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3458 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3459 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3460
3461 /* Set VRF ID */
3462 zvrf->vrf_id = vrf_id;
3463
Feng Lu758fb8f2014-07-03 18:23:09 +08003464#ifdef HAVE_NETLINK
3465 /* Initialize netlink sockets */
3466 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3467 zvrf->netlink.sock = -1;
3468 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3469
3470 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3471 zvrf->netlink_cmd.sock = -1;
3472 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3473#endif
3474
Feng Lu41f44a22015-05-22 11:39:56 +02003475 return zvrf;
3476}
3477
3478/* Lookup the routing table in an enabled VRF. */
3479struct route_table *
3480zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3481{
3482 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3483
3484 if (!zvrf)
3485 return NULL;
3486
3487 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3488 return NULL;
3489
3490 return zvrf->table[afi][safi];
3491}
3492
3493/* Lookup the static routing table in a VRF. */
3494struct route_table *
3495zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3496{
3497 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3498
3499 if (!zvrf)
3500 return NULL;
3501
3502 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3503 return NULL;
3504
3505 return zvrf->stable[afi][safi];
3506}
3507