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