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