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