Coverage Report

Created: 2026-04-27 06:43

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