blob: 4d122c42b74554c02be2cbeb896531592bfdcf58 [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
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05001672 * state, or static_install_route (when an existing RIB is updated)
Paul Jakma3c0755d2006-12-08 00:53:14 +00001673 * 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 Sharp9bcdd1a2015-11-04 13:26:37 -05002282static_install_route (afi_t afi, 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. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002289 table = zebra_vrf_table (afi, 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 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002311 case STATIC_IPV4_GATEWAY:
2312 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2313 break;
2314 case STATIC_IPV4_IFNAME:
2315 nexthop_ifname_add (rib, si->ifname);
2316 break;
2317 case STATIC_IPV4_BLACKHOLE:
2318 nexthop_blackhole_add (rib);
2319 break;
2320 case STATIC_IPV6_GATEWAY:
2321 nexthop_ipv6_add (rib, &si->addr.ipv6);
2322 break;
2323 case STATIC_IPV6_IFNAME:
2324 nexthop_ifname_add (rib, si->ifname);
2325 break;
2326 case STATIC_IPV6_GATEWAY_IFNAME:
2327 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2328 break;
paul4d38fdb2005-04-28 17:35:14 +00002329 }
Paul Jakma3c0755d2006-12-08 00:53:14 +00002330 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002331 }
2332 else
2333 {
2334 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002335 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2336
paul718e3742002-12-13 20:15:29 +00002337 rib->type = ZEBRA_ROUTE_STATIC;
2338 rib->distance = si->distance;
2339 rib->metric = 0;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002340 rib->vrf_id = si->vrf_id;
Nolan Leakeb0145dd2012-09-13 17:17:31 +00002341 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00002342 rib->nexthop_num = 0;
2343
2344 switch (si->type)
paul7021c422003-07-15 12:52:22 +00002345 {
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002346 case STATIC_IPV4_GATEWAY:
2347 nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
2348 break;
2349 case STATIC_IPV4_IFNAME:
2350 nexthop_ifname_add (rib, si->ifname);
2351 break;
2352 case STATIC_IPV4_BLACKHOLE:
2353 nexthop_blackhole_add (rib);
2354 break;
2355 case STATIC_IPV6_GATEWAY:
2356 nexthop_ipv6_add (rib, &si->addr.ipv6);
2357 break;
2358 case STATIC_IPV6_IFNAME:
2359 nexthop_ifname_add (rib, si->ifname);
2360 break;
2361 case STATIC_IPV6_GATEWAY_IFNAME:
2362 nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
2363 break;
paul7021c422003-07-15 12:52:22 +00002364 }
paul718e3742002-12-13 20:15:29 +00002365
hasso81dfcaa2003-05-25 19:21:25 +00002366 /* Save the flags of this static routes (reject, blackhole) */
2367 rib->flags = si->flags;
2368
paul718e3742002-12-13 20:15:29 +00002369 /* Link this rib to the tree. */
2370 rib_addnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002371 }
2372}
2373
paula1ac18c2005-06-28 17:17:12 +00002374static int
Donald Sharpd4c27d62015-11-04 13:26:35 -05002375static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002376{
2377 if (nexthop->type == NEXTHOP_TYPE_IPV4
2378 && si->type == STATIC_IPV4_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002379 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
paul718e3742002-12-13 20:15:29 +00002380 return 1;
2381 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2382 && si->type == STATIC_IPV4_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002383 && strcmp (nexthop->ifname, si->ifname) == 0)
paul718e3742002-12-13 20:15:29 +00002384 return 1;
paul595db7f2003-05-25 21:35:06 +00002385 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2386 && si->type == STATIC_IPV4_BLACKHOLE)
2387 return 1;
paule8e19462006-01-19 20:16:55 +00002388 return 0;
paul718e3742002-12-13 20:15:29 +00002389}
2390
2391/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00002392static void
Donald Sharpd4c27d62015-11-04 13:26:35 -05002393static_uninstall_ipv4 (safi_t safi, struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002394{
2395 struct route_node *rn;
2396 struct rib *rib;
2397 struct nexthop *nexthop;
2398 struct route_table *table;
2399
2400 /* Lookup table. */
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002401 table = zebra_vrf_table (AFI_IP, safi, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002402 if (! table)
2403 return;
paul4d38fdb2005-04-28 17:35:14 +00002404
paul718e3742002-12-13 20:15:29 +00002405 /* Lookup existing route with type and distance. */
2406 rn = route_node_lookup (table, p);
2407 if (! rn)
2408 return;
2409
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002410 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002411 {
2412 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2413 continue;
2414
2415 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2416 break;
2417 }
paul718e3742002-12-13 20:15:29 +00002418
2419 if (! rib)
2420 {
2421 route_unlock_node (rn);
2422 return;
2423 }
2424
2425 /* Lookup nexthop. */
2426 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2427 if (static_ipv4_nexthop_same (nexthop, si))
2428 break;
2429
2430 /* Can't find nexthop. */
2431 if (! nexthop)
2432 {
2433 route_unlock_node (rn);
2434 return;
2435 }
2436
2437 /* Check nexthop. */
2438 if (rib->nexthop_num == 1)
Paul Jakma6d691122006-07-27 21:49:00 +00002439 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002440 else
2441 {
paul6baeb982003-10-28 03:47:15 +00002442 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2443 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002444 nexthop_delete (rib, nexthop);
2445 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002446 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002447 }
paul718e3742002-12-13 20:15:29 +00002448 /* Unlock node. */
2449 route_unlock_node (rn);
2450}
2451
paul718e3742002-12-13 20:15:29 +00002452int
Everton Marques33d86db2014-07-14 11:19:00 -03002453static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
2454 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002455 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002456{
2457 u_char type = 0;
2458 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002459 struct static_route *si;
2460 struct static_route *pp;
2461 struct static_route *cp;
2462 struct static_route *update = NULL;
Feng Lu0d0686f2015-05-22 11:40:02 +02002463 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2464 struct route_table *stable = zvrf->stable[AFI_IP][safi];
paul718e3742002-12-13 20:15:29 +00002465
paul718e3742002-12-13 20:15:29 +00002466 if (! stable)
2467 return -1;
2468
2469 /* Lookup static route prefix. */
2470 rn = route_node_get (stable, p);
2471
2472 /* Make flags. */
2473 if (gate)
2474 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00002475 else if (ifname)
paul718e3742002-12-13 20:15:29 +00002476 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002477 else
2478 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002479
2480 /* Do nothing if there is a same static route. */
2481 for (si = rn->info; si; si = si->next)
2482 {
2483 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002484 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2485 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002486 {
2487 if (distance == si->distance)
2488 {
2489 route_unlock_node (rn);
2490 return 0;
2491 }
2492 else
2493 update = si;
2494 }
2495 }
2496
Paul Jakma3c0755d2006-12-08 00:53:14 +00002497 /* Distance changed. */
paul718e3742002-12-13 20:15:29 +00002498 if (update)
Everton Marques33d86db2014-07-14 11:19:00 -03002499 static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
paul718e3742002-12-13 20:15:29 +00002500
2501 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002502 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002503
2504 si->type = type;
2505 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002506 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002507 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002508
2509 if (gate)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002510 si->addr.ipv4 = *gate;
paul718e3742002-12-13 20:15:29 +00002511 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002512 si->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +00002513
2514 /* Add new static route information to the tree with sort by
2515 distance value and gateway address. */
2516 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2517 {
2518 if (si->distance < cp->distance)
2519 break;
2520 if (si->distance > cp->distance)
2521 continue;
2522 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2523 {
Donald Sharpd4c27d62015-11-04 13:26:35 -05002524 if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002525 break;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002526 if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
paul718e3742002-12-13 20:15:29 +00002527 continue;
2528 }
2529 }
2530
2531 /* Make linked list. */
2532 if (pp)
2533 pp->next = si;
2534 else
2535 rn->info = si;
2536 if (cp)
2537 cp->prev = si;
2538 si->prev = pp;
2539 si->next = cp;
2540
2541 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05002542 static_install_route (AFI_IP, safi, p, si);
paul718e3742002-12-13 20:15:29 +00002543
2544 return 1;
2545}
2546
paul718e3742002-12-13 20:15:29 +00002547int
Everton Marques33d86db2014-07-14 11:19:00 -03002548static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02002549 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002550{
2551 u_char type = 0;
2552 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002553 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00002554 struct route_table *stable;
2555
2556 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02002557 stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002558 if (! stable)
2559 return -1;
2560
2561 /* Lookup static route prefix. */
2562 rn = route_node_lookup (stable, p);
2563 if (! rn)
2564 return 0;
2565
2566 /* Make flags. */
2567 if (gate)
2568 type = STATIC_IPV4_GATEWAY;
2569 else if (ifname)
2570 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00002571 else
2572 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00002573
2574 /* Find same static route is the tree */
2575 for (si = rn->info; si; si = si->next)
2576 if (type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002577 && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
2578 && (! ifname || strcmp (ifname, si->ifname) == 0))
paul718e3742002-12-13 20:15:29 +00002579 break;
2580
2581 /* Can't find static route. */
2582 if (! si)
2583 {
2584 route_unlock_node (rn);
2585 return 0;
2586 }
2587
2588 /* Install into rib. */
Everton Marques33d86db2014-07-14 11:19:00 -03002589 static_uninstall_ipv4 (safi, p, si);
paul718e3742002-12-13 20:15:29 +00002590
2591 /* Unlink static route from linked list. */
2592 if (si->prev)
2593 si->prev->next = si->next;
2594 else
2595 rn->info = si->next;
2596 if (si->next)
2597 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00002598 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002599
2600 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002601 if (ifname)
Donald Sharpd4c27d62015-11-04 13:26:35 -05002602 XFREE (0, si->ifname);
2603 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00002604
paul143a3852003-09-29 20:06:13 +00002605 route_unlock_node (rn);
2606
paul718e3742002-12-13 20:15:29 +00002607 return 1;
2608}
2609
paul718e3742002-12-13 20:15:29 +00002610int
2611rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002612 struct in6_addr *gate, unsigned int ifindex,
2613 vrf_id_t vrf_id, int table_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +02002614 u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002615{
2616 struct rib *rib;
2617 struct rib *same = NULL;
2618 struct route_table *table;
2619 struct route_node *rn;
2620 struct nexthop *nexthop;
2621
paul718e3742002-12-13 20:15:29 +00002622 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002623 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002624 if (! table)
2625 return 0;
2626
2627 /* Make sure mask is applied. */
2628 apply_mask_ipv6 (p);
2629
2630 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00002631 if (!distance)
2632 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00002633
2634 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2635 distance = 200;
2636
paul718e3742002-12-13 20:15:29 +00002637 /* Lookup route node.*/
2638 rn = route_node_get (table, (struct prefix *) p);
2639
2640 /* If same type of route are installed, treat it as a implicit
2641 withdraw. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002642 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002643 {
Paul Jakma6d691122006-07-27 21:49:00 +00002644 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2645 continue;
2646
hassoebf1ead2005-09-21 14:58:20 +00002647 if (rib->type != type)
2648 continue;
2649 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00002650 {
2651 same = rib;
paul718e3742002-12-13 20:15:29 +00002652 break;
2653 }
hassoebf1ead2005-09-21 14:58:20 +00002654 else if ((nexthop = rib->nexthop) &&
2655 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2656 nexthop->ifindex == ifindex)
2657 {
2658 rib->refcnt++;
2659 return 0;
2660 }
paul718e3742002-12-13 20:15:29 +00002661 }
2662
2663 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00002664 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2665
paul718e3742002-12-13 20:15:29 +00002666 rib->type = type;
2667 rib->distance = distance;
2668 rib->flags = flags;
2669 rib->metric = metric;
Timo Teräsb11f3b52015-11-02 16:50:07 +02002670 rib->mtu = mtu;
Feng Lu0d0686f2015-05-22 11:40:02 +02002671 rib->vrf_id = vrf_id;
2672 rib->table = table_id;
paul718e3742002-12-13 20:15:29 +00002673 rib->nexthop_num = 0;
2674 rib->uptime = time (NULL);
2675
2676 /* Nexthop settings. */
2677 if (gate)
2678 {
2679 if (ifindex)
2680 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2681 else
2682 nexthop_ipv6_add (rib, gate);
2683 }
2684 else
2685 nexthop_ifindex_add (rib, ifindex);
2686
2687 /* If this route is kernel route, set FIB flag to the route. */
2688 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2689 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2690 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2691
2692 /* Link new rib to node.*/
2693 rib_addnode (rn, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002694 if (IS_ZEBRA_DEBUG_RIB)
2695 {
2696 zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002697 __func__, (void *)rn, (void *)rib);
David Lamparterf7bf4152013-10-22 17:10:21 +00002698 rib_dump (p, rib);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002699 }
paul718e3742002-12-13 20:15:29 +00002700
paul718e3742002-12-13 20:15:29 +00002701 /* Free implicit route.*/
2702 if (same)
Vincent Bernatfed643f2012-10-23 16:00:42 +00002703 {
2704 if (IS_ZEBRA_DEBUG_RIB)
2705 {
2706 zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
David Lampartereed3c482015-03-03 08:51:53 +01002707 __func__, (void *)rn, (void *)same);
David Lamparterf7bf4152013-10-22 17:10:21 +00002708 rib_dump (p, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002709 }
paul4d38fdb2005-04-28 17:35:14 +00002710 rib_delnode (rn, same);
Vincent Bernatfed643f2012-10-23 16:00:42 +00002711 }
paul4d38fdb2005-04-28 17:35:14 +00002712
2713 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002714 return 0;
2715}
2716
hassoebf1ead2005-09-21 14:58:20 +00002717/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00002718int
2719rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
Feng Lu0d0686f2015-05-22 11:40:02 +02002720 struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002721{
2722 struct route_table *table;
2723 struct route_node *rn;
2724 struct rib *rib;
2725 struct rib *fib = NULL;
2726 struct rib *same = NULL;
Christian Frankefa713d92013-07-05 15:35:37 +00002727 struct nexthop *nexthop, *tnexthop;
2728 int recursing;
Timo Teräsbe6335d2015-05-23 11:08:41 +03002729 char buf1[PREFIX_STRLEN];
Stephen Hemminger81cce012009-04-28 14:28:00 -07002730 char buf2[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00002731
2732 /* Apply mask. */
2733 apply_mask_ipv6 (p);
2734
2735 /* Lookup table. */
Feng Lu0d0686f2015-05-22 11:40:02 +02002736 table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
paul718e3742002-12-13 20:15:29 +00002737 if (! table)
2738 return 0;
paul4d38fdb2005-04-28 17:35:14 +00002739
paul718e3742002-12-13 20:15:29 +00002740 /* Lookup route node. */
2741 rn = route_node_lookup (table, (struct prefix *) p);
2742 if (! rn)
2743 {
2744 if (IS_ZEBRA_DEBUG_KERNEL)
2745 {
2746 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002747 zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
2748 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002749 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002750 ifindex);
2751 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002752 zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
2753 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002754 ifindex);
2755 }
2756 return ZEBRA_ERR_RTNOEXIST;
2757 }
2758
2759 /* Lookup same type route. */
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002760 RNODE_FOREACH_RIB (rn, rib)
paul718e3742002-12-13 20:15:29 +00002761 {
Paul Jakma6d691122006-07-27 21:49:00 +00002762 if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2763 continue;
2764
paul718e3742002-12-13 20:15:29 +00002765 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2766 fib = rib;
2767
hassoebf1ead2005-09-21 14:58:20 +00002768 if (rib->type != type)
2769 continue;
2770 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002771 nexthop->type == NEXTHOP_TYPE_IFINDEX)
paul718e3742002-12-13 20:15:29 +00002772 {
Matthias Ferdinand4f1735f2011-12-26 16:35:30 +04002773 if (nexthop->ifindex != ifindex)
2774 continue;
hassoebf1ead2005-09-21 14:58:20 +00002775 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00002776 {
hassoebf1ead2005-09-21 14:58:20 +00002777 rib->refcnt--;
2778 route_unlock_node (rn);
2779 route_unlock_node (rn);
2780 return 0;
paul718e3742002-12-13 20:15:29 +00002781 }
hassoebf1ead2005-09-21 14:58:20 +00002782 same = rib;
2783 break;
paul718e3742002-12-13 20:15:29 +00002784 }
hassoebf1ead2005-09-21 14:58:20 +00002785 /* Make sure that the route found has the same gateway. */
Christian Frankefa713d92013-07-05 15:35:37 +00002786 else
2787 {
2788 if (gate == NULL)
2789 {
2790 same = rib;
2791 break;
2792 }
2793 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
2794 if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
2795 {
2796 same = rib;
2797 break;
2798 }
2799 if (same)
2800 break;
2801 }
paul718e3742002-12-13 20:15:29 +00002802 }
2803
2804 /* If same type of route can't be found and this message is from
2805 kernel. */
2806 if (! same)
2807 {
2808 if (fib && type == ZEBRA_ROUTE_KERNEL)
2809 {
2810 /* Unset flags. */
2811 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2812 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2813
2814 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
2815 }
2816 else
2817 {
2818 if (IS_ZEBRA_DEBUG_KERNEL)
2819 {
2820 if (gate)
Feng Lu0d0686f2015-05-22 11:40:02 +02002821 zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
2822 "doesn't exist in rib",
2823 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
Stephen Hemminger81cce012009-04-28 14:28:00 -07002824 inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
paul718e3742002-12-13 20:15:29 +00002825 ifindex,
2826 type);
2827 else
Feng Lu0d0686f2015-05-22 11:40:02 +02002828 zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
2829 prefix2str (p, buf1, sizeof(buf1)), vrf_id,
paul718e3742002-12-13 20:15:29 +00002830 ifindex,
2831 type);
2832 }
2833 route_unlock_node (rn);
2834 return ZEBRA_ERR_RTNOEXIST;
2835 }
2836 }
2837
2838 if (same)
2839 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00002840
paul718e3742002-12-13 20:15:29 +00002841 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00002842 return 0;
2843}
David Lamparter6b0655a2014-06-04 06:53:35 +02002844
paula1ac18c2005-06-28 17:17:12 +00002845static int
Donald Sharpd4c27d62015-11-04 13:26:35 -05002846static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002847{
2848 if (nexthop->type == NEXTHOP_TYPE_IPV6
2849 && si->type == STATIC_IPV6_GATEWAY
Donald Sharpd4c27d62015-11-04 13:26:35 -05002850 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002851 return 1;
2852 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2853 && si->type == STATIC_IPV6_IFNAME
2854 && strcmp (nexthop->ifname, si->ifname) == 0)
2855 return 1;
2856 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2857 && si->type == STATIC_IPV6_GATEWAY_IFNAME
Donald Sharpd4c27d62015-11-04 13:26:35 -05002858 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
paul718e3742002-12-13 20:15:29 +00002859 && strcmp (nexthop->ifname, si->ifname) == 0)
2860 return 1;
paule8e19462006-01-19 20:16:55 +00002861 return 0;
paul718e3742002-12-13 20:15:29 +00002862}
2863
paula1ac18c2005-06-28 17:17:12 +00002864static void
Donald Sharpd4c27d62015-11-04 13:26:35 -05002865static_uninstall_ipv6 (struct prefix *p, struct static_route *si)
paul718e3742002-12-13 20:15:29 +00002866{
2867 struct route_table *table;
2868 struct route_node *rn;
2869 struct rib *rib;
2870 struct nexthop *nexthop;
2871
2872 /* Lookup table. */
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002873 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id);
paul718e3742002-12-13 20:15:29 +00002874 if (! table)
2875 return;
2876
2877 /* Lookup existing route with type and distance. */
2878 rn = route_node_lookup (table, (struct prefix *) p);
2879 if (! rn)
2880 return;
2881
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00002882 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00002883 {
2884 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2885 continue;
2886
2887 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2888 break;
2889 }
2890
paul718e3742002-12-13 20:15:29 +00002891 if (! rib)
2892 {
2893 route_unlock_node (rn);
2894 return;
2895 }
2896
2897 /* Lookup nexthop. */
2898 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2899 if (static_ipv6_nexthop_same (nexthop, si))
2900 break;
2901
2902 /* Can't find nexthop. */
2903 if (! nexthop)
2904 {
2905 route_unlock_node (rn);
2906 return;
2907 }
2908
2909 /* Check nexthop. */
2910 if (rib->nexthop_num == 1)
2911 {
2912 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002913 }
2914 else
2915 {
paul6baeb982003-10-28 03:47:15 +00002916 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2917 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002918 nexthop_delete (rib, nexthop);
2919 nexthop_free (nexthop);
Paul Jakma6d691122006-07-27 21:49:00 +00002920 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00002921 }
paul718e3742002-12-13 20:15:29 +00002922 /* Unlock node. */
2923 route_unlock_node (rn);
2924}
2925
2926/* Add static route into static route configuration. */
2927int
2928static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002929 const char *ifname, u_char flags, u_char distance,
Feng Lu0d0686f2015-05-22 11:40:02 +02002930 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002931{
2932 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05002933 struct static_route *si;
2934 struct static_route *pp;
2935 struct static_route *cp;
Feng Lu0d0686f2015-05-22 11:40:02 +02002936 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
2937 struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
paul718e3742002-12-13 20:15:29 +00002938
paul718e3742002-12-13 20:15:29 +00002939 if (! stable)
2940 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002941
2942 if (!gate &&
2943 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2944 return -1;
2945
2946 if (!ifname &&
2947 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2948 return -1;
paul718e3742002-12-13 20:15:29 +00002949
2950 /* Lookup static route prefix. */
2951 rn = route_node_get (stable, p);
2952
2953 /* Do nothing if there is a same static route. */
2954 for (si = rn->info; si; si = si->next)
2955 {
2956 if (distance == si->distance
2957 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05002958 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00002959 && (! ifname || strcmp (ifname, si->ifname) == 0))
2960 {
2961 route_unlock_node (rn);
2962 return 0;
2963 }
2964 }
2965
2966 /* Make new static route structure. */
Donald Sharpd4c27d62015-11-04 13:26:35 -05002967 si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
paul718e3742002-12-13 20:15:29 +00002968
2969 si->type = type;
2970 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002971 si->flags = flags;
Feng Lu7aaf4ea2015-05-22 11:40:06 +02002972 si->vrf_id = vrf_id;
paul718e3742002-12-13 20:15:29 +00002973
2974 switch (type)
2975 {
2976 case STATIC_IPV6_GATEWAY:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002977 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002978 break;
2979 case STATIC_IPV6_IFNAME:
2980 si->ifname = XSTRDUP (0, ifname);
2981 break;
2982 case STATIC_IPV6_GATEWAY_IFNAME:
Donald Sharpd4c27d62015-11-04 13:26:35 -05002983 si->addr.ipv6 = *gate;
paul718e3742002-12-13 20:15:29 +00002984 si->ifname = XSTRDUP (0, ifname);
2985 break;
2986 }
2987
2988 /* Add new static route information to the tree with sort by
2989 distance value and gateway address. */
2990 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2991 {
2992 if (si->distance < cp->distance)
2993 break;
2994 if (si->distance > cp->distance)
2995 continue;
2996 }
2997
2998 /* Make linked list. */
2999 if (pp)
3000 pp->next = si;
3001 else
3002 rn->info = si;
3003 if (cp)
3004 cp->prev = si;
3005 si->prev = pp;
3006 si->next = cp;
3007
3008 /* Install into rib. */
Donald Sharp9bcdd1a2015-11-04 13:26:37 -05003009 static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
paul718e3742002-12-13 20:15:29 +00003010
3011 return 1;
3012}
3013
3014/* Delete static route from static route configuration. */
3015int
3016static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
Feng Lu0d0686f2015-05-22 11:40:02 +02003017 const char *ifname, u_char distance, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003018{
3019 struct route_node *rn;
Donald Sharpd4c27d62015-11-04 13:26:35 -05003020 struct static_route *si;
paul718e3742002-12-13 20:15:29 +00003021 struct route_table *stable;
3022
3023 /* Lookup table. */
Feng Lu41f44a22015-05-22 11:39:56 +02003024 stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003025 if (! stable)
3026 return -1;
3027
3028 /* Lookup static route prefix. */
3029 rn = route_node_lookup (stable, p);
3030 if (! rn)
3031 return 0;
3032
3033 /* Find same static route is the tree */
3034 for (si = rn->info; si; si = si->next)
3035 if (distance == si->distance
3036 && type == si->type
Donald Sharpd4c27d62015-11-04 13:26:35 -05003037 && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
paul718e3742002-12-13 20:15:29 +00003038 && (! ifname || strcmp (ifname, si->ifname) == 0))
3039 break;
3040
3041 /* Can't find static route. */
3042 if (! si)
3043 {
3044 route_unlock_node (rn);
3045 return 0;
3046 }
3047
3048 /* Install into rib. */
3049 static_uninstall_ipv6 (p, si);
3050
3051 /* Unlink static route from linked list. */
3052 if (si->prev)
3053 si->prev->next = si->next;
3054 else
3055 rn->info = si->next;
3056 if (si->next)
3057 si->next->prev = si->prev;
3058
3059 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00003060 if (ifname)
3061 XFREE (0, si->ifname);
Donald Sharpd4c27d62015-11-04 13:26:35 -05003062 XFREE (MTYPE_STATIC_ROUTE, si);
paul718e3742002-12-13 20:15:29 +00003063
3064 return 1;
3065}
David Lamparter6b0655a2014-06-04 06:53:35 +02003066
paul718e3742002-12-13 20:15:29 +00003067/* RIB update function. */
3068void
Feng Lu0d0686f2015-05-22 11:40:02 +02003069rib_update (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00003070{
3071 struct route_node *rn;
3072 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00003073
Feng Lu0d0686f2015-05-22 11:40:02 +02003074 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003075 if (table)
3076 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003077 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003078 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003079
Feng Lu0d0686f2015-05-22 11:40:02 +02003080 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
paul718e3742002-12-13 20:15:29 +00003081 if (table)
3082 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003083 if (rnode_to_ribs (rn))
Paul Jakma6d691122006-07-27 21:49:00 +00003084 rib_queue_add (&zebrad, rn);
paul718e3742002-12-13 20:15:29 +00003085}
3086
David Lamparter6b0655a2014-06-04 06:53:35 +02003087
paul718e3742002-12-13 20:15:29 +00003088/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00003089static void
paul718e3742002-12-13 20:15:29 +00003090rib_weed_table (struct route_table *table)
3091{
3092 struct route_node *rn;
3093 struct rib *rib;
3094 struct rib *next;
3095
3096 if (table)
3097 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003098 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003099 {
Paul Jakma6d691122006-07-27 21:49:00 +00003100 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3101 continue;
3102
paulb21b19c2003-06-15 01:28:29 +00003103 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00003104 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00003105 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003106 }
3107}
3108
3109/* Delete all routes from non main table. */
3110void
paula1ac18c2005-06-28 17:17:12 +00003111rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00003112{
Feng Lu0d0686f2015-05-22 11:40:02 +02003113 vrf_iter_t iter;
3114 struct zebra_vrf *zvrf;
3115
3116 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3117 if ((zvrf = vrf_iter2info (iter)) != NULL)
3118 {
3119 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3120 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3121 }
paul718e3742002-12-13 20:15:29 +00003122}
David Lamparter6b0655a2014-06-04 06:53:35 +02003123
Feng Lu0d0686f2015-05-22 11:40:02 +02003124#if 0
paul718e3742002-12-13 20:15:29 +00003125/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00003126static void
paul718e3742002-12-13 20:15:29 +00003127rib_sweep_table (struct route_table *table)
3128{
3129 struct route_node *rn;
3130 struct rib *rib;
3131 struct rib *next;
3132 int ret = 0;
3133
3134 if (table)
3135 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003136 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
paul718e3742002-12-13 20:15:29 +00003137 {
Paul Jakma6d691122006-07-27 21:49:00 +00003138 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3139 continue;
3140
paul718e3742002-12-13 20:15:29 +00003141 if (rib->type == ZEBRA_ROUTE_KERNEL &&
3142 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3143 {
3144 ret = rib_uninstall_kernel (rn, rib);
3145 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00003146 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00003147 }
3148 }
3149}
Feng Lu0d0686f2015-05-22 11:40:02 +02003150#endif
paul718e3742002-12-13 20:15:29 +00003151
3152/* Sweep all RIB tables. */
3153void
paula1ac18c2005-06-28 17:17:12 +00003154rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00003155{
Feng Lu0d0686f2015-05-22 11:40:02 +02003156 vrf_iter_t iter;
3157 struct zebra_vrf *zvrf;
3158
3159 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3160 if ((zvrf = vrf_iter2info (iter)) != NULL)
3161 {
3162 rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3163 rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3164 }
paul718e3742002-12-13 20:15:29 +00003165}
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003166
3167/* Remove specific by protocol routes from 'table'. */
3168static unsigned long
3169rib_score_proto_table (u_char proto, struct route_table *table)
3170{
3171 struct route_node *rn;
3172 struct rib *rib;
3173 struct rib *next;
3174 unsigned long n = 0;
3175
3176 if (table)
3177 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003178 RNODE_FOREACH_RIB_SAFE (rn, rib, next)
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003179 {
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003180 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3181 continue;
3182 if (rib->type == proto)
3183 {
3184 rib_delnode (rn, rib);
3185 n++;
3186 }
3187 }
3188
3189 return n;
3190}
3191
3192/* Remove specific by protocol routes. */
3193unsigned long
3194rib_score_proto (u_char proto)
3195{
Feng Lu0d0686f2015-05-22 11:40:02 +02003196 vrf_iter_t iter;
3197 struct zebra_vrf *zvrf;
3198 unsigned long cnt = 0;
3199
3200 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3201 if ((zvrf = vrf_iter2info (iter)) != NULL)
3202 cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
3203 +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
3204
3205 return cnt;
Vyacheslav Trushkin2ea1ab12011-12-11 18:48:47 +04003206}
3207
paul718e3742002-12-13 20:15:29 +00003208/* Close RIB and clean up kernel routes. */
Feng Lu267ceb22015-05-22 11:40:09 +02003209void
paul718e3742002-12-13 20:15:29 +00003210rib_close_table (struct route_table *table)
3211{
3212 struct route_node *rn;
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003213 rib_table_info_t *info = table->info;
paul718e3742002-12-13 20:15:29 +00003214 struct rib *rib;
3215
3216 if (table)
3217 for (rn = route_top (table); rn; rn = route_next (rn))
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003218 RNODE_FOREACH_RIB (rn, rib)
Paul Jakma6d691122006-07-27 21:49:00 +00003219 {
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003220 if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
3221 continue;
3222
David Lamparter7ce9e6a2015-01-12 07:05:06 +01003223 if (info->safi == SAFI_UNICAST)
3224 zfpm_trigger_update (rn, NULL);
Avneesh Sachdev5adc2522012-11-13 22:48:59 +00003225
Avneesh Sachdev9fd92e32012-11-13 22:48:53 +00003226 if (! RIB_SYSTEM_ROUTE (rib))
3227 rib_uninstall_kernel (rn, rib);
Paul Jakma6d691122006-07-27 21:49:00 +00003228 }
paul718e3742002-12-13 20:15:29 +00003229}
3230
3231/* Close all RIB tables. */
3232void
paula1ac18c2005-06-28 17:17:12 +00003233rib_close (void)
paul718e3742002-12-13 20:15:29 +00003234{
Feng Lu0d0686f2015-05-22 11:40:02 +02003235 vrf_iter_t iter;
3236 struct zebra_vrf *zvrf;
3237
3238 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
3239 if ((zvrf = vrf_iter2info (iter)) != NULL)
3240 {
3241 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
3242 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
3243 }
paul718e3742002-12-13 20:15:29 +00003244}
David Lamparter6b0655a2014-06-04 06:53:35 +02003245
paul718e3742002-12-13 20:15:29 +00003246/* Routing information base initialize. */
3247void
paula1ac18c2005-06-28 17:17:12 +00003248rib_init (void)
paul718e3742002-12-13 20:15:29 +00003249{
paul4d38fdb2005-04-28 17:35:14 +00003250 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00003251}
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003252
3253/*
3254 * vrf_id_get_next
3255 *
3256 * Get the first vrf id that is greater than the given vrf id if any.
3257 *
3258 * Returns TRUE if a vrf id was found, FALSE otherwise.
3259 */
3260static inline int
Feng Lu41f44a22015-05-22 11:39:56 +02003261vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003262{
Feng Lu41f44a22015-05-22 11:39:56 +02003263 vrf_iter_t iter = vrf_iterator (vrf_id);
3264 struct zebra_vrf *zvrf = vrf_iter2info (iter);
3265
3266 /* The same one ? Then find out the next. */
3267 if (zvrf && (zvrf->vrf_id == vrf_id))
3268 zvrf = vrf_iter2info (vrf_next (iter));
3269
3270 if (zvrf)
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003271 {
Feng Lu41f44a22015-05-22 11:39:56 +02003272 *next_id_p = zvrf->vrf_id;
3273 return 1;
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003274 }
3275
3276 return 0;
3277}
3278
3279/*
3280 * rib_tables_iter_next
3281 *
3282 * Returns the next table in the iteration.
3283 */
3284struct route_table *
3285rib_tables_iter_next (rib_tables_iter_t *iter)
3286{
3287 struct route_table *table;
3288
3289 /*
3290 * Array that helps us go over all AFI/SAFI combinations via one
3291 * index.
3292 */
3293 static struct {
3294 afi_t afi;
3295 safi_t safi;
3296 } afi_safis[] = {
3297 { AFI_IP, SAFI_UNICAST },
3298 { AFI_IP, SAFI_MULTICAST },
3299 { AFI_IP6, SAFI_UNICAST },
3300 { AFI_IP6, SAFI_MULTICAST },
3301 };
3302
3303 table = NULL;
3304
3305 switch (iter->state)
3306 {
3307
3308 case RIB_TABLES_ITER_S_INIT:
3309 iter->vrf_id = 0;
3310 iter->afi_safi_ix = -1;
3311
3312 /* Fall through */
3313
3314 case RIB_TABLES_ITER_S_ITERATING:
3315 iter->afi_safi_ix++;
3316 while (1)
3317 {
3318
3319 while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3320 {
Feng Lu41f44a22015-05-22 11:39:56 +02003321 table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
Avneesh Sachdev0915bb02012-11-13 22:48:55 +00003322 afi_safis[iter->afi_safi_ix].safi,
3323 iter->vrf_id);
3324 if (table)
3325 break;
3326
3327 iter->afi_safi_ix++;
3328 }
3329
3330 /*
3331 * Found another table in this vrf.
3332 */
3333 if (table)
3334 break;
3335
3336 /*
3337 * Done with all tables in the current vrf, go to the next
3338 * one.
3339 */
3340 if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3341 break;
3342
3343 iter->afi_safi_ix = 0;
3344 }
3345
3346 break;
3347
3348 case RIB_TABLES_ITER_S_DONE:
3349 return NULL;
3350 }
3351
3352 if (table)
3353 iter->state = RIB_TABLES_ITER_S_ITERATING;
3354 else
3355 iter->state = RIB_TABLES_ITER_S_DONE;
3356
3357 return table;
3358}
Feng Lu41f44a22015-05-22 11:39:56 +02003359
3360/*
3361 * Create a routing table for the specific AFI/SAFI in the given VRF.
3362 */
3363static void
3364zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
3365{
3366 rib_table_info_t *info;
3367 struct route_table *table;
3368
3369 assert (!zvrf->table[afi][safi]);
3370
3371 table = route_table_init ();
3372 zvrf->table[afi][safi] = table;
3373
3374 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
3375 info->zvrf = zvrf;
3376 info->afi = afi;
3377 info->safi = safi;
3378 table->info = info;
3379}
3380
3381/* Allocate new zebra VRF. */
3382struct zebra_vrf *
3383zebra_vrf_alloc (vrf_id_t vrf_id)
3384{
3385 struct zebra_vrf *zvrf;
Feng Lu758fb8f2014-07-03 18:23:09 +08003386#ifdef HAVE_NETLINK
3387 char nl_name[64];
3388#endif
Feng Lu41f44a22015-05-22 11:39:56 +02003389
3390 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
3391
3392 /* Allocate routing table and static table. */
3393 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
3394 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
3395 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
3396 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
3397 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
3398 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
3399 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
3400 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
3401
3402 /* Set VRF ID */
3403 zvrf->vrf_id = vrf_id;
3404
Feng Lu758fb8f2014-07-03 18:23:09 +08003405#ifdef HAVE_NETLINK
3406 /* Initialize netlink sockets */
3407 snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
3408 zvrf->netlink.sock = -1;
3409 zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3410
3411 snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
3412 zvrf->netlink_cmd.sock = -1;
3413 zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
3414#endif
3415
Feng Lu41f44a22015-05-22 11:39:56 +02003416 return zvrf;
3417}
3418
3419/* Lookup the routing table in an enabled VRF. */
3420struct route_table *
3421zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3422{
3423 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3424
3425 if (!zvrf)
3426 return NULL;
3427
3428 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3429 return NULL;
3430
3431 return zvrf->table[afi][safi];
3432}
3433
3434/* Lookup the static routing table in a VRF. */
3435struct route_table *
3436zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
3437{
3438 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
3439
3440 if (!zvrf)
3441 return NULL;
3442
3443 if (afi >= AFI_MAX || safi >= SAFI_MAX)
3444 return NULL;
3445
3446 return zvrf->stable[afi][safi];
3447}
3448