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