]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_rib.c
lib: use const in nexthop_level() api
[mirror_frr.git] / zebra / zebra_rib.c
CommitLineData
718e3744 1/* 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 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
22
718e3744 23#include "command.h"
43e52561
QY
24#include "if.h"
25#include "linklist.h"
718e3744 26#include "log.h"
43e52561
QY
27#include "memory.h"
28#include "mpls.h"
29#include "nexthop.h"
30#include "prefix.h"
7514fb77
PJ
31#include "prefix.h"
32#include "routemap.h"
43e52561 33#include "sockunion.h"
05737783 34#include "srcdest_table.h"
43e52561
QY
35#include "table.h"
36#include "thread.h"
37#include "vrf.h"
38#include "workqueue.h"
50d89650 39#include "nexthop_group_private.h"
00dffa8c 40#include "frr_pthread.h"
718e3744 41
89272910 42#include "zebra/zebra_router.h"
43e52561
QY
43#include "zebra/connected.h"
44#include "zebra/debug.h"
45#include "zebra/interface.h"
46#include "zebra/redistribute.h"
718e3744 47#include "zebra/rib.h"
48#include "zebra/rt.h"
43e52561
QY
49#include "zebra/zapi_msg.h"
50#include "zebra/zebra_errors.h"
51#include "zebra/zebra_memory.h"
7c551956 52#include "zebra/zebra_ns.h"
fb018d25 53#include "zebra/zebra_rnh.h"
43e52561
QY
54#include "zebra/zebra_routemap.h"
55#include "zebra/zebra_vrf.h"
6134fd82 56#include "zebra/zebra_vxlan.h"
7cdb1a84
MS
57#include "zebra/zapi_msg.h"
58#include "zebra/zebra_dplane.h"
59
2a99ab95
SW
60DEFINE_MTYPE_STATIC(ZEBRA, RIB_UPDATE_CTX, "Rib update context object");
61
7cdb1a84
MS
62/*
63 * Event, list, and mutex for delivery of dataplane results
64 */
65static pthread_mutex_t dplane_mutex;
66static struct thread *t_dplane;
25779064 67static struct dplane_ctx_q rib_dplane_q;
718e3744 68
d62a17ae 69DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
70 (rn, reason))
4f8ea50c 71
6baf7bb8
DS
72/* Should we allow non Quagga processes to delete our routes */
73extern int allow_delete;
74
718e3744 75/* Each route type's string and default distance value. */
d62a17ae 76static const struct {
77 int key;
8dc7a759 78 uint8_t distance;
73547a75 79 uint8_t meta_q_map;
d62a17ae 80} route_info[ZEBRA_ROUTE_MAX] = {
e22e8001
SW
81 [ZEBRA_ROUTE_NHG] = {ZEBRA_ROUTE_NHG, 255 /* Uneeded for nhg's */, 0},
82 [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, 5},
83 [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, 1},
84 [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, 1},
85 [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, 2},
86 [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, 3},
87 [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, 3},
88 [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, 3},
89 [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, 3},
90 [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, 3},
91 [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */, 4},
92 [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, 5},
93 [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, 3},
94 [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, 3},
95 [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, 5},
96 [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, 5},
97 [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, 2},
98 [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, 5},
99 [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, 4},
100 [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, 4},
101 [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20, 4},
102 [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, 4},
103 [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20, 4},
104 [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, 3},
105 [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, 5},
106 [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 5},
107 [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 5},
108 [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 3},
109 [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 5}
d6abd8b0 110 /* Any new route type added to zebra, should be mirrored here */
c710b277 111
d62a17ae 112 /* no entry/default: 150 */
718e3744 113};
6b0655a2 114
07ef3e34 115static void PRINTFRR(5, 6)
d62a17ae 116_rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn,
117 int priority, const char *msgfmt, ...)
2263a412 118{
d62a17ae 119 char buf[SRCDEST2STR_BUFFER + sizeof(" (MRIB)")];
120 char msgbuf[512];
121 va_list ap;
2263a412 122
d62a17ae 123 va_start(ap, msgfmt);
124 vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
125 va_end(ap);
2263a412 126
d62a17ae 127 if (rn) {
630d5962 128 struct rib_table_info *info = srcdest_rnode_table_info(rn);
d62a17ae 129 srcdest_rnode2str(rn, buf, sizeof(buf));
cb653491 130
d62a17ae 131 if (info->safi == SAFI_MULTICAST)
eab4a5c2 132 strlcat(buf, " (MRIB)", sizeof(buf));
d62a17ae 133 } else {
134 snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
135 }
2263a412 136
d62a17ae 137 zlog(priority, "%s: %d:%s: %s", _func, vrf_id, buf, msgbuf);
2263a412
DL
138}
139
d62a17ae 140#define rnode_debug(node, vrf_id, ...) \
2263a412 141 _rnode_zlog(__func__, vrf_id, node, LOG_DEBUG, __VA_ARGS__)
d62a17ae 142#define rnode_info(node, ...) \
2263a412
DL
143 _rnode_zlog(__func__, vrf_id, node, LOG_INFO, __VA_ARGS__)
144
fd289fc8 145uint8_t route_distance(int type)
40c7bdb0 146{
fd289fc8 147 uint8_t distance;
40c7bdb0 148
d62a17ae 149 if ((unsigned)type >= array_size(route_info))
150 distance = 150;
151 else
152 distance = route_info[type].distance;
40c7bdb0 153
d62a17ae 154 return distance;
40c7bdb0 155}
156
d7c0a89a 157int is_zebra_valid_kernel_table(uint32_t table_id)
7a4bb9c5 158{
8f500a1c 159#ifdef linux
d62a17ae 160 if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL)
161 || (table_id == RT_TABLE_COMPAT))
162 return 0;
8f500a1c
RW
163#endif
164
d62a17ae 165 return 1;
7a4bb9c5
DS
166}
167
d7c0a89a 168int is_zebra_main_routing_table(uint32_t table_id)
7a4bb9c5 169{
c447ad08 170 if (table_id == RT_TABLE_MAIN)
d62a17ae 171 return 1;
172 return 0;
7a4bb9c5
DS
173}
174
86391e56 175int zebra_check_addr(const struct prefix *p)
0aabccc0 176{
d62a17ae 177 if (p->family == AF_INET) {
d7c0a89a 178 uint32_t addr;
0aabccc0 179
d62a17ae 180 addr = p->u.prefix4.s_addr;
181 addr = ntohl(addr);
0aabccc0 182
d62a17ae 183 if (IPV4_NET127(addr) || IN_CLASSD(addr)
184 || IPV4_LINKLOCAL(addr))
185 return 0;
186 }
187 if (p->family == AF_INET6) {
188 if (IN6_IS_ADDR_LOOPBACK(&p->u.prefix6))
189 return 0;
190 if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
191 return 0;
192 }
193 return 1;
0aabccc0
DD
194}
195
6e26278c
DS
196/**
197 * copy_nexthop - copy a nexthop to the rib structure.
198 */
d62a17ae 199void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh)
6e26278c 200{
c415d895
MS
201 assert(!re->nhe->nhg.nexthop);
202 copy_nexthops(&re->nhe->nhg.nexthop, nh, NULL);
718e3744 203}
204
5463ce26
MS
205static void route_entry_attach_ref(struct route_entry *re,
206 struct nhg_hash_entry *new)
718e3744 207{
0eb97b86 208 re->nhe = new;
5463ce26 209 re->nhe_id = new->id;
718e3744 210
5463ce26 211 zebra_nhg_increment_ref(new);
718e3744 212}
213
cd7108ba
EDP
214int route_entry_update_nhe(struct route_entry *re,
215 struct nhg_hash_entry *new_nhghe)
718e3744 216{
377e29f7 217 struct nhg_hash_entry *old;
5463ce26 218 int ret = 0;
718e3744 219
cd7108ba 220 if (new_nhghe == NULL) {
c415d895
MS
221 if (re->nhe)
222 zebra_nhg_decrement_ref(re->nhe);
223 re->nhe = NULL;
5463ce26
MS
224 goto done;
225 }
718e3744 226
cd7108ba 227 if ((re->nhe_id != 0) && (re->nhe_id != new_nhghe->id)) {
c415d895 228 old = re->nhe;
718e3744 229
cd7108ba 230 route_entry_attach_ref(re, new_nhghe);
718e3744 231
5463ce26
MS
232 if (old)
233 zebra_nhg_decrement_ref(old);
84a89a8d 234 } else if (!re->nhe)
5463ce26 235 /* This is the first time it's being attached */
cd7108ba 236 route_entry_attach_ref(re, new_nhghe);
595db7f1 237
5463ce26
MS
238done:
239 return ret;
595db7f1 240}
241
d62a17ae 242struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
243 union g_addr *addr, struct route_node **rn_out)
244{
245 struct prefix p;
246 struct route_table *table;
247 struct route_node *rn;
5f7a4718 248 struct route_entry *match = NULL;
d62a17ae 249
250 /* Lookup table. */
251 table = zebra_vrf_table(afi, safi, vrf_id);
252 if (!table)
253 return 0;
254
255 memset(&p, 0, sizeof(struct prefix));
256 p.family = afi;
257 if (afi == AFI_IP) {
258 p.u.prefix4 = addr->ipv4;
259 p.prefixlen = IPV4_MAX_PREFIXLEN;
260 } else {
261 p.u.prefix6 = addr->ipv6;
262 p.prefixlen = IPV6_MAX_PREFIXLEN;
263 }
718e3744 264
c4efd0f4 265 rn = route_node_match(table, &p);
718e3744 266
d62a17ae 267 while (rn) {
5f7a4718
DS
268 rib_dest_t *dest;
269
d62a17ae 270 route_unlock_node(rn);
718e3744 271
5f7a4718 272 dest = rib_dest_from_rnode(rn);
996c9314
LB
273 if (dest && dest->selected_fib
274 && !CHECK_FLAG(dest->selected_fib->status,
275 ROUTE_ENTRY_REMOVED))
5f7a4718 276 match = dest->selected_fib;
718e3744 277
d62a17ae 278 /* If there is no selected route or matched route is EGP, go up
279 tree. */
280 if (!match) {
281 do {
282 rn = rn->parent;
283 } while (rn && rn->info == NULL);
284 if (rn)
285 route_lock_node(rn);
286 } else {
287 if (match->type != ZEBRA_ROUTE_CONNECT) {
677c1dd5
DS
288 if (!CHECK_FLAG(match->status,
289 ROUTE_ENTRY_INSTALLED))
d62a17ae 290 return NULL;
291 }
292
293 if (rn_out)
294 *rn_out = rn;
295 return match;
296 }
16814f96 297 }
d62a17ae 298 return NULL;
299}
300
301struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id,
302 struct in_addr addr,
303 struct route_node **rn_out)
304{
305 struct route_entry *re = NULL, *mre = NULL, *ure = NULL;
306 struct route_node *m_rn = NULL, *u_rn = NULL;
307 union g_addr gaddr = {.ipv4 = addr};
308
526052fb 309 switch (zrouter.ipv4_multicast_mode) {
d62a17ae 310 case MCAST_MRIB_ONLY:
311 return rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr,
312 rn_out);
313 case MCAST_URIB_ONLY:
314 return rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out);
315 case MCAST_NO_CONFIG:
316 case MCAST_MIX_MRIB_FIRST:
317 re = mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr,
318 &m_rn);
319 if (!mre)
320 re = ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id,
321 &gaddr, &u_rn);
322 break;
323 case MCAST_MIX_DISTANCE:
324 mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
325 ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
326 if (mre && ure)
327 re = ure->distance < mre->distance ? ure : mre;
328 else if (mre)
329 re = mre;
330 else if (ure)
331 re = ure;
332 break;
333 case MCAST_MIX_PFXLEN:
334 mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
335 ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
336 if (mre && ure)
337 re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre;
338 else if (mre)
339 re = mre;
340 else if (ure)
341 re = ure;
342 break;
718e3744 343 }
33550aa8 344
d62a17ae 345 if (rn_out)
346 *rn_out = (re == mre) ? m_rn : u_rn;
718e3744 347
d62a17ae 348 if (IS_ZEBRA_DEBUG_RIB) {
349 char buf[BUFSIZ];
350 inet_ntop(AF_INET, &addr, buf, BUFSIZ);
4623d897 351
bd47f3a3
JU
352 zlog_debug("%s: %s: vrf: %s(%u) found %s, using %s", __func__,
353 buf, vrf_id_to_name(vrf_id), vrf_id,
d62a17ae 354 mre ? (ure ? "MRIB+URIB" : "MRIB")
355 : ure ? "URIB" : "nothing",
356 re == ure ? "URIB" : re == mre ? "MRIB" : "none");
357 }
358 return re;
4623d897
DL
359}
360
d62a17ae 361struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
718e3744 362{
d62a17ae 363 struct route_table *table;
364 struct route_node *rn;
5f7a4718 365 struct route_entry *match = NULL;
5f7a4718 366 rib_dest_t *dest;
718e3744 367
d62a17ae 368 /* Lookup table. */
369 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
370 if (!table)
371 return 0;
718e3744 372
d62a17ae 373 rn = route_node_lookup(table, (struct prefix *)p);
718e3744 374
d62a17ae 375 /* No route for this prefix. */
376 if (!rn)
377 return NULL;
718e3744 378
d62a17ae 379 /* Unlock node. */
380 route_unlock_node(rn);
5f7a4718 381 dest = rib_dest_from_rnode(rn);
718e3744 382
996c9314
LB
383 if (dest && dest->selected_fib
384 && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
5f7a4718 385 match = dest->selected_fib;
718e3744 386
d62a17ae 387 if (!match)
388 return NULL;
718e3744 389
d62a17ae 390 if (match->type == ZEBRA_ROUTE_CONNECT)
391 return match;
f9e1b38e 392
677c1dd5
DS
393 if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
394 return match;
718e3744 395
d62a17ae 396 return NULL;
718e3744 397}
398
a64448ba
DS
399/*
400 * Is this RIB labeled-unicast? It must be of type BGP and all paths
401 * (nexthops) must have a label.
402 */
d62a17ae 403int zebra_rib_labeled_unicast(struct route_entry *re)
a64448ba 404{
d62a17ae 405 struct nexthop *nexthop = NULL;
a64448ba 406
d62a17ae 407 if (re->type != ZEBRA_ROUTE_BGP)
408 return 0;
a64448ba 409
c415d895 410 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
d62a17ae 411 if (!nexthop->nh_label || !nexthop->nh_label->num_labels)
412 return 0;
6b0655a2 413
d62a17ae 414 return 1;
a64448ba 415}
718e3744 416
6ae24471
DS
417/* Update flag indicates whether this is a "replace" or not. Currently, this
418 * is only used for IPv4.
419 */
0c555cc6
DS
420void rib_install_kernel(struct route_node *rn, struct route_entry *re,
421 struct route_entry *old)
718e3744 422{
d62a17ae 423 struct nexthop *nexthop;
630d5962 424 struct rib_table_info *info = srcdest_rnode_table_info(rn);
d62a17ae 425 struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
97f5b441
MS
426 const struct prefix *p, *src_p;
427 enum zebra_dplane_result ret;
428
429 rib_dest_t *dest = rib_dest_from_rnode(rn);
718e3744 430
d62a17ae 431 srcdest_rnode_prefixes(rn, &p, &src_p);
416ec78d 432
d62a17ae 433 if (info->safi != SAFI_UNICAST) {
c415d895 434 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
d62a17ae 435 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
0c555cc6 436 return;
d62a17ae 437 }
718e3744 438
9ef49038 439
8dfbc657
SW
440 /*
441 * Install the resolved nexthop object first.
442 */
c415d895 443 zebra_nhg_install_kernel(re->nhe);
8dfbc657 444
2063a814
DS
445 /*
446 * If this is a replace to a new RE let the originator of the RE
447 * know that they've lost
448 */
9a9f8926 449 if (old && (old != re) && (old->type != re->type))
28610f7e 450 zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON);
25b9cb0c 451
97f5b441
MS
452 /* Update fib selection */
453 dest->selected_fib = re;
454
d62a17ae 455 /*
456 * Make sure we update the FPM any time we send new information to
457 * the kernel.
458 */
459 hook_call(rib_update, rn, "installing in kernel");
97f5b441
MS
460
461 /* Send add or update */
8263d1d0 462 if (old)
97f5b441 463 ret = dplane_route_update(rn, re, old);
5709131c 464 else
97f5b441 465 ret = dplane_route_add(rn, re);
97f5b441
MS
466
467 switch (ret) {
ea1c14f6 468 case ZEBRA_DPLANE_REQUEST_QUEUED:
60f98b23 469 SET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
efe6c026
MS
470
471 if (old) {
60f98b23 472 SET_FLAG(old->status, ROUTE_ENTRY_QUEUED);
efe6c026
MS
473
474 /* Free old FIB nexthop group */
475 if (old->fib_ng.nexthop) {
476 nexthops_free(old->fib_ng.nexthop);
477 old->fib_ng.nexthop = NULL;
478 }
efe6c026
MS
479 }
480
97f5b441
MS
481 if (zvrf)
482 zvrf->installs_queued++;
1e885672 483 break;
ea1c14f6 484 case ZEBRA_DPLANE_REQUEST_FAILURE:
97f5b441
MS
485 {
486 char str[SRCDEST2STR_BUFFER];
487
488 srcdest_rnode2str(rn, str, sizeof(str));
489 flog_err(EC_ZEBRA_DP_INSTALL_FAIL,
490 "%u:%s: Failed to enqueue dataplane install",
491 re->vrf_id, str);
1e885672 492 break;
97f5b441 493 }
ea1c14f6 494 case ZEBRA_DPLANE_REQUEST_SUCCESS:
97f5b441
MS
495 if (zvrf)
496 zvrf->installs++;
1e885672 497 break;
2f74a82a
JU
498 /* Should never happen */
499 case ZEBRA_DPLANE_REQUEST_PENDING:
500 break;
1e885672 501 }
d62a17ae 502
0c555cc6 503 return;
718e3744 504}
505
506/* Uninstall the route from kernel. */
0c555cc6 507void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
718e3744 508{
d62a17ae 509 struct nexthop *nexthop;
630d5962 510 struct rib_table_info *info = srcdest_rnode_table_info(rn);
d62a17ae 511 struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
05737783 512
d62a17ae 513 if (info->safi != SAFI_UNICAST) {
677c1dd5 514 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
c415d895 515 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
d6792f9d 516 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
0c555cc6 517 return;
d62a17ae 518 }
416ec78d 519
d62a17ae 520 /*
521 * Make sure we update the FPM any time we send new information to
97f5b441 522 * the dataplane.
d62a17ae 523 */
524 hook_call(rib_update, rn, "uninstalling from kernel");
97f5b441
MS
525
526 switch (dplane_route_delete(rn, re)) {
ea1c14f6 527 case ZEBRA_DPLANE_REQUEST_QUEUED:
97f5b441
MS
528 if (zvrf)
529 zvrf->removals_queued++;
1e885672 530 break;
ea1c14f6 531 case ZEBRA_DPLANE_REQUEST_FAILURE:
97f5b441
MS
532 {
533 char str[SRCDEST2STR_BUFFER];
534
535 srcdest_rnode2str(rn, str, sizeof(str));
536 flog_err(EC_ZEBRA_DP_INSTALL_FAIL,
537 "%u:%s: Failed to enqueue dataplane uninstall",
538 re->vrf_id, str);
1e885672 539 break;
97f5b441 540 }
ea1c14f6 541 case ZEBRA_DPLANE_REQUEST_SUCCESS:
1e885672
DS
542 if (zvrf)
543 zvrf->removals++;
544 break;
2f74a82a
JU
545 /* Should never happen */
546 case ZEBRA_DPLANE_REQUEST_PENDING:
547 break;
1e885672 548 }
718e3744 549
0c555cc6 550 return;
718e3744 551}
552
553/* Uninstall the route from kernel. */
d62a17ae 554static void rib_uninstall(struct route_node *rn, struct route_entry *re)
718e3744 555{
630d5962 556 struct rib_table_info *info = srcdest_rnode_table_info(rn);
5f7a4718 557 rib_dest_t *dest = rib_dest_from_rnode(rn);
97f5b441 558 struct nexthop *nexthop;
416ec78d 559
5f7a4718 560 if (dest && dest->selected_fib == re) {
d62a17ae 561 if (info->safi == SAFI_UNICAST)
562 hook_call(rib_update, rn, "rib_uninstall");
5adc2528 563
d62a17ae 564 /* If labeled-unicast route, uninstall transit LSP. */
565 if (zebra_rib_labeled_unicast(re))
566 zebra_mpls_lsp_uninstall(info->zvrf, rn, re);
7cdb1a84 567
3cdba47a 568 rib_uninstall_kernel(rn, re);
97f5b441
MS
569
570 dest->selected_fib = NULL;
571
efe6c026
MS
572 /* Free FIB nexthop group, if present */
573 if (re->fib_ng.nexthop) {
574 nexthops_free(re->fib_ng.nexthop);
575 re->fib_ng.nexthop = NULL;
576 }
577
c415d895 578 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
97f5b441 579 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
d62a17ae 580 }
446bb95e 581
d62a17ae 582 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
86391e56
MS
583 const struct prefix *p, *src_p;
584
d62a17ae 585 srcdest_rnode_prefixes(rn, &p, &src_p);
05737783 586
40f321c0 587 redistribute_delete(p, src_p, re, NULL);
d62a17ae 588 UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED);
589 }
718e3744 590}
591
9fd92e3c
AS
592/*
593 * rib_can_delete_dest
594 *
2951a7a4 595 * Returns true if the given dest can be deleted from the table.
9fd92e3c 596 */
d62a17ae 597static int rib_can_delete_dest(rib_dest_t *dest)
9fd92e3c 598{
045207e2 599 if (re_list_first(&dest->routes)) {
d62a17ae 600 return 0;
601 }
9fd92e3c 602
c86ba6c2
DS
603 /*
604 * Unresolved rnh's are stored on the default route's list
605 *
606 * dest->rnode can also be the source prefix node in an
607 * ipv6 sourcedest table. Fortunately the prefix of a
608 * source prefix node can never be the default prefix.
609 */
610 if (is_default_prefix(&dest->rnode->p))
611 return 0;
612
d62a17ae 613 /*
614 * Don't delete the dest if we have to update the FPM about this
615 * prefix.
616 */
617 if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)
618 || CHECK_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM))
619 return 0;
5adc2528 620
d62a17ae 621 return 1;
9fd92e3c
AS
622}
623
699dae23
DS
624void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
625{
626 rib_dest_t *dest = rib_dest_from_rnode(rn);
699dae23
DS
627 struct rnh *rnh;
628
629 /*
50872b08 630 * We are storing the rnh's associated withb
699dae23
DS
631 * the tracked nexthop as a list of the rn's.
632 * Unresolved rnh's are placed at the top
633 * of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 )
634 * As such for each rn we need to walk up the tree
635 * and see if any rnh's need to see if they
636 * would match a more specific route
637 */
638 while (rn) {
50872b08
DS
639 if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
640 char buf[PREFIX_STRLEN];
641
15569c58
DA
642 zlog_debug(
643 "%s: %s Being examined for Nexthop Tracking Count: %zd",
644 __func__,
645 srcdest_rnode2str(rn, buf, sizeof(buf)),
646 dest ? rnh_list_count(&dest->nht) : 0);
50872b08 647 }
699dae23
DS
648 if (!dest) {
649 rn = rn->parent;
650 if (rn)
651 dest = rib_dest_from_rnode(rn);
652 continue;
653 }
654 /*
655 * If we have any rnh's stored in the nht list
656 * then we know that this route node was used for
657 * nht resolution and as such we need to call the
658 * nexthop tracking evaluation code
659 */
739c9c90 660 frr_each_safe(rnh_list, &dest->nht, rnh) {
699dae23
DS
661 struct zebra_vrf *zvrf =
662 zebra_vrf_lookup_by_id(rnh->vrf_id);
663 struct prefix *p = &rnh->node->p;
664
50872b08 665 if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
699dae23
DS
666 char buf1[PREFIX_STRLEN];
667 char buf2[PREFIX_STRLEN];
668
bd47f3a3
JU
669 zlog_debug(
670 "%s(%u):%s has Nexthop(%s) Type: %s depending on it, evaluating %u:%u",
671 zvrf_name(zvrf), zvrf_id(zvrf),
672 srcdest_rnode2str(rn, buf1,
673 sizeof(buf1)),
674 prefix2str(p, buf2, sizeof(buf2)),
675 rnh_type2str(rnh->type), seq,
676 rnh->seqno);
699dae23
DS
677 }
678
679 /*
680 * If we have evaluated this node on this pass
681 * already, due to following the tree up
682 * then we know that we can move onto the next
683 * rnh to process.
684 *
685 * Additionally we call zebra_evaluate_rnh
686 * when we gc the dest. In this case we know
687 * that there must be no other re's where
688 * we were originally as such we know that
689 * that sequence number is ok to respect.
690 */
50872b08
DS
691 if (rnh->seqno == seq) {
692 if (IS_ZEBRA_DEBUG_NHT_DETAILED)
693 zlog_debug(
694 "\tNode processed and moved already");
699dae23 695 continue;
50872b08 696 }
699dae23
DS
697
698 rnh->seqno = seq;
699 zebra_evaluate_rnh(zvrf, family2afi(p->family), 0,
700 rnh->type, p);
701 }
702
703 rn = rn->parent;
704 if (rn)
705 dest = rib_dest_from_rnode(rn);
706 }
707}
708
9fd92e3c
AS
709/*
710 * rib_gc_dest
711 *
712 * Garbage collect the rib dest corresponding to the given route node
713 * if appropriate.
714 *
2951a7a4 715 * Returns true if the dest was deleted, false otherwise.
9fd92e3c 716 */
d62a17ae 717int rib_gc_dest(struct route_node *rn)
9fd92e3c 718{
d62a17ae 719 rib_dest_t *dest;
9fd92e3c 720
d62a17ae 721 dest = rib_dest_from_rnode(rn);
722 if (!dest)
723 return 0;
9fd92e3c 724
d62a17ae 725 if (!rib_can_delete_dest(dest))
726 return 0;
9fd92e3c 727
c9abf558
DS
728 if (IS_ZEBRA_DEBUG_RIB) {
729 struct zebra_vrf *zvrf;
730
731 zvrf = rib_dest_vrf(dest);
d62a17ae 732 rnode_debug(rn, zvrf_id(zvrf), "removing dest from table");
c9abf558 733 }
9fd92e3c 734
699dae23
DS
735 zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence());
736
d62a17ae 737 dest->rnode = NULL;
aa57abfb 738 rnh_list_fini(&dest->nht);
d62a17ae 739 XFREE(MTYPE_RIB_DEST, dest);
740 rn->info = NULL;
9fd92e3c 741
d62a17ae 742 /*
743 * Release the one reference that we keep on the route node.
744 */
745 route_unlock_node(rn);
746 return 1;
9fd92e3c
AS
747}
748
d62a17ae 749static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
750 struct route_entry *new)
3e5c6e00 751{
d62a17ae 752 hook_call(rib_update, rn, "new route selected");
3e5c6e00 753
d62a17ae 754 /* Update real nexthop. This may actually determine if nexthop is active
755 * or not. */
c415d895 756 if (!nexthop_group_active_nexthop_num(&(new->nhe->nhg))) {
d62a17ae 757 UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
758 return;
759 }
3e5c6e00 760
d62a17ae 761 if (IS_ZEBRA_DEBUG_RIB) {
762 char buf[SRCDEST2STR_BUFFER];
763 srcdest_rnode2str(rn, buf, sizeof(buf));
bd47f3a3
JU
764 zlog_debug("%s(%u):%s: Adding route rn %p, re %p (%s)",
765 zvrf_name(zvrf), zvrf_id(zvrf), buf, rn, new,
2da33d6b 766 zebra_route_string(new->type));
d62a17ae 767 }
3e5c6e00 768
d62a17ae 769 /* If labeled-unicast route, install transit LSP. */
770 if (zebra_rib_labeled_unicast(new))
771 zebra_mpls_lsp_install(zvrf, rn, new);
a64448ba 772
3cdba47a 773 rib_install_kernel(rn, new, NULL);
3e5c6e00 774
d62a17ae 775 UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
3e5c6e00 776}
777
d62a17ae 778static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
779 struct route_entry *old)
3e5c6e00 780{
d62a17ae 781 hook_call(rib_update, rn, "removing existing route");
3e5c6e00 782
d62a17ae 783 /* Uninstall from kernel. */
784 if (IS_ZEBRA_DEBUG_RIB) {
785 char buf[SRCDEST2STR_BUFFER];
786 srcdest_rnode2str(rn, buf, sizeof(buf));
bd47f3a3
JU
787 zlog_debug("%s(%u):%s: Deleting route rn %p, re %p (%s)",
788 zvrf_name(zvrf), zvrf_id(zvrf), buf, rn, old,
2da33d6b 789 zebra_route_string(old->type));
d62a17ae 790 }
3e5c6e00 791
d62a17ae 792 /* If labeled-unicast route, uninstall transit LSP. */
793 if (zebra_rib_labeled_unicast(old))
794 zebra_mpls_lsp_uninstall(zvrf, rn, old);
795
3cdba47a 796 rib_uninstall_kernel(rn, old);
d62a17ae 797
798 /* Update nexthop for route, reset changed flag. */
ef57f35f
DL
799 /* Note: this code also handles the Linux case when an interface goes
800 * down, causing the kernel to delete routes without sending DELROUTE
801 * notifications
802 */
6883bf8d 803 if (RIB_KERNEL_ROUTE(old))
212df1de
PG
804 SET_FLAG(old->status, ROUTE_ENTRY_REMOVED);
805 else
806 UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
d62a17ae 807}
808
809static void rib_process_update_fib(struct zebra_vrf *zvrf,
810 struct route_node *rn,
811 struct route_entry *old,
812 struct route_entry *new)
813{
d62a17ae 814 int nh_active = 0;
d62a17ae 815
816 /*
817 * We have to install or update if a new route has been selected or
818 * something has changed.
819 */
820 if (new != old || CHECK_FLAG(new->status, ROUTE_ENTRY_CHANGED)) {
821 hook_call(rib_update, rn, "updating existing route");
822
823 /* Update the nexthop; we could determine here that nexthop is
824 * inactive. */
c415d895 825 if (nexthop_group_active_nexthop_num(&(new->nhe->nhg)))
d62a17ae 826 nh_active = 1;
827
828 /* If nexthop is active, install the selected route, if
829 * appropriate. If
830 * the install succeeds, cleanup flags for prior route, if
831 * different from
832 * newly selected.
833 */
834 if (nh_active) {
835 if (IS_ZEBRA_DEBUG_RIB) {
836 char buf[SRCDEST2STR_BUFFER];
837 srcdest_rnode2str(rn, buf, sizeof(buf));
838 if (new != old)
839 zlog_debug(
bd47f3a3
JU
840 "%s(%u):%s: Updating route rn %p, re %p (%s) old %p (%s)",
841 zvrf_name(zvrf), zvrf_id(zvrf),
842 buf, rn, new,
2da33d6b
DS
843 zebra_route_string(new->type),
844 old,
845 zebra_route_string(old->type));
d62a17ae 846 else
847 zlog_debug(
bd47f3a3
JU
848 "%s(%u):%s: Updating route rn %p, re %p (%s)",
849 zvrf_name(zvrf), zvrf_id(zvrf),
850 buf, rn, new,
2da33d6b 851 zebra_route_string(new->type));
d62a17ae 852 }
853
854 /* If labeled-unicast route, uninstall transit LSP. */
855 if (zebra_rib_labeled_unicast(old))
856 zebra_mpls_lsp_uninstall(zvrf, rn, old);
857
3cdba47a
DS
858 /*
859 * Non-system route should be installed.
860 * If labeled-unicast route, install transit
861 * LSP.
862 */
863 if (zebra_rib_labeled_unicast(new))
864 zebra_mpls_lsp_install(zvrf, rn, new);
d62a17ae 865
3cdba47a 866 rib_install_kernel(rn, new, old);
d62a17ae 867 }
a64448ba 868
d62a17ae 869 /*
870 * If nexthop for selected route is not active or install
871 * failed, we
872 * may need to uninstall and delete for redistribution.
873 */
ed216282 874 if (!nh_active) {
d62a17ae 875 if (IS_ZEBRA_DEBUG_RIB) {
876 char buf[SRCDEST2STR_BUFFER];
877 srcdest_rnode2str(rn, buf, sizeof(buf));
878 if (new != old)
879 zlog_debug(
bd47f3a3
JU
880 "%s(%u):%s: Deleting route rn %p, re %p (%s) old %p (%s) - nexthop inactive",
881 zvrf_name(zvrf), zvrf_id(zvrf),
882 buf, rn, new,
2da33d6b
DS
883 zebra_route_string(new->type),
884 old,
885 zebra_route_string(old->type));
d62a17ae 886 else
887 zlog_debug(
bd47f3a3
JU
888 "%s(%u):%s: Deleting route rn %p, re %p (%s) - nexthop inactive",
889 zvrf_name(zvrf), zvrf_id(zvrf),
890 buf, rn, new,
2da33d6b 891 zebra_route_string(new->type));
d62a17ae 892 }
893
894 /* If labeled-unicast route, uninstall transit LSP. */
895 if (zebra_rib_labeled_unicast(old))
896 zebra_mpls_lsp_uninstall(zvrf, rn, old);
897
3cdba47a 898 rib_uninstall_kernel(rn, old);
d62a17ae 899 }
900 } else {
901 /*
902 * Same route selected; check if in the FIB and if not,
3cdba47a
DS
903 * re-install. This is housekeeping code to deal with
904 * race conditions in kernel with linux netlink reporting
905 * interface up before IPv4 or IPv6 protocol is ready
d62a17ae 906 * to add routes.
907 */
3cdba47a
DS
908 if (!CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED) ||
909 RIB_SYSTEM_ROUTE(new))
677c1dd5 910 rib_install_kernel(rn, new, NULL);
d62a17ae 911 }
912
913 /* Update prior route. */
6883bf8d 914 if (new != old)
d62a17ae 915 UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
3e5c6e00 916
d62a17ae 917 /* Clear changed flag. */
918 UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
3e5c6e00 919}
920
d62a17ae 921/* Check if 'alternate' RIB entry is better than 'current'. */
922static struct route_entry *rib_choose_best(struct route_entry *current,
923 struct route_entry *alternate)
924{
925 if (current == NULL)
926 return alternate;
927
928 /* filter route selection in following order:
929 * - connected beats other types
fec4ca19 930 * - if both connected, loopback or vrf wins
d62a17ae 931 * - lower distance beats higher
932 * - lower metric beats higher for equal distance
933 * - last, hence oldest, route wins tie break.
934 */
935
fec4ca19
DS
936 /* Connected routes. Check to see if either are a vrf
937 * or loopback interface. If not, pick the last connected
d62a17ae 938 * route of the set of lowest metric connected routes.
939 */
940 if (alternate->type == ZEBRA_ROUTE_CONNECT) {
fec4ca19
DS
941 if (current->type != ZEBRA_ROUTE_CONNECT)
942 return alternate;
943
944 /* both are connected. are either loop or vrf? */
945 struct nexthop *nexthop = NULL;
946
c415d895 947 for (ALL_NEXTHOPS(alternate->nhe->nhg, nexthop)) {
873fde8c 948 struct interface *ifp = if_lookup_by_index(
949 nexthop->ifindex, alternate->vrf_id);
950
951 if (ifp && if_is_loopback_or_vrf(ifp))
fec4ca19
DS
952 return alternate;
953 }
954
c415d895 955 for (ALL_NEXTHOPS(current->nhe->nhg, nexthop)) {
873fde8c 956 struct interface *ifp = if_lookup_by_index(
957 nexthop->ifindex, current->vrf_id);
958
959 if (ifp && if_is_loopback_or_vrf(ifp))
fec4ca19
DS
960 return current;
961 }
962
963 /* Neither are loop or vrf so pick best metric */
964 if (alternate->metric <= current->metric)
d62a17ae 965 return alternate;
966
967 return current;
968 }
3e5c6e00 969
d62a17ae 970 if (current->type == ZEBRA_ROUTE_CONNECT)
971 return current;
3e5c6e00 972
d62a17ae 973 /* higher distance loses */
974 if (alternate->distance < current->distance)
975 return alternate;
976 if (current->distance < alternate->distance)
977 return current;
3e5c6e00 978
d62a17ae 979 /* metric tie-breaks equal distance */
980 if (alternate->metric <= current->metric)
981 return alternate;
3e5c6e00 982
d62a17ae 983 return current;
3e5c6e00 984}
985
e22e8001
SW
986/* Core function for processing nexthop group contexts's off metaq */
987static void rib_nhg_process(struct nhg_ctx *ctx)
988{
989 nhg_ctx_process(ctx);
990}
991
d62a17ae 992/* Core function for processing routing information base. */
993static void rib_process(struct route_node *rn)
994{
995 struct route_entry *re;
996 struct route_entry *next;
997 struct route_entry *old_selected = NULL;
998 struct route_entry *new_selected = NULL;
999 struct route_entry *old_fib = NULL;
1000 struct route_entry *new_fib = NULL;
1001 struct route_entry *best = NULL;
1002 char buf[SRCDEST2STR_BUFFER];
1003 rib_dest_t *dest;
1004 struct zebra_vrf *zvrf = NULL;
bd47f3a3 1005 struct vrf *vrf;
86391e56
MS
1006 const struct prefix *p, *src_p;
1007
d62a17ae 1008 srcdest_rnode_prefixes(rn, &p, &src_p);
1009 vrf_id_t vrf_id = VRF_UNKNOWN;
1010
1011 assert(rn);
1012
1013 dest = rib_dest_from_rnode(rn);
1014 if (dest) {
1015 zvrf = rib_dest_vrf(dest);
1016 vrf_id = zvrf_id(zvrf);
1017 }
bab85d4f 1018
bd47f3a3
JU
1019 vrf = vrf_lookup_by_id(vrf_id);
1020
d62a17ae 1021 if (IS_ZEBRA_DEBUG_RIB)
1022 srcdest_rnode2str(rn, buf, sizeof(buf));
bab85d4f 1023
d62a17ae 1024 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
bd47f3a3
JU
1025 zlog_debug("%s(%u):%s: Processing rn %p", VRF_LOGNAME(vrf),
1026 vrf_id, buf, rn);
bab85d4f 1027
607425e5
DS
1028 /*
1029 * we can have rn's that have a NULL info pointer
1030 * (dest). As such let's not let the deref happen
1031 * additionally we know RNODE_FOREACH_RE_SAFE
1032 * will not iterate so we are ok.
1033 */
1034 if (dest)
1035 old_fib = dest->selected_fib;
5f7a4718 1036
a2addae8 1037 RNODE_FOREACH_RE_SAFE (rn, re, next) {
d62a17ae 1038 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1039 zlog_debug(
bd47f3a3
JU
1040 "%s(%u):%s: Examine re %p (%s) status %x flags %x dist %d metric %d",
1041 VRF_LOGNAME(vrf), vrf_id, buf, re,
1042 zebra_route_string(re->type), re->status,
1043 re->flags, re->distance, re->metric);
d62a17ae 1044
d62a17ae 1045 /* Currently selected re. */
1046 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
1047 assert(old_selected == NULL);
1048 old_selected = re;
1049 }
bab85d4f 1050
d62a17ae 1051 /* Skip deleted entries from selection */
1052 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
1053 continue;
1054
1055 /* Skip unreachable nexthop. */
1056 /* This first call to nexthop_active_update is merely to
6883bf8d
DS
1057 * determine if there's any change to nexthops associated
1058 * with this RIB entry. Now, rib_process() can be invoked due
1059 * to an external event such as link down or due to
1060 * next-hop-tracking evaluation. In the latter case,
d62a17ae 1061 * a decision has already been made that the NHs have changed.
6883bf8d
DS
1062 * So, no need to invoke a potentially expensive call again.
1063 * Further, since the change might be in a recursive NH which
1064 * is not caught in the nexthop_active_update() code. Thus, we
1065 * might miss changes to recursive NHs.
d62a17ae 1066 */
6883bf8d 1067 if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)
99eabcec 1068 && !nexthop_active_update(rn, re)) {
d62a17ae 1069 if (re->type == ZEBRA_ROUTE_TABLE) {
1070 /* XXX: HERE BE DRAGONS!!!!!
1071 * In all honesty, I have not yet figured out
6883bf8d
DS
1072 * what this part does or why the
1073 * ROUTE_ENTRY_CHANGED test above is correct
d62a17ae 1074 * or why we need to delete a route here, and
6883bf8d
DS
1075 * also not whether this concerns both selected
1076 * and fib route, or only selected
1077 * or only fib
1078 *
1079 * This entry was denied by the 'ip protocol
1080 * table' route-map, we need to delete it */
d62a17ae 1081 if (re != old_selected) {
1082 if (IS_ZEBRA_DEBUG_RIB)
1083 zlog_debug(
bd47f3a3 1084 "%s: %s(%u):%s: imported via import-table but denied "
d62a17ae 1085 "by the ip protocol table route-map",
bd47f3a3
JU
1086 __func__,
1087 VRF_LOGNAME(vrf),
1088 vrf_id, buf);
d62a17ae 1089 rib_unlink(rn, re);
1090 } else
1091 SET_FLAG(re->status,
1092 ROUTE_ENTRY_REMOVED);
1093 }
1094
1095 continue;
1096 }
bab85d4f 1097
d62a17ae 1098 /* Infinite distance. */
3332f4f0
DS
1099 if (re->distance == DISTANCE_INFINITY &&
1100 re->type != ZEBRA_ROUTE_KERNEL) {
d62a17ae 1101 UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
1102 continue;
1103 }
bab85d4f 1104
d62a17ae 1105 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_FIB_OVERRIDE)) {
1106 best = rib_choose_best(new_fib, re);
1107 if (new_fib && best != new_fib)
1108 UNSET_FLAG(new_fib->status,
1109 ROUTE_ENTRY_CHANGED);
1110 new_fib = best;
1111 } else {
1112 best = rib_choose_best(new_selected, re);
1113 if (new_selected && best != new_selected)
1114 UNSET_FLAG(new_selected->status,
1115 ROUTE_ENTRY_CHANGED);
1116 new_selected = best;
1117 }
1118 if (best != re)
1119 UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
1120 } /* RNODE_FOREACH_RE */
1121
1122 /* If no FIB override route, use the selected route also for FIB */
1123 if (new_fib == NULL)
1124 new_fib = new_selected;
1125
1126 /* After the cycle is finished, the following pointers will be set:
1127 * old_selected --- RE entry currently having SELECTED
1128 * new_selected --- RE entry that is newly SELECTED
1129 * old_fib --- RE entry currently in kernel FIB
1130 * new_fib --- RE entry that is newly to be in kernel FIB
1131 *
1132 * new_selected will get SELECTED flag, and is going to be redistributed
1133 * the zclients. new_fib (which can be new_selected) will be installed
1134 * in kernel.
1135 */
1136
1137 if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
1138 zlog_debug(
bd47f3a3
JU
1139 "%s(%u):%s: After processing: old_selected %p new_selected %p old_fib %p new_fib %p",
1140 VRF_LOGNAME(vrf), vrf_id, buf, (void *)old_selected,
1141 (void *)new_selected, (void *)old_fib, (void *)new_fib);
d62a17ae 1142 }
446bb95e 1143
d62a17ae 1144 /* Buffer ROUTE_ENTRY_CHANGED here, because it will get cleared if
1145 * fib == selected */
9d303b37
DL
1146 bool selected_changed = new_selected && CHECK_FLAG(new_selected->status,
1147 ROUTE_ENTRY_CHANGED);
d62a17ae 1148
1149 /* Update fib according to selection results */
1150 if (new_fib && old_fib)
1151 rib_process_update_fib(zvrf, rn, old_fib, new_fib);
1152 else if (new_fib)
1153 rib_process_add_fib(zvrf, rn, new_fib);
1154 else if (old_fib)
1155 rib_process_del_fib(zvrf, rn, old_fib);
1156
8cb41cd6 1157 /* Update SELECTED entry */
d62a17ae 1158 if (old_selected != new_selected || selected_changed) {
93bdadae 1159
6883bf8d 1160 if (new_selected && new_selected != new_fib)
d62a17ae 1161 UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED);
41ec9222 1162
3cdba47a 1163 if (new_selected)
5af4b346
MS
1164 SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED);
1165
d62a17ae 1166 if (old_selected) {
40f321c0
MS
1167 /*
1168 * If we're removing the old entry, we should tell
1169 * redist subscribers about that *if* they aren't
1170 * going to see a redist for the new entry.
1171 */
1172 if (!new_selected || CHECK_FLAG(old_selected->status,
1173 ROUTE_ENTRY_REMOVED))
1174 redistribute_delete(p, src_p,
1175 old_selected,
1176 new_selected);
1177
d62a17ae 1178 if (old_selected != new_selected)
1179 UNSET_FLAG(old_selected->flags,
1180 ZEBRA_FLAG_SELECTED);
f857321e 1181 }
d62a17ae 1182 }
3e5c6e00 1183
d62a17ae 1184 /* Remove all RE entries queued for removal */
a2addae8 1185 RNODE_FOREACH_RE_SAFE (rn, re, next) {
d62a17ae 1186 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
1187 if (IS_ZEBRA_DEBUG_RIB) {
1188 rnode_debug(rn, vrf_id, "rn %p, removing re %p",
1189 (void *)rn, (void *)re);
1190 }
1191 rib_unlink(rn, re);
1192 }
1193 }
4d38fdb4 1194
d62a17ae 1195 /*
1196 * Check if the dest can be deleted now.
1197 */
1198 rib_gc_dest(rn);
e96f9203
DO
1199}
1200
a1494c25
DS
1201static void zebra_rib_evaluate_mpls(struct route_node *rn)
1202{
1203 rib_dest_t *dest = rib_dest_from_rnode(rn);
1204 struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
1205
1206 if (!dest)
1207 return;
1208
1209 if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS)) {
1210 if (IS_ZEBRA_DEBUG_MPLS)
1211 zlog_debug(
bd47f3a3
JU
1212 "%s(%u): Scheduling all LSPs upon RIB completion",
1213 zvrf_name(zvrf), zvrf_id(zvrf));
a1494c25
DS
1214 zebra_mpls_lsp_schedule(zvrf);
1215 mpls_unmark_lsps_for_processing(rn);
1216 }
1217}
1218
e5ac2adf
MS
1219/*
1220 * Utility to match route with dplane context data
1221 */
1222static bool rib_route_match_ctx(const struct route_entry *re,
25779064
MS
1223 const struct zebra_dplane_ctx *ctx,
1224 bool is_update)
e5ac2adf
MS
1225{
1226 bool result = false;
1227
1228 if (is_update) {
1229 /*
1230 * In 'update' case, we test info about the 'previous' or
1231 * 'old' route
1232 */
1233 if ((re->type == dplane_ctx_get_old_type(ctx)) &&
1234 (re->instance == dplane_ctx_get_old_instance(ctx))) {
1235 result = true;
1236
9db35a5e
MS
1237 /* We use an extra test for statics, and another for
1238 * kernel routes.
e5ac2adf
MS
1239 */
1240 if (re->type == ZEBRA_ROUTE_STATIC &&
1241 (re->distance != dplane_ctx_get_old_distance(ctx) ||
1242 re->tag != dplane_ctx_get_old_tag(ctx))) {
1243 result = false;
9db35a5e
MS
1244 } else if (re->type == ZEBRA_ROUTE_KERNEL &&
1245 re->metric !=
1246 dplane_ctx_get_old_metric(ctx)) {
1247 result = false;
e5ac2adf
MS
1248 }
1249 }
1250
1251 } else {
1252 /*
1253 * Ordinary, single-route case using primary context info
1254 */
1255 if ((dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) &&
1256 CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
1257 /* Skip route that's been deleted */
1258 goto done;
1259 }
1260
1261 if ((re->type == dplane_ctx_get_type(ctx)) &&
1262 (re->instance == dplane_ctx_get_instance(ctx))) {
1263 result = true;
1264
9db35a5e
MS
1265 /* We use an extra test for statics, and another for
1266 * kernel routes.
e5ac2adf
MS
1267 */
1268 if (re->type == ZEBRA_ROUTE_STATIC &&
1269 (re->distance != dplane_ctx_get_distance(ctx) ||
1270 re->tag != dplane_ctx_get_tag(ctx))) {
1271 result = false;
9db35a5e
MS
1272 } else if (re->type == ZEBRA_ROUTE_KERNEL &&
1273 re->metric != dplane_ctx_get_metric(ctx)) {
1274 result = false;
1275 } else if (re->type == ZEBRA_ROUTE_CONNECT) {
1276 result = nexthop_group_equal_no_recurse(
1277 &re->nhe->nhg, dplane_ctx_get_ng(ctx));
e5ac2adf
MS
1278 }
1279 }
1280 }
1281
1282done:
1283
1284 return (result);
1285}
1286
3cdba47a
DS
1287static void zebra_rib_fixup_system(struct route_node *rn)
1288{
1289 struct route_entry *re;
1290
1291 RNODE_FOREACH_RE(rn, re) {
1292 struct nexthop *nhop;
1293
1294 if (!RIB_SYSTEM_ROUTE(re))
1295 continue;
1296
1297 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
1298 continue;
1299
1300 SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
6d0ee6a0 1301 UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
3cdba47a 1302
c415d895 1303 for (ALL_NEXTHOPS(re->nhe->nhg, nhop)) {
3cdba47a
DS
1304 if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
1305 continue;
1306
1307 SET_FLAG(nhop->flags, NEXTHOP_FLAG_FIB);
1308 }
1309 }
1310}
1311
9db35a5e
MS
1312/* Route comparison logic, with various special cases. */
1313static bool rib_compare_routes(const struct route_entry *re1,
1314 const struct route_entry *re2)
1315{
1316 bool result = false;
1317
1318 if (re1->type != re2->type)
1319 return false;
1320
1321 if (re1->instance != re2->instance)
1322 return false;
1323
1324 if (re1->type == ZEBRA_ROUTE_KERNEL && re1->metric != re2->metric)
1325 return false;
1326
1327 if (CHECK_FLAG(re1->flags, ZEBRA_FLAG_RR_USE_DISTANCE) &&
1328 re1->distance != re2->distance)
1329 return false;
1330
1331 /* Only connected routes need more checking, nexthop-by-nexthop */
1332 if (re1->type != ZEBRA_ROUTE_CONNECT)
1333 return true;
1334
1335 /* Quick check if shared nhe */
1336 if (re1->nhe == re2->nhe)
1337 return true;
1338
1339 result = nexthop_group_equal_no_recurse(&re1->nhe->nhg, &re2->nhe->nhg);
1340
1341 return result;
1342}
1343
9959f1da
MS
1344/*
1345 * Compare nexthop lists from a route and a dplane context; test whether
1346 * the list installed in the FIB matches the route's list.
1347 * Set 'changed_p' to 'true' if there were changes to the route's
1348 * installed nexthops.
1349 *
1350 * Return 'false' if any ACTIVE route nexthops are not mentioned in the FIB
1351 * list.
1352 */
1353static bool rib_update_nhg_from_ctx(struct nexthop_group *re_nhg,
1354 const struct nexthop_group *ctx_nhg,
1355 bool *changed_p)
1356{
1357 bool matched_p = true;
1358 struct nexthop *nexthop, *ctx_nexthop;
1359
1360 /* Get the first `installed` one to check against.
1361 * If the dataplane doesn't set these to be what was actually installed,
1362 * it will just be whatever was in re->nhe->nhg?
1363 */
1364 ctx_nexthop = ctx_nhg->nexthop;
1365
1366 if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
1367 || !CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1368 ctx_nexthop = nexthop_next_active_resolved(ctx_nexthop);
1369
1370 for (ALL_NEXTHOPS_PTR(re_nhg, nexthop)) {
1371
1372 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1373 continue;
1374
1375 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1376 continue;
1377
1378 /* Check for a FIB nexthop corresponding to the RIB nexthop */
1379 if (nexthop_same(ctx_nexthop, nexthop) == false) {
1380 /* If the FIB doesn't know about the nexthop,
1381 * it's not installed
1382 */
1383 if (IS_ZEBRA_DEBUG_RIB_DETAILED ||
1384 IS_ZEBRA_DEBUG_NHG_DETAIL) {
1385 zlog_debug("%s: no ctx match for rib nh %pNHv %s",
1386 __func__, nexthop,
1387 (CHECK_FLAG(nexthop->flags,
1388 NEXTHOP_FLAG_FIB) ?
1389 "(FIB)":""));
1390 }
1391 matched_p = false;
1392
1393 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1394 *changed_p = true;
1395
1396 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
1397
1398 /* Keep checking nexthops */
1399 continue;
1400 }
1401
1402 if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_FIB)) {
1403 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
1404 if (IS_ZEBRA_DEBUG_NHG_DETAIL)
1405 zlog_debug("%s: rib nh %pNHv -> installed",
1406 __func__, nexthop);
1407
1408 *changed_p = true;
1409 }
1410
1411 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
1412 } else {
1413 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
1414 if (IS_ZEBRA_DEBUG_NHG_DETAIL)
1415 zlog_debug("%s: rib nh %pNHv -> uninstalled",
1416 __func__, nexthop);
1417
1418 *changed_p = true;
1419 }
1420
1421 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
1422 }
1423
1424 ctx_nexthop = nexthop_next_active_resolved(ctx_nexthop);
1425 }
1426
1427 return matched_p;
1428}
1429
e5ac2adf 1430/*
78bf56b0
MS
1431 * Update a route from a dplane context. This consolidates common code
1432 * that can be used in processing of results from FIB updates, and in
1433 * async notification processing.
efe6c026 1434 * The return is 'true' if the installed nexthops changed; 'false' otherwise.
e5ac2adf 1435 */
efe6c026
MS
1436static bool rib_update_re_from_ctx(struct route_entry *re,
1437 struct route_node *rn,
1438 struct zebra_dplane_ctx *ctx)
78bf56b0 1439{
941e261c 1440 char dest_str[PREFIX_STRLEN] = "";
9959f1da 1441 struct nexthop *nexthop;
941e261c
MS
1442 bool matched;
1443 const struct nexthop_group *ctxnhg;
9959f1da 1444 struct nexthop_group *re_nhg;
efe6c026
MS
1445 bool is_selected = false; /* Is 're' currently the selected re? */
1446 bool changed_p = false; /* Change to nexthops? */
1447 rib_dest_t *dest;
bd47f3a3
JU
1448 struct vrf *vrf;
1449
1450 vrf = vrf_lookup_by_id(re->vrf_id);
78bf56b0 1451
941e261c
MS
1452 /* Note well: only capturing the prefix string if debug is enabled here;
1453 * unconditional log messages will have to generate the string.
1454 */
1455 if (IS_ZEBRA_DEBUG_RIB)
1456 prefix2str(&(rn->p), dest_str, sizeof(dest_str));
78bf56b0 1457
efe6c026
MS
1458 dest = rib_dest_from_rnode(rn);
1459 if (dest)
1460 is_selected = (re == dest->selected_fib);
1461
1462 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
9db35a5e 1463 zlog_debug("update_from_ctx: %s(%u):%s: %sSELECTED, re %p",
bd47f3a3 1464 VRF_LOGNAME(vrf), re->vrf_id, dest_str,
9db35a5e 1465 (is_selected ? "" : "NOT "), re);
efe6c026
MS
1466
1467 /* Update zebra's nexthop FIB flag for each nexthop that was installed.
941e261c 1468 * If the installed set differs from the set requested by the rib/owner,
efe6c026
MS
1469 * we use the fib-specific nexthop-group to record the actual FIB
1470 * status.
78bf56b0 1471 */
a126f120
MS
1472 matched = false;
1473 ctxnhg = dplane_ctx_get_ng(ctx);
941e261c 1474
9959f1da 1475 /* Check route's fib group and incoming notif group for equivalence.
986a6617
SW
1476 *
1477 * Let's assume the nexthops are ordered here to save time.
941e261c 1478 */
9959f1da
MS
1479 /* TODO -- this isn't testing or comparing the FIB flags; we should
1480 * do a more explicit loop, checking the incoming notification's flags.
1481 */
a126f120
MS
1482 if (re->fib_ng.nexthop && ctxnhg->nexthop &&
1483 nexthop_group_equal(&re->fib_ng, ctxnhg))
986a6617 1484 matched = true;
941e261c
MS
1485
1486 /* If the new FIB set matches the existing FIB set, we're done. */
1487 if (matched) {
1488 if (IS_ZEBRA_DEBUG_RIB)
bd47f3a3
JU
1489 zlog_debug(
1490 "%s(%u):%s update_from_ctx(): existing fib nhg, no change",
1491 VRF_LOGNAME(vrf), re->vrf_id, dest_str);
9959f1da 1492 goto check_backups;
941e261c
MS
1493
1494 } else if (re->fib_ng.nexthop) {
1495 /*
1496 * Free stale fib list and move on to check the rib nhg.
1497 */
1498 if (IS_ZEBRA_DEBUG_RIB)
bd47f3a3
JU
1499 zlog_debug(
1500 "%s(%u):%s update_from_ctx(): replacing fib nhg",
1501 VRF_LOGNAME(vrf), re->vrf_id, dest_str);
941e261c
MS
1502 nexthops_free(re->fib_ng.nexthop);
1503 re->fib_ng.nexthop = NULL;
efe6c026
MS
1504
1505 /* Note that the installed nexthops have changed */
1506 changed_p = true;
941e261c
MS
1507 } else {
1508 if (IS_ZEBRA_DEBUG_RIB)
bd47f3a3
JU
1509 zlog_debug("%s(%u):%s update_from_ctx(): no fib nhg",
1510 VRF_LOGNAME(vrf), re->vrf_id, dest_str);
941e261c
MS
1511 }
1512
1513 /*
1514 * Compare with the rib nexthop group. The comparison here is different:
1515 * the RIB group may be a superset of the list installed in the FIB. We
1516 * walk the RIB group, looking for the 'installable' candidate
1517 * nexthops, and then check those against the set
1518 * that is actually installed.
986a6617
SW
1519 *
1520 * Assume nexthops are ordered here as well.
941e261c 1521 */
986a6617 1522
9959f1da 1523 /* If nothing is installed, we can skip some of the checking/comparison
1f6a5aca
MS
1524 * of nexthops.
1525 */
9959f1da 1526 if (ctxnhg->nexthop == NULL) {
1f6a5aca
MS
1527 changed_p = true;
1528 goto no_nexthops;
1529 }
1530
9959f1da 1531 matched = rib_update_nhg_from_ctx(&(re->nhe->nhg), ctxnhg, &changed_p);
78bf56b0 1532
941e261c
MS
1533 /* If all nexthops were processed, we're done */
1534 if (matched) {
1535 if (IS_ZEBRA_DEBUG_RIB)
bd47f3a3
JU
1536 zlog_debug(
1537 "%s(%u):%s update_from_ctx(): rib nhg matched, changed '%s'",
1538 VRF_LOGNAME(vrf), re->vrf_id, dest_str,
1539 (changed_p ? "true" : "false"));
9959f1da 1540 goto check_backups;
941e261c 1541 }
78bf56b0 1542
1f6a5aca
MS
1543no_nexthops:
1544
941e261c
MS
1545 /* FIB nexthop set differs from the RIB set:
1546 * create a fib-specific nexthop-group
1547 */
1548 if (IS_ZEBRA_DEBUG_RIB)
bd47f3a3
JU
1549 zlog_debug(
1550 "%s(%u):%s update_from_ctx(): changed %s, adding new fib nhg",
1551 VRF_LOGNAME(vrf), re->vrf_id, dest_str,
1552 (changed_p ? "true" : "false"));
941e261c 1553
188a00e0
MS
1554 if (ctxnhg->nexthop)
1555 copy_nexthops(&(re->fib_ng.nexthop), ctxnhg->nexthop, NULL);
1556 else {
1557 /* Bit of a special case when the fib has _no_ installed
1558 * nexthops.
1559 */
1560 nexthop = nexthop_new();
1561 nexthop->type = NEXTHOP_TYPE_IPV4;
50d89650 1562 _nexthop_add(&(re->fib_ng.nexthop), nexthop);
188a00e0 1563 }
941e261c 1564
9959f1da
MS
1565check_backups:
1566
1567 /*
1568 * Check the status of the route's backup nexthops, if any.
1569 * The logic for backups is somewhat different: if any backup is
1570 * installed, a new fib nhg will be attached to the route.
1571 */
1572 re_nhg = zebra_nhg_get_backup_nhg(re->nhe);
1573 if (re_nhg == NULL)
1574 goto done; /* No backup nexthops */
1575
1576 /* First check the route's 'fib' list of backups, if it's present
1577 * from some previous event.
1578 */
1579 re_nhg = &re->fib_backup_ng;
1580 ctxnhg = dplane_ctx_get_backup_ng(ctx);
1581
1582 matched = false;
1583 if (re_nhg->nexthop && ctxnhg && nexthop_group_equal(re_nhg, ctxnhg))
1584 matched = true;
1585
1586 /* If the new FIB set matches an existing FIB set, we're done. */
1587 if (matched) {
1588 if (IS_ZEBRA_DEBUG_RIB)
1589 zlog_debug(
1590 "%s(%u):%s update_from_ctx(): existing fib backup nhg, no change",
1591 VRF_LOGNAME(vrf), re->vrf_id, dest_str);
1592 goto done;
1593
1594 } else if (re->fib_backup_ng.nexthop) {
1595 /*
1596 * Free stale fib backup list and move on to check
1597 * the route's backups.
1598 */
1599 if (IS_ZEBRA_DEBUG_RIB)
1600 zlog_debug(
1601 "%s(%u):%s update_from_ctx(): replacing fib backup nhg",
1602 VRF_LOGNAME(vrf), re->vrf_id, dest_str);
1603 nexthops_free(re->fib_backup_ng.nexthop);
1604 re->fib_backup_ng.nexthop = NULL;
1605
1606 /* Note that the installed nexthops have changed */
1607 changed_p = true;
1608 } else {
1609 if (IS_ZEBRA_DEBUG_RIB)
1610 zlog_debug("%s(%u):%s update_from_ctx(): no fib backup nhg",
1611 VRF_LOGNAME(vrf), re->vrf_id, dest_str);
1612 }
1613
1614 /*
1615 * If a FIB backup nexthop set exists: attach a copy
1616 * to the route if any backup is installed
1617 */
1618 if (ctxnhg && ctxnhg->nexthop) {
1619
1620 for (ALL_NEXTHOPS_PTR(ctxnhg, nexthop)) {
1621 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1622 break;
1623 }
1624
1625 /* If no installed backups, we're done */
1626 if (nexthop == NULL)
1627 goto done;
1628
1629 if (IS_ZEBRA_DEBUG_RIB)
1630 zlog_debug("%s(%u):%s update_from_ctx(): changed %s, adding new backup fib nhg",
1631 VRF_LOGNAME(vrf), re->vrf_id, dest_str,
1632 (changed_p ? "true" : "false"));
1633
1634 copy_nexthops(&(re->fib_backup_ng.nexthop), ctxnhg->nexthop,
1635 NULL);
1636 }
1637
941e261c 1638done:
9959f1da 1639
efe6c026 1640 return changed_p;
78bf56b0
MS
1641}
1642
e5ac2adf 1643/*
fad4d69c
MS
1644 * Helper to locate a zebra route-node from a dplane context. This is used
1645 * when processing dplane results, e.g. Note well: the route-node is returned
1646 * with a ref held - route_unlock_node() must be called eventually.
e5ac2adf 1647 */
fad4d69c
MS
1648static struct route_node *
1649rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx)
e5ac2adf
MS
1650{
1651 struct route_table *table = NULL;
1652 struct route_node *rn = NULL;
e5ac2adf
MS
1653 const struct prefix *dest_pfx, *src_pfx;
1654
1655 /* Locate rn and re(s) from ctx */
1656
c7c0b007
SW
1657 table = zebra_vrf_lookup_table_with_table_id(
1658 dplane_ctx_get_afi(ctx), dplane_ctx_get_safi(ctx),
1659 dplane_ctx_get_vrf(ctx), dplane_ctx_get_table(ctx));
e5ac2adf
MS
1660 if (table == NULL) {
1661 if (IS_ZEBRA_DEBUG_DPLANE) {
bd47f3a3
JU
1662 zlog_debug(
1663 "Failed to find route for ctx: no table for afi %d, safi %d, vrf %s(%u)",
1664 dplane_ctx_get_afi(ctx),
1665 dplane_ctx_get_safi(ctx),
1666 vrf_id_to_name(dplane_ctx_get_vrf(ctx)),
1667 dplane_ctx_get_vrf(ctx));
e5ac2adf
MS
1668 }
1669 goto done;
1670 }
1671
fad4d69c
MS
1672 dest_pfx = dplane_ctx_get_dest(ctx);
1673 src_pfx = dplane_ctx_get_src(ctx);
1674
1675 rn = srcdest_rnode_get(table, dest_pfx,
1676 src_pfx ? (struct prefix_ipv6 *)src_pfx : NULL);
1677
1678done:
1679 return rn;
1680}
1681
1682
97f5b441 1683
fad4d69c
MS
1684/*
1685 * Route-update results processing after async dataplane update.
1686 */
1687static void rib_process_result(struct zebra_dplane_ctx *ctx)
1688{
1689 struct zebra_vrf *zvrf = NULL;
bd47f3a3 1690 struct vrf *vrf;
fad4d69c
MS
1691 struct route_node *rn = NULL;
1692 struct route_entry *re = NULL, *old_re = NULL, *rib;
1693 bool is_update = false;
1694 char dest_str[PREFIX_STRLEN] = "";
1695 enum dplane_op_e op;
1696 enum zebra_dplane_result status;
1697 const struct prefix *dest_pfx, *src_pfx;
1698 uint32_t seq;
9db35a5e 1699 rib_dest_t *dest;
efe6c026 1700 bool fib_changed = false;
97f5b441 1701
fad4d69c 1702 zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx));
bd47f3a3 1703 vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
e5ac2adf
MS
1704 dest_pfx = dplane_ctx_get_dest(ctx);
1705
1706 /* Note well: only capturing the prefix string if debug is enabled here;
1707 * unconditional log messages will have to generate the string.
1708 */
5709131c 1709 if (IS_ZEBRA_DEBUG_DPLANE)
e5ac2adf 1710 prefix2str(dest_pfx, dest_str, sizeof(dest_str));
e5ac2adf 1711
fad4d69c
MS
1712 /* Locate rn and re(s) from ctx */
1713 rn = rib_find_rn_from_ctx(ctx);
e5ac2adf
MS
1714 if (rn == NULL) {
1715 if (IS_ZEBRA_DEBUG_DPLANE) {
bd47f3a3
JU
1716 zlog_debug(
1717 "Failed to process dplane results: no route for %s(%u):%s",
1718 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
1719 dest_str);
e5ac2adf
MS
1720 }
1721 goto done;
1722 }
1723
9db35a5e 1724 dest = rib_dest_from_rnode(rn);
e5ac2adf
MS
1725 srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
1726
1727 op = dplane_ctx_get_op(ctx);
1728 status = dplane_ctx_get_status(ctx);
1729
c831033f 1730 if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
bd47f3a3 1731 zlog_debug(
9db35a5e 1732 "%s(%u):%s Processing dplane result ctx %p, op %s result %s",
bd47f3a3
JU
1733 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), dest_str,
1734 ctx, dplane_op2str(op), dplane_res2str(status));
e5ac2adf 1735
e5ac2adf
MS
1736 /*
1737 * Update is a bit of a special case, where we may have both old and new
1738 * routes to post-process.
1739 */
1740 is_update = dplane_ctx_is_update(ctx);
1741
1742 /*
1743 * Take a pass through the routes, look for matches with the context
1744 * info.
1745 */
1746 RNODE_FOREACH_RE(rn, rib) {
1747
1748 if (re == NULL) {
5709131c 1749 if (rib_route_match_ctx(rib, ctx, false))
e5ac2adf 1750 re = rib;
e5ac2adf
MS
1751 }
1752
1753 /* Check for old route match */
1754 if (is_update && (old_re == NULL)) {
5709131c 1755 if (rib_route_match_ctx(rib, ctx, true /*is_update*/))
e5ac2adf 1756 old_re = rib;
e5ac2adf
MS
1757 }
1758
1759 /* Have we found the routes we need to work on? */
5709131c 1760 if (re && ((!is_update || old_re)))
e5ac2adf 1761 break;
e5ac2adf
MS
1762 }
1763
699dae23
DS
1764 seq = dplane_ctx_get_seq(ctx);
1765
e5ac2adf
MS
1766 /*
1767 * Check sequence number(s) to detect stale results before continuing
1768 */
60f98b23 1769 if (re) {
699dae23 1770 if (re->dplane_sequence != seq) {
60f98b23 1771 if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
bd47f3a3
JU
1772 zlog_debug(
1773 "%s(%u):%s Stale dplane result for re %p",
1774 VRF_LOGNAME(vrf),
1775 dplane_ctx_get_vrf(ctx), dest_str, re);
60f98b23
DS
1776 } else
1777 UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
e5ac2adf
MS
1778 }
1779
60f98b23
DS
1780 if (old_re) {
1781 if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) {
1782 if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
bd47f3a3
JU
1783 zlog_debug(
1784 "%s(%u):%s Stale dplane result for old_re %p",
1785 VRF_LOGNAME(vrf),
1786 dplane_ctx_get_vrf(ctx), dest_str,
1787 old_re);
60f98b23 1788 } else
9ef0c6ba 1789 UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED);
e5ac2adf
MS
1790 }
1791
12e7fe3a 1792 switch (op) {
12e7fe3a
DS
1793 case DPLANE_OP_ROUTE_INSTALL:
1794 case DPLANE_OP_ROUTE_UPDATE:
1795 if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
677c1dd5
DS
1796 if (re) {
1797 UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
1798 SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
1799 }
b9f0e5ee
DS
1800 /*
1801 * On an update operation from the same route type
1802 * context retrieval currently has no way to know
1803 * which was the old and which was the new.
1804 * So don't unset our flags that we just set.
1805 * We know redistribution is ok because the
1806 * old_re in this case is used for nothing
1807 * more than knowing whom to contact if necessary.
1808 */
1809 if (old_re && old_re != re) {
677c1dd5
DS
1810 UNSET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
1811 UNSET_FLAG(old_re->status,
1812 ROUTE_ENTRY_INSTALLED);
1813 }
f183e380 1814
78bf56b0 1815 /* Update zebra route based on the results in
941e261c 1816 * the context struct.
78bf56b0 1817 */
941e261c 1818 if (re) {
efe6c026
MS
1819 fib_changed =
1820 rib_update_re_from_ctx(re, rn, ctx);
1821
1822 if (!fib_changed) {
1823 if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
bd47f3a3
JU
1824 zlog_debug(
1825 "%s(%u):%s no fib change for re",
1826 VRF_LOGNAME(vrf),
1827 dplane_ctx_get_vrf(ctx),
1828 dest_str);
12e7fe3a
DS
1829 }
1830
9db35a5e
MS
1831 /* Redistribute if this is the selected re */
1832 if (dest && re == dest->selected_fib)
1833 redistribute_update(dest_pfx, src_pfx,
1834 re, old_re);
f183e380
MS
1835 }
1836
3cdba47a
DS
1837 /*
1838 * System routes are weird in that they
1839 * allow multiple to be installed that match
1840 * to the same prefix, so after we get the
1841 * result we need to clean them up so that
1842 * we can actually use them.
1843 */
1844 if ((re && RIB_SYSTEM_ROUTE(re)) ||
1845 (old_re && RIB_SYSTEM_ROUTE(old_re)))
1846 zebra_rib_fixup_system(rn);
1847
f4c6e2a8 1848 if (zvrf)
12e7fe3a 1849 zvrf->installs++;
f183e380 1850
12e7fe3a 1851 /* Notify route owner */
677c1dd5 1852 zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
e5ac2adf 1853
12e7fe3a 1854 } else {
7a230a9d 1855 if (re) {
677c1dd5 1856 SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
7a230a9d
DS
1857 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
1858 } if (old_re)
677c1dd5
DS
1859 SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
1860 if (re)
1861 zsend_route_notify_owner(re, dest_pfx,
1862 ZAPI_ROUTE_FAIL_INSTALL);
97f5b441 1863
bd47f3a3
JU
1864 zlog_warn("%s(%u):%s: Route install failed",
1865 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
1866 prefix2str(dest_pfx, dest_str,
1867 sizeof(dest_str)));
12e7fe3a
DS
1868 }
1869 break;
1870 case DPLANE_OP_ROUTE_DELETE:
677c1dd5
DS
1871 if (re)
1872 SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
12e7fe3a
DS
1873 /*
1874 * In the delete case, the zebra core datastructs were
1875 * updated (or removed) at the time the delete was issued,
1876 * so we're just notifying the route owner.
e5ac2adf 1877 */
12e7fe3a 1878 if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
677c1dd5
DS
1879 if (re) {
1880 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
1881 UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
1882 }
12e7fe3a 1883 zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
e5ac2adf 1884
12e7fe3a
DS
1885 if (zvrf)
1886 zvrf->removals++;
1887 } else {
677c1dd5
DS
1888 if (re)
1889 SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
12e7fe3a
DS
1890 zsend_route_notify_owner_ctx(ctx,
1891 ZAPI_ROUTE_REMOVE_FAIL);
e5ac2adf 1892
bd47f3a3
JU
1893 zlog_warn("%s(%u):%s: Route Deletion failure",
1894 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
1895 prefix2str(dest_pfx, dest_str,
1896 sizeof(dest_str)));
12e7fe3a 1897 }
3cdba47a
DS
1898
1899 /*
1900 * System routes are weird in that they
1901 * allow multiple to be installed that match
1902 * to the same prefix, so after we get the
1903 * result we need to clean them up so that
1904 * we can actually use them.
1905 */
1906 if ((re && RIB_SYSTEM_ROUTE(re)) ||
1907 (old_re && RIB_SYSTEM_ROUTE(old_re)))
1908 zebra_rib_fixup_system(rn);
12e7fe3a 1909 break;
d37f4d6c
MS
1910 default:
1911 break;
e5ac2adf 1912 }
699dae23
DS
1913
1914 zebra_rib_evaluate_rn_nexthops(rn, seq);
a1494c25 1915 zebra_rib_evaluate_mpls(rn);
e5ac2adf
MS
1916done:
1917
5f27bcba
DS
1918 if (rn)
1919 route_unlock_node(rn);
1920
e5ac2adf
MS
1921 /* Return context to dataplane module */
1922 dplane_ctx_fini(&ctx);
1923}
1924
9959f1da
MS
1925/*
1926 * Count installed/FIB nexthops
1927 */
1928static int rib_count_installed_nh(struct route_entry *re)
1929{
1930 int count = 0;
1931 struct nexthop *nexthop;
1932 struct nexthop_group *nhg;
1933
1934 nhg = rib_get_fib_nhg(re);
1935
1936 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
1937 /* The meaningful flag depends on where the installed
1938 * nexthops reside.
1939 */
1940 if (nhg == &(re->fib_backup_ng)) {
1941 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1942 count++;
1943 } else {
1944 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1945 count++;
1946 }
1947 }
1948
1949 for (ALL_NEXTHOPS_PTR(rib_get_fib_backup_nhg(re), nexthop)) {
1950 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1951 count++;
1952 }
1953
1954 return count;
1955}
1956
54818e3b
MS
1957/*
1958 * Handle notification from async dataplane: the dataplane has detected
1959 * some change to a route, and notifies zebra so that the control plane
1960 * can reflect that change.
1961 */
1962static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
1963{
1964 struct route_node *rn = NULL;
efe6c026 1965 struct route_entry *re = NULL;
bd47f3a3 1966 struct vrf *vrf;
efe6c026 1967 struct nexthop *nexthop;
54818e3b
MS
1968 char dest_str[PREFIX_STRLEN] = "";
1969 const struct prefix *dest_pfx, *src_pfx;
941e261c 1970 rib_dest_t *dest;
efe6c026 1971 bool fib_changed = false;
941e261c 1972 bool debug_p = IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_RIB;
efe6c026 1973 int start_count, end_count;
54818e3b 1974 dest_pfx = dplane_ctx_get_dest(ctx);
bd47f3a3 1975 vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
54818e3b
MS
1976
1977 /* Note well: only capturing the prefix string if debug is enabled here;
1978 * unconditional log messages will have to generate the string.
1979 */
941e261c 1980 if (debug_p)
54818e3b
MS
1981 prefix2str(dest_pfx, dest_str, sizeof(dest_str));
1982
1983 /* Locate rn and re(s) from ctx */
1984 rn = rib_find_rn_from_ctx(ctx);
1985 if (rn == NULL) {
941e261c 1986 if (debug_p) {
bd47f3a3
JU
1987 zlog_debug(
1988 "Failed to process dplane notification: no routes for %s(%u):%s",
1989 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
1990 dest_str);
54818e3b
MS
1991 }
1992 goto done;
1993 }
1994
941e261c 1995 dest = rib_dest_from_rnode(rn);
54818e3b
MS
1996 srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
1997
efe6c026 1998 if (debug_p)
bd47f3a3
JU
1999 zlog_debug("%s(%u):%s Processing dplane notif ctx %p",
2000 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), dest_str,
2001 ctx);
54818e3b
MS
2002
2003 /*
2004 * Take a pass through the routes, look for matches with the context
2005 * info.
2006 */
efe6c026
MS
2007 RNODE_FOREACH_RE(rn, re) {
2008 if (rib_route_match_ctx(re, ctx, false /*!update*/))
54818e3b
MS
2009 break;
2010 }
2011
2012 /* No match? Nothing we can do */
2013 if (re == NULL) {
941e261c 2014 if (debug_p)
bd47f3a3
JU
2015 zlog_debug(
2016 "%s(%u):%s Unable to process dplane notification: no entry for type %s",
2017 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
2018 dest_str,
2019 zebra_route_string(dplane_ctx_get_type(ctx)));
54818e3b
MS
2020
2021 goto done;
2022 }
2023
272e8903
MS
2024 /* Ensure we clear the QUEUED flag */
2025 UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
2026
4c0b5436
MS
2027 /* Is this a notification that ... matters? We mostly care about
2028 * the route that is currently selected for installation; we may also
2029 * get an un-install notification, and handle that too.
941e261c
MS
2030 */
2031 if (re != dest->selected_fib) {
4c0b5436
MS
2032 /*
2033 * If we need to, clean up after a delete that was part of
2034 * an update operation.
941e261c 2035 */
4c0b5436
MS
2036 end_count = 0;
2037 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
2038 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
2039 end_count++;
2040 }
2041
2042 /* If no nexthops or none installed, ensure that this re
2043 * gets its 'installed' flag cleared.
2044 */
2045 if (end_count == 0) {
2046 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
2047 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
2048 if (debug_p)
bd47f3a3
JU
2049 zlog_debug(
2050 "%s(%u):%s dplane notif, uninstalled type %s route",
2051 VRF_LOGNAME(vrf),
2052 dplane_ctx_get_vrf(ctx), dest_str,
2053 zebra_route_string(
2054 dplane_ctx_get_type(ctx)));
4c0b5436
MS
2055 } else {
2056 /* At least report on the event. */
2057 if (debug_p)
bd47f3a3
JU
2058 zlog_debug(
2059 "%s(%u):%s dplane notif, but type %s not selected_fib",
2060 VRF_LOGNAME(vrf),
2061 dplane_ctx_get_vrf(ctx), dest_str,
2062 zebra_route_string(
2063 dplane_ctx_get_type(ctx)));
4c0b5436 2064 }
941e261c
MS
2065 goto done;
2066 }
2067
efe6c026
MS
2068 /* We'll want to determine whether the installation status of the
2069 * route has changed: we'll check the status before processing,
2070 * and then again if there's been a change.
2071 */
2072 start_count = 0;
1c30d64b 2073
9959f1da
MS
2074 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
2075 start_count = rib_count_installed_nh(re);
efe6c026 2076
54818e3b
MS
2077 /* Update zebra's nexthop FIB flags based on the context struct's
2078 * nexthops.
2079 */
efe6c026 2080 fib_changed = rib_update_re_from_ctx(re, rn, ctx);
54818e3b 2081
efe6c026
MS
2082 if (!fib_changed) {
2083 if (debug_p)
bd47f3a3
JU
2084 zlog_debug(
2085 "%s(%u):%s dplane notification: rib_update returns FALSE",
2086 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
2087 dest_str);
54818e3b
MS
2088 }
2089
188a00e0
MS
2090 /*
2091 * Perform follow-up work if the actual status of the prefix
efe6c026 2092 * changed.
941e261c 2093 */
9959f1da 2094 end_count = rib_count_installed_nh(re);
941e261c 2095
188a00e0
MS
2096 /* Various fib transitions: changed nexthops; from installed to
2097 * not-installed; or not-installed to installed.
efe6c026 2098 */
188a00e0 2099 if (start_count > 0 && end_count > 0) {
11260e70 2100 if (debug_p)
bd47f3a3
JU
2101 zlog_debug(
2102 "%s(%u):%s applied nexthop changes from dplane notification",
2103 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
2104 dest_str);
188a00e0
MS
2105
2106 /* Changed nexthops - update kernel/others */
2107 dplane_route_notif_update(rn, re,
2108 DPLANE_OP_ROUTE_UPDATE, ctx);
2109
2110 } else if (start_count == 0 && end_count > 0) {
efe6c026 2111 if (debug_p)
bd47f3a3
JU
2112 zlog_debug(
2113 "%s(%u):%s installed transition from dplane notification",
2114 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
2115 dest_str);
efe6c026
MS
2116
2117 /* We expect this to be the selected route, so we want
272e8903 2118 * to tell others about this transition.
efe6c026
MS
2119 */
2120 SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
2121
188a00e0 2122 /* Changed nexthops - update kernel/others */
9959f1da 2123 dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_UPDATE, ctx);
188a00e0 2124
efe6c026
MS
2125 /* Redistribute, lsp, and nht update */
2126 redistribute_update(dest_pfx, src_pfx, re, NULL);
2127
efe6c026
MS
2128 } else if (start_count > 0 && end_count == 0) {
2129 if (debug_p)
bd47f3a3
JU
2130 zlog_debug(
2131 "%s(%u):%s un-installed transition from dplane notification",
2132 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
2133 dest_str);
efe6c026
MS
2134
2135 /* Transition from _something_ installed to _nothing_
2136 * installed.
2137 */
2138 /* We expect this to be the selected route, so we want
2139 * to tell others about this transistion.
2140 */
2141 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
2142
188a00e0
MS
2143 /* Changed nexthops - update kernel/others */
2144 dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_DELETE, ctx);
2145
efe6c026 2146 /* Redistribute, lsp, and nht update */
40f321c0 2147 redistribute_delete(dest_pfx, src_pfx, re, NULL);
9287b4c5 2148 }
efe6c026 2149
9287b4c5
MS
2150 /* Make any changes visible for lsp and nexthop-tracking processing */
2151 zebra_rib_evaluate_rn_nexthops(
2152 rn, zebra_router_get_next_sequence());
efe6c026 2153
9287b4c5 2154 zebra_rib_evaluate_mpls(rn);
941e261c 2155
54818e3b 2156done:
941e261c
MS
2157 if (rn)
2158 route_unlock_node(rn);
2159
54818e3b
MS
2160 /* Return context to dataplane module */
2161 dplane_ctx_fini(&ctx);
2162}
2163
e22e8001 2164static void process_subq_nhg(struct listnode *lnode)
e96f9203 2165{
e22e8001
SW
2166 struct nhg_ctx *ctx = NULL;
2167 uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
5110a0c6 2168
e22e8001
SW
2169 ctx = listgetdata(lnode);
2170
2171 if (!ctx)
2172 return;
2173
2174 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
2175 zlog_debug("NHG Context id=%u dequeued from sub-queue %u",
2176 ctx->id, qindex);
2177
2178 rib_nhg_process(ctx);
2179}
2180
2181static void process_subq_route(struct listnode *lnode, uint8_t qindex)
2182{
2183 struct route_node *rnode = NULL;
2184 rib_dest_t *dest = NULL;
2185 struct zebra_vrf *zvrf = NULL;
5110a0c6 2186
d62a17ae 2187 rnode = listgetdata(lnode);
2188 dest = rib_dest_from_rnode(rnode);
2189 if (dest)
2190 zvrf = rib_dest_vrf(dest);
41ec9222 2191
d62a17ae 2192 rib_process(rnode);
5110a0c6 2193
d62a17ae 2194 if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
2195 char buf[SRCDEST2STR_BUFFER];
efe6c026 2196
d62a17ae 2197 srcdest_rnode2str(rnode, buf, sizeof(buf));
bd47f3a3
JU
2198 zlog_debug("%s(%u):%s: rn %p dequeued from sub-queue %u",
2199 zvrf_name(zvrf), zvrf_id(zvrf), buf, rnode, qindex);
d62a17ae 2200 }
41ec9222 2201
d62a17ae 2202 if (rnode->info)
2203 UNSET_FLAG(rib_dest_from_rnode(rnode)->flags,
2204 RIB_ROUTE_QUEUED(qindex));
9fd92e3c 2205
67b9467f 2206#if 0
5110a0c6
SH
2207 else
2208 {
2209 zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
2210 __func__, rnode, rnode->lock);
2211 zlog_backtrace(LOG_DEBUG);
2212 }
67b9467f 2213#endif
d62a17ae 2214 route_unlock_node(rnode);
e22e8001
SW
2215}
2216
2217/* Take a list of route_node structs and return 1, if there was a record
2218 * picked from it and processed by rib_process(). Don't process more,
2219 * than one RN record; operate only in the specified sub-queue.
2220 */
2221static unsigned int process_subq(struct list *subq, uint8_t qindex)
2222{
2223 struct listnode *lnode = listhead(subq);
2224
2225 if (!lnode)
2226 return 0;
2227
2228 if (qindex == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
2229 process_subq_nhg(lnode);
2230 else
2231 process_subq_route(lnode, qindex);
2232
d62a17ae 2233 list_delete_node(subq, lnode);
e22e8001 2234
d62a17ae 2235 return 1;
e96f9203
DO
2236}
2237
2238/* Dispatch the meta queue by picking, processing and unlocking the next RN from
d62a17ae 2239 * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
2240 * data
e96f9203
DO
2241 * is pointed to the meta queue structure.
2242 */
d62a17ae 2243static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
e96f9203 2244{
d62a17ae 2245 struct meta_queue *mq = data;
2246 unsigned i;
91f16812
MS
2247 uint32_t queue_len, queue_limit;
2248
2249 /* Ensure there's room for more dataplane updates */
2250 queue_limit = dplane_get_in_queue_limit();
2251 queue_len = dplane_get_in_queue_len();
2252 if (queue_len > queue_limit) {
2253 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
8b962e77
MS
2254 zlog_debug("rib queue: dplane queue len %u, limit %u, retrying",
2255 queue_len, queue_limit);
91f16812
MS
2256
2257 /* Ensure that the meta-queue is actually enqueued */
489a9614 2258 if (work_queue_empty(zrouter.ribq))
ea45a4e7 2259 work_queue_add(zrouter.ribq, zrouter.mq);
91f16812
MS
2260
2261 return WQ_QUEUE_BLOCKED;
2262 }
5110a0c6 2263
d62a17ae 2264 for (i = 0; i < MQ_SIZE; i++)
2265 if (process_subq(mq->subq[i], i)) {
2266 mq->size--;
2267 break;
2268 }
2269 return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
e96f9203
DO
2270}
2271
f52ed677
DS
2272
2273/*
2274 * Look into the RN and queue it into the highest priority queue
2275 * at this point in time for processing.
2276 *
2277 * We will enqueue a route node only once per invocation.
2278 *
2279 * There are two possibilities here that should be kept in mind.
2280 * If the original invocation has not been pulled off for processing
2281 * yet, A subsuquent invocation can have a route entry with a better
2282 * meta queue index value and we can have a situation where
2283 * we might have the same node enqueued 2 times. Not necessarily
2284 * an optimal situation but it should be ok.
2285 *
2286 * The other possibility is that the original invocation has not
2287 * been pulled off for processing yet, A subsusquent invocation
2288 * doesn't have a route_entry with a better meta-queue and the
2289 * original metaqueue index value will win and we'll end up with
2290 * the route node enqueued once.
e96f9203 2291 */
e22e8001 2292static int rib_meta_queue_add(struct meta_queue *mq, void *data)
e96f9203 2293{
e22e8001 2294 struct route_node *rn = NULL;
f52ed677
DS
2295 struct route_entry *re = NULL, *curr_re = NULL;
2296 uint8_t qindex = MQ_SIZE, curr_qindex = MQ_SIZE;
5110a0c6 2297
e22e8001
SW
2298 rn = (struct route_node *)data;
2299
f52ed677
DS
2300 RNODE_FOREACH_RE (rn, curr_re) {
2301 curr_qindex = route_info[curr_re->type].meta_q_map;
d62a17ae 2302
f52ed677
DS
2303 if (curr_qindex <= qindex) {
2304 re = curr_re;
2305 qindex = curr_qindex;
d62a17ae 2306 }
f52ed677 2307 }
5110a0c6 2308
f52ed677 2309 if (!re)
e22e8001 2310 return -1;
5110a0c6 2311
f52ed677
DS
2312 /* Invariant: at this point we always have rn->info set. */
2313 if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
2314 RIB_ROUTE_QUEUED(qindex))) {
d62a17ae 2315 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
2316 rnode_debug(rn, re->vrf_id,
f52ed677 2317 "rn %p is already queued in sub-queue %u",
d62a17ae 2318 (void *)rn, qindex);
e22e8001 2319 return -1;
d62a17ae 2320 }
f52ed677
DS
2321
2322 SET_FLAG(rib_dest_from_rnode(rn)->flags, RIB_ROUTE_QUEUED(qindex));
2323 listnode_add(mq->subq[qindex], rn);
2324 route_lock_node(rn);
2325 mq->size++;
2326
2327 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
2328 rnode_debug(rn, re->vrf_id, "queued rn %p into sub-queue %u",
2329 (void *)rn, qindex);
e22e8001
SW
2330
2331 return 0;
4d38fdb4 2332}
2333
e22e8001 2334static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
4d38fdb4 2335{
e22e8001
SW
2336 struct nhg_ctx *ctx = NULL;
2337 uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
fc328ac9 2338
e22e8001
SW
2339 ctx = (struct nhg_ctx *)data;
2340
2341 if (!ctx)
2342 return -1;
4d38fdb4 2343
e22e8001
SW
2344 listnode_add(mq->subq[qindex], ctx);
2345 mq->size++;
2346
2347 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
2348 zlog_debug("NHG Context id=%u queued into sub-queue %u",
2349 ctx->id, qindex);
2350
2351 return 0;
2352}
2353
2354static int mq_add_handler(void *data,
2355 int (*mq_add_func)(struct meta_queue *mq, void *data))
2356{
489a9614 2357 if (zrouter.ribq == NULL) {
e914ccbe 2358 flog_err(EC_ZEBRA_WQ_NONEXISTENT,
1c50c1c0 2359 "%s: work_queue does not exist!", __func__);
e22e8001 2360 return -1;
d62a17ae 2361 }
2362
2363 /*
2364 * The RIB queue should normally be either empty or holding the only
2365 * work_queue_item element. In the latter case this element would
2366 * hold a pointer to the meta queue structure, which must be used to
2367 * actually queue the route nodes to process. So create the MQ
2368 * holder, if necessary, then push the work into it in any case.
2369 * This semantics was introduced after 0.99.9 release.
2370 */
489a9614 2371 if (work_queue_empty(zrouter.ribq))
ea45a4e7 2372 work_queue_add(zrouter.ribq, zrouter.mq);
e96f9203 2373
e22e8001
SW
2374 return mq_add_func(zrouter.mq, data);
2375}
fc328ac9 2376
e22e8001
SW
2377/* Add route_node to work queue and schedule processing */
2378int rib_queue_add(struct route_node *rn)
2379{
2380 assert(rn);
2381
2382 /* Pointless to queue a route_node with no RIB entries to add or remove
2383 */
2384 if (!rnode_to_ribs(rn)) {
2385 zlog_debug("%s: called for route_node (%p, %d) with no ribs",
2386 __func__, (void *)rn, rn->lock);
2387 zlog_backtrace(LOG_DEBUG);
2388 return -1;
2389 }
2390
2391 return mq_add_handler(rn, &rib_meta_queue_add);
2392}
2393
2394int rib_queue_nhg_add(struct nhg_ctx *ctx)
2395{
2396 assert(ctx);
2397
2398 return mq_add_handler(ctx, &rib_meta_queue_nhg_add);
4d38fdb4 2399}
2400
5110a0c6
SH
2401/* Create new meta queue.
2402 A destructor function doesn't seem to be necessary here.
2403 */
d62a17ae 2404static struct meta_queue *meta_queue_new(void)
e96f9203 2405{
d62a17ae 2406 struct meta_queue *new;
2407 unsigned i;
5110a0c6 2408
d62a17ae 2409 new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct meta_queue));
e96f9203 2410
d62a17ae 2411 for (i = 0; i < MQ_SIZE; i++) {
2412 new->subq[i] = list_new();
2413 assert(new->subq[i]);
2414 }
5110a0c6 2415
d62a17ae 2416 return new;
e96f9203
DO
2417}
2418
d62a17ae 2419void meta_queue_free(struct meta_queue *mq)
5a8dfcd8 2420{
d62a17ae 2421 unsigned i;
5a8dfcd8 2422
d62a17ae 2423 for (i = 0; i < MQ_SIZE; i++)
6a154c88 2424 list_delete(&mq->subq[i]);
5a8dfcd8 2425
d62a17ae 2426 XFREE(MTYPE_WORK_QUEUE, mq);
5a8dfcd8
RW
2427}
2428
4d38fdb4 2429/* initialise zebra rib work queue */
2561d12e 2430static void rib_queue_init(void)
4d38fdb4 2431{
489a9614
DS
2432 if (!(zrouter.ribq = work_queue_new(zrouter.master,
2433 "route_node processing"))) {
e914ccbe 2434 flog_err(EC_ZEBRA_WQ_NONEXISTENT,
1c50c1c0 2435 "%s: could not initialise work queue!", __func__);
d62a17ae 2436 return;
2437 }
4d38fdb4 2438
d62a17ae 2439 /* fill in the work queue spec */
489a9614
DS
2440 zrouter.ribq->spec.workfunc = &meta_queue_process;
2441 zrouter.ribq->spec.errorfunc = NULL;
46a4e345 2442 zrouter.ribq->spec.completion_func = NULL;
d62a17ae 2443 /* XXX: TODO: These should be runtime configurable via vty */
489a9614
DS
2444 zrouter.ribq->spec.max_retries = 3;
2445 zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
2446 zrouter.ribq->spec.retry = ZEBRA_RIB_PROCESS_RETRY_TIME;
d62a17ae 2447
ea45a4e7 2448 if (!(zrouter.mq = meta_queue_new())) {
e914ccbe 2449 flog_err(EC_ZEBRA_WQ_NONEXISTENT,
1c50c1c0 2450 "%s: could not initialise meta queue!", __func__);
d62a17ae 2451 return;
2452 }
2453 return;
718e3744 2454}
2455
434434f7
DS
2456rib_dest_t *zebra_rib_create_dest(struct route_node *rn)
2457{
2458 rib_dest_t *dest;
2459
2460 dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t));
aa57abfb 2461 rnh_list_init(&dest->nht);
daaeaa21 2462 re_list_init(&dest->routes);
434434f7
DS
2463 route_lock_node(rn); /* rn route table reference */
2464 rn->info = dest;
2465 dest->rnode = rn;
2466
2467 return dest;
2468}
2469
6d691129
PJ
2470/* RIB updates are processed via a queue of pointers to route_nodes.
2471 *
2472 * The queue length is bounded by the maximal size of the routing table,
2473 * as a route_node will not be requeued, if already queued.
2474 *
f0f77c9a
DS
2475 * REs are submitted via rib_addnode or rib_delnode which set minimal
2476 * state, or static_install_route (when an existing RE is updated)
3c0755dc 2477 * and then submit route_node to queue for best-path selection later.
f0f77c9a 2478 * Order of add/delete state changes are preserved for any given RE.
6d691129 2479 *
f0f77c9a 2480 * Deleted REs are reaped during best-path selection.
6d691129
PJ
2481 *
2482 * rib_addnode
f0f77c9a
DS
2483 * |-> rib_link or unset ROUTE_ENTRY_REMOVE |->Update kernel with
2484 * |-------->| | best RE, if required
3c0755dc
PJ
2485 * | |
2486 * static_install->|->rib_addqueue...... -> rib_process
2487 * | |
2488 * |-------->| |-> rib_unlink
f0f77c9a
DS
2489 * |-> set ROUTE_ENTRY_REMOVE |
2490 * rib_delnode (RE freed)
6d691129 2491 *
9fd92e3c
AS
2492 * The 'info' pointer of a route_node points to a rib_dest_t
2493 * ('dest'). Queueing state for a route_node is kept on the dest. The
2494 * dest is created on-demand by rib_link() and is kept around at least
2495 * as long as there are ribs hanging off it (@see rib_gc_dest()).
d62a17ae 2496 *
6d691129
PJ
2497 * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
2498 *
2499 * - route_nodes: refcounted by:
9fd92e3c
AS
2500 * - dest attached to route_node:
2501 * - managed by: rib_link/rib_gc_dest
6d691129
PJ
2502 * - route_node processing queue
2503 * - managed by: rib_addqueue, rib_process.
2504 *
2505 */
d62a17ae 2506
f0f77c9a 2507/* Add RE to head of the route node. */
d62a17ae 2508static void rib_link(struct route_node *rn, struct route_entry *re, int process)
2509{
d62a17ae 2510 rib_dest_t *dest;
2511 afi_t afi;
2512 const char *rmap_name;
9fd92e3c 2513
d62a17ae 2514 assert(re && rn);
9fd92e3c 2515
d62a17ae 2516 dest = rib_dest_from_rnode(rn);
2517 if (!dest) {
2518 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
2519 rnode_debug(rn, re->vrf_id, "rn %p adding dest", rn);
7a4bb9c5 2520
434434f7 2521 dest = zebra_rib_create_dest(rn);
d62a17ae 2522 }
2263a412 2523
045207e2 2524 re_list_add_head(&dest->routes, re);
d62a17ae 2525
2526 afi = (rn->p.family == AF_INET)
2527 ? AFI_IP
2528 : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
fe257ae7
DS
2529 if (is_zebra_import_table_enabled(afi, re->vrf_id, re->table)) {
2530 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
2531
d62a17ae 2532 rmap_name = zebra_get_import_table_route_map(afi, re->table);
fe257ae7 2533 zebra_add_import_table_entry(zvrf, rn, re, rmap_name);
d62a17ae 2534 } else if (process)
2535 rib_queue_add(rn);
2536}
2537
7e24fdf3
DS
2538static void rib_addnode(struct route_node *rn,
2539 struct route_entry *re, int process)
d62a17ae 2540{
2541 /* RE node has been un-removed before route-node is processed.
2542 * route_node must hence already be on the queue for processing..
2543 */
2544 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
2545 if (IS_ZEBRA_DEBUG_RIB)
2546 rnode_debug(rn, re->vrf_id, "rn %p, un-removed re %p",
2547 (void *)rn, (void *)re);
2548
2549 UNSET_FLAG(re->status, ROUTE_ENTRY_REMOVED);
2550 return;
2551 }
2552 rib_link(rn, re, process);
6d691129
PJ
2553}
2554
9fd92e3c
AS
2555/*
2556 * rib_unlink
2557 *
2558 * Detach a rib structure from a route_node.
2559 *
2560 * Note that a call to rib_unlink() should be followed by a call to
2561 * rib_gc_dest() at some point. This allows a rib_dest_t that is no
2562 * longer required to be deleted.
2563 */
d62a17ae 2564void rib_unlink(struct route_node *rn, struct route_entry *re)
6d691129 2565{
d62a17ae 2566 rib_dest_t *dest;
9fd92e3c 2567
d62a17ae 2568 assert(rn && re);
6d691129 2569
d62a17ae 2570 if (IS_ZEBRA_DEBUG_RIB)
2571 rnode_debug(rn, re->vrf_id, "rn %p, re %p", (void *)rn,
2572 (void *)re);
6d691129 2573
d62a17ae 2574 dest = rib_dest_from_rnode(rn);
6d691129 2575
045207e2 2576 re_list_del(&dest->routes, re);
7a4bb9c5 2577
2eb07de3
DS
2578 if (dest->selected_fib == re)
2579 dest->selected_fib = NULL;
2580
1d48702e
MS
2581 if (re->nhe && re->nhe_id) {
2582 assert(re->nhe->id == re->nhe_id);
2583 zebra_nhg_decrement_ref(re->nhe);
2584 } else if (re->nhe && re->nhe->nhg.nexthop)
c415d895 2585 nexthops_free(re->nhe->nhg.nexthop);
22bcedb2 2586
ee5e8a48
MS
2587 nexthops_free(re->fib_ng.nexthop);
2588
d62a17ae 2589 XFREE(MTYPE_RE, re);
2590}
2591
2592void rib_delnode(struct route_node *rn, struct route_entry *re)
2593{
2594 afi_t afi;
2595
2596 if (IS_ZEBRA_DEBUG_RIB)
2597 rnode_debug(rn, re->vrf_id, "rn %p, re %p, removing",
2598 (void *)rn, (void *)re);
2599 SET_FLAG(re->status, ROUTE_ENTRY_REMOVED);
2600
2601 afi = (rn->p.family == AF_INET)
2602 ? AFI_IP
2603 : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
fe257ae7
DS
2604 if (is_zebra_import_table_enabled(afi, re->vrf_id, re->table)) {
2605 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
2606
2607 zebra_del_import_table_entry(zvrf, rn, re);
d62a17ae 2608 /* Just clean up if non main table */
2609 if (IS_ZEBRA_DEBUG_RIB) {
2610 char buf[SRCDEST2STR_BUFFER];
2611 srcdest_rnode2str(rn, buf, sizeof(buf));
bd47f3a3
JU
2612 zlog_debug("%s(%u):%s: Freeing route rn %p, re %p (%s)",
2613 vrf_id_to_name(re->vrf_id), re->vrf_id, buf,
2614 rn, re, zebra_route_string(re->type));
d62a17ae 2615 }
7a4bb9c5 2616
d62a17ae 2617 rib_unlink(rn, re);
2618 } else {
2619 rib_queue_add(rn);
2620 }
718e3744 2621}
2622
6d81b590
MS
2623/*
2624 * Helper that debugs a single nexthop within a route-entry
2625 */
2626static void _route_entry_dump_nh(const struct route_entry *re,
2627 const char *straddr,
2628 const struct nexthop *nexthop)
2629{
2630 char nhname[PREFIX_STRLEN];
2631 char backup_str[50];
2632 char wgt_str[50];
474aebd9
MS
2633 char temp_str[10];
2634 int i;
6d81b590
MS
2635 struct interface *ifp;
2636 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
2637
2638 switch (nexthop->type) {
2639 case NEXTHOP_TYPE_BLACKHOLE:
772270f3 2640 snprintf(nhname, sizeof(nhname), "Blackhole");
6d81b590
MS
2641 break;
2642 case NEXTHOP_TYPE_IFINDEX:
2643 ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
772270f3
QY
2644 snprintf(nhname, sizeof(nhname), "%s",
2645 ifp ? ifp->name : "Unknown");
6d81b590
MS
2646 break;
2647 case NEXTHOP_TYPE_IPV4:
2648 /* fallthrough */
2649 case NEXTHOP_TYPE_IPV4_IFINDEX:
2650 inet_ntop(AF_INET, &nexthop->gate, nhname, INET6_ADDRSTRLEN);
2651 break;
2652 case NEXTHOP_TYPE_IPV6:
2653 case NEXTHOP_TYPE_IPV6_IFINDEX:
2654 inet_ntop(AF_INET6, &nexthop->gate, nhname, INET6_ADDRSTRLEN);
2655 break;
2656 }
2657
2658 backup_str[0] = '\0';
2659 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
474aebd9
MS
2660 snprintf(backup_str, sizeof(backup_str), "backup ");
2661 for (i = 0; i < nexthop->backup_num; i++) {
2662 snprintf(temp_str, sizeof(temp_str), "%d, ",
2663 nexthop->backup_idx[i]);
2664 strlcat(backup_str, temp_str, sizeof(backup_str));
2665 }
6d81b590
MS
2666 }
2667
2668 wgt_str[0] = '\0';
2669 if (nexthop->weight)
2670 snprintf(wgt_str, sizeof(wgt_str), "wgt %d,", nexthop->weight);
2671
2672 zlog_debug("%s: %s %s[%u] vrf %s(%u) %s%s with flags %s%s%s%s%s",
2673 straddr, (nexthop->rparent ? " NH" : "NH"), nhname,
2674 nexthop->ifindex, vrf ? vrf->name : "Unknown",
2675 nexthop->vrf_id,
2676 wgt_str, backup_str,
2677 (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
2678 ? "ACTIVE "
2679 : ""),
2680 (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
2681 ? "FIB "
2682 : ""),
2683 (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
2684 ? "RECURSIVE "
2685 : ""),
2686 (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)
2687 ? "ONLINK "
2688 : ""),
2689 (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)
2690 ? "DUPLICATE "
2691 : ""));
2692
2693}
2694
f0f77c9a 2695/* This function dumps the contents of a given RE entry into
dc95824a
DO
2696 * standard debug log. Calling function name and IP prefix in
2697 * question are passed as 1st and 2nd arguments.
2698 */
d62a17ae 2699void _route_entry_dump(const char *func, union prefixconstptr pp,
2700 union prefixconstptr src_pp,
2701 const struct route_entry *re)
2702{
d62a17ae 2703 const struct prefix *src_p = src_pp.p;
2704 bool is_srcdst = src_p && src_p->prefixlen;
2705 char straddr[PREFIX_STRLEN];
2706 char srcaddr[PREFIX_STRLEN];
2707 struct nexthop *nexthop;
c479e756 2708 struct vrf *vrf = vrf_lookup_by_id(re->vrf_id);
6d81b590 2709 struct nexthop_group *nhg;
d62a17ae 2710
c479e756 2711 zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %s(%u)", func,
d62a17ae 2712 (const void *)re, prefix2str(pp, straddr, sizeof(straddr)),
2713 is_srcdst ? " from " : "",
2714 is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr))
2715 : "",
c479e756 2716 VRF_LOGNAME(vrf), re->vrf_id);
cc54cfee 2717 zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d",
53c16fbe 2718 straddr, (unsigned long)re->uptime, re->type, re->instance,
cc54cfee 2719 re->table);
6d81b590
MS
2720 zlog_debug("%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
2721 straddr, re->metric, re->mtu, re->distance, re->flags,
2722 re->status);
53c16fbe 2723 zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
c415d895
MS
2724 nexthop_group_nexthop_num(&(re->nhe->nhg)),
2725 nexthop_group_active_nexthop_num(&(re->nhe->nhg)));
d62a17ae 2726
6d81b590
MS
2727 /* Dump nexthops */
2728 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
2729 _route_entry_dump_nh(re, straddr, nexthop);
2d68a0f2 2730
6d81b590
MS
2731 if (zebra_nhg_get_backup_nhg(re->nhe)) {
2732 zlog_debug("%s: backup nexthops:", straddr);
2733
2734 nhg = zebra_nhg_get_backup_nhg(re->nhe);
2735 for (ALL_NEXTHOPS_PTR(nhg, nexthop))
2736 _route_entry_dump_nh(re, straddr, nexthop);
d62a17ae 2737 }
6d81b590 2738
53c16fbe 2739 zlog_debug("%s: dump complete", straddr);
dc95824a
DO
2740}
2741
6d81b590
MS
2742/*
2743 * This is an exported helper to rtm_read() to dump the strange
f0f77c9a 2744 * RE entry found by rib_lookup_ipv4_route()
dc95824a 2745 */
d62a17ae 2746void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id)
2747{
2748 struct route_table *table;
2749 struct route_node *rn;
2750 struct route_entry *re;
bd47f3a3 2751 struct vrf *vrf;
d62a17ae 2752 char prefix_buf[INET_ADDRSTRLEN];
2753
bd47f3a3
JU
2754 vrf = vrf_lookup_by_id(vrf_id);
2755
d62a17ae 2756 /* Lookup table. */
2757 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
2758 if (!table) {
e914ccbe 2759 flog_err(EC_ZEBRA_TABLE_LOOKUP_FAILED,
bd47f3a3
JU
2760 "%s:%s(%u) zebra_vrf_table() returned NULL", __func__,
2761 VRF_LOGNAME(vrf), vrf_id);
d62a17ae 2762 return;
2763 }
2764
2765 /* Scan the RIB table for exactly matching RE entry. */
2766 rn = route_node_lookup(table, (struct prefix *)p);
2767
2768 /* No route for this prefix. */
2769 if (!rn) {
bd47f3a3
JU
2770 zlog_debug("%s:%s(%u) lookup failed for %s", __func__,
2771 VRF_LOGNAME(vrf), vrf_id,
d62a17ae 2772 prefix2str((struct prefix *)p, prefix_buf,
2773 sizeof(prefix_buf)));
2774 return;
2775 }
2776
2777 /* Unlock node. */
2778 route_unlock_node(rn);
2779
2780 /* let's go */
a2addae8 2781 RNODE_FOREACH_RE (rn, re) {
bd47f3a3
JU
2782 zlog_debug("%s:%s(%u) rn %p, re %p: %s, %s", __func__,
2783 VRF_LOGNAME(vrf), vrf_id, (void *)rn, (void *)re,
d62a17ae 2784 (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)
2785 ? "removed"
2786 : "NOT removed"),
2787 (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
2788 ? "selected"
2789 : "NOT selected"));
2790 route_entry_dump(p, NULL, re);
2791 }
dc95824a
DO
2792}
2793
20e5ff0a
DO
2794/* Check if requested address assignment will fail due to another
2795 * route being installed by zebra in FIB already. Take necessary
2796 * actions, if needed: remove such a route from FIB and deSELECT
f0f77c9a 2797 * corresponding RE entry. Then put affected RN into RIBQ head.
20e5ff0a 2798 */
d62a17ae 2799void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
2800{
2801 struct route_table *table;
2802 struct route_node *rn;
5f7a4718 2803 rib_dest_t *dest;
d62a17ae 2804
2805 if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) {
bd47f3a3
JU
2806 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
2807
e914ccbe 2808 flog_err(EC_ZEBRA_TABLE_LOOKUP_FAILED,
bd47f3a3
JU
2809 "%s:%s(%u) zebra_vrf_table() returned NULL", __func__,
2810 VRF_LOGNAME(vrf), vrf_id);
d62a17ae 2811 return;
2812 }
2813
2814 /* No matches would be the simplest case. */
2815 if (NULL == (rn = route_node_lookup(table, (struct prefix *)p)))
2816 return;
2817
2818 /* Unlock node. */
2819 route_unlock_node(rn);
2820
5f7a4718 2821 dest = rib_dest_from_rnode(rn);
d62a17ae 2822 /* Check all RE entries. In case any changes have to be done, requeue
2823 * the RN into RIBQ head. If the routing message about the new connected
2824 * route (generated by the IP address we are going to assign very soon)
2825 * comes before the RIBQ is processed, the new RE entry will join
2826 * RIBQ record already on head. This is necessary for proper
2827 * revalidation
2828 * of the rest of the RE.
2829 */
3cdba47a 2830 if (dest->selected_fib) {
5f7a4718
DS
2831 if (IS_ZEBRA_DEBUG_RIB) {
2832 char buf[PREFIX_STRLEN];
bd47f3a3
JU
2833 struct vrf *vrf =
2834 vrf_lookup_by_id(dest->selected_fib->vrf_id);
5f7a4718 2835
bd47f3a3
JU
2836 zlog_debug(
2837 "%s(%u):%s: freeing way for connected prefix",
2838 VRF_LOGNAME(vrf), dest->selected_fib->vrf_id,
2839 prefix2str(&rn->p, buf, sizeof(buf)));
5f7a4718 2840 route_entry_dump(&rn->p, NULL, dest->selected_fib);
d62a17ae 2841 }
5f7a4718 2842 rib_uninstall(rn, dest->selected_fib);
d62a17ae 2843 rib_queue_add(rn);
ade4a886 2844 }
20e5ff0a
DO
2845}
2846
1d48702e
MS
2847/*
2848 * Internal route-add implementation; there are a couple of different public
2849 * signatures. Callers in this path are responsible for the memory they
2850 * allocate: if they allocate a nexthop_group or backup nexthop info, they
2851 * must free those objects. If this returns < 0, an error has occurred and the
2852 * route_entry 're' has not been captured; the caller should free that also.
2853 */
2854int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
6d81b590 2855 struct prefix_ipv6 *src_p, struct route_entry *re,
1d48702e 2856 struct nhg_hash_entry *re_nhe)
718e3744 2857{
98cda54a 2858 struct nhg_hash_entry *nhe = NULL;
d62a17ae 2859 struct route_table *table;
2860 struct route_node *rn;
40ecd8e4 2861 struct route_entry *same = NULL;
d62a17ae 2862 int ret = 0;
b4c034b0 2863
1d48702e
MS
2864 if (!re || !re_nhe)
2865 return -1;
b4c034b0 2866
1f610a1f 2867 assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
05737783 2868
d62a17ae 2869 /* Lookup table. */
c7c0b007
SW
2870 table = zebra_vrf_get_table_with_table_id(afi, safi, re->vrf_id,
2871 re->table);
1d48702e
MS
2872 if (!table)
2873 return -1;
cddf391b 2874
1d48702e
MS
2875 if (re_nhe->id > 0) {
2876 nhe = zebra_nhg_lookup_id(re_nhe->id);
98cda54a
SW
2877
2878 if (!nhe) {
2879 flog_err(
2880 EC_ZEBRA_TABLE_LOOKUP_FAILED,
2881 "Zebra failed to find the nexthop hash entry for id=%u in a route entry",
1d48702e
MS
2882 re_nhe->id);
2883
98cda54a
SW
2884 return -1;
2885 }
2886 } else {
377e29f7
MS
2887 /* Lookup nhe from route information */
2888 nhe = zebra_nhg_rib_find_nhe(re_nhe, afi);
98cda54a
SW
2889 if (!nhe) {
2890 char buf[PREFIX_STRLEN] = "";
2891 char buf2[PREFIX_STRLEN] = "";
2892
2893 flog_err(
2894 EC_ZEBRA_TABLE_LOOKUP_FAILED,
2895 "Zebra failed to find or create a nexthop hash entry for %s%s%s",
2896 prefix2str(p, buf, sizeof(buf)),
2897 src_p ? " from " : "",
2898 src_p ? prefix2str(src_p, buf2, sizeof(buf2))
2899 : "");
2900
98cda54a
SW
2901 return -1;
2902 }
98cda54a
SW
2903 }
2904
4b87c90d
SW
2905 /*
2906 * Attach the re to the nhe's nexthop group.
2907 *
2908 * TODO: This will need to change when we start getting IDs from upper
2909 * level protocols, as the refcnt might be wrong, since it checks
2910 * if old_id != new_id.
2911 */
5463ce26 2912 route_entry_update_nhe(re, nhe);
98cda54a 2913
d62a17ae 2914 /* Make it sure prefixlen is applied to the prefix. */
2915 apply_mask(p);
2916 if (src_p)
2917 apply_mask_ipv6(src_p);
718e3744 2918
d62a17ae 2919 /* Set default distance by route type. */
eea2ef07 2920 if (re->distance == 0)
0492eea0 2921 re->distance = route_distance(re->type);
718e3744 2922
d62a17ae 2923 /* Lookup route node.*/
2924 rn = srcdest_rnode_get(table, p, src_p);
718e3744 2925
40ecd8e4
DS
2926 /*
2927 * If same type of route are installed, treat it as a implicit
9db35a5e 2928 * withdraw. If the user has specified the No route replace semantics
40ecd8e4
DS
2929 * for the install don't do a route replace.
2930 */
a2addae8 2931 RNODE_FOREACH_RE (rn, same) {
d62a17ae 2932 if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
2933 continue;
41ec9222 2934
9db35a5e
MS
2935 /* Compare various route_entry properties */
2936 if (rib_compare_routes(re, same))
d62a17ae 2937 break;
2938 }
718e3744 2939
cf363e1b
MS
2940 /* If this route is kernel/connected route, notify the dataplane. */
2941 if (RIB_SYSTEM_ROUTE(re)) {
2942 /* Notify dataplane */
2943 dplane_sys_route_add(rn, re);
2944 }
2945
d62a17ae 2946 /* Link new re to node.*/
2947 if (IS_ZEBRA_DEBUG_RIB) {
2da33d6b
DS
2948 rnode_debug(rn, re->vrf_id,
2949 "Inserting route rn %p, re %p (%s) existing %p",
2950 rn, re, zebra_route_string(re->type), same);
718e3744 2951
d62a17ae 2952 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
2953 route_entry_dump(p, src_p, re);
718e3744 2954 }
6883bf8d
DS
2955
2956 SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
d62a17ae 2957 rib_addnode(rn, re, 1);
2958 ret = 1;
6b0655a2 2959
d62a17ae 2960 /* Free implicit route.*/
1d48702e 2961 if (same)
d62a17ae 2962 rib_delnode(rn, same);
718e3744 2963
d62a17ae 2964 route_unlock_node(rn);
2965 return ret;
2966}
2967
1d48702e
MS
2968/*
2969 * Add a single route.
2970 */
2971int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
2972 struct prefix_ipv6 *src_p, struct route_entry *re,
2973 struct nexthop_group *ng)
2974{
2975 int ret;
377e29f7 2976 struct nhg_hash_entry nhe;
1d48702e
MS
2977
2978 if (!re)
2979 return -1;
2980
2981 /* We either need nexthop(s) or an existing nexthop id */
2982 if (ng == NULL && re->nhe_id == 0)
2983 return -1;
2984
2985 /*
2986 * Use a temporary nhe to convey info to the common/main api.
2987 */
377e29f7 2988 zebra_nhe_init(&nhe, afi, (ng ? ng->nexthop : NULL));
1d48702e
MS
2989 if (ng)
2990 nhe.nhg.nexthop = ng->nexthop;
2991 else if (re->nhe_id > 0)
2992 nhe.id = re->nhe_id;
2993
2994 ret = rib_add_multipath_nhe(afi, safi, p, src_p, re, &nhe);
2995
2996 /* In this path, the callers expect memory to be freed. */
2997 nexthop_group_delete(&ng);
2998
2999 /* In error cases, free the route also */
3000 if (ret < 0)
3001 XFREE(MTYPE_RE, re);
3002
3003 return ret;
3004}
3005
d62a17ae 3006void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
d7c0a89a 3007 unsigned short instance, int flags, struct prefix *p,
fd36be7e 3008 struct prefix_ipv6 *src_p, const struct nexthop *nh,
bc541126
SW
3009 uint32_t nhe_id, uint32_t table_id, uint32_t metric,
3010 uint8_t distance, bool fromkernel)
d62a17ae 3011{
3012 struct route_table *table;
3013 struct route_node *rn;
3014 struct route_entry *re;
3015 struct route_entry *fib = NULL;
3016 struct route_entry *same = NULL;
fd36be7e 3017 struct nexthop *rtnh;
d62a17ae 3018 char buf2[INET6_ADDRSTRLEN];
5f7a4718 3019 rib_dest_t *dest;
d62a17ae 3020
1f610a1f 3021 assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
d62a17ae 3022
3023 /* Lookup table. */
c7c0b007
SW
3024 table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id,
3025 table_id);
d62a17ae 3026 if (!table)
3027 return;
3028
3029 /* Apply mask. */
3030 apply_mask(p);
3031 if (src_p)
3032 apply_mask_ipv6(src_p);
3033
3034 /* Lookup route node. */
3035 rn = srcdest_rnode_lookup(table, p, src_p);
3036 if (!rn) {
3037 char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN];
3038
3039 prefix2str(p, dst_buf, sizeof(dst_buf));
3040 if (src_p && src_p->prefixlen)
3041 prefix2str(src_p, src_buf, sizeof(src_buf));
3042 else
3043 src_buf[0] = '\0';
3044
82d7d0e2
DS
3045 if (IS_ZEBRA_DEBUG_RIB) {
3046 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
3047
3048 zlog_debug("%s[%d]:%s%s%s doesn't exist in rib",
3049 vrf->name, table_id, dst_buf,
d62a17ae 3050 (src_buf[0] != '\0') ? " from " : "",
3051 src_buf);
82d7d0e2 3052 }
d62a17ae 3053 return;
3054 }
718e3744 3055
5f7a4718
DS
3056 dest = rib_dest_from_rnode(rn);
3057 fib = dest->selected_fib;
3058
d62a17ae 3059 /* Lookup same type route. */
a2addae8 3060 RNODE_FOREACH_RE (rn, re) {
d62a17ae 3061 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
3062 continue;
3063
d62a17ae 3064 if (re->type != type)
3065 continue;
3066 if (re->instance != instance)
3067 continue;
40ecd8e4
DS
3068 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE) &&
3069 distance != re->distance)
3070 continue;
3071
996c9314 3072 if (re->type == ZEBRA_ROUTE_KERNEL && re->metric != metric)
f19435a8 3073 continue;
0eb97b86 3074 if (re->type == ZEBRA_ROUTE_CONNECT &&
c415d895 3075 (rtnh = re->nhe->nhg.nexthop)
fd36be7e
DL
3076 && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
3077 if (rtnh->ifindex != nh->ifindex)
d62a17ae 3078 continue;
d62a17ae 3079 same = re;
3080 break;
3081 }
fec211ad 3082
d62a17ae 3083 /* Make sure that the route found has the same gateway. */
fec211ad 3084 if (nhe_id && re->nhe_id == nhe_id) {
bc541126
SW
3085 same = re;
3086 break;
fec211ad
SW
3087 }
3088
3089 if (nh == NULL) {
3090 same = re;
3091 break;
3092 }
c415d895 3093 for (ALL_NEXTHOPS(re->nhe->nhg, rtnh)) {
fec211ad
SW
3094 /*
3095 * No guarantee all kernel send nh with labels
3096 * on delete.
3097 */
3098 if (nexthop_same_no_labels(rtnh, nh)) {
d62a17ae 3099 same = re;
3100 break;
3101 }
d62a17ae 3102 }
fec211ad
SW
3103
3104 if (same)
3105 break;
d62a17ae 3106 }
3107 /* If same type of route can't be found and this message is from
3108 kernel. */
3109 if (!same) {
5dfeba19
DS
3110 /*
3111 * In the past(HA!) we could get here because
3112 * we were receiving a route delete from the
3113 * kernel and we're not marking the proto
3114 * as coming from it's appropriate originator.
3115 * Now that we are properly noticing the fact
3116 * that the kernel has deleted our route we
3117 * are not going to get called in this path
3118 * I am going to leave this here because
3119 * this might still work this way on non-linux
3120 * platforms as well as some weird state I have
3121 * not properly thought of yet.
3122 * If we can show that this code path is
3123 * dead then we can remove it.
3124 */
b8faa875 3125 if (fib && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) {
d62a17ae 3126 if (IS_ZEBRA_DEBUG_RIB) {
2da33d6b
DS
3127 rnode_debug(rn, vrf_id,
3128 "rn %p, re %p (%s) was deleted from kernel, adding",
3129 rn, fib,
3130 zebra_route_string(fib->type));
d62a17ae 3131 }
3132 if (allow_delete) {
677c1dd5 3133 UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
d62a17ae 3134 /* Unset flags. */
c415d895 3135 for (rtnh = fib->nhe->nhg.nexthop; rtnh;
fd36be7e
DL
3136 rtnh = rtnh->next)
3137 UNSET_FLAG(rtnh->flags,
d62a17ae 3138 NEXTHOP_FLAG_FIB);
3139
ed216282
DS
3140 /*
3141 * This is a non FRR route
3142 * as such we should mark
3143 * it as deleted
3144 */
5f7a4718 3145 dest->selected_fib = NULL;
d62a17ae 3146 } else {
3147 /* This means someone else, other than Zebra,
3148 * has deleted
3149 * a Zebra router from the kernel. We will add
3150 * it back */
3151 rib_install_kernel(rn, fib, NULL);
3152 }
3153 } else {
3154 if (IS_ZEBRA_DEBUG_RIB) {
fd36be7e 3155 if (nh)
d62a17ae 3156 rnode_debug(
3157 rn, vrf_id,
3158 "via %s ifindex %d type %d "
3159 "doesn't exist in rib",
36228974 3160 inet_ntop(afi2family(afi),
3161 &nh->gate, buf2,
3162 sizeof(buf2)),
3163 nh->ifindex, type);
d62a17ae 3164 else
3165 rnode_debug(
3166 rn, vrf_id,
fd36be7e
DL
3167 "type %d doesn't exist in rib",
3168 type);
d62a17ae 3169 }
3170 route_unlock_node(rn);
3171 return;
3172 }
3173 }
718e3744 3174
5dfeba19 3175 if (same) {
996c9314
LB
3176 if (fromkernel && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)
3177 && !allow_delete) {
5dfeba19
DS
3178 rib_install_kernel(rn, same, NULL);
3179 route_unlock_node(rn);
3180
3181 return;
3182 }
6134fd82 3183
2b83602b 3184 /* Special handling for IPv4 or IPv6 routes sourced from
3185 * EVPN - the nexthop (and associated MAC) need to be
3186 * uninstalled if no more refs.
3187 */
90264d64 3188 if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
6134fd82 3189 struct nexthop *tmp_nh;
3190
c415d895 3191 for (ALL_NEXTHOPS(re->nhe->nhg, tmp_nh)) {
6134fd82 3192 struct ipaddr vtep_ip;
3193
3194 memset(&vtep_ip, 0, sizeof(struct ipaddr));
1ec31309 3195 if (afi == AFI_IP) {
3196 vtep_ip.ipa_type = IPADDR_V4;
3197 memcpy(&(vtep_ip.ipaddr_v4),
3198 &(tmp_nh->gate.ipv4),
3199 sizeof(struct in_addr));
3200 } else {
3201 vtep_ip.ipa_type = IPADDR_V6;
3202 memcpy(&(vtep_ip.ipaddr_v6),
3203 &(tmp_nh->gate.ipv6),
3204 sizeof(struct in6_addr));
3205 }
a317a9b9 3206 zebra_vxlan_evpn_vrf_route_del(re->vrf_id,
6134fd82 3207 &vtep_ip, p);
3208 }
3209 }
cf363e1b
MS
3210
3211 /* Notify dplane if system route changes */
3212 if (RIB_SYSTEM_ROUTE(re))
3213 dplane_sys_route_del(rn, same);
3214
d62a17ae 3215 rib_delnode(rn, same);
5dfeba19 3216 }
05737783 3217
d62a17ae 3218 route_unlock_node(rn);
3219 return;
3220}
718e3744 3221
718e3744 3222
d7c0a89a
QY
3223int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
3224 unsigned short instance, int flags, struct prefix *p,
3225 struct prefix_ipv6 *src_p, const struct nexthop *nh,
8032b717
SW
3226 uint32_t nhe_id, uint32_t table_id, uint32_t metric, uint32_t mtu,
3227 uint8_t distance, route_tag_t tag)
d62a17ae 3228{
bbb322f2
SW
3229 struct route_entry *re = NULL;
3230 struct nexthop *nexthop = NULL;
0eb97b86 3231 struct nexthop_group *ng = NULL;
718e3744 3232
66af6845 3233 /* Allocate new route_entry structure. */
d62a17ae 3234 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
d62a17ae 3235 re->type = type;
3236 re->instance = instance;
3237 re->distance = distance;
3238 re->flags = flags;
3239 re->metric = metric;
3240 re->mtu = mtu;
3241 re->table = table_id;
3242 re->vrf_id = vrf_id;
98572489 3243 re->uptime = monotime(NULL);
4e40b6d6 3244 re->tag = tag;
bbb322f2
SW
3245 re->nhe_id = nhe_id;
3246
0eb97b86
MS
3247 /* If the owner of the route supplies a shared nexthop-group id,
3248 * we'll use that. Otherwise, pass the nexthop along directly.
3249 */
e22e8001 3250 if (!nhe_id) {
0eb97b86 3251 ng = nexthop_group_new();
d62a17ae 3252
e22e8001
SW
3253 /* Add nexthop. */
3254 nexthop = nexthop_new();
3255 *nexthop = *nh;
0eb97b86 3256 nexthop_group_add_sorted(ng, nexthop);
e22e8001 3257 }
718e3744 3258
0eb97b86 3259 return rib_add_multipath(afi, safi, p, src_p, re, ng);
718e3744 3260}
3261
91e6f25b 3262static const char *rib_update_event2str(enum rib_update_event event)
2a99ab95
SW
3263{
3264 const char *ret = "UNKNOWN";
3265
3266 switch (event) {
3267 case RIB_UPDATE_KERNEL:
3268 ret = "RIB_UPDATE_KERNEL";
3269 break;
3270 case RIB_UPDATE_RMAP_CHANGE:
3271 ret = "RIB_UPDATE_RMAP_CHANGE";
3272 break;
3273 case RIB_UPDATE_OTHER:
3274 ret = "RIB_UPDATE_OTHER";
3275 break;
3276 case RIB_UPDATE_MAX:
3277 break;
3278 }
3279
3280 return ret;
3281}
3282
3283
3284/* Schedule route nodes to be processed if they match the type */
3285static void rib_update_route_node(struct route_node *rn, int type)
3286{
3287 struct route_entry *re, *next;
3288 bool re_changed = false;
3289
3290 RNODE_FOREACH_RE_SAFE (rn, re, next) {
3291 if (type == ZEBRA_ROUTE_ALL || type == re->type) {
3292 SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
3293 re_changed = true;
3294 }
3295 }
3296
3297 if (re_changed)
3298 rib_queue_add(rn);
3299}
3300
1c848137 3301/* Schedule routes of a particular table (address-family) based on event. */
91e6f25b 3302void rib_update_table(struct route_table *table, enum rib_update_event event)
d62a17ae 3303{
3304 struct route_node *rn;
2a99ab95
SW
3305
3306 if (IS_ZEBRA_DEBUG_EVENT) {
3307 struct zebra_vrf *zvrf;
3308 struct vrf *vrf;
3309
630d5962
DS
3310 zvrf = table->info
3311 ? ((struct rib_table_info *)table->info)->zvrf
3312 : NULL;
2a99ab95
SW
3313 vrf = zvrf ? zvrf->vrf : NULL;
3314
3315 zlog_debug("%s: %s VRF %s Table %u event %s", __func__,
3316 table->info ? afi2str(
630d5962 3317 ((struct rib_table_info *)table->info)->afi)
2a99ab95 3318 : "Unknown",
bd47f3a3 3319 VRF_LOGNAME(vrf), zvrf ? zvrf->table_id : 0,
2a99ab95
SW
3320 rib_update_event2str(event));
3321 }
d62a17ae 3322
3323 /* Walk all routes and queue for processing, if appropriate for
3324 * the trigger event.
3325 */
3326 for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
1ca60f2c
DS
3327 /*
3328 * If we are looking at a route node and the node
3329 * has already been queued we don't
3330 * need to queue it up again
3331 */
2a99ab95
SW
3332 if (rn->info
3333 && CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
3334 RIB_ROUTE_ANY_QUEUED))
1ca60f2c 3335 continue;
2a99ab95 3336
d62a17ae 3337 switch (event) {
2a99ab95
SW
3338 case RIB_UPDATE_KERNEL:
3339 rib_update_route_node(rn, ZEBRA_ROUTE_KERNEL);
3340 break;
d62a17ae 3341 case RIB_UPDATE_RMAP_CHANGE:
3342 case RIB_UPDATE_OTHER:
2a99ab95 3343 rib_update_route_node(rn, ZEBRA_ROUTE_ALL);
d62a17ae 3344 break;
d62a17ae 3345 default:
3346 break;
3347 }
3348 }
b84c7253 3349}
3350
91e6f25b 3351static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event)
718e3744 3352{
d62a17ae 3353 struct route_table *table;
1c848137 3354
2a99ab95
SW
3355 if (IS_ZEBRA_DEBUG_EVENT)
3356 zlog_debug("%s: Handling VRF %s event %s", __func__,
3357 vrf_id_to_name(vrf_id), rib_update_event2str(event));
3358
d62a17ae 3359 /* Process routes of interested address-families. */
3360 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
2a99ab95 3361 if (table)
d62a17ae 3362 rib_update_table(table, event);
718e3744 3363
d62a17ae 3364 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
2a99ab95 3365 if (table)
d62a17ae 3366 rib_update_table(table, event);
2a99ab95
SW
3367}
3368
91e6f25b 3369static void rib_update_handle_vrf_all(enum rib_update_event event)
2a99ab95
SW
3370{
3371 struct zebra_router_table *zrt;
3372
3373 if (IS_ZEBRA_DEBUG_EVENT)
3374 zlog_debug("%s: Handling VRF (ALL) event %s", __func__,
3375 rib_update_event2str(event));
3376
3377 /* Just iterate over all the route tables, rather than vrf lookups */
3378 RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables)
3379 rib_update_table(zrt->table, event);
3380}
3381
3382struct rib_update_ctx {
91e6f25b 3383 enum rib_update_event event;
2a99ab95
SW
3384 bool vrf_all;
3385 vrf_id_t vrf_id;
3386};
3387
3388static struct rib_update_ctx *rib_update_ctx_init(vrf_id_t vrf_id,
91e6f25b 3389 enum rib_update_event event)
2a99ab95
SW
3390{
3391 struct rib_update_ctx *ctx;
3392
3393 ctx = XCALLOC(MTYPE_RIB_UPDATE_CTX, sizeof(struct rib_update_ctx));
3394
3395 ctx->event = event;
3396 ctx->vrf_id = vrf_id;
3397
3398 return ctx;
3399}
3400
3401static void rib_update_ctx_fini(struct rib_update_ctx **ctx)
3402{
3403 XFREE(MTYPE_RIB_UPDATE_CTX, *ctx);
2a99ab95
SW
3404}
3405
3406static int rib_update_handler(struct thread *thread)
3407{
3408 struct rib_update_ctx *ctx;
3409
3410 ctx = THREAD_ARG(thread);
3411
3412 if (ctx->vrf_all)
3413 rib_update_handle_vrf_all(ctx->event);
3414 else
3415 rib_update_handle_vrf(ctx->vrf_id, ctx->event);
3416
3417 rib_update_ctx_fini(&ctx);
3418
3419 return 0;
3420}
3421
3422/*
3423 * Thread list to ensure we don't schedule a ton of events
3424 * if interfaces are flapping for instance.
3425 */
3426static struct thread *t_rib_update_threads[RIB_UPDATE_MAX];
3427
3428/* Schedule a RIB update event for specific vrf */
91e6f25b 3429void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event)
2a99ab95
SW
3430{
3431 struct rib_update_ctx *ctx;
3432
3433 ctx = rib_update_ctx_init(vrf_id, event);
3434
3435 /* Don't worry about making sure multiple rib updates for specific vrf
3436 * are scheduled at once for now. If it becomes a problem, we can use a
3437 * lookup of some sort to keep track of running threads via t_vrf_id
3438 * like how we are doing it in t_rib_update_threads[].
3439 */
3440 thread_add_event(zrouter.master, rib_update_handler, ctx, 0, NULL);
3441
3442 if (IS_ZEBRA_DEBUG_EVENT)
3443 zlog_debug("%s: Scheduled VRF %s, event %s", __func__,
3444 vrf_id_to_name(ctx->vrf_id),
3445 rib_update_event2str(event));
3446}
3447
3448/* Schedule a RIB update event for all vrfs */
91e6f25b 3449void rib_update(enum rib_update_event event)
2a99ab95
SW
3450{
3451 struct rib_update_ctx *ctx;
3452
3453 ctx = rib_update_ctx_init(0, event);
3454
3455 ctx->vrf_all = true;
3456
3457 if (!thread_add_event(zrouter.master, rib_update_handler, ctx, 0,
3458 &t_rib_update_threads[event]))
3459 rib_update_ctx_fini(&ctx); /* Already scheduled */
3460 else if (IS_ZEBRA_DEBUG_EVENT)
05267678 3461 zlog_debug("%s: Scheduled VRF (ALL), event %s", __func__,
2a99ab95 3462 rib_update_event2str(event));
718e3744 3463}
3464
718e3744 3465/* Delete self installed routes after zebra is relaunched. */
95a29032 3466void rib_sweep_table(struct route_table *table)
d62a17ae 3467{
3468 struct route_node *rn;
3469 struct route_entry *re;
3470 struct route_entry *next;
915902cb 3471 struct nexthop *nexthop;
d62a17ae 3472
915902cb
DS
3473 if (!table)
3474 return;
d62a17ae 3475
6d81b590
MS
3476 if (IS_ZEBRA_DEBUG_RIB)
3477 zlog_debug("%s: starting", __func__);
3478
915902cb 3479 for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
a2addae8 3480 RNODE_FOREACH_RE_SAFE (rn, re, next) {
d4644d41 3481
915902cb
DS
3482 if (IS_ZEBRA_DEBUG_RIB)
3483 route_entry_dump(&rn->p, NULL, re);
3484
3485 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
3486 continue;
3487
3488 if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
3489 continue;
3490
d4644d41
DS
3491 /*
3492 * If routes are older than startup_time then
3493 * we know we read them in from the kernel.
3494 * As such we can safely remove them.
3495 */
3496 if (zrouter.startup_time < re->uptime)
3497 continue;
3498
915902cb
DS
3499 /*
3500 * So we are starting up and have received
3501 * routes from the kernel that we have installed
3502 * from a previous run of zebra but not cleaned
3503 * up ( say a kill -9 )
3504 * But since we haven't actually installed
3505 * them yet( we received them from the kernel )
3506 * we don't think they are active.
3507 * So let's pretend they are active to actually
3508 * remove them.
3509 * In all honesty I'm not sure if we should
3510 * mark them as active when we receive them
3511 * This is startup only so probably ok.
3512 *
3513 * If we ever decide to move rib_sweep_table
3514 * to a different spot (ie startup )
3515 * this decision needs to be revisited
3516 */
677c1dd5 3517 SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
c415d895 3518 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
915902cb
DS
3519 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
3520
0c555cc6
DS
3521 rib_uninstall_kernel(rn, re);
3522 rib_delnode(rn, re);
915902cb
DS
3523 }
3524 }
6d81b590
MS
3525
3526 if (IS_ZEBRA_DEBUG_RIB)
3527 zlog_debug("%s: ends", __func__);
718e3744 3528}
3529
3530/* Sweep all RIB tables. */
d4644d41 3531int rib_sweep_route(struct thread *t)
718e3744 3532{
d62a17ae 3533 struct vrf *vrf;
3534 struct zebra_vrf *zvrf;
78104b9b 3535
a2addae8 3536 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
915902cb
DS
3537 if ((zvrf = vrf->info) == NULL)
3538 continue;
3539
d62a17ae 3540 rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]);
3541 rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]);
3542 }
95a29032 3543
89272910 3544 zebra_router_sweep_route();
38e40db1 3545 zebra_router_sweep_nhgs();
d4644d41
DS
3546
3547 return 0;
718e3744 3548}
2ea1ab1c
VT
3549
3550/* Remove specific by protocol routes from 'table'. */
d7c0a89a 3551unsigned long rib_score_proto_table(uint8_t proto, unsigned short instance,
47a08aa9 3552 struct route_table *table)
d62a17ae 3553{
3554 struct route_node *rn;
3555 struct route_entry *re;
3556 struct route_entry *next;
3557 unsigned long n = 0;
3558
3559 if (table)
3560 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
a2addae8 3561 RNODE_FOREACH_RE_SAFE (rn, re, next) {
d62a17ae 3562 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
3563 continue;
3564 if (re->type == proto
3565 && re->instance == instance) {
3566 rib_delnode(rn, re);
3567 n++;
3568 }
3569 }
3570 return n;
2ea1ab1c
VT
3571}
3572
3573/* Remove specific by protocol routes. */
d7c0a89a 3574unsigned long rib_score_proto(uint8_t proto, unsigned short instance)
2ea1ab1c 3575{
d62a17ae 3576 struct vrf *vrf;
3577 struct zebra_vrf *zvrf;
d8612e65 3578 struct other_route_table *ort;
d62a17ae 3579 unsigned long cnt = 0;
78104b9b 3580
d8612e65
DS
3581 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
3582 zvrf = vrf->info;
3583 if (!zvrf)
3584 continue;
78104b9b 3585
d8612e65
DS
3586 cnt += rib_score_proto_table(proto, instance,
3587 zvrf->table[AFI_IP][SAFI_UNICAST])
3588 + rib_score_proto_table(
3589 proto, instance,
3590 zvrf->table[AFI_IP6][SAFI_UNICAST]);
3591
81fddbe7 3592 frr_each(otable, &zvrf->other_tables, ort) cnt +=
d8612e65
DS
3593 rib_score_proto_table(proto, instance, ort->table);
3594 }
47a08aa9 3595
d62a17ae 3596 return cnt;
2ea1ab1c
VT
3597}
3598
718e3744 3599/* Close RIB and clean up kernel routes. */
d62a17ae 3600void rib_close_table(struct route_table *table)
718e3744 3601{
d62a17ae 3602 struct route_node *rn;
630d5962 3603 struct rib_table_info *info;
5f7a4718 3604 rib_dest_t *dest;
718e3744 3605
1e9f448f
DS
3606 if (!table)
3607 return;
9fd92e3c 3608
6ca30e9e 3609 info = route_table_get_info(table);
5adc2528 3610
5f7a4718
DS
3611 for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
3612 dest = rib_dest_from_rnode(rn);
1e9f448f 3613
5f7a4718 3614 if (dest && dest->selected_fib) {
1e9f448f
DS
3615 if (info->safi == SAFI_UNICAST)
3616 hook_call(rib_update, rn, NULL);
3617
3cdba47a
DS
3618 rib_uninstall_kernel(rn, dest->selected_fib);
3619 dest->selected_fib = NULL;
1e9f448f 3620 }
5f7a4718 3621 }
718e3744 3622}
3623
9bd9717b
MS
3624/*
3625 * Handler for async dataplane results after a pseudowire installation
3626 */
3627static int handle_pw_result(struct zebra_dplane_ctx *ctx)
3628{
9bd9717b
MS
3629 struct zebra_pw *pw;
3630 struct zebra_vrf *vrf;
3631
3632 /* The pseudowire code assumes success - we act on an error
3633 * result for installation attempts here.
3634 */
3635 if (dplane_ctx_get_op(ctx) != DPLANE_OP_PW_INSTALL)
3636 goto done;
3637
3638 if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
3639 vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
7c7ef4a8 3640 pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
9bd9717b 3641 if (pw)
fd563cc7
KS
3642 zebra_pw_install_failure(pw,
3643 dplane_ctx_get_pw_status(ctx));
9bd9717b
MS
3644 }
3645
3646done:
3647
9f2d0354 3648 return 0;
9bd9717b
MS
3649}
3650
3651
7cdb1a84 3652/*
d37f4d6c
MS
3653 * Handle results from the dataplane system. Dequeue update context
3654 * structs, dispatch to appropriate internal handlers.
7cdb1a84
MS
3655 */
3656static int rib_process_dplane_results(struct thread *thread)
3657{
25779064 3658 struct zebra_dplane_ctx *ctx;
4c206c8f 3659 struct dplane_ctx_q ctxlist;
2fc69f03 3660 bool shut_p = false;
4c206c8f
MS
3661
3662 /* Dequeue a list of completed updates with one lock/unlock cycle */
7cdb1a84
MS
3663
3664 do {
4c206c8f
MS
3665 TAILQ_INIT(&ctxlist);
3666
7cdb1a84 3667 /* Take lock controlling queue of results */
00dffa8c 3668 frr_with_mutex(&dplane_mutex) {
d37f4d6c 3669 /* Dequeue list of context structs */
4c206c8f 3670 dplane_ctx_list_append(&ctxlist, &rib_dplane_q);
7cdb1a84 3671 }
7cdb1a84 3672
4c206c8f
MS
3673 /* Dequeue context block */
3674 ctx = dplane_ctx_dequeue(&ctxlist);
3675
3676 /* If we've emptied the results queue, we're done */
3677 if (ctx == NULL)
7cdb1a84 3678 break;
7cdb1a84 3679
2fc69f03
MS
3680 /* If zebra is shutting down, avoid processing results,
3681 * just drain the results queue.
3682 */
3683 shut_p = atomic_load_explicit(&zrouter.in_shutdown,
3684 memory_order_relaxed);
3685 if (shut_p) {
3686 while (ctx) {
3687 dplane_ctx_fini(&ctx);
3688
3689 ctx = dplane_ctx_dequeue(&ctxlist);
3690 }
3691
3692 continue;
3693 }
3694
4c206c8f 3695 while (ctx) {
d37f4d6c
MS
3696 switch (dplane_ctx_get_op(ctx)) {
3697 case DPLANE_OP_ROUTE_INSTALL:
3698 case DPLANE_OP_ROUTE_UPDATE:
3699 case DPLANE_OP_ROUTE_DELETE:
188a00e0
MS
3700 {
3701 /* Bit of special case for route updates
3702 * that were generated by async notifications:
3703 * we don't want to continue processing these
3704 * in the rib.
3705 */
3706 if (dplane_ctx_get_notif_provider(ctx) == 0)
3707 rib_process_result(ctx);
3708 else
3709 dplane_ctx_fini(&ctx);
3710 }
3711 break;
d37f4d6c 3712
54818e3b
MS
3713 case DPLANE_OP_ROUTE_NOTIFY:
3714 rib_process_dplane_notify(ctx);
d37f4d6c
MS
3715 break;
3716
9865e1c3
SW
3717 case DPLANE_OP_NH_INSTALL:
3718 case DPLANE_OP_NH_UPDATE:
3719 case DPLANE_OP_NH_DELETE:
3720 zebra_nhg_dplane_result(ctx);
3721 break;
3722
d37f4d6c
MS
3723 case DPLANE_OP_LSP_INSTALL:
3724 case DPLANE_OP_LSP_UPDATE:
3725 case DPLANE_OP_LSP_DELETE:
188a00e0
MS
3726 {
3727 /* Bit of special case for LSP updates
3728 * that were generated by async notifications:
3729 * we don't want to continue processing these.
3730 */
3731 if (dplane_ctx_get_notif_provider(ctx) == 0)
3732 zebra_mpls_lsp_dplane_result(ctx);
3733 else
3734 dplane_ctx_fini(&ctx);
3735 }
3736 break;
d37f4d6c 3737
104e3ad9
MS
3738 case DPLANE_OP_LSP_NOTIFY:
3739 zebra_mpls_process_dplane_notify(ctx);
d37f4d6c
MS
3740 break;
3741
9bd9717b
MS
3742 case DPLANE_OP_PW_INSTALL:
3743 case DPLANE_OP_PW_UNINSTALL:
3744 handle_pw_result(ctx);
3745 break;
3746
cf363e1b
MS
3747 case DPLANE_OP_SYS_ROUTE_ADD:
3748 case DPLANE_OP_SYS_ROUTE_DELETE:
3749 /* No further processing in zebra for these. */
3750 dplane_ctx_fini(&ctx);
3751 break;
3752
036d93c0
MS
3753 case DPLANE_OP_MAC_INSTALL:
3754 case DPLANE_OP_MAC_DELETE:
3755 zebra_vxlan_handle_result(ctx);
3756 break;
3757
f62e5480
JU
3758 case DPLANE_OP_RULE_ADD:
3759 case DPLANE_OP_RULE_DELETE:
3760 case DPLANE_OP_RULE_UPDATE:
3761 zebra_pbr_dplane_result(ctx);
3762 break;
3763
931fa60c
MS
3764 /* Some op codes not handled here */
3765 case DPLANE_OP_ADDR_INSTALL:
3766 case DPLANE_OP_ADDR_UNINSTALL:
3767 case DPLANE_OP_NEIGH_INSTALL:
3768 case DPLANE_OP_NEIGH_UPDATE:
3769 case DPLANE_OP_NEIGH_DELETE:
0bbd4ff4
MS
3770 case DPLANE_OP_VTEP_ADD:
3771 case DPLANE_OP_VTEP_DELETE:
931fa60c 3772 case DPLANE_OP_NONE:
d37f4d6c
MS
3773 /* Don't expect this: just return the struct? */
3774 dplane_ctx_fini(&ctx);
3775 break;
931fa60c 3776
d37f4d6c 3777 } /* Dispatch by op code */
4c206c8f
MS
3778
3779 ctx = dplane_ctx_dequeue(&ctxlist);
3780 }
3781
5709131c 3782 } while (1);
7cdb1a84 3783
5709131c 3784 return 0;
7cdb1a84
MS
3785}
3786
3787/*
3788 * Results are returned from the dataplane subsystem, in the context of
1bcea841 3789 * the dataplane pthread. We enqueue the results here for processing by
7cdb1a84
MS
3790 * the main thread later.
3791 */
4c206c8f 3792static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
7cdb1a84
MS
3793{
3794 /* Take lock controlling queue of results */
00dffa8c 3795 frr_with_mutex(&dplane_mutex) {
4c206c8f
MS
3796 /* Enqueue context blocks */
3797 dplane_ctx_list_append(&rib_dplane_q, ctxlist);
7cdb1a84 3798 }
7cdb1a84 3799
4c206c8f 3800 /* Ensure event is signalled to zebra main pthread */
3801e764 3801 thread_add_event(zrouter.master, rib_process_dplane_results, NULL, 0,
7cdb1a84
MS
3802 &t_dplane);
3803
5709131c 3804 return 0;
7cdb1a84
MS
3805}
3806
eaa2716d
SW
3807/*
3808 * Ensure there are no empty slots in the route_info array.
3809 * Every route type in zebra should be present there.
3810 */
3811static void check_route_info(void)
3812{
3813 int len = array_size(route_info);
3814
3815 /*
3816 * ZEBRA_ROUTE_SYSTEM is special cased since
3817 * its key is 0 anyway.
3818 *
3819 * ZEBRA_ROUTE_ALL is also ignored.
3820 */
3821 for (int i = 0; i < len; i++) {
3822 if (i == ZEBRA_ROUTE_SYSTEM || i == ZEBRA_ROUTE_ALL)
3823 continue;
3824 assert(route_info[i].key);
8dc7a759 3825 assert(route_info[i].meta_q_map < MQ_SIZE);
eaa2716d
SW
3826 }
3827}
3828
718e3744 3829/* Routing information base initialize. */
d62a17ae 3830void rib_init(void)
718e3744 3831{
eaa2716d
SW
3832 check_route_info();
3833
2561d12e 3834 rib_queue_init();
7cdb1a84
MS
3835
3836 /* Init dataplane, and register for results */
3837 pthread_mutex_init(&dplane_mutex, NULL);
3838 TAILQ_INIT(&rib_dplane_q);
4c206c8f 3839 zebra_dplane_init(rib_dplane_results);
718e3744 3840}
0915bb0c
AS
3841
3842/*
3843 * vrf_id_get_next
3844 *
3845 * Get the first vrf id that is greater than the given vrf id if any.
3846 *
2951a7a4 3847 * Returns true if a vrf id was found, false otherwise.
0915bb0c 3848 */
d62a17ae 3849static inline int vrf_id_get_next(vrf_id_t vrf_id, vrf_id_t *next_id_p)
0915bb0c 3850{
d62a17ae 3851 struct vrf *vrf;
b72ede27 3852
d62a17ae 3853 vrf = vrf_lookup_by_id(vrf_id);
3854 if (vrf) {
3855 vrf = RB_NEXT(vrf_id_head, vrf);
3856 if (vrf) {
3857 *next_id_p = vrf->vrf_id;
3858 return 1;
3859 }
3860 }
0915bb0c 3861
d62a17ae 3862 return 0;
0915bb0c
AS
3863}
3864
3865/*
3866 * rib_tables_iter_next
3867 *
3868 * Returns the next table in the iteration.
3869 */
d62a17ae 3870struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter)
3871{
3872 struct route_table *table;
3873
3874 /*
3875 * Array that helps us go over all AFI/SAFI combinations via one
3876 * index.
3877 */
2b64873d 3878 static const struct {
d62a17ae 3879 afi_t afi;
3880 safi_t safi;
3881 } afi_safis[] = {
3882 {AFI_IP, SAFI_UNICAST}, {AFI_IP, SAFI_MULTICAST},
3883 {AFI_IP, SAFI_LABELED_UNICAST}, {AFI_IP6, SAFI_UNICAST},
3884 {AFI_IP6, SAFI_MULTICAST}, {AFI_IP6, SAFI_LABELED_UNICAST},
3885 };
3886
3887 table = NULL;
3888
3889 switch (iter->state) {
3890
3891 case RIB_TABLES_ITER_S_INIT:
3892 iter->vrf_id = VRF_DEFAULT;
3893 iter->afi_safi_ix = -1;
3894
3895 /* Fall through */
3896
3897 case RIB_TABLES_ITER_S_ITERATING:
3898 iter->afi_safi_ix++;
3899 while (1) {
3900
3901 while (iter->afi_safi_ix
7e3a1ec7 3902 < (int)array_size(afi_safis)) {
d62a17ae 3903 table = zebra_vrf_table(
3904 afi_safis[iter->afi_safi_ix].afi,
3905 afi_safis[iter->afi_safi_ix].safi,
3906 iter->vrf_id);
3907 if (table)
3908 break;
3909
3910 iter->afi_safi_ix++;
3911 }
3912
3913 /*
3914 * Found another table in this vrf.
3915 */
3916 if (table)
3917 break;
3918
3919 /*
3920 * Done with all tables in the current vrf, go to the
3921 * next
3922 * one.
3923 */
3924 if (!vrf_id_get_next(iter->vrf_id, &iter->vrf_id))
3925 break;
3926
3927 iter->afi_safi_ix = 0;
3928 }
0915bb0c 3929
0915bb0c
AS
3930 break;
3931
d62a17ae 3932 case RIB_TABLES_ITER_S_DONE:
3933 return NULL;
0915bb0c
AS
3934 }
3935
d62a17ae 3936 if (table)
3937 iter->state = RIB_TABLES_ITER_S_ITERATING;
3938 else
3939 iter->state = RIB_TABLES_ITER_S_DONE;
0915bb0c 3940
d62a17ae 3941 return table;
0915bb0c 3942}