Coverage Report

Created: 2026-01-21 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_route.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* BGP routing information
3
 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4
 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5
 */
6
7
#include <zebra.h>
8
#include <math.h>
9
10
#include "printfrr.h"
11
#include "frrstr.h"
12
#include "prefix.h"
13
#include "linklist.h"
14
#include "memory.h"
15
#include "command.h"
16
#include "stream.h"
17
#include "filter.h"
18
#include "log.h"
19
#include "routemap.h"
20
#include "buffer.h"
21
#include "sockunion.h"
22
#include "plist.h"
23
#include "frrevent.h"
24
#include "workqueue.h"
25
#include "queue.h"
26
#include "memory.h"
27
#include "srv6.h"
28
#include "lib/json.h"
29
#include "lib_errors.h"
30
#include "zclient.h"
31
#include "bgpd/bgpd.h"
32
#include "bgpd/bgp_table.h"
33
#include "bgpd/bgp_route.h"
34
#include "bgpd/bgp_attr.h"
35
#include "bgpd/bgp_debug.h"
36
#include "bgpd/bgp_errors.h"
37
#include "bgpd/bgp_aspath.h"
38
#include "bgpd/bgp_regex.h"
39
#include "bgpd/bgp_community.h"
40
#include "bgpd/bgp_community_alias.h"
41
#include "bgpd/bgp_ecommunity.h"
42
#include "bgpd/bgp_lcommunity.h"
43
#include "bgpd/bgp_clist.h"
44
#include "bgpd/bgp_packet.h"
45
#include "bgpd/bgp_filter.h"
46
#include "bgpd/bgp_fsm.h"
47
#include "bgpd/bgp_mplsvpn.h"
48
#include "bgpd/bgp_nexthop.h"
49
#include "bgpd/bgp_damp.h"
50
#include "bgpd/bgp_advertise.h"
51
#include "bgpd/bgp_zebra.h"
52
#include "bgpd/bgp_vty.h"
53
#include "bgpd/bgp_mpath.h"
54
#include "bgpd/bgp_nht.h"
55
#include "bgpd/bgp_updgrp.h"
56
#include "bgpd/bgp_label.h"
57
#include "bgpd/bgp_addpath.h"
58
#include "bgpd/bgp_mac.h"
59
#include "bgpd/bgp_network.h"
60
#include "bgpd/bgp_trace.h"
61
#include "bgpd/bgp_rpki.h"
62
63
#ifdef ENABLE_BGP_VNC
64
#include "bgpd/rfapi/rfapi_backend.h"
65
#include "bgpd/rfapi/vnc_import_bgp.h"
66
#include "bgpd/rfapi/vnc_export_bgp.h"
67
#endif
68
#include "bgpd/bgp_encap_types.h"
69
#include "bgpd/bgp_encap_tlv.h"
70
#include "bgpd/bgp_evpn.h"
71
#include "bgpd/bgp_evpn_mh.h"
72
#include "bgpd/bgp_evpn_vty.h"
73
#include "bgpd/bgp_flowspec.h"
74
#include "bgpd/bgp_flowspec_util.h"
75
#include "bgpd/bgp_pbr.h"
76
77
#include "bgpd/bgp_route_clippy.c"
78
79
DEFINE_HOOK(bgp_snmp_update_stats,
80
      (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
81
      (rn, pi, added));
82
83
DEFINE_HOOK(bgp_rpki_prefix_status,
84
      (struct peer *peer, struct attr *attr,
85
       const struct prefix *prefix),
86
      (peer, attr, prefix));
87
88
/* Extern from bgp_dump.c */
89
extern const char *bgp_origin_str[];
90
extern const char *bgp_origin_long_str[];
91
92
/* PMSI strings. */
93
0
#define PMSI_TNLTYPE_STR_NO_INFO "No info"
94
0
#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95
static const struct message bgp_pmsi_tnltype_str[] = {
96
  {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
97
  {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
98
  {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
99
  {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
100
  {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
101
  {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
102
  {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
103
  {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
104
  {0}
105
};
106
107
0
#define VRFID_NONE_STR "-"
108
#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
109
110
DEFINE_HOOK(bgp_process,
111
      (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
112
       struct peer *peer, bool withdraw),
113
      (bgp, afi, safi, bn, peer, withdraw));
114
115
/** Test if path is suppressed. */
116
static bool bgp_path_suppressed(struct bgp_path_info *pi)
117
0
{
118
0
  if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
119
0
    return false;
120
121
0
  return listcount(pi->extra->aggr_suppressors) > 0;
122
0
}
123
124
struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
125
          safi_t safi, const struct prefix *p,
126
          struct prefix_rd *prd)
127
3.11k
{
128
3.11k
  struct bgp_dest *dest;
129
3.11k
  struct bgp_dest *pdest = NULL;
130
131
3.11k
  assert(table);
132
133
3.11k
  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
134
3.00k
      || (safi == SAFI_EVPN)) {
135
404
    pdest = bgp_node_get(table, (struct prefix *)prd);
136
137
404
    if (!bgp_dest_has_bgp_path_info_data(pdest))
138
315
      bgp_dest_set_bgp_table_info(
139
315
        pdest, bgp_table_init(table->bgp, afi, safi));
140
89
    else
141
89
      bgp_dest_unlock_node(pdest);
142
404
    table = bgp_dest_get_bgp_table_info(pdest);
143
404
  }
144
145
3.11k
  dest = bgp_node_get(table, p);
146
147
3.11k
  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
148
3.00k
      || (safi == SAFI_EVPN))
149
404
    dest->pdest = pdest;
150
151
3.11k
  return dest;
152
3.11k
}
153
154
struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table, safi_t safi,
155
              const struct prefix *p,
156
              struct prefix_rd *prd)
157
0
{
158
0
  struct bgp_dest *dest;
159
0
  struct bgp_dest *pdest = NULL;
160
161
0
  if (!table)
162
0
    return NULL;
163
164
0
  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
165
0
      || (safi == SAFI_EVPN)) {
166
0
    pdest = bgp_node_lookup(table, (struct prefix *)prd);
167
0
    if (!pdest)
168
0
      return NULL;
169
170
0
    if (!bgp_dest_has_bgp_path_info_data(pdest)) {
171
0
      bgp_dest_unlock_node(pdest);
172
0
      return NULL;
173
0
    }
174
175
0
    table = bgp_dest_get_bgp_table_info(pdest);
176
0
  }
177
178
0
  dest = bgp_node_lookup(table, p);
179
180
0
  return dest;
181
0
}
182
183
/* Allocate bgp_path_info_extra */
184
static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
185
0
{
186
0
  struct bgp_path_info_extra *new;
187
0
  new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
188
0
          sizeof(struct bgp_path_info_extra));
189
0
  new->label[0] = MPLS_INVALID_LABEL;
190
0
  new->num_labels = 0;
191
0
  new->bgp_fs_pbr = NULL;
192
0
  new->bgp_fs_iprule = NULL;
193
0
  return new;
194
0
}
195
196
void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
197
0
{
198
0
  struct bgp_path_info_extra *e;
199
200
0
  if (!extra || !*extra)
201
0
    return;
202
203
0
  e = *extra;
204
0
  if (e->damp_info)
205
0
    bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
206
0
           e->damp_info->safi);
207
208
0
  e->damp_info = NULL;
209
0
  if (e->parent) {
210
0
    struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
211
212
0
    if (bpi->net) {
213
      /* FIXME: since multiple e may have the same e->parent
214
       * and e->parent->net is holding a refcount for each
215
       * of them, we need to do some fudging here.
216
       *
217
       * WARNING: if bpi->net->lock drops to 0, bpi may be
218
       * freed as well (because bpi->net was holding the
219
       * last reference to bpi) => write after free!
220
       */
221
0
      unsigned refcount;
222
223
0
      bpi = bgp_path_info_lock(bpi);
224
0
      refcount = bgp_dest_get_lock_count(bpi->net) - 1;
225
0
      bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
226
0
      if (!refcount)
227
0
        bpi->net = NULL;
228
0
      bgp_path_info_unlock(bpi);
229
0
    }
230
0
    bgp_path_info_unlock(e->parent);
231
0
    e->parent = NULL;
232
0
  }
233
234
0
  if (e->bgp_orig)
235
0
    bgp_unlock(e->bgp_orig);
236
237
0
  if (e->peer_orig)
238
0
    peer_unlock(e->peer_orig);
239
240
0
  if (e->aggr_suppressors)
241
0
    list_delete(&e->aggr_suppressors);
242
243
0
  if (e->mh_info)
244
0
    bgp_evpn_path_mh_info_free(e->mh_info);
245
246
0
  if ((*extra)->bgp_fs_iprule)
247
0
    list_delete(&((*extra)->bgp_fs_iprule));
248
0
  if ((*extra)->bgp_fs_pbr)
249
0
    list_delete(&((*extra)->bgp_fs_pbr));
250
0
  XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
251
0
}
252
253
/* Get bgp_path_info extra information for the given bgp_path_info, lazy
254
 * allocated if required.
255
 */
256
struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
257
0
{
258
0
  if (!pi->extra)
259
0
    pi->extra = bgp_path_info_extra_new();
260
0
  return pi->extra;
261
0
}
262
263
/* Free bgp route information. */
264
void bgp_path_info_free_with_caller(const char *name,
265
            struct bgp_path_info *path)
266
0
{
267
0
  frrtrace(2, frr_bgp, bgp_path_info_free, path, name);
268
0
  bgp_attr_unintern(&path->attr);
269
270
0
  bgp_unlink_nexthop(path);
271
0
  bgp_path_info_extra_free(&path->extra);
272
0
  bgp_path_info_mpath_free(&path->mpath);
273
0
  if (path->net)
274
0
    bgp_addpath_free_info_data(&path->tx_addpath,
275
0
             &path->net->tx_addpath);
276
277
0
  peer_unlock(path->peer); /* bgp_path_info peer reference */
278
279
0
  XFREE(MTYPE_BGP_ROUTE, path);
280
0
}
281
282
struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
283
0
{
284
0
  path->lock++;
285
0
  return path;
286
0
}
287
288
struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
289
0
{
290
0
  assert(path && path->lock > 0);
291
0
  path->lock--;
292
293
0
  if (path->lock == 0) {
294
0
    bgp_path_info_free(path);
295
0
    return NULL;
296
0
  }
297
298
0
  return path;
299
0
}
300
301
/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302
static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
303
0
{
304
0
  struct peer *peer;
305
0
  struct bgp_path_info *old_pi, *nextpi;
306
0
  bool set_flag = false;
307
0
  struct bgp *bgp = NULL;
308
0
  struct bgp_table *table = NULL;
309
0
  afi_t afi = 0;
310
0
  safi_t safi = 0;
311
312
  /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313
   * then the route selection is deferred
314
   */
315
0
  if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
316
0
    return 0;
317
318
0
  if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
319
0
    if (BGP_DEBUG(update, UPDATE_OUT)) {
320
0
      table = bgp_dest_table(dest);
321
0
      if (table)
322
0
        bgp = table->bgp;
323
324
0
      zlog_debug(
325
0
        "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326
0
        dest, bgp ? bgp->name_pretty : "(Unknown)");
327
0
    }
328
329
0
    return 0;
330
0
  }
331
332
0
  table = bgp_dest_table(dest);
333
0
  if (table) {
334
0
    bgp = table->bgp;
335
0
    afi = table->afi;
336
0
    safi = table->safi;
337
0
  }
338
339
0
  for (old_pi = bgp_dest_get_bgp_path_info(dest);
340
0
       (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
341
0
    if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
342
0
      continue;
343
344
    /* Route selection is deferred if there is a stale path which
345
     * which indicates peer is in restart mode
346
     */
347
0
    if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
348
0
        && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
349
0
      set_flag = true;
350
0
    } else {
351
      /* If the peer is graceful restart capable and peer is
352
       * restarting mode, set the flag BGP_NODE_SELECT_DEFER
353
       */
354
0
      peer = old_pi->peer;
355
0
      if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
356
0
          && BGP_PEER_RESTARTING_MODE(peer)
357
0
          && (old_pi
358
0
        && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
359
0
        set_flag = true;
360
0
      }
361
0
    }
362
0
    if (set_flag)
363
0
      break;
364
0
  }
365
366
  /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
367
   * is active
368
   */
369
0
  if (set_flag && table) {
370
0
    if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
371
0
      if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
372
0
        bgp->gr_info[afi][safi].gr_deferred++;
373
0
      SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
374
0
      if (BGP_DEBUG(update, UPDATE_OUT))
375
0
        zlog_debug("DEFER route %pBD(%s), dest %p",
376
0
             dest, bgp->name_pretty, dest);
377
0
      return 0;
378
0
    }
379
0
  }
380
0
  return -1;
381
0
}
382
383
void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
384
           struct bgp_path_info *pi)
385
0
{
386
0
  frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
387
0
  struct bgp_path_info *top;
388
389
0
  top = bgp_dest_get_bgp_path_info(dest);
390
391
0
  pi->next = top;
392
0
  pi->prev = NULL;
393
0
  if (top)
394
0
    top->prev = pi;
395
0
  bgp_dest_set_bgp_path_info(dest, pi);
396
397
0
  bgp_path_info_lock(pi);
398
0
  bgp_dest_lock_node(dest);
399
0
  peer_lock(pi->peer); /* bgp_path_info peer reference */
400
0
  bgp_dest_set_defer_flag(dest, false);
401
0
  hook_call(bgp_snmp_update_stats, dest, pi, true);
402
0
}
403
404
/* Do the actual removal of info from RIB, for use by bgp_process
405
   completion callback *only* */
406
void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
407
0
{
408
0
  if (pi->next)
409
0
    pi->next->prev = pi->prev;
410
0
  if (pi->prev)
411
0
    pi->prev->next = pi->next;
412
0
  else
413
0
    bgp_dest_set_bgp_path_info(dest, pi->next);
414
415
0
  bgp_path_info_mpath_dequeue(pi);
416
0
  bgp_path_info_unlock(pi);
417
0
  hook_call(bgp_snmp_update_stats, dest, pi, false);
418
0
  bgp_dest_unlock_node(dest);
419
0
}
420
421
void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
422
0
{
423
0
  bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
424
  /* set of previous already took care of pcount */
425
0
  UNSET_FLAG(pi->flags, BGP_PATH_VALID);
426
0
}
427
428
/* undo the effects of a previous call to bgp_path_info_delete; typically
429
   called when a route is deleted and then quickly re-added before the
430
   deletion has been processed */
431
void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
432
0
{
433
0
  bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
434
  /* unset of previous already took care of pcount */
435
0
  SET_FLAG(pi->flags, BGP_PATH_VALID);
436
0
}
437
438
/* Adjust pcount as required */
439
static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
440
0
{
441
0
  struct bgp_table *table;
442
443
0
  assert(dest && bgp_dest_table(dest));
444
0
  assert(pi && pi->peer && pi->peer->bgp);
445
446
0
  table = bgp_dest_table(dest);
447
448
0
  if (pi->peer == pi->peer->bgp->peer_self)
449
0
    return;
450
451
0
  if (!BGP_PATH_COUNTABLE(pi)
452
0
      && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
453
454
0
    UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
455
456
    /* slight hack, but more robust against errors. */
457
0
    if (pi->peer->pcount[table->afi][table->safi])
458
0
      pi->peer->pcount[table->afi][table->safi]--;
459
0
    else
460
0
      flog_err(EC_LIB_DEVELOPMENT,
461
0
         "Asked to decrement 0 prefix count for peer");
462
0
  } else if (BGP_PATH_COUNTABLE(pi)
463
0
       && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
464
0
    SET_FLAG(pi->flags, BGP_PATH_COUNTED);
465
0
    pi->peer->pcount[table->afi][table->safi]++;
466
0
  }
467
0
}
468
469
static int bgp_label_index_differs(struct bgp_path_info *pi1,
470
           struct bgp_path_info *pi2)
471
0
{
472
0
  return (!(pi1->attr->label_index == pi2->attr->label_index));
473
0
}
474
475
/* Set/unset bgp_path_info flags, adjusting any other state as needed.
476
 * This is here primarily to keep prefix-count in check.
477
 */
478
void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
479
          uint32_t flag)
480
0
{
481
0
  SET_FLAG(pi->flags, flag);
482
483
  /* early bath if we know it's not a flag that changes countability state
484
   */
485
0
  if (!CHECK_FLAG(flag,
486
0
      BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
487
0
    return;
488
489
0
  bgp_pcount_adjust(dest, pi);
490
0
}
491
492
void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
493
            uint32_t flag)
494
0
{
495
0
  UNSET_FLAG(pi->flags, flag);
496
497
  /* early bath if we know it's not a flag that changes countability state
498
   */
499
0
  if (!CHECK_FLAG(flag,
500
0
      BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
501
0
    return;
502
503
0
  bgp_pcount_adjust(dest, pi);
504
0
}
505
506
/* Get MED value.  If MED value is missing and "bgp bestpath
507
   missing-as-worst" is specified, treat it as the worst value. */
508
static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
509
0
{
510
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
511
0
    return attr->med;
512
0
  else {
513
0
    if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
514
0
      return BGP_MED_MAX;
515
0
    else
516
0
      return 0;
517
0
  }
518
0
}
519
520
void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
521
              size_t buf_len)
522
0
{
523
0
  struct peer *peer;
524
525
0
  if (pi->sub_type == BGP_ROUTE_IMPORTED &&
526
0
      bgp_get_imported_bpi_ultimate(pi))
527
0
    peer = bgp_get_imported_bpi_ultimate(pi)->peer;
528
0
  else
529
0
    peer = pi->peer;
530
531
0
  if (pi->addpath_rx_id)
532
0
    snprintf(buf, buf_len, "path %s (addpath rxid %d)", peer->host,
533
0
       pi->addpath_rx_id);
534
0
  else
535
0
    snprintf(buf, buf_len, "path %s", peer->host);
536
0
}
537
538
539
/*
540
 * Get the ultimate path info.
541
 */
542
struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
543
0
{
544
0
  struct bgp_path_info *bpi_ultimate;
545
546
0
  if (info->sub_type != BGP_ROUTE_IMPORTED)
547
0
    return info;
548
549
0
  for (bpi_ultimate = info;
550
0
       bpi_ultimate->extra && bpi_ultimate->extra->parent;
551
0
       bpi_ultimate = bpi_ultimate->extra->parent)
552
0
    ;
553
554
0
  return bpi_ultimate;
555
0
}
556
557
/* Compare two bgp route entity.  If 'new' is preferable over 'exist' return 1.
558
 */
559
static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
560
           struct bgp_path_info *exist, int *paths_eq,
561
           struct bgp_maxpaths_cfg *mpath_cfg, int debug,
562
           char *pfx_buf, afi_t afi, safi_t safi,
563
           enum bgp_path_selection_reason *reason)
564
0
{
565
0
  const struct prefix *new_p;
566
0
  struct attr *newattr, *existattr;
567
0
  enum bgp_peer_sort new_sort;
568
0
  enum bgp_peer_sort exist_sort;
569
0
  uint32_t new_pref;
570
0
  uint32_t exist_pref;
571
0
  uint32_t new_med;
572
0
  uint32_t exist_med;
573
0
  uint32_t new_weight;
574
0
  uint32_t exist_weight;
575
0
  uint32_t newm, existm;
576
0
  struct in_addr new_id;
577
0
  struct in_addr exist_id;
578
0
  int new_cluster;
579
0
  int exist_cluster;
580
0
  int internal_as_route;
581
0
  int confed_as_route;
582
0
  int ret = 0;
583
0
  int igp_metric_ret = 0;
584
0
  int peer_sort_ret = -1;
585
0
  char new_buf[PATH_ADDPATH_STR_BUFFER];
586
0
  char exist_buf[PATH_ADDPATH_STR_BUFFER];
587
0
  uint32_t new_mm_seq;
588
0
  uint32_t exist_mm_seq;
589
0
  int nh_cmp;
590
0
  esi_t *exist_esi;
591
0
  esi_t *new_esi;
592
0
  bool same_esi;
593
0
  bool old_proxy;
594
0
  bool new_proxy;
595
0
  bool new_origin, exist_origin;
596
0
  struct bgp_path_info *bpi_ultimate;
597
0
  struct peer *peer_new, *peer_exist;
598
599
0
  *paths_eq = 0;
600
601
  /* 0. Null check. */
602
0
  if (new == NULL) {
603
0
    *reason = bgp_path_selection_none;
604
0
    if (debug)
605
0
      zlog_debug("%s: new is NULL", pfx_buf);
606
0
    return 0;
607
0
  }
608
609
0
  if (debug) {
610
0
    bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611
0
    bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
612
0
                   sizeof(new_buf));
613
0
  }
614
615
0
  if (exist == NULL) {
616
0
    *reason = bgp_path_selection_first;
617
0
    if (debug)
618
0
      zlog_debug("%s(%s): %s is the initial bestpath",
619
0
           pfx_buf, bgp->name_pretty, new_buf);
620
0
    return 1;
621
0
  }
622
623
0
  if (debug) {
624
0
    bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625
0
    bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
626
0
                   sizeof(exist_buf));
627
0
    zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628
0
         pfx_buf, bgp->name_pretty, new_buf, new->flags,
629
0
         exist_buf, exist->flags);
630
0
  }
631
632
0
  newattr = new->attr;
633
0
  existattr = exist->attr;
634
635
  /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636
   * Capability" to a neighbor MUST perform the following upon receiving
637
   * a route from that neighbor with the "LLGR_STALE" community, or upon
638
   * attaching the "LLGR_STALE" community itself per Section 4.2:
639
   *
640
   * Treat the route as the least-preferred in route selection (see
641
   * below). See the Risks of Depreferencing Routes section (Section 5.2)
642
   * for a discussion of potential risks inherent in doing this.
643
   */
644
0
  if (bgp_attr_get_community(newattr) &&
645
0
      community_include(bgp_attr_get_community(newattr),
646
0
            COMMUNITY_LLGR_STALE)) {
647
0
    if (debug)
648
0
      zlog_debug(
649
0
        "%s: %s wins over %s due to LLGR_STALE community",
650
0
        pfx_buf, new_buf, exist_buf);
651
0
    return 0;
652
0
  }
653
654
0
  if (bgp_attr_get_community(existattr) &&
655
0
      community_include(bgp_attr_get_community(existattr),
656
0
            COMMUNITY_LLGR_STALE)) {
657
0
    if (debug)
658
0
      zlog_debug(
659
0
        "%s: %s loses to %s due to LLGR_STALE community",
660
0
        pfx_buf, new_buf, exist_buf);
661
0
    return 1;
662
0
  }
663
664
0
  new_p = bgp_dest_get_prefix(new->net);
665
666
  /* For EVPN routes, we cannot just go by local vs remote, we have to
667
   * look at the MAC mobility sequence number, if present.
668
   */
669
0
  if ((safi == SAFI_EVPN)
670
0
      && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
671
    /* This is an error condition described in RFC 7432 Section
672
     * 15.2. The RFC
673
     * states that in this scenario "the PE MUST alert the operator"
674
     * but it
675
     * does not state what other action to take. In order to provide
676
     * some
677
     * consistency in this scenario we are going to prefer the path
678
     * with the
679
     * sticky flag.
680
     */
681
0
    if (newattr->sticky != existattr->sticky) {
682
0
      if (!debug) {
683
0
        prefix2str(new_p, pfx_buf,
684
0
             sizeof(*pfx_buf)
685
0
               * PREFIX2STR_BUFFER);
686
0
        bgp_path_info_path_with_addpath_rx_str(
687
0
          new, new_buf, sizeof(new_buf));
688
0
        bgp_path_info_path_with_addpath_rx_str(
689
0
          exist, exist_buf, sizeof(exist_buf));
690
0
      }
691
692
0
      if (newattr->sticky && !existattr->sticky) {
693
0
        *reason = bgp_path_selection_evpn_sticky_mac;
694
0
        if (debug)
695
0
          zlog_debug(
696
0
            "%s: %s wins over %s due to sticky MAC flag",
697
0
            pfx_buf, new_buf, exist_buf);
698
0
        return 1;
699
0
      }
700
701
0
      if (!newattr->sticky && existattr->sticky) {
702
0
        *reason = bgp_path_selection_evpn_sticky_mac;
703
0
        if (debug)
704
0
          zlog_debug(
705
0
            "%s: %s loses to %s due to sticky MAC flag",
706
0
            pfx_buf, new_buf, exist_buf);
707
0
        return 0;
708
0
      }
709
0
    }
710
711
0
    new_esi = bgp_evpn_attr_get_esi(newattr);
712
0
    exist_esi = bgp_evpn_attr_get_esi(existattr);
713
0
    if (bgp_evpn_is_esi_valid(new_esi) &&
714
0
        !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715
0
      same_esi = true;
716
0
    } else {
717
0
      same_esi = false;
718
0
    }
719
720
    /* If both paths have the same non-zero ES and
721
     * one path is local it wins.
722
     * PS: Note the local path wins even if the remote
723
     * has the higher MM seq. The local path's
724
     * MM seq will be fixed up to match the highest
725
     * rem seq, subsequently.
726
     */
727
0
    if (same_esi) {
728
0
      char esi_buf[ESI_STR_LEN];
729
730
0
      if (bgp_evpn_is_path_local(bgp, new)) {
731
0
        *reason = bgp_path_selection_evpn_local_path;
732
0
        if (debug)
733
0
          zlog_debug(
734
0
            "%s: %s wins over %s as ES %s is same and local",
735
0
            pfx_buf, new_buf, exist_buf,
736
0
            esi_to_str(new_esi, esi_buf,
737
0
            sizeof(esi_buf)));
738
0
        return 1;
739
0
      }
740
0
      if (bgp_evpn_is_path_local(bgp, exist)) {
741
0
        *reason = bgp_path_selection_evpn_local_path;
742
0
        if (debug)
743
0
          zlog_debug(
744
0
            "%s: %s loses to %s as ES %s is same and local",
745
0
            pfx_buf, new_buf, exist_buf,
746
0
            esi_to_str(new_esi, esi_buf,
747
0
            sizeof(esi_buf)));
748
0
        return 0;
749
0
      }
750
0
    }
751
752
0
    new_mm_seq = mac_mobility_seqnum(newattr);
753
0
    exist_mm_seq = mac_mobility_seqnum(existattr);
754
755
0
    if (new_mm_seq > exist_mm_seq) {
756
0
      *reason = bgp_path_selection_evpn_seq;
757
0
      if (debug)
758
0
        zlog_debug(
759
0
          "%s: %s wins over %s due to MM seq %u > %u",
760
0
          pfx_buf, new_buf, exist_buf, new_mm_seq,
761
0
          exist_mm_seq);
762
0
      return 1;
763
0
    }
764
765
0
    if (new_mm_seq < exist_mm_seq) {
766
0
      *reason = bgp_path_selection_evpn_seq;
767
0
      if (debug)
768
0
        zlog_debug(
769
0
          "%s: %s loses to %s due to MM seq %u < %u",
770
0
          pfx_buf, new_buf, exist_buf, new_mm_seq,
771
0
          exist_mm_seq);
772
0
      return 0;
773
0
    }
774
775
    /* if the sequence numbers and ESI are the same and one path
776
     * is non-proxy it wins (over proxy)
777
     */
778
0
    new_proxy = bgp_evpn_attr_is_proxy(newattr);
779
0
    old_proxy = bgp_evpn_attr_is_proxy(existattr);
780
0
    if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781
0
        old_proxy != new_proxy) {
782
0
      if (!new_proxy) {
783
0
        *reason = bgp_path_selection_evpn_non_proxy;
784
0
        if (debug)
785
0
          zlog_debug(
786
0
            "%s: %s wins over %s, same seq/es and non-proxy",
787
0
            pfx_buf, new_buf, exist_buf);
788
0
        return 1;
789
0
      }
790
791
0
      *reason = bgp_path_selection_evpn_non_proxy;
792
0
      if (debug)
793
0
        zlog_debug(
794
0
          "%s: %s loses to %s, same seq/es and non-proxy",
795
0
          pfx_buf, new_buf, exist_buf);
796
0
      return 0;
797
0
    }
798
799
    /*
800
     * if sequence numbers are the same path with the lowest IP
801
     * wins
802
     */
803
0
    nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804
0
    if (nh_cmp < 0) {
805
0
      *reason = bgp_path_selection_evpn_lower_ip;
806
0
      if (debug)
807
0
        zlog_debug(
808
0
          "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809
0
          pfx_buf, new_buf, exist_buf, new_mm_seq,
810
0
          &new->attr->nexthop);
811
0
      return 1;
812
0
    }
813
0
    if (nh_cmp > 0) {
814
0
      *reason = bgp_path_selection_evpn_lower_ip;
815
0
      if (debug)
816
0
        zlog_debug(
817
0
          "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818
0
          pfx_buf, new_buf, exist_buf, new_mm_seq,
819
0
          &new->attr->nexthop);
820
0
      return 0;
821
0
    }
822
0
  }
823
824
  /* 1. Weight check. */
825
0
  new_weight = newattr->weight;
826
0
  exist_weight = existattr->weight;
827
828
0
  if (new_weight > exist_weight) {
829
0
    *reason = bgp_path_selection_weight;
830
0
    if (debug)
831
0
      zlog_debug("%s: %s wins over %s due to weight %d > %d",
832
0
           pfx_buf, new_buf, exist_buf, new_weight,
833
0
           exist_weight);
834
0
    return 1;
835
0
  }
836
837
0
  if (new_weight < exist_weight) {
838
0
    *reason = bgp_path_selection_weight;
839
0
    if (debug)
840
0
      zlog_debug("%s: %s loses to %s due to weight %d < %d",
841
0
           pfx_buf, new_buf, exist_buf, new_weight,
842
0
           exist_weight);
843
0
    return 0;
844
0
  }
845
846
  /* 2. Local preference check. */
847
0
  new_pref = exist_pref = bgp->default_local_pref;
848
849
0
  if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850
0
    new_pref = newattr->local_pref;
851
0
  if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852
0
    exist_pref = existattr->local_pref;
853
854
0
  if (new_pref > exist_pref) {
855
0
    *reason = bgp_path_selection_local_pref;
856
0
    if (debug)
857
0
      zlog_debug(
858
0
        "%s: %s wins over %s due to localpref %d > %d",
859
0
        pfx_buf, new_buf, exist_buf, new_pref,
860
0
        exist_pref);
861
0
    return 1;
862
0
  }
863
864
0
  if (new_pref < exist_pref) {
865
0
    *reason = bgp_path_selection_local_pref;
866
0
    if (debug)
867
0
      zlog_debug(
868
0
        "%s: %s loses to %s due to localpref %d < %d",
869
0
        pfx_buf, new_buf, exist_buf, new_pref,
870
0
        exist_pref);
871
0
    return 0;
872
0
  }
873
874
  /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875
   * extensions defined in this document, the following step is inserted
876
   * after the LOCAL_PREF comparison step in the BGP decision process:
877
   *  When comparing a pair of routes for a BGP destination, the
878
   *  route with the ACCEPT_OWN community attached is preferred over
879
   *  the route that does not have the community.
880
   * This extra step MUST only be invoked during the best path selection
881
   * process of VPN-IP routes.
882
   */
883
0
  if (safi == SAFI_MPLS_VPN &&
884
0
      (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
885
0
       CHECK_FLAG(exist->peer->af_flags[afi][safi],
886
0
      PEER_FLAG_ACCEPT_OWN))) {
887
0
    bool new_accept_own = false;
888
0
    bool exist_accept_own = false;
889
0
    uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
890
891
0
    if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
892
0
      new_accept_own = community_include(
893
0
        bgp_attr_get_community(newattr), accept_own);
894
0
    if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
895
0
      exist_accept_own = community_include(
896
0
        bgp_attr_get_community(existattr), accept_own);
897
898
0
    if (new_accept_own && !exist_accept_own) {
899
0
      *reason = bgp_path_selection_accept_own;
900
0
      if (debug)
901
0
        zlog_debug(
902
0
          "%s: %s wins over %s due to accept-own",
903
0
          pfx_buf, new_buf, exist_buf);
904
0
      return 1;
905
0
    }
906
907
0
    if (!new_accept_own && exist_accept_own) {
908
0
      *reason = bgp_path_selection_accept_own;
909
0
      if (debug)
910
0
        zlog_debug(
911
0
          "%s: %s loses to %s due to accept-own",
912
0
          pfx_buf, new_buf, exist_buf);
913
0
      return 0;
914
0
    }
915
0
  }
916
917
  /* Tie-breaker - AIGP (Metric TLV) attribute */
918
0
  if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
919
0
      CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
920
0
      CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
921
0
    uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
922
0
    uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
923
924
0
    if (new_aigp < exist_aigp) {
925
0
      *reason = bgp_path_selection_aigp;
926
0
      if (debug)
927
0
        zlog_debug(
928
0
          "%s: %s wins over %s due to AIGP %" PRIu64
929
0
          " < %" PRIu64,
930
0
          pfx_buf, new_buf, exist_buf, new_aigp,
931
0
          exist_aigp);
932
0
      return 1;
933
0
    }
934
935
0
    if (new_aigp > exist_aigp) {
936
0
      *reason = bgp_path_selection_aigp;
937
0
      if (debug)
938
0
        zlog_debug(
939
0
          "%s: %s loses to %s due to AIGP %" PRIu64
940
0
          " > %" PRIu64,
941
0
          pfx_buf, new_buf, exist_buf, new_aigp,
942
0
          exist_aigp);
943
0
      return 0;
944
0
    }
945
0
  }
946
947
  /* 3. Local route check. We prefer:
948
   *  - BGP_ROUTE_STATIC
949
   *  - BGP_ROUTE_AGGREGATE
950
   *  - BGP_ROUTE_REDISTRIBUTE
951
   */
952
0
  new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
953
0
           new->sub_type == BGP_ROUTE_IMPORTED);
954
0
  exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
955
0
       exist->sub_type == BGP_ROUTE_IMPORTED);
956
957
0
  if (new_origin && !exist_origin) {
958
0
    *reason = bgp_path_selection_local_route;
959
0
    if (debug)
960
0
      zlog_debug(
961
0
        "%s: %s wins over %s due to preferred BGP_ROUTE type",
962
0
        pfx_buf, new_buf, exist_buf);
963
0
    return 1;
964
0
  }
965
966
0
  if (!new_origin && exist_origin) {
967
0
    *reason = bgp_path_selection_local_route;
968
0
    if (debug)
969
0
      zlog_debug(
970
0
        "%s: %s loses to %s due to preferred BGP_ROUTE type",
971
0
        pfx_buf, new_buf, exist_buf);
972
0
    return 0;
973
0
  }
974
975
  /* Here if these are imported routes then get ultimate pi for
976
   * path compare.
977
   */
978
0
  new = bgp_get_imported_bpi_ultimate(new);
979
0
  exist = bgp_get_imported_bpi_ultimate(exist);
980
0
  newattr = new->attr;
981
0
  existattr = exist->attr;
982
983
  /* 4. AS path length check. */
984
0
  if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
985
0
    int exist_hops = aspath_count_hops(existattr->aspath);
986
0
    int exist_confeds = aspath_count_confeds(existattr->aspath);
987
988
0
    if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
989
0
      int aspath_hops;
990
991
0
      aspath_hops = aspath_count_hops(newattr->aspath);
992
0
      aspath_hops += aspath_count_confeds(newattr->aspath);
993
994
0
      if (aspath_hops < (exist_hops + exist_confeds)) {
995
0
        *reason = bgp_path_selection_confed_as_path;
996
0
        if (debug)
997
0
          zlog_debug(
998
0
            "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999
0
            pfx_buf, new_buf, exist_buf,
1000
0
            aspath_hops,
1001
0
            (exist_hops + exist_confeds));
1002
0
        return 1;
1003
0
      }
1004
1005
0
      if (aspath_hops > (exist_hops + exist_confeds)) {
1006
0
        *reason = bgp_path_selection_confed_as_path;
1007
0
        if (debug)
1008
0
          zlog_debug(
1009
0
            "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010
0
            pfx_buf, new_buf, exist_buf,
1011
0
            aspath_hops,
1012
0
            (exist_hops + exist_confeds));
1013
0
        return 0;
1014
0
      }
1015
0
    } else {
1016
0
      int newhops = aspath_count_hops(newattr->aspath);
1017
1018
0
      if (newhops < exist_hops) {
1019
0
        *reason = bgp_path_selection_as_path;
1020
0
        if (debug)
1021
0
          zlog_debug(
1022
0
            "%s: %s wins over %s due to aspath hopcount %d < %d",
1023
0
            pfx_buf, new_buf, exist_buf,
1024
0
            newhops, exist_hops);
1025
0
        return 1;
1026
0
      }
1027
1028
0
      if (newhops > exist_hops) {
1029
0
        *reason = bgp_path_selection_as_path;
1030
0
        if (debug)
1031
0
          zlog_debug(
1032
0
            "%s: %s loses to %s due to aspath hopcount %d > %d",
1033
0
            pfx_buf, new_buf, exist_buf,
1034
0
            newhops, exist_hops);
1035
0
        return 0;
1036
0
      }
1037
0
    }
1038
0
  }
1039
1040
  /* 5. Origin check. */
1041
0
  if (newattr->origin < existattr->origin) {
1042
0
    *reason = bgp_path_selection_origin;
1043
0
    if (debug)
1044
0
      zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045
0
           pfx_buf, new_buf, exist_buf,
1046
0
           bgp_origin_long_str[newattr->origin],
1047
0
           bgp_origin_long_str[existattr->origin]);
1048
0
    return 1;
1049
0
  }
1050
1051
0
  if (newattr->origin > existattr->origin) {
1052
0
    *reason = bgp_path_selection_origin;
1053
0
    if (debug)
1054
0
      zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055
0
           pfx_buf, new_buf, exist_buf,
1056
0
           bgp_origin_long_str[newattr->origin],
1057
0
           bgp_origin_long_str[existattr->origin]);
1058
0
    return 0;
1059
0
  }
1060
1061
  /* 6. MED check. */
1062
0
  internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1063
0
           && aspath_count_hops(existattr->aspath) == 0);
1064
0
  confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1065
0
         && aspath_count_confeds(existattr->aspath) > 0
1066
0
         && aspath_count_hops(newattr->aspath) == 0
1067
0
         && aspath_count_hops(existattr->aspath) == 0);
1068
1069
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1070
0
      || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
1071
0
      || aspath_cmp_left(newattr->aspath, existattr->aspath)
1072
0
      || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1073
0
      || internal_as_route) {
1074
0
    new_med = bgp_med_value(new->attr, bgp);
1075
0
    exist_med = bgp_med_value(exist->attr, bgp);
1076
1077
0
    if (new_med < exist_med) {
1078
0
      *reason = bgp_path_selection_med;
1079
0
      if (debug)
1080
0
        zlog_debug(
1081
0
          "%s: %s wins over %s due to MED %d < %d",
1082
0
          pfx_buf, new_buf, exist_buf, new_med,
1083
0
          exist_med);
1084
0
      return 1;
1085
0
    }
1086
1087
0
    if (new_med > exist_med) {
1088
0
      *reason = bgp_path_selection_med;
1089
0
      if (debug)
1090
0
        zlog_debug(
1091
0
          "%s: %s loses to %s due to MED %d > %d",
1092
0
          pfx_buf, new_buf, exist_buf, new_med,
1093
0
          exist_med);
1094
0
      return 0;
1095
0
    }
1096
0
  }
1097
1098
0
  if (exist->sub_type == BGP_ROUTE_IMPORTED) {
1099
0
    bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
1100
0
    peer_exist = bpi_ultimate->peer;
1101
0
  } else
1102
0
    peer_exist = exist->peer;
1103
1104
0
  if (new->sub_type == BGP_ROUTE_IMPORTED) {
1105
0
    bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
1106
0
    peer_new = bpi_ultimate->peer;
1107
0
  } else
1108
0
    peer_new = new->peer;
1109
1110
  /* 7. Peer type check. */
1111
0
  new_sort = peer_new->sort;
1112
0
  exist_sort = peer_exist->sort;
1113
1114
0
  if (new_sort == BGP_PEER_EBGP
1115
0
      && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
1116
0
    *reason = bgp_path_selection_peer;
1117
0
    if (debug)
1118
0
      zlog_debug(
1119
0
        "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120
0
        pfx_buf, new_buf, exist_buf);
1121
0
    if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1122
0
      return 1;
1123
0
    peer_sort_ret = 1;
1124
0
  }
1125
1126
0
  if (exist_sort == BGP_PEER_EBGP
1127
0
      && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
1128
0
    *reason = bgp_path_selection_peer;
1129
0
    if (debug)
1130
0
      zlog_debug(
1131
0
        "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132
0
        pfx_buf, new_buf, exist_buf);
1133
0
    if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1134
0
      return 0;
1135
0
    peer_sort_ret = 0;
1136
0
  }
1137
1138
  /* 8. IGP metric check. */
1139
0
  newm = existm = 0;
1140
1141
0
  if (new->extra)
1142
0
    newm = new->extra->igpmetric;
1143
0
  if (exist->extra)
1144
0
    existm = exist->extra->igpmetric;
1145
1146
0
  if (newm < existm) {
1147
0
    if (debug && peer_sort_ret < 0)
1148
0
      zlog_debug(
1149
0
        "%s: %s wins over %s due to IGP metric %u < %u",
1150
0
        pfx_buf, new_buf, exist_buf, newm, existm);
1151
0
    igp_metric_ret = 1;
1152
0
  }
1153
1154
0
  if (newm > existm) {
1155
0
    if (debug && peer_sort_ret < 0)
1156
0
      zlog_debug(
1157
0
        "%s: %s loses to %s due to IGP metric %u > %u",
1158
0
        pfx_buf, new_buf, exist_buf, newm, existm);
1159
0
    igp_metric_ret = 0;
1160
0
  }
1161
1162
  /* 9. Same IGP metric. Compare the cluster list length as
1163
     representative of IGP hops metric. Rewrite the metric value
1164
     pair (newm, existm) with the cluster list length. Prefer the
1165
     path with smaller cluster list length.                       */
1166
0
  if (newm == existm) {
1167
0
    if (peer_sort_lookup(peer_new) == BGP_PEER_IBGP &&
1168
0
        peer_sort_lookup(peer_exist) == BGP_PEER_IBGP &&
1169
0
        (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
1170
0
      newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1171
0
      existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1172
1173
0
      if (newm < existm) {
1174
0
        if (debug && peer_sort_ret < 0)
1175
0
          zlog_debug(
1176
0
            "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177
0
            pfx_buf, new_buf, exist_buf,
1178
0
            newm, existm);
1179
0
        igp_metric_ret = 1;
1180
0
      }
1181
1182
0
      if (newm > existm) {
1183
0
        if (debug && peer_sort_ret < 0)
1184
0
          zlog_debug(
1185
0
            "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186
0
            pfx_buf, new_buf, exist_buf,
1187
0
            newm, existm);
1188
0
        igp_metric_ret = 0;
1189
0
      }
1190
0
    }
1191
0
  }
1192
1193
  /* 10. confed-external vs. confed-internal */
1194
0
  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1195
0
    if (new_sort == BGP_PEER_CONFED
1196
0
        && exist_sort == BGP_PEER_IBGP) {
1197
0
      *reason = bgp_path_selection_confed;
1198
0
      if (debug)
1199
0
        zlog_debug(
1200
0
          "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201
0
          pfx_buf, new_buf, exist_buf);
1202
0
      if (!CHECK_FLAG(bgp->flags,
1203
0
          BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1204
0
        return 1;
1205
0
      peer_sort_ret = 1;
1206
0
    }
1207
1208
0
    if (exist_sort == BGP_PEER_CONFED
1209
0
        && new_sort == BGP_PEER_IBGP) {
1210
0
      *reason = bgp_path_selection_confed;
1211
0
      if (debug)
1212
0
        zlog_debug(
1213
0
          "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214
0
          pfx_buf, new_buf, exist_buf);
1215
0
      if (!CHECK_FLAG(bgp->flags,
1216
0
          BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1217
0
        return 0;
1218
0
      peer_sort_ret = 0;
1219
0
    }
1220
0
  }
1221
1222
  /* 11. Maximum path check. */
1223
0
  if (newm == existm) {
1224
    /* If one path has a label but the other does not, do not treat
1225
     * them as equals for multipath
1226
     */
1227
0
    int newl, existl;
1228
1229
0
    newl = existl = 0;
1230
1231
0
    if (new->extra)
1232
0
      newl = new->extra->num_labels;
1233
0
    if (exist->extra)
1234
0
      existl = exist->extra->num_labels;
1235
0
    if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
1236
0
         (exist->extra &&
1237
0
          bgp_is_valid_label(&exist->extra->label[0]))) ||
1238
0
        (newl != existl)) {
1239
0
      if (debug)
1240
0
        zlog_debug(
1241
0
          "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242
0
          pfx_buf, new_buf, exist_buf);
1243
0
    } else if (CHECK_FLAG(bgp->flags,
1244
0
              BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
1245
1246
      /*
1247
       * For the two paths, all comparison steps till IGP
1248
       * metric
1249
       * have succeeded - including AS_PATH hop count. Since
1250
       * 'bgp
1251
       * bestpath as-path multipath-relax' knob is on, we
1252
       * don't need
1253
       * an exact match of AS_PATH. Thus, mark the paths are
1254
       * equal.
1255
       * That will trigger both these paths to get into the
1256
       * multipath
1257
       * array.
1258
       */
1259
0
      *paths_eq = 1;
1260
1261
0
      if (debug)
1262
0
        zlog_debug(
1263
0
          "%s: %s and %s are equal via multipath-relax",
1264
0
          pfx_buf, new_buf, exist_buf);
1265
0
    } else if (peer_new->sort == BGP_PEER_IBGP) {
1266
0
      if (aspath_cmp(new->attr->aspath,
1267
0
               exist->attr->aspath)) {
1268
0
        *paths_eq = 1;
1269
1270
0
        if (debug)
1271
0
          zlog_debug(
1272
0
            "%s: %s and %s are equal via matching aspaths",
1273
0
            pfx_buf, new_buf, exist_buf);
1274
0
      }
1275
0
    } else if (peer_new->as == peer_exist->as) {
1276
0
      *paths_eq = 1;
1277
1278
0
      if (debug)
1279
0
        zlog_debug(
1280
0
          "%s: %s and %s are equal via same remote-as",
1281
0
          pfx_buf, new_buf, exist_buf);
1282
0
    }
1283
0
  } else {
1284
    /*
1285
     * TODO: If unequal cost ibgp multipath is enabled we can
1286
     * mark the paths as equal here instead of returning
1287
     */
1288
1289
    /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290
     * if either step 7 or 10 (peer type checks) yielded a winner,
1291
     * that result was returned immediately. Returning from step 10
1292
     * ignored the return value computed in steps 8 and 9 (IGP
1293
     * metric checks). In order to preserve that behavior, if
1294
     * peer_sort_ret is set, return that rather than igp_metric_ret.
1295
     */
1296
0
    ret = peer_sort_ret;
1297
0
    if (peer_sort_ret < 0) {
1298
0
      ret = igp_metric_ret;
1299
0
      if (debug) {
1300
0
        if (ret == 1)
1301
0
          zlog_debug(
1302
0
            "%s: %s wins over %s after IGP metric comparison",
1303
0
            pfx_buf, new_buf, exist_buf);
1304
0
        else
1305
0
          zlog_debug(
1306
0
            "%s: %s loses to %s after IGP metric comparison",
1307
0
            pfx_buf, new_buf, exist_buf);
1308
0
      }
1309
0
      *reason = bgp_path_selection_igp_metric;
1310
0
    }
1311
0
    return ret;
1312
0
  }
1313
1314
  /*
1315
   * At this point, the decision whether to set *paths_eq = 1 has been
1316
   * completed. If we deferred returning because of bestpath peer-type
1317
   * relax configuration, return now.
1318
   */
1319
0
  if (peer_sort_ret >= 0)
1320
0
    return peer_sort_ret;
1321
1322
  /* 12. If both paths are external, prefer the path that was received
1323
     first (the oldest one).  This step minimizes route-flap, since a
1324
     newer path won't displace an older one, even if it was the
1325
     preferred route based on the additional decision criteria below.  */
1326
0
  if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
1327
0
      && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1328
0
    if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
1329
0
      *reason = bgp_path_selection_older;
1330
0
      if (debug)
1331
0
        zlog_debug(
1332
0
          "%s: %s wins over %s due to oldest external",
1333
0
          pfx_buf, new_buf, exist_buf);
1334
0
      return 1;
1335
0
    }
1336
1337
0
    if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
1338
0
      *reason = bgp_path_selection_older;
1339
0
      if (debug)
1340
0
        zlog_debug(
1341
0
          "%s: %s loses to %s due to oldest external",
1342
0
          pfx_buf, new_buf, exist_buf);
1343
0
      return 0;
1344
0
    }
1345
0
  }
1346
1347
  /* 13. Router-ID comparison. */
1348
  /* If one of the paths is "stale", the corresponding peer router-id will
1349
   * be 0 and would always win over the other path. If originator id is
1350
   * used for the comparison, it will decide which path is better.
1351
   */
1352
0
  if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1353
0
    new_id.s_addr = newattr->originator_id.s_addr;
1354
0
  else
1355
0
    new_id.s_addr = peer_new->remote_id.s_addr;
1356
0
  if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1357
0
    exist_id.s_addr = existattr->originator_id.s_addr;
1358
0
  else
1359
0
    exist_id.s_addr = peer_exist->remote_id.s_addr;
1360
1361
0
  if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
1362
0
    *reason = bgp_path_selection_router_id;
1363
0
    if (debug)
1364
0
      zlog_debug(
1365
0
        "%s: %s wins over %s due to Router-ID comparison",
1366
0
        pfx_buf, new_buf, exist_buf);
1367
0
    return 1;
1368
0
  }
1369
1370
0
  if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
1371
0
    *reason = bgp_path_selection_router_id;
1372
0
    if (debug)
1373
0
      zlog_debug(
1374
0
        "%s: %s loses to %s due to Router-ID comparison",
1375
0
        pfx_buf, new_buf, exist_buf);
1376
0
    return 0;
1377
0
  }
1378
1379
  /* 14. Cluster length comparison. */
1380
0
  new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1381
0
  exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1382
1383
0
  if (new_cluster < exist_cluster) {
1384
0
    *reason = bgp_path_selection_cluster_length;
1385
0
    if (debug)
1386
0
      zlog_debug(
1387
0
        "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388
0
        pfx_buf, new_buf, exist_buf, new_cluster,
1389
0
        exist_cluster);
1390
0
    return 1;
1391
0
  }
1392
1393
0
  if (new_cluster > exist_cluster) {
1394
0
    *reason = bgp_path_selection_cluster_length;
1395
0
    if (debug)
1396
0
      zlog_debug(
1397
0
        "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398
0
        pfx_buf, new_buf, exist_buf, new_cluster,
1399
0
        exist_cluster);
1400
0
    return 0;
1401
0
  }
1402
1403
  /* 15. Neighbor address comparison. */
1404
  /* Do this only if neither path is "stale" as stale paths do not have
1405
   * valid peer information (as the connection may or may not be up).
1406
   */
1407
0
  if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
1408
0
    *reason = bgp_path_selection_stale;
1409
0
    if (debug)
1410
0
      zlog_debug(
1411
0
        "%s: %s wins over %s due to latter path being STALE",
1412
0
        pfx_buf, new_buf, exist_buf);
1413
0
    return 1;
1414
0
  }
1415
1416
0
  if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
1417
0
    *reason = bgp_path_selection_stale;
1418
0
    if (debug)
1419
0
      zlog_debug(
1420
0
        "%s: %s loses to %s due to former path being STALE",
1421
0
        pfx_buf, new_buf, exist_buf);
1422
0
    return 0;
1423
0
  }
1424
1425
  /* locally configured routes to advertise do not have su_remote */
1426
0
  if (peer_new->su_remote == NULL) {
1427
0
    *reason = bgp_path_selection_local_configured;
1428
0
    return 0;
1429
0
  }
1430
1431
0
  if (peer_exist->su_remote == NULL) {
1432
0
    *reason = bgp_path_selection_local_configured;
1433
0
    return 1;
1434
0
  }
1435
1436
0
  ret = sockunion_cmp(peer_new->su_remote, peer_exist->su_remote);
1437
1438
0
  if (ret == 1) {
1439
0
    *reason = bgp_path_selection_neighbor_ip;
1440
0
    if (debug)
1441
0
      zlog_debug(
1442
0
        "%s: %s loses to %s due to Neighor IP comparison",
1443
0
        pfx_buf, new_buf, exist_buf);
1444
0
    return 0;
1445
0
  }
1446
1447
0
  if (ret == -1) {
1448
0
    *reason = bgp_path_selection_neighbor_ip;
1449
0
    if (debug)
1450
0
      zlog_debug(
1451
0
        "%s: %s wins over %s due to Neighor IP comparison",
1452
0
        pfx_buf, new_buf, exist_buf);
1453
0
    return 1;
1454
0
  }
1455
1456
0
  *reason = bgp_path_selection_default;
1457
0
  if (debug)
1458
0
    zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459
0
         pfx_buf, new_buf, exist_buf);
1460
1461
0
  return 1;
1462
0
}
1463
1464
1465
int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1466
           struct bgp_path_info *exist, int *paths_eq)
1467
0
{
1468
0
  enum bgp_path_selection_reason reason;
1469
0
  char pfx_buf[PREFIX2STR_BUFFER] = {};
1470
1471
0
  return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1472
0
        AFI_L2VPN, SAFI_EVPN, &reason);
1473
0
}
1474
1475
/* Compare two bgp route entity.  Return -1 if new is preferred, 1 if exist
1476
 * is preferred, or 0 if they are the same (usually will only occur if
1477
 * multipath is enabled
1478
 * This version is compatible with */
1479
int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1480
         struct bgp_path_info *exist, char *pfx_buf,
1481
         afi_t afi, safi_t safi,
1482
         enum bgp_path_selection_reason *reason)
1483
0
{
1484
0
  int paths_eq;
1485
0
  int ret;
1486
0
  ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1487
0
        afi, safi, reason);
1488
1489
0
  if (paths_eq)
1490
0
    ret = 0;
1491
0
  else {
1492
0
    if (ret == 1)
1493
0
      ret = -1;
1494
0
    else
1495
0
      ret = 1;
1496
0
  }
1497
0
  return ret;
1498
0
}
1499
1500
static enum filter_type bgp_input_filter(struct peer *peer,
1501
           const struct prefix *p,
1502
           struct attr *attr, afi_t afi,
1503
           safi_t safi)
1504
2.42k
{
1505
2.42k
  struct bgp_filter *filter;
1506
2.42k
  enum filter_type ret = FILTER_PERMIT;
1507
1508
2.42k
  filter = &peer->filter[afi][safi];
1509
1510
2.42k
#define FILTER_EXIST_WARN(F, f, filter)                                        \
1511
2.42k
  if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter)))                 \
1512
0
    zlog_debug("%s: Could not find configured input %s-list %s!",  \
1513
0
         peer->host, #f, F##_IN_NAME(filter));
1514
1515
2.42k
  if (DISTRIBUTE_IN_NAME(filter)) {
1516
0
    FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1517
1518
0
    if (access_list_apply(DISTRIBUTE_IN(filter), p)
1519
0
        == FILTER_DENY) {
1520
0
      ret = FILTER_DENY;
1521
0
      goto done;
1522
0
    }
1523
0
  }
1524
1525
2.42k
  if (PREFIX_LIST_IN_NAME(filter)) {
1526
0
    FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1527
1528
0
    if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1529
0
        == PREFIX_DENY) {
1530
0
      ret = FILTER_DENY;
1531
0
      goto done;
1532
0
    }
1533
0
  }
1534
1535
2.42k
  if (FILTER_LIST_IN_NAME(filter)) {
1536
0
    FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1537
1538
0
    if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1539
0
        == AS_FILTER_DENY) {
1540
0
      ret = FILTER_DENY;
1541
0
      goto done;
1542
0
    }
1543
0
  }
1544
1545
2.42k
done:
1546
2.42k
  if (frrtrace_enabled(frr_bgp, input_filter)) {
1547
0
    char pfxprint[PREFIX2STR_BUFFER];
1548
1549
0
    prefix2str(p, pfxprint, sizeof(pfxprint));
1550
0
    frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1551
0
       ret == FILTER_PERMIT ? "permit" : "deny");
1552
0
  }
1553
1554
2.42k
  return ret;
1555
2.42k
#undef FILTER_EXIST_WARN
1556
2.42k
}
1557
1558
static enum filter_type bgp_output_filter(struct peer *peer,
1559
            const struct prefix *p,
1560
            struct attr *attr, afi_t afi,
1561
            safi_t safi)
1562
0
{
1563
0
  struct bgp_filter *filter;
1564
0
  enum filter_type ret = FILTER_PERMIT;
1565
1566
0
  filter = &peer->filter[afi][safi];
1567
1568
0
#define FILTER_EXIST_WARN(F, f, filter)                                        \
1569
0
  if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter)))               \
1570
0
    zlog_debug("%s: Could not find configured output %s-list %s!", \
1571
0
         peer->host, #f, F##_OUT_NAME(filter));
1572
1573
0
  if (DISTRIBUTE_OUT_NAME(filter)) {
1574
0
    FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1575
1576
0
    if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1577
0
        == FILTER_DENY) {
1578
0
      ret = FILTER_DENY;
1579
0
      goto done;
1580
0
    }
1581
0
  }
1582
1583
0
  if (PREFIX_LIST_OUT_NAME(filter)) {
1584
0
    FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1585
1586
0
    if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1587
0
        == PREFIX_DENY) {
1588
0
      ret = FILTER_DENY;
1589
0
      goto done;
1590
0
    }
1591
0
  }
1592
1593
0
  if (FILTER_LIST_OUT_NAME(filter)) {
1594
0
    FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1595
1596
0
    if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1597
0
        == AS_FILTER_DENY) {
1598
0
      ret = FILTER_DENY;
1599
0
      goto done;
1600
0
    }
1601
0
  }
1602
1603
0
  if (frrtrace_enabled(frr_bgp, output_filter)) {
1604
0
    char pfxprint[PREFIX2STR_BUFFER];
1605
1606
0
    prefix2str(p, pfxprint, sizeof(pfxprint));
1607
0
    frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1608
0
       ret == FILTER_PERMIT ? "permit" : "deny");
1609
0
  }
1610
1611
0
done:
1612
0
  return ret;
1613
0
#undef FILTER_EXIST_WARN
1614
0
}
1615
1616
/* If community attribute includes no_export then return 1. */
1617
static bool bgp_community_filter(struct peer *peer, struct attr *attr)
1618
0
{
1619
0
  if (bgp_attr_get_community(attr)) {
1620
    /* NO_ADVERTISE check. */
1621
0
    if (community_include(bgp_attr_get_community(attr),
1622
0
              COMMUNITY_NO_ADVERTISE))
1623
0
      return true;
1624
1625
    /* NO_EXPORT check. */
1626
0
    if (peer->sort == BGP_PEER_EBGP &&
1627
0
        community_include(bgp_attr_get_community(attr),
1628
0
              COMMUNITY_NO_EXPORT))
1629
0
      return true;
1630
1631
    /* NO_EXPORT_SUBCONFED check. */
1632
0
    if (peer->sort == BGP_PEER_EBGP
1633
0
        || peer->sort == BGP_PEER_CONFED)
1634
0
      if (community_include(bgp_attr_get_community(attr),
1635
0
                COMMUNITY_NO_EXPORT_SUBCONFED))
1636
0
        return true;
1637
0
  }
1638
0
  return false;
1639
0
}
1640
1641
/* Route reflection loop check.  */
1642
static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
1643
2.42k
{
1644
2.42k
  struct in_addr cluster_id;
1645
2.42k
  struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1646
1647
2.42k
  if (cluster) {
1648
3
    if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1649
0
      cluster_id = peer->bgp->cluster_id;
1650
3
    else
1651
3
      cluster_id = peer->bgp->router_id;
1652
1653
3
    if (cluster_loop_check(cluster, cluster_id))
1654
0
      return true;
1655
3
  }
1656
2.42k
  return false;
1657
2.42k
}
1658
1659
static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1660
0
{
1661
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1662
0
    if (peer->local_role == ROLE_PROVIDER ||
1663
0
        peer->local_role == ROLE_RS_SERVER)
1664
0
      return true;
1665
0
    if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1666
0
      return true;
1667
0
    return false;
1668
0
  }
1669
0
  if (peer->local_role == ROLE_CUSTOMER ||
1670
0
      peer->local_role == ROLE_PEER ||
1671
0
      peer->local_role == ROLE_RS_CLIENT) {
1672
0
    attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1673
0
    attr->otc = peer->as;
1674
0
  }
1675
0
  return false;
1676
0
}
1677
1678
static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1679
0
{
1680
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1681
0
    if (peer->local_role == ROLE_CUSTOMER ||
1682
0
        peer->local_role == ROLE_RS_CLIENT ||
1683
0
        peer->local_role == ROLE_PEER)
1684
0
      return true;
1685
0
    return false;
1686
0
  }
1687
0
  if (peer->local_role == ROLE_PROVIDER ||
1688
0
      peer->local_role == ROLE_PEER ||
1689
0
      peer->local_role == ROLE_RS_SERVER) {
1690
0
    attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1691
0
    attr->otc = peer->bgp->as;
1692
0
  }
1693
0
  return false;
1694
0
}
1695
1696
static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1697
0
{
1698
0
  return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1699
0
}
1700
1701
static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
1702
            struct attr *attr, afi_t afi, safi_t safi,
1703
            const char *rmap_name, mpls_label_t *label,
1704
            uint32_t num_labels, struct bgp_dest *dest)
1705
2.27k
{
1706
2.27k
  struct bgp_filter *filter;
1707
2.27k
  struct bgp_path_info rmap_path = { 0 };
1708
2.27k
  struct bgp_path_info_extra extra = { 0 };
1709
2.27k
  route_map_result_t ret;
1710
2.27k
  struct route_map *rmap = NULL;
1711
1712
2.27k
  filter = &peer->filter[afi][safi];
1713
1714
  /* Apply default weight value. */
1715
2.27k
  if (peer->weight[afi][safi])
1716
0
    attr->weight = peer->weight[afi][safi];
1717
1718
2.27k
  if (rmap_name) {
1719
0
    rmap = route_map_lookup_by_name(rmap_name);
1720
1721
0
    if (rmap == NULL)
1722
0
      return RMAP_DENY;
1723
2.27k
  } else {
1724
2.27k
    if (ROUTE_MAP_IN_NAME(filter)) {
1725
0
      rmap = ROUTE_MAP_IN(filter);
1726
1727
0
      if (rmap == NULL)
1728
0
        return RMAP_DENY;
1729
0
    }
1730
2.27k
  }
1731
1732
  /* Route map apply. */
1733
2.27k
  if (rmap) {
1734
0
    memset(&rmap_path, 0, sizeof(rmap_path));
1735
    /* Duplicate current value to new structure for modification. */
1736
0
    rmap_path.peer = peer;
1737
0
    rmap_path.attr = attr;
1738
0
    rmap_path.extra = &extra;
1739
0
    rmap_path.net = dest;
1740
1741
0
    extra.num_labels = num_labels;
1742
0
    if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1743
0
      memcpy(extra.label, label,
1744
0
        num_labels * sizeof(mpls_label_t));
1745
1746
0
    SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
1747
1748
    /* Apply BGP route map to the attribute. */
1749
0
    ret = route_map_apply(rmap, p, &rmap_path);
1750
1751
0
    peer->rmap_type = 0;
1752
1753
0
    if (ret == RMAP_DENYMATCH)
1754
0
      return RMAP_DENY;
1755
0
  }
1756
2.27k
  return RMAP_PERMIT;
1757
2.27k
}
1758
1759
static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
1760
             struct attr *attr, afi_t afi, safi_t safi,
1761
             const char *rmap_name)
1762
0
{
1763
0
  struct bgp_path_info rmap_path;
1764
0
  route_map_result_t ret;
1765
0
  struct route_map *rmap = NULL;
1766
0
  uint8_t rmap_type;
1767
1768
  /*
1769
   * So if we get to this point and have no rmap_name
1770
   * we want to just show the output as it currently
1771
   * exists.
1772
   */
1773
0
  if (!rmap_name)
1774
0
    return RMAP_PERMIT;
1775
1776
  /* Apply default weight value. */
1777
0
  if (peer->weight[afi][safi])
1778
0
    attr->weight = peer->weight[afi][safi];
1779
1780
0
  rmap = route_map_lookup_by_name(rmap_name);
1781
1782
  /*
1783
   * If we have a route map name and we do not find
1784
   * the routemap that means we have an implicit
1785
   * deny.
1786
   */
1787
0
  if (rmap == NULL)
1788
0
    return RMAP_DENY;
1789
1790
0
  memset(&rmap_path, 0, sizeof(rmap_path));
1791
  /* Route map apply. */
1792
  /* Duplicate current value to new structure for modification. */
1793
0
  rmap_path.peer = peer;
1794
0
  rmap_path.attr = attr;
1795
1796
0
  rmap_type = peer->rmap_type;
1797
0
  SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
1798
1799
  /* Apply BGP route map to the attribute. */
1800
0
  ret = route_map_apply(rmap, p, &rmap_path);
1801
1802
0
  peer->rmap_type = rmap_type;
1803
1804
0
  if (ret == RMAP_DENYMATCH)
1805
    /*
1806
     * caller has multiple error paths with bgp_attr_flush()
1807
     */
1808
0
    return RMAP_DENY;
1809
1810
0
  return RMAP_PERMIT;
1811
0
}
1812
1813
/* If this is an EBGP peer with remove-private-AS */
1814
static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1815
               struct peer *peer, struct attr *attr)
1816
0
{
1817
0
  if (peer->sort == BGP_PEER_EBGP
1818
0
      && (peer_af_flag_check(peer, afi, safi,
1819
0
           PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1820
0
    || peer_af_flag_check(peer, afi, safi,
1821
0
              PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1822
0
    || peer_af_flag_check(peer, afi, safi,
1823
0
              PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1824
0
    || peer_af_flag_check(peer, afi, safi,
1825
0
              PEER_FLAG_REMOVE_PRIVATE_AS))) {
1826
    // Take action on the entire aspath
1827
0
    if (peer_af_flag_check(peer, afi, safi,
1828
0
               PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1829
0
        || peer_af_flag_check(peer, afi, safi,
1830
0
            PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1831
0
      if (peer_af_flag_check(
1832
0
            peer, afi, safi,
1833
0
            PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1834
0
        attr->aspath = aspath_replace_private_asns(
1835
0
          attr->aspath, bgp->as, peer->as);
1836
1837
      /*
1838
       * Even if the aspath consists of just private ASNs we
1839
       * need to walk the AS-Path to maintain all instances
1840
       * of the peer's ASN to break possible loops.
1841
       */
1842
0
      else
1843
0
        attr->aspath = aspath_remove_private_asns(
1844
0
          attr->aspath, peer->as);
1845
0
    }
1846
1847
    // 'all' was not specified so the entire aspath must be private
1848
    // ASNs
1849
    // for us to do anything
1850
0
    else if (aspath_private_as_check(attr->aspath)) {
1851
0
      if (peer_af_flag_check(
1852
0
            peer, afi, safi,
1853
0
            PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1854
0
        attr->aspath = aspath_replace_private_asns(
1855
0
          attr->aspath, bgp->as, peer->as);
1856
0
      else
1857
        /*
1858
         * Walk the aspath to retain any instances of
1859
         * the peer_asn
1860
         */
1861
0
        attr->aspath = aspath_remove_private_asns(
1862
0
          attr->aspath, peer->as);
1863
0
    }
1864
0
  }
1865
0
}
1866
1867
/* If this is an EBGP peer with as-override */
1868
static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1869
         struct peer *peer, struct attr *attr)
1870
0
{
1871
0
  struct aspath *aspath;
1872
1873
0
  if (peer->sort == BGP_PEER_EBGP &&
1874
0
      peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1875
0
    if (attr->aspath->refcnt)
1876
0
      aspath = aspath_dup(attr->aspath);
1877
0
    else
1878
0
      aspath = attr->aspath;
1879
1880
0
    attr->aspath = aspath_intern(
1881
0
      aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1882
1883
0
    aspath_free(aspath);
1884
0
  }
1885
0
}
1886
1887
void bgp_attr_add_llgr_community(struct attr *attr)
1888
0
{
1889
0
  struct community *old;
1890
0
  struct community *new;
1891
0
  struct community *merge;
1892
0
  struct community *llgr;
1893
1894
0
  old = bgp_attr_get_community(attr);
1895
0
  llgr = community_str2com("llgr-stale");
1896
1897
0
  assert(llgr);
1898
1899
0
  if (old) {
1900
0
    merge = community_merge(community_dup(old), llgr);
1901
1902
0
    if (old->refcnt == 0)
1903
0
      community_free(&old);
1904
1905
0
    new = community_uniq_sort(merge);
1906
0
    community_free(&merge);
1907
0
  } else {
1908
0
    new = community_dup(llgr);
1909
0
  }
1910
1911
0
  community_free(&llgr);
1912
1913
0
  bgp_attr_set_community(attr, new);
1914
0
}
1915
1916
void bgp_attr_add_gshut_community(struct attr *attr)
1917
0
{
1918
0
  struct community *old;
1919
0
  struct community *new;
1920
0
  struct community *merge;
1921
0
  struct community *gshut;
1922
1923
0
  old = bgp_attr_get_community(attr);
1924
0
  gshut = community_str2com("graceful-shutdown");
1925
1926
0
  assert(gshut);
1927
1928
0
  if (old) {
1929
0
    merge = community_merge(community_dup(old), gshut);
1930
1931
0
    if (old->refcnt == 0)
1932
0
      community_free(&old);
1933
1934
0
    new = community_uniq_sort(merge);
1935
0
    community_free(&merge);
1936
0
  } else {
1937
0
    new = community_dup(gshut);
1938
0
  }
1939
1940
0
  community_free(&gshut);
1941
0
  bgp_attr_set_community(attr, new);
1942
1943
  /* When we add the graceful-shutdown community we must also
1944
   * lower the local-preference */
1945
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1946
0
  attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1947
0
}
1948
1949
1950
/* Notify BGP Conditional advertisement scanner process. */
1951
void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1952
0
{
1953
0
  struct peer *peer = SUBGRP_PEER(subgrp);
1954
0
  afi_t afi = SUBGRP_AFI(subgrp);
1955
0
  safi_t safi = SUBGRP_SAFI(subgrp);
1956
0
  struct bgp_filter *filter = &peer->filter[afi][safi];
1957
1958
0
  if (!ADVERTISE_MAP_NAME(filter))
1959
0
    return;
1960
1961
0
  if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1962
0
    return;
1963
1964
0
  peer->advmap_table_change = true;
1965
0
}
1966
1967
1968
void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
1969
0
{
1970
0
  if (family == AF_INET) {
1971
0
    attr->nexthop.s_addr = INADDR_ANY;
1972
0
    attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
1973
0
  }
1974
0
  if (family == AF_INET6)
1975
0
    memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
1976
0
  if (family == AF_EVPN)
1977
0
    memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
1978
0
}
1979
1980
bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
1981
           struct update_subgroup *subgrp,
1982
           const struct prefix *p, struct attr *attr,
1983
           struct attr *post_attr)
1984
0
{
1985
0
  struct bgp_filter *filter;
1986
0
  struct peer *from;
1987
0
  struct peer *peer;
1988
0
  struct peer *onlypeer;
1989
0
  struct bgp *bgp;
1990
0
  struct attr *piattr;
1991
0
  route_map_result_t ret;
1992
0
  int transparent;
1993
0
  int reflect;
1994
0
  afi_t afi;
1995
0
  safi_t safi;
1996
0
  int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1997
0
  bool nh_reset = false;
1998
0
  uint64_t cum_bw;
1999
2000
0
  if (DISABLE_BGP_ANNOUNCE)
2001
0
    return false;
2002
2003
0
  afi = SUBGRP_AFI(subgrp);
2004
0
  safi = SUBGRP_SAFI(subgrp);
2005
0
  peer = SUBGRP_PEER(subgrp);
2006
0
  onlypeer = NULL;
2007
0
  if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2008
0
    onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2009
2010
0
  from = pi->peer;
2011
0
  filter = &peer->filter[afi][safi];
2012
0
  bgp = SUBGRP_INST(subgrp);
2013
0
  piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2014
0
                 : pi->attr;
2015
2016
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2017
0
      peer->pmax_out[afi][safi] != 0 &&
2018
0
      subgrp->pscount >= peer->pmax_out[afi][safi]) {
2019
0
    if (BGP_DEBUG(update, UPDATE_OUT) ||
2020
0
        BGP_DEBUG(update, UPDATE_PREFIX)) {
2021
0
      zlog_debug("%s reached maximum prefix to be send (%u)",
2022
0
           peer->host, peer->pmax_out[afi][safi]);
2023
0
    }
2024
0
    return false;
2025
0
  }
2026
2027
0
#ifdef ENABLE_BGP_VNC
2028
0
  if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
2029
0
      && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2030
0
    || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
2031
2032
    /*
2033
     * direct and direct_ext type routes originate internally even
2034
     * though they can have peer pointers that reference other
2035
     * systems
2036
     */
2037
0
    zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2038
0
         __func__, p);
2039
0
    samepeer_safe = 1;
2040
0
  }
2041
0
#endif
2042
2043
0
  if (((afi == AFI_IP) || (afi == AFI_IP6))
2044
0
      && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
2045
0
      && (pi->type == ZEBRA_ROUTE_BGP)
2046
0
      && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
2047
2048
    /* Applies to routes leaked vpn->vrf and vrf->vpn */
2049
2050
0
    samepeer_safe = 1;
2051
0
  }
2052
2053
  /* With addpath we may be asked to TX all kinds of paths so make sure
2054
   * pi is valid */
2055
0
  if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2056
0
      || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2057
0
      || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
2058
0
    return false;
2059
0
  }
2060
2061
  /* If this is not the bestpath then check to see if there is an enabled
2062
   * addpath
2063
   * feature that requires us to advertise it */
2064
0
  if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2065
0
    if (!bgp_addpath_capable(pi, peer, afi, safi))
2066
0
      return false;
2067
2068
  /* Aggregate-address suppress check. */
2069
0
  if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2070
0
    return false;
2071
2072
  /*
2073
   * If we are doing VRF 2 VRF leaking via the import
2074
   * statement, we want to prevent the route going
2075
   * off box as that the RT and RD created are localy
2076
   * significant and globaly useless.
2077
   */
2078
0
  if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2079
0
      && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
2080
0
    return false;
2081
2082
  /* If it's labeled safi, make sure the route has a valid label. */
2083
0
  if (safi == SAFI_LABELED_UNICAST) {
2084
0
    mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
2085
0
    if (!bgp_is_valid_label(&label)) {
2086
0
      if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2087
0
        zlog_debug("u%" PRIu64 ":s%" PRIu64
2088
0
             " %pFX is filtered - no label (%p)",
2089
0
             subgrp->update_group->id, subgrp->id,
2090
0
             p, &label);
2091
0
      return false;
2092
0
    }
2093
0
  }
2094
2095
  /* Do not send back route to sender. */
2096
0
  if (onlypeer && from == onlypeer) {
2097
0
    return false;
2098
0
  }
2099
2100
  /* Do not send the default route in the BGP table if the neighbor is
2101
   * configured for default-originate */
2102
0
  if (CHECK_FLAG(peer->af_flags[afi][safi],
2103
0
           PEER_FLAG_DEFAULT_ORIGINATE)) {
2104
0
    if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
2105
0
      return false;
2106
0
    else if (p->family == AF_INET6 && p->prefixlen == 0)
2107
0
      return false;
2108
0
  }
2109
2110
  /* Transparency check. */
2111
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2112
0
      && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2113
0
    transparent = 1;
2114
0
  else
2115
0
    transparent = 0;
2116
2117
  /* If community is not disabled check the no-export and local. */
2118
0
  if (!transparent && bgp_community_filter(peer, piattr)) {
2119
0
    if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2120
0
      zlog_debug("%s: community filter check fail for %pFX",
2121
0
           __func__, p);
2122
0
    return false;
2123
0
  }
2124
2125
  /* If the attribute has originator-id and it is same as remote
2126
     peer's id. */
2127
0
  if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2128
0
      && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
2129
0
    if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2130
0
      zlog_debug(
2131
0
        "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2132
0
        onlypeer, p);
2133
0
    return false;
2134
0
  }
2135
2136
  /* ORF prefix-list filter check */
2137
0
  if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2138
0
      && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2139
0
    || CHECK_FLAG(peer->af_cap[afi][safi],
2140
0
            PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2141
0
    if (peer->orf_plist[afi][safi]) {
2142
0
      if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2143
0
          == PREFIX_DENY) {
2144
0
        if (bgp_debug_update(NULL, p,
2145
0
                 subgrp->update_group, 0))
2146
0
          zlog_debug(
2147
0
            "%pBP [Update:SEND] %pFX is filtered via ORF",
2148
0
            peer, p);
2149
0
        return false;
2150
0
      }
2151
0
    }
2152
2153
  /* Output filter check. */
2154
0
  if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
2155
0
    if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2156
0
      zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2157
0
           p);
2158
0
    return false;
2159
0
  }
2160
2161
  /* AS path loop check. */
2162
0
  if (peer->as_path_loop_detection &&
2163
0
      aspath_loop_check(piattr->aspath, peer->as)) {
2164
0
    if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2165
0
      zlog_debug(
2166
0
        "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2167
0
        peer, peer->as);
2168
0
    return false;
2169
0
  }
2170
2171
  /* If we're a CONFED we need to loop check the CONFED ID too */
2172
0
  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
2173
0
    if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
2174
0
      if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2175
0
        zlog_debug(
2176
0
          "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177
0
          peer, bgp->confed_id);
2178
0
      return false;
2179
0
    }
2180
0
  }
2181
2182
  /* Route-Reflect check. */
2183
0
  if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2184
0
    reflect = 1;
2185
0
  else
2186
0
    reflect = 0;
2187
2188
  /* IBGP reflection check. */
2189
0
  if (reflect && !samepeer_safe) {
2190
    /* A route from a Client peer. */
2191
0
    if (CHECK_FLAG(from->af_flags[afi][safi],
2192
0
             PEER_FLAG_REFLECTOR_CLIENT)) {
2193
      /* Reflect to all the Non-Client peers and also to the
2194
         Client peers other than the originator.  Originator
2195
         check
2196
         is already done.  So there is noting to do. */
2197
      /* no bgp client-to-client reflection check. */
2198
0
      if (CHECK_FLAG(bgp->flags,
2199
0
               BGP_FLAG_NO_CLIENT_TO_CLIENT))
2200
0
        if (CHECK_FLAG(peer->af_flags[afi][safi],
2201
0
                 PEER_FLAG_REFLECTOR_CLIENT))
2202
0
          return false;
2203
0
    } else {
2204
      /* A route from a Non-client peer. Reflect to all other
2205
         clients. */
2206
0
      if (!CHECK_FLAG(peer->af_flags[afi][safi],
2207
0
          PEER_FLAG_REFLECTOR_CLIENT))
2208
0
        return false;
2209
0
    }
2210
0
  }
2211
2212
  /* For modify attribute, copy it to temporary structure.
2213
   * post_attr comes from BGP conditional advertisements, where
2214
   * attributes are already processed by advertise-map route-map,
2215
   * and this needs to be saved instead of overwriting from the
2216
   * path attributes.
2217
   */
2218
0
  if (post_attr)
2219
0
    *attr = *post_attr;
2220
0
  else
2221
0
    *attr = *piattr;
2222
2223
  /* If local-preference is not set. */
2224
0
  if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2225
0
      && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2226
0
    attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2227
0
    attr->local_pref = bgp->default_local_pref;
2228
0
  }
2229
2230
  /* If originator-id is not set and the route is to be reflected,
2231
     set the originator id */
2232
0
  if (reflect
2233
0
      && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2234
0
    IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2235
0
    SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2236
0
  }
2237
2238
  /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2239
   */
2240
0
  if (peer->sort == BGP_PEER_EBGP
2241
0
      && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2242
0
    if (from != bgp->peer_self && !transparent
2243
0
        && !CHECK_FLAG(peer->af_flags[afi][safi],
2244
0
           PEER_FLAG_MED_UNCHANGED))
2245
0
      attr->flag &=
2246
0
        ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2247
0
  }
2248
2249
  /* Since the nexthop attribute can vary per peer, it is not explicitly
2250
   * set
2251
   * in announce check, only certain flags and length (or number of
2252
   * nexthops
2253
   * -- for IPv6/MP_REACH) are set here in order to guide the update
2254
   * formation
2255
   * code in setting the nexthop(s) on a per peer basis in
2256
   * reformat_peer().
2257
   * Typically, the source nexthop in the attribute is preserved but in
2258
   * the
2259
   * scenarios where we know it will always be overwritten, we reset the
2260
   * nexthop to "0" in an attempt to achieve better Update packing. An
2261
   * example of this is when a prefix from each of 2 IBGP peers needs to
2262
   * be
2263
   * announced to an EBGP peer (and they have the same attributes barring
2264
   * their nexthop).
2265
   */
2266
0
  if (reflect)
2267
0
    SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2268
2269
0
#define NEXTHOP_IS_V6                                                          \
2270
0
  ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN                          \
2271
0
    && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)))        \
2272
0
   || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)                     \
2273
0
       && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2274
2275
  /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2276
   * if
2277
   * the peer (group) is configured to receive link-local nexthop
2278
   * unchanged
2279
   * and it is available in the prefix OR we're not reflecting the route,
2280
   * link-local nexthop address is valid and
2281
   * the peer (group) to whom we're going to announce is on a shared
2282
   * network
2283
   * and this is either a self-originated route or the peer is EBGP.
2284
   * By checking if nexthop LL address is valid we are sure that
2285
   * we do not announce LL address as `::`.
2286
   */
2287
0
  if (NEXTHOP_IS_V6) {
2288
0
    attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2289
0
    if ((CHECK_FLAG(peer->af_flags[afi][safi],
2290
0
        PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2291
0
         && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2292
0
        || (!reflect && !transparent
2293
0
      && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2294
0
      && peer->shared_network
2295
0
      && (from == bgp->peer_self
2296
0
          || peer->sort == BGP_PEER_EBGP))) {
2297
0
      if (safi == SAFI_MPLS_VPN)
2298
0
        attr->mp_nexthop_len =
2299
0
          BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2300
0
      else
2301
0
        attr->mp_nexthop_len =
2302
0
          BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2303
0
    }
2304
2305
    /* Clear off link-local nexthop in source, whenever it is not
2306
     * needed to
2307
     * ensure more prefixes share the same attribute for
2308
     * announcement.
2309
     */
2310
0
    if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2311
0
         PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2312
0
      memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2313
0
  }
2314
2315
0
  if (bgp_check_role_applicability(afi, safi) &&
2316
0
      bgp_otc_egress(peer, attr))
2317
0
    return false;
2318
2319
0
  bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2320
0
  bgp_peer_as_override(bgp, afi, safi, peer, attr);
2321
2322
0
  if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2323
0
      filter->advmap.aname &&
2324
0
      route_map_lookup_by_name(filter->advmap.aname)) {
2325
0
    struct bgp_path_info rmap_path = {0};
2326
0
    struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2327
0
    struct attr dummy_attr = *attr;
2328
2329
    /* Fill temp path_info */
2330
0
    prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2331
0
            pi, peer, &dummy_attr);
2332
2333
0
    struct route_map *amap =
2334
0
      route_map_lookup_by_name(filter->advmap.aname);
2335
2336
0
    ret = route_map_apply(amap, p, &rmap_path);
2337
2338
0
    bgp_attr_flush(&dummy_attr);
2339
2340
    /*
2341
     * The conditional advertisement mode is Withdraw and this
2342
     * prefix is a conditional prefix. Don't advertise it
2343
     */
2344
0
    if (ret == RMAP_PERMITMATCH)
2345
0
      return false;
2346
0
  }
2347
2348
  /* Route map & unsuppress-map apply. */
2349
0
  if (!post_attr &&
2350
0
      (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
2351
0
    struct bgp_path_info rmap_path = {0};
2352
0
    struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2353
0
    struct attr dummy_attr = {0};
2354
2355
    /* Fill temp path_info */
2356
0
    prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2357
0
            pi, peer, attr);
2358
2359
    /* don't confuse inbound and outbound setting */
2360
0
    RESET_FLAG(attr->rmap_change_flags);
2361
2362
    /*
2363
     * The route reflector is not allowed to modify the attributes
2364
     * of the reflected IBGP routes unless explicitly allowed.
2365
     */
2366
0
    if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2367
0
        && !CHECK_FLAG(bgp->flags,
2368
0
           BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
2369
0
      dummy_attr = *attr;
2370
0
      rmap_path.attr = &dummy_attr;
2371
0
    }
2372
2373
0
    SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
2374
2375
0
    if (bgp_path_suppressed(pi))
2376
0
      ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
2377
0
                &rmap_path);
2378
0
    else
2379
0
      ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
2380
0
                &rmap_path);
2381
2382
0
    bgp_attr_flush(&dummy_attr);
2383
0
    peer->rmap_type = 0;
2384
2385
0
    if (ret == RMAP_DENYMATCH) {
2386
0
      if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2387
0
        zlog_debug(
2388
0
          "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2389
0
          peer, p,
2390
0
          bgp_path_suppressed(pi)
2391
0
            ? UNSUPPRESS_MAP_NAME(filter)
2392
0
            : ROUTE_MAP_OUT_NAME(filter));
2393
0
      bgp_attr_flush(rmap_path.attr);
2394
0
      return false;
2395
0
    }
2396
0
  }
2397
2398
  /* RFC 8212 to prevent route leaks.
2399
   * This specification intends to improve this situation by requiring the
2400
   * explicit configuration of both BGP Import and Export Policies for any
2401
   * External BGP (EBGP) session such as customers, peers, or
2402
   * confederation boundaries for all enabled address families. Through
2403
   * codification of the aforementioned requirement, operators will
2404
   * benefit from consistent behavior across different BGP
2405
   * implementations.
2406
   */
2407
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
2408
0
    if (!bgp_outbound_policy_exists(peer, filter)) {
2409
0
      if (monotime_since(&bgp->ebgprequirespolicywarning,
2410
0
             NULL) > FIFTEENMINUTE2USEC ||
2411
0
          bgp->ebgprequirespolicywarning.tv_sec == 0) {
2412
0
        zlog_warn(
2413
0
          "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414
0
        monotime(&bgp->ebgprequirespolicywarning);
2415
0
      }
2416
0
      return false;
2417
0
    }
2418
2419
  /* draft-ietf-idr-deprecate-as-set-confed-set
2420
   * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421
   * Eventually, This document (if approved) updates RFC 4271
2422
   * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423
   * and obsoletes RFC 6472.
2424
   */
2425
0
  if (peer->bgp->reject_as_sets)
2426
0
    if (aspath_check_as_sets(attr->aspath))
2427
0
      return false;
2428
2429
  /* If neighbor soo is configured, then check if the route has
2430
   * SoO extended community and validate against the configured
2431
   * one. If they match, do not announce, to prevent routing
2432
   * loops.
2433
   */
2434
0
  if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2435
0
      peer->soo[afi][safi]) {
2436
0
    struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2437
0
    struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2438
2439
0
    if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2440
0
               ECOMMUNITY_SITE_ORIGIN) ||
2441
0
         ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
2442
0
               ECOMMUNITY_SITE_ORIGIN) ||
2443
0
         ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
2444
0
               ECOMMUNITY_SITE_ORIGIN)) &&
2445
0
        ecommunity_include(ecomm, ecomm_soo)) {
2446
0
      if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2447
0
        zlog_debug(
2448
0
          "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449
0
          peer, p, ecommunity_str(ecomm_soo));
2450
0
      return false;
2451
0
    }
2452
0
  }
2453
2454
  /* Codification of AS 0 Processing */
2455
0
  if (aspath_check_as_zero(attr->aspath))
2456
0
    return false;
2457
2458
0
  if (bgp_in_graceful_shutdown(bgp)) {
2459
0
    if (peer->sort == BGP_PEER_IBGP
2460
0
        || peer->sort == BGP_PEER_CONFED) {
2461
0
      attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2462
0
      attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2463
0
    } else {
2464
0
      bgp_attr_add_gshut_community(attr);
2465
0
    }
2466
0
  }
2467
2468
  /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469
   * Capability" to a neighbor MUST perform the following upon receiving
2470
   * a route from that neighbor with the "LLGR_STALE" community, or upon
2471
   * attaching the "LLGR_STALE" community itself per Section 4.2:
2472
   *
2473
   * The route SHOULD NOT be advertised to any neighbor from which the
2474
   * Long-lived Graceful Restart Capability has not been received.
2475
   */
2476
0
  if (bgp_attr_get_community(attr) &&
2477
0
      community_include(bgp_attr_get_community(attr),
2478
0
            COMMUNITY_LLGR_STALE) &&
2479
0
      !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2480
0
      !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2481
0
    return false;
2482
2483
  /* After route-map has been applied, we check to see if the nexthop to
2484
   * be carried in the attribute (that is used for the announcement) can
2485
   * be cleared off or not. We do this in all cases where we would be
2486
   * setting the nexthop to "ourselves". For IPv6, we only need to
2487
   * consider
2488
   * the global nexthop here; the link-local nexthop would have been
2489
   * cleared
2490
   * already, and if not, it is required by the update formation code.
2491
   * Also see earlier comments in this function.
2492
   */
2493
  /*
2494
   * If route-map has performed some operation on the nexthop or the peer
2495
   * configuration says to pass it unchanged, we cannot reset the nexthop
2496
   * here, so only attempt to do it if these aren't true. Note that the
2497
   * route-map handler itself might have cleared the nexthop, if for
2498
   * example,
2499
   * it is configured as 'peer-address'.
2500
   */
2501
0
  if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
2502
0
           piattr->rmap_change_flags)
2503
0
      && !transparent
2504
0
      && !CHECK_FLAG(peer->af_flags[afi][safi],
2505
0
         PEER_FLAG_NEXTHOP_UNCHANGED)) {
2506
    /* We can reset the nexthop, if setting (or forcing) it to
2507
     * 'self' */
2508
0
    if (CHECK_FLAG(peer->af_flags[afi][safi],
2509
0
             PEER_FLAG_NEXTHOP_SELF)
2510
0
        || CHECK_FLAG(peer->af_flags[afi][safi],
2511
0
          PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2512
0
      if (!reflect
2513
0
          || CHECK_FLAG(peer->af_flags[afi][safi],
2514
0
            PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2515
0
        subgroup_announce_reset_nhop(
2516
0
          (peer_cap_enhe(peer, afi, safi)
2517
0
             ? AF_INET6
2518
0
             : p->family),
2519
0
          attr);
2520
0
        nh_reset = true;
2521
0
      }
2522
0
    } else if (peer->sort == BGP_PEER_EBGP) {
2523
      /* Can also reset the nexthop if announcing to EBGP, but
2524
       * only if
2525
       * no peer in the subgroup is on a shared subnet.
2526
       * Note: 3rd party nexthop currently implemented for
2527
       * IPv4 only.
2528
       */
2529
0
      if ((p->family == AF_INET) &&
2530
0
        (!bgp_subgrp_multiaccess_check_v4(
2531
0
          piattr->nexthop,
2532
0
          subgrp, from))) {
2533
0
        subgroup_announce_reset_nhop(
2534
0
          (peer_cap_enhe(peer, afi, safi)
2535
0
             ? AF_INET6
2536
0
             : p->family),
2537
0
            attr);
2538
0
        nh_reset = true;
2539
0
      }
2540
2541
0
      if ((p->family == AF_INET6) &&
2542
0
        (!bgp_subgrp_multiaccess_check_v6(
2543
0
          piattr->mp_nexthop_global,
2544
0
          subgrp, from))) {
2545
0
        subgroup_announce_reset_nhop(
2546
0
          (peer_cap_enhe(peer, afi, safi)
2547
0
            ? AF_INET6
2548
0
            : p->family),
2549
0
            attr);
2550
0
        nh_reset = true;
2551
0
      }
2552
2553
2554
2555
0
    } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
2556
      /*
2557
       * This flag is used for leaked vpn-vrf routes
2558
       */
2559
0
      int family = p->family;
2560
2561
0
      if (peer_cap_enhe(peer, afi, safi))
2562
0
        family = AF_INET6;
2563
2564
0
      if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2565
0
        zlog_debug(
2566
0
          "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567
0
          __func__, p, family2str(family));
2568
0
      subgroup_announce_reset_nhop(family, attr);
2569
0
      nh_reset = true;
2570
0
    }
2571
0
  }
2572
2573
  /* If IPv6/MP and nexthop does not have any override and happens
2574
   * to
2575
   * be a link-local address, reset it so that we don't pass along
2576
   * the
2577
   * source's link-local IPv6 address to recipients who may not be
2578
   * on
2579
   * the same interface.
2580
   */
2581
0
  if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2582
0
    if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2583
0
      subgroup_announce_reset_nhop(AF_INET6, attr);
2584
0
        nh_reset = true;
2585
0
      }
2586
0
  }
2587
2588
  /* If this is an iBGP, send Origin Validation State (OVS)
2589
   * extended community (rfc8097).
2590
   */
2591
0
  if (peer->sort == BGP_PEER_IBGP) {
2592
0
    enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2593
2594
0
    rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2595
2596
0
    if (rpki_state != RPKI_NOT_BEING_USED)
2597
0
      bgp_attr_set_ecommunity(
2598
0
        attr, ecommunity_add_origin_validation_state(
2599
0
                rpki_state,
2600
0
                bgp_attr_get_ecommunity(attr)));
2601
0
  }
2602
2603
  /*
2604
   * When the next hop is set to ourselves, if all multipaths have
2605
   * link-bandwidth announce the cumulative bandwidth as that makes
2606
   * the most sense. However, don't modify if the link-bandwidth has
2607
   * been explicitly set by user policy.
2608
   */
2609
0
  if (nh_reset &&
2610
0
      bgp_path_info_mpath_chkwtd(bgp, pi) &&
2611
0
      (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2612
0
      !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2613
0
    bgp_attr_set_ecommunity(
2614
0
      attr,
2615
0
      ecommunity_replace_linkbw(
2616
0
        bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2617
0
        CHECK_FLAG(
2618
0
          peer->flags,
2619
0
          PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
2620
2621
0
  return true;
2622
0
}
2623
2624
static void bgp_route_select_timer_expire(struct event *thread)
2625
0
{
2626
0
  struct afi_safi_info *info;
2627
0
  afi_t afi;
2628
0
  safi_t safi;
2629
0
  struct bgp *bgp;
2630
0
2631
0
  info = EVENT_ARG(thread);
2632
0
  afi = info->afi;
2633
0
  safi = info->safi;
2634
0
  bgp = info->bgp;
2635
0
2636
0
  bgp->gr_info[afi][safi].t_route_select = NULL;
2637
0
  XFREE(MTYPE_TMP, info);
2638
0
2639
0
  /* Best path selection */
2640
0
  bgp_best_path_select_defer(bgp, afi, safi);
2641
0
}
2642
2643
void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
2644
      struct bgp_maxpaths_cfg *mpath_cfg,
2645
      struct bgp_path_info_pair *result, afi_t afi,
2646
      safi_t safi)
2647
0
{
2648
0
  struct bgp_path_info *new_select;
2649
0
  struct bgp_path_info *old_select;
2650
0
  struct bgp_path_info *pi;
2651
0
  struct bgp_path_info *pi1;
2652
0
  struct bgp_path_info *pi2;
2653
0
  struct bgp_path_info *nextpi = NULL;
2654
0
  int paths_eq, do_mpath, debug;
2655
0
  struct list mp_list;
2656
0
  char pfx_buf[PREFIX2STR_BUFFER] = {};
2657
0
  char path_buf[PATH_ADDPATH_STR_BUFFER];
2658
2659
0
  bgp_mp_list_init(&mp_list);
2660
0
  do_mpath =
2661
0
    (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2662
2663
0
  debug = bgp_debug_bestpath(dest);
2664
2665
0
  if (debug)
2666
0
    prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
2667
2668
0
  dest->reason = bgp_path_selection_none;
2669
  /* bgp deterministic-med */
2670
0
  new_select = NULL;
2671
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
2672
2673
    /* Clear BGP_PATH_DMED_SELECTED for all paths */
2674
0
    for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2675
0
         pi1 = pi1->next)
2676
0
      bgp_path_info_unset_flag(dest, pi1,
2677
0
             BGP_PATH_DMED_SELECTED);
2678
2679
0
    for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2680
0
         pi1 = pi1->next) {
2681
0
      if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
2682
0
        continue;
2683
0
      if (BGP_PATH_HOLDDOWN(pi1))
2684
0
        continue;
2685
0
      if (pi1->peer != bgp->peer_self &&
2686
0
          !CHECK_FLAG(pi1->peer->sflags,
2687
0
          PEER_STATUS_NSF_WAIT)) {
2688
0
        if (!peer_established(pi1->peer))
2689
0
          continue;
2690
0
      }
2691
2692
0
      new_select = pi1;
2693
0
      if (pi1->next) {
2694
0
        for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2695
0
          if (CHECK_FLAG(pi2->flags,
2696
0
                   BGP_PATH_DMED_CHECK))
2697
0
            continue;
2698
0
          if (BGP_PATH_HOLDDOWN(pi2))
2699
0
            continue;
2700
0
          if (pi2->peer != bgp->peer_self
2701
0
              && !CHECK_FLAG(
2702
0
                pi2->peer->sflags,
2703
0
                PEER_STATUS_NSF_WAIT))
2704
0
            if (pi2->peer->status
2705
0
                != Established)
2706
0
              continue;
2707
2708
0
          if (!aspath_cmp_left(pi1->attr->aspath,
2709
0
                   pi2->attr->aspath)
2710
0
              && !aspath_cmp_left_confed(
2711
0
                   pi1->attr->aspath,
2712
0
                   pi2->attr->aspath))
2713
0
            continue;
2714
2715
0
          if (bgp_path_info_cmp(
2716
0
                bgp, pi2, new_select,
2717
0
                &paths_eq, mpath_cfg, debug,
2718
0
                pfx_buf, afi, safi,
2719
0
                &dest->reason)) {
2720
0
            bgp_path_info_unset_flag(
2721
0
              dest, new_select,
2722
0
              BGP_PATH_DMED_SELECTED);
2723
0
            new_select = pi2;
2724
0
          }
2725
2726
0
          bgp_path_info_set_flag(
2727
0
            dest, pi2, BGP_PATH_DMED_CHECK);
2728
0
        }
2729
0
      }
2730
0
      bgp_path_info_set_flag(dest, new_select,
2731
0
                 BGP_PATH_DMED_CHECK);
2732
0
      bgp_path_info_set_flag(dest, new_select,
2733
0
                 BGP_PATH_DMED_SELECTED);
2734
2735
0
      if (debug) {
2736
0
        bgp_path_info_path_with_addpath_rx_str(
2737
0
          new_select, path_buf, sizeof(path_buf));
2738
0
        zlog_debug(
2739
0
          "%pBD(%s): %s is the bestpath from AS %u",
2740
0
          dest, bgp->name_pretty, path_buf,
2741
0
          aspath_get_first_as(
2742
0
            new_select->attr->aspath));
2743
0
      }
2744
0
    }
2745
0
  }
2746
2747
  /* Check old selected route and new selected route. */
2748
0
  old_select = NULL;
2749
0
  new_select = NULL;
2750
0
  for (pi = bgp_dest_get_bgp_path_info(dest);
2751
0
       (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2752
0
    enum bgp_path_selection_reason reason;
2753
2754
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2755
0
      old_select = pi;
2756
2757
0
    if (BGP_PATH_HOLDDOWN(pi)) {
2758
      /* reap REMOVED routes, if needs be
2759
       * selected route must stay for a while longer though
2760
       */
2761
0
      if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2762
0
          && (pi != old_select))
2763
0
        bgp_path_info_reap(dest, pi);
2764
2765
0
      if (debug)
2766
0
        zlog_debug(
2767
0
          "%s: %pBD(%s) pi from %s in holddown",
2768
0
          __func__, dest, bgp->name_pretty,
2769
0
          pi->peer->host);
2770
2771
0
      continue;
2772
0
    }
2773
2774
0
    if (pi->peer && pi->peer != bgp->peer_self
2775
0
        && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2776
0
      if (!peer_established(pi->peer)) {
2777
2778
0
        if (debug)
2779
0
          zlog_debug(
2780
0
            "%s: %pBD(%s) non self peer %s not estab state",
2781
0
            __func__, dest,
2782
0
            bgp->name_pretty,
2783
0
            pi->peer->host);
2784
2785
0
        continue;
2786
0
      }
2787
2788
0
    if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
2789
0
        && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2790
0
      bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2791
0
      if (debug)
2792
0
        zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
2793
0
             dest, bgp->name_pretty,
2794
0
             pi->peer->host);
2795
0
      continue;
2796
0
    }
2797
2798
0
    bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2799
2800
0
    reason = dest->reason;
2801
0
    if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
2802
0
              debug, pfx_buf, afi, safi,
2803
0
              &dest->reason)) {
2804
0
      if (new_select == NULL &&
2805
0
          reason != bgp_path_selection_none)
2806
0
        dest->reason = reason;
2807
0
      new_select = pi;
2808
0
    }
2809
0
  }
2810
2811
  /* Now that we know which path is the bestpath see if any of the other
2812
   * paths
2813
   * qualify as multipaths
2814
   */
2815
0
  if (debug) {
2816
0
    if (new_select)
2817
0
      bgp_path_info_path_with_addpath_rx_str(
2818
0
        new_select, path_buf, sizeof(path_buf));
2819
0
    else
2820
0
      snprintf(path_buf, sizeof(path_buf), "NONE");
2821
0
    zlog_debug(
2822
0
      "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823
0
      dest, bgp->name_pretty, path_buf,
2824
0
      old_select ? old_select->peer->host : "NONE");
2825
0
  }
2826
2827
0
  if (do_mpath && new_select) {
2828
0
    for (pi = bgp_dest_get_bgp_path_info(dest);
2829
0
         (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2830
2831
0
      if (debug)
2832
0
        bgp_path_info_path_with_addpath_rx_str(
2833
0
          pi, path_buf, sizeof(path_buf));
2834
2835
0
      if (pi == new_select) {
2836
0
        if (debug)
2837
0
          zlog_debug(
2838
0
            "%pBD(%s): %s is the bestpath, add to the multipath list",
2839
0
            dest, bgp->name_pretty,
2840
0
            path_buf);
2841
0
        bgp_mp_list_add(&mp_list, pi);
2842
0
        continue;
2843
0
      }
2844
2845
0
      if (BGP_PATH_HOLDDOWN(pi))
2846
0
        continue;
2847
2848
0
      if (pi->peer && pi->peer != bgp->peer_self
2849
0
          && !CHECK_FLAG(pi->peer->sflags,
2850
0
             PEER_STATUS_NSF_WAIT))
2851
0
        if (!peer_established(pi->peer))
2852
0
          continue;
2853
2854
0
      if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
2855
0
        if (debug)
2856
0
          zlog_debug(
2857
0
            "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858
0
            dest, bgp->name_pretty,
2859
0
            path_buf);
2860
0
        continue;
2861
0
      }
2862
2863
0
      bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
2864
0
            mpath_cfg, debug, pfx_buf, afi, safi,
2865
0
            &dest->reason);
2866
2867
0
      if (paths_eq) {
2868
0
        if (debug)
2869
0
          zlog_debug(
2870
0
            "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871
0
            dest, bgp->name_pretty,
2872
0
            path_buf);
2873
0
        bgp_mp_list_add(&mp_list, pi);
2874
0
      }
2875
0
    }
2876
0
  }
2877
2878
0
  bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
2879
0
           mpath_cfg);
2880
0
  bgp_path_info_mpath_aggregate_update(new_select, old_select);
2881
0
  bgp_mp_list_clear(&mp_list);
2882
2883
0
  bgp_addpath_update_ids(bgp, dest, afi, safi);
2884
2885
0
  result->old = old_select;
2886
0
  result->new = new_select;
2887
2888
0
  return;
2889
0
}
2890
2891
/*
2892
 * A new route/change in bestpath of an existing route. Evaluate the path
2893
 * for advertisement to the subgroup.
2894
 */
2895
void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2896
          struct bgp_path_info *selected,
2897
          struct bgp_dest *dest, afi_t afi,
2898
          safi_t safi, uint32_t addpath_tx_id)
2899
0
{
2900
0
  const struct prefix *p;
2901
0
  struct peer *onlypeer;
2902
0
  struct attr attr;
2903
0
  struct bgp *bgp;
2904
0
  bool advertise;
2905
2906
0
  p = bgp_dest_get_prefix(dest);
2907
0
  bgp = SUBGRP_INST(subgrp);
2908
0
  onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2909
0
             : NULL);
2910
2911
0
  if (BGP_DEBUG(update, UPDATE_OUT))
2912
0
    zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
2913
2914
  /* First update is deferred until ORF or ROUTE-REFRESH is received */
2915
0
  if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2916
0
           PEER_STATUS_ORF_WAIT_REFRESH))
2917
0
    return;
2918
2919
0
  memset(&attr, 0, sizeof(attr));
2920
  /* It's initialized in bgp_announce_check() */
2921
2922
  /* Announcement to the subgroup. If the route is filtered withdraw it.
2923
   * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2924
   * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2925
   * route
2926
   */
2927
0
  advertise = bgp_check_advertise(bgp, dest);
2928
2929
0
  if (selected) {
2930
0
    if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2931
0
              NULL)) {
2932
      /* Route is selected, if the route is already installed
2933
       * in FIB, then it is advertised
2934
       */
2935
0
      if (advertise) {
2936
0
        if (!bgp_check_withdrawal(bgp, dest)) {
2937
0
          struct attr *adv_attr =
2938
0
            bgp_attr_intern(&attr);
2939
2940
0
          bgp_adj_out_set_subgroup(dest, subgrp,
2941
0
                 adv_attr,
2942
0
                 selected);
2943
0
        } else
2944
0
          bgp_adj_out_unset_subgroup(
2945
0
            dest, subgrp, 1, addpath_tx_id);
2946
0
      }
2947
0
    } else
2948
0
      bgp_adj_out_unset_subgroup(dest, subgrp, 1,
2949
0
               addpath_tx_id);
2950
0
  }
2951
2952
  /* If selected is NULL we must withdraw the path using addpath_tx_id */
2953
0
  else {
2954
0
    bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
2955
0
  }
2956
0
}
2957
2958
/*
2959
 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2960
 * This is called at the end of route processing.
2961
 */
2962
void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
2963
0
{
2964
0
  struct bgp_path_info *pi;
2965
2966
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2967
0
    if (BGP_PATH_HOLDDOWN(pi))
2968
0
      continue;
2969
0
    UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2970
0
    UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
2971
0
  }
2972
0
}
2973
2974
/*
2975
 * Has the route changed from the RIB's perspective? This is invoked only
2976
 * if the route selection returns the same best route as earlier - to
2977
 * determine if we need to update zebra or not.
2978
 */
2979
bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
2980
0
{
2981
0
  struct bgp_path_info *mpinfo;
2982
2983
  /* If this is multipath, check all selected paths for any nexthop
2984
   * change or attribute change. Some attribute changes (e.g., community)
2985
   * aren't of relevance to the RIB, but we'll update zebra to ensure
2986
   * we handle the case of BGP nexthop change. This is the behavior
2987
   * when the best path has an attribute change anyway.
2988
   */
2989
0
  if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2990
0
      || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2991
0
      || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
2992
0
    return true;
2993
2994
  /*
2995
   * If this is multipath, check all selected paths for any nexthop change
2996
   */
2997
0
  for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2998
0
       mpinfo = bgp_path_info_mpath_next(mpinfo)) {
2999
0
    if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3000
0
        || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3001
0
      return true;
3002
0
  }
3003
3004
  /* Nothing has changed from the RIB's perspective. */
3005
0
  return false;
3006
0
}
3007
3008
struct bgp_process_queue {
3009
  struct bgp *bgp;
3010
  STAILQ_HEAD(, bgp_dest) pqueue;
3011
#define BGP_PROCESS_QUEUE_EOIU_MARKER   (1 << 0)
3012
  unsigned int flags;
3013
  unsigned int queued;
3014
};
3015
3016
static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
3017
               safi_t safi, struct bgp_dest *dest,
3018
               struct bgp_path_info *new_select,
3019
               struct bgp_path_info *old_select)
3020
0
{
3021
0
  const struct prefix *p = bgp_dest_get_prefix(dest);
3022
3023
0
  if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3024
0
    return;
3025
3026
0
  if (advertise_type5_routes(bgp, afi) && new_select
3027
0
      && is_route_injectable_into_evpn(new_select)) {
3028
3029
    /* apply the route-map */
3030
0
    if (bgp->adv_cmd_rmap[afi][safi].map) {
3031
0
      route_map_result_t ret;
3032
0
      struct bgp_path_info rmap_path;
3033
0
      struct bgp_path_info_extra rmap_path_extra;
3034
0
      struct attr dummy_attr;
3035
3036
0
      dummy_attr = *new_select->attr;
3037
3038
      /* Fill temp path_info */
3039
0
      prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3040
0
              new_select, new_select->peer,
3041
0
              &dummy_attr);
3042
3043
0
      RESET_FLAG(dummy_attr.rmap_change_flags);
3044
3045
0
      ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
3046
0
                p, &rmap_path);
3047
3048
0
      if (ret == RMAP_DENYMATCH) {
3049
0
        bgp_attr_flush(&dummy_attr);
3050
0
        bgp_evpn_withdraw_type5_route(bgp, p, afi,
3051
0
                    safi);
3052
0
      } else
3053
0
        bgp_evpn_advertise_type5_route(
3054
0
          bgp, p, &dummy_attr, afi, safi);
3055
0
    } else {
3056
0
      bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3057
0
                   afi, safi);
3058
0
    }
3059
0
  } else if (advertise_type5_routes(bgp, afi) && old_select
3060
0
       && is_route_injectable_into_evpn(old_select))
3061
0
    bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3062
0
}
3063
3064
/*
3065
 * Utility to determine whether a particular path_info should use
3066
 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3067
 * in a path where we basically _know_ this is a BGP-LU route.
3068
 */
3069
static bool bgp_lu_need_null_label(struct bgp *bgp,
3070
           const struct bgp_path_info *new_select,
3071
           afi_t afi, mpls_label_t *label)
3072
0
{
3073
  /* Certain types get imp null; so do paths where the nexthop is
3074
   * not labeled.
3075
   */
3076
0
  if (new_select->sub_type == BGP_ROUTE_STATIC
3077
0
      || new_select->sub_type == BGP_ROUTE_AGGREGATE
3078
0
      || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3079
0
    goto need_null_label;
3080
0
  else if (new_select->extra &&
3081
0
     bgp_is_valid_label(&new_select->extra->label[0]))
3082
0
    return false;
3083
0
need_null_label:
3084
0
  if (label == NULL)
3085
0
    return true;
3086
  /* Disable PHP : explicit-null */
3087
0
  if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&
3088
0
      afi == AFI_IP)
3089
0
    *label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
3090
0
  else if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL) &&
3091
0
     afi == AFI_IP6)
3092
0
    *label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
3093
0
  else
3094
    /* Enforced PHP popping: implicit-null */
3095
0
    *label = MPLS_LABEL_IMPLICIT_NULL;
3096
3097
0
  return true;
3098
0
}
3099
3100
/*
3101
 * old_select = The old best path
3102
 * new_select = the new best path
3103
 *
3104
 * if (!old_select && new_select)
3105
 *     We are sending new information on.
3106
 *
3107
 * if (old_select && new_select) {
3108
 *         if (new_select != old_select)
3109
 *                 We have a new best path send a change
3110
 *         else
3111
 *                 We've received a update with new attributes that needs
3112
 *                 to be passed on.
3113
 * }
3114
 *
3115
 * if (old_select && !new_select)
3116
 *     We have no eligible route that we can announce or the rn
3117
 *     is being removed.
3118
 */
3119
static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
3120
         afi_t afi, safi_t safi)
3121
0
{
3122
0
  struct bgp_path_info *new_select;
3123
0
  struct bgp_path_info *old_select;
3124
0
  struct bgp_path_info_pair old_and_new;
3125
0
  int debug = 0;
3126
0
  mpls_label_t mpls_label_null;
3127
3128
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
3129
0
    if (dest)
3130
0
      debug = bgp_debug_bestpath(dest);
3131
0
    if (debug)
3132
0
      zlog_debug(
3133
0
        "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3134
0
        __func__, dest, bgp->name_pretty);
3135
0
    return;
3136
0
  }
3137
  /* Is it end of initial update? (after startup) */
3138
0
  if (!dest) {
3139
0
    frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3140
0
            sizeof(bgp->update_delay_zebra_resume_time));
3141
3142
0
    bgp->main_zebra_update_hold = 0;
3143
0
    FOREACH_AFI_SAFI (afi, safi) {
3144
0
      if (bgp_fibupd_safi(safi))
3145
0
        bgp_zebra_announce_table(bgp, afi, safi);
3146
0
    }
3147
0
    bgp->main_peers_update_hold = 0;
3148
3149
0
    bgp_start_routeadv(bgp);
3150
0
    return;
3151
0
  }
3152
3153
0
  const struct prefix *p = bgp_dest_get_prefix(dest);
3154
3155
0
  debug = bgp_debug_bestpath(dest);
3156
0
  if (debug)
3157
0
    zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__,
3158
0
         dest, bgp->name_pretty, afi2str(afi),
3159
0
         safi2str(safi));
3160
3161
  /* The best path calculation for the route is deferred if
3162
   * BGP_NODE_SELECT_DEFER is set
3163
   */
3164
0
  if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3165
0
    if (BGP_DEBUG(update, UPDATE_OUT))
3166
0
      zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3167
0
           dest, bgp->name_pretty);
3168
0
    return;
3169
0
  }
3170
3171
  /* Best path selection. */
3172
0
  bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
3173
0
         afi, safi);
3174
0
  old_select = old_and_new.old;
3175
0
  new_select = old_and_new.new;
3176
3177
  /* Do we need to allocate or free labels?
3178
   * Right now, since we only deal with per-prefix labels, it is not
3179
   * necessary to do this upon changes to best path. Exceptions:
3180
   * - label index has changed -> recalculate resulting label
3181
   * - path_info sub_type changed -> switch to/from null label value
3182
   * - no valid label (due to removed static label binding) -> get new one
3183
   */
3184
0
  if (bgp->allocate_mpls_labels[afi][safi]) {
3185
0
    if (new_select) {
3186
0
      if (!old_select
3187
0
          || bgp_label_index_differs(new_select, old_select)
3188
0
          || new_select->sub_type != old_select->sub_type
3189
0
          || !bgp_is_valid_label(&dest->local_label)) {
3190
        /* control label imposition for local routes,
3191
         * aggregate and redistributed routes
3192
         */
3193
0
        mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
3194
0
        if (bgp_lu_need_null_label(bgp, new_select, afi,
3195
0
                 &mpls_label_null)) {
3196
0
          if (CHECK_FLAG(
3197
0
                dest->flags,
3198
0
                BGP_NODE_REGISTERED_FOR_LABEL)
3199
0
              || CHECK_FLAG(
3200
0
                dest->flags,
3201
0
                BGP_NODE_LABEL_REQUESTED))
3202
0
            bgp_unregister_for_label(dest);
3203
0
          dest->local_label = mpls_lse_encode(
3204
0
            mpls_label_null, 0, 0, 1);
3205
0
          bgp_set_valid_label(&dest->local_label);
3206
0
        } else
3207
0
          bgp_register_for_label(dest,
3208
0
                     new_select);
3209
0
      }
3210
0
    } else if (CHECK_FLAG(dest->flags,
3211
0
              BGP_NODE_REGISTERED_FOR_LABEL)
3212
0
         || CHECK_FLAG(dest->flags,
3213
0
           BGP_NODE_LABEL_REQUESTED)) {
3214
0
      bgp_unregister_for_label(dest);
3215
0
    }
3216
0
  } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3217
0
       || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
3218
0
    bgp_unregister_for_label(dest);
3219
0
  }
3220
3221
0
  if (debug)
3222
0
    zlog_debug(
3223
0
      "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3224
0
      __func__, dest, bgp->name_pretty, afi2str(afi),
3225
0
      safi2str(safi), old_select, new_select);
3226
3227
  /* If best route remains the same and this is not due to user-initiated
3228
   * clear, see exactly what needs to be done.
3229
   */
3230
0
  if (old_select && old_select == new_select
3231
0
      && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
3232
0
      && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
3233
0
      && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
3234
0
    if (bgp_zebra_has_route_changed(old_select)) {
3235
0
#ifdef ENABLE_BGP_VNC
3236
0
      vnc_import_bgp_add_route(bgp, p, old_select);
3237
0
      vnc_import_bgp_exterior_add_route(bgp, p, old_select);
3238
0
#endif
3239
0
      if (bgp_fibupd_safi(safi)
3240
0
          && !bgp_option_check(BGP_OPT_NO_FIB)) {
3241
3242
0
        if (new_select->type == ZEBRA_ROUTE_BGP
3243
0
            && (new_select->sub_type == BGP_ROUTE_NORMAL
3244
0
          || new_select->sub_type
3245
0
               == BGP_ROUTE_IMPORTED))
3246
3247
0
          bgp_zebra_announce(dest, p, old_select,
3248
0
                 bgp, afi, safi);
3249
0
      }
3250
0
    }
3251
3252
    /* If there is a change of interest to peers, reannounce the
3253
     * route. */
3254
0
    if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
3255
0
        || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3256
0
        || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3257
0
      group_announce_route(bgp, afi, safi, dest, new_select);
3258
3259
      /* unicast routes must also be annouced to
3260
       * labeled-unicast update-groups */
3261
0
      if (safi == SAFI_UNICAST)
3262
0
        group_announce_route(bgp, afi,
3263
0
                 SAFI_LABELED_UNICAST, dest,
3264
0
                 new_select);
3265
3266
0
      UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
3267
0
      UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
3268
0
    }
3269
3270
    /* advertise/withdraw type-5 routes */
3271
0
    if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3272
0
        || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3273
0
      bgp_process_evpn_route_injection(
3274
0
        bgp, afi, safi, dest, old_select, old_select);
3275
3276
0
    UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3277
0
    UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
3278
0
    bgp_zebra_clear_route_change_flags(dest);
3279
0
    UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3280
0
    return;
3281
0
  }
3282
3283
  /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3284
   */
3285
0
  UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
3286
3287
  /* bestpath has changed; bump version */
3288
0
  if (old_select || new_select) {
3289
0
    bgp_bump_version(dest);
3290
3291
0
    if (!bgp->t_rmap_def_originate_eval) {
3292
0
      bgp_lock(bgp);
3293
0
      event_add_timer(
3294
0
        bm->master,
3295
0
        update_group_refresh_default_originate_route_map,
3296
0
        bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3297
0
        &bgp->t_rmap_def_originate_eval);
3298
0
    }
3299
0
  }
3300
3301
0
  if (old_select)
3302
0
    bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
3303
0
  if (new_select) {
3304
0
    if (debug)
3305
0
      zlog_debug("%s: setting SELECTED flag", __func__);
3306
0
    bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3307
0
    bgp_path_info_unset_flag(dest, new_select,
3308
0
           BGP_PATH_ATTR_CHANGED);
3309
0
    UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
3310
0
    UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
3311
0
  }
3312
3313
0
#ifdef ENABLE_BGP_VNC
3314
0
  if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3315
0
    if (old_select != new_select) {
3316
0
      if (old_select) {
3317
0
        vnc_import_bgp_exterior_del_route(bgp, p,
3318
0
                  old_select);
3319
0
        vnc_import_bgp_del_route(bgp, p, old_select);
3320
0
      }
3321
0
      if (new_select) {
3322
0
        vnc_import_bgp_exterior_add_route(bgp, p,
3323
0
                  new_select);
3324
0
        vnc_import_bgp_add_route(bgp, p, new_select);
3325
0
      }
3326
0
    }
3327
0
  }
3328
0
#endif
3329
3330
0
  group_announce_route(bgp, afi, safi, dest, new_select);
3331
3332
  /* unicast routes must also be annouced to labeled-unicast update-groups
3333
   */
3334
0
  if (safi == SAFI_UNICAST)
3335
0
    group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
3336
0
             new_select);
3337
3338
  /* FIB update. */
3339
0
  if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3340
0
      && !bgp_option_check(BGP_OPT_NO_FIB)) {
3341
3342
0
    if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3343
0
        && (new_select->sub_type == BGP_ROUTE_NORMAL
3344
0
      || new_select->sub_type == BGP_ROUTE_AGGREGATE
3345
0
      || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3346
3347
      /* if this is an evpn imported type-5 prefix,
3348
       * we need to withdraw the route first to clear
3349
       * the nh neigh and the RMAC entry.
3350
       */
3351
0
      if (old_select &&
3352
0
          is_route_parent_evpn(old_select))
3353
0
        bgp_zebra_withdraw(p, old_select, bgp, safi);
3354
3355
0
      bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
3356
0
    } else {
3357
      /* Withdraw the route from the kernel. */
3358
0
      if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3359
0
          && (old_select->sub_type == BGP_ROUTE_NORMAL
3360
0
        || old_select->sub_type == BGP_ROUTE_AGGREGATE
3361
0
        || old_select->sub_type == BGP_ROUTE_IMPORTED))
3362
3363
0
        bgp_zebra_withdraw(p, old_select, bgp, safi);
3364
0
    }
3365
0
  }
3366
3367
0
  bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3368
0
           old_select);
3369
3370
  /* Clear any route change flags. */
3371
0
  bgp_zebra_clear_route_change_flags(dest);
3372
3373
  /* Reap old select bgp_path_info, if it has been removed */
3374
0
  if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
3375
0
    bgp_path_info_reap(dest, old_select);
3376
3377
0
  UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3378
0
  return;
3379
0
}
3380
3381
/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3382
void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3383
0
{
3384
0
  struct bgp_dest *dest;
3385
0
  int cnt = 0;
3386
0
  struct afi_safi_info *thread_info;
3387
3388
0
  if (bgp->gr_info[afi][safi].t_route_select) {
3389
0
    struct event *t = bgp->gr_info[afi][safi].t_route_select;
3390
3391
0
    thread_info = EVENT_ARG(t);
3392
0
    XFREE(MTYPE_TMP, thread_info);
3393
0
    EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
3394
0
  }
3395
3396
0
  if (BGP_DEBUG(update, UPDATE_OUT)) {
3397
0
    zlog_debug("%s: processing route for %s : cnt %d", __func__,
3398
0
         get_afi_safi_str(afi, safi, false),
3399
0
         bgp->gr_info[afi][safi].gr_deferred);
3400
0
  }
3401
3402
  /* Process the route list */
3403
0
  for (dest = bgp_table_top(bgp->rib[afi][safi]);
3404
0
       dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3405
0
       cnt < BGP_MAX_BEST_ROUTE_SELECT;
3406
0
       dest = bgp_route_next(dest)) {
3407
0
    if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3408
0
      continue;
3409
3410
0
    UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3411
0
    bgp->gr_info[afi][safi].gr_deferred--;
3412
0
    bgp_process_main_one(bgp, dest, afi, safi);
3413
0
    cnt++;
3414
0
  }
3415
  /* If iteration stopped before the entire table was traversed then the
3416
   * node needs to be unlocked.
3417
   */
3418
0
  if (dest) {
3419
0
    bgp_dest_unlock_node(dest);
3420
0
    dest = NULL;
3421
0
  }
3422
3423
  /* Send EOR message when all routes are processed */
3424
0
  if (!bgp->gr_info[afi][safi].gr_deferred) {
3425
0
    bgp_send_delayed_eor(bgp);
3426
    /* Send route processing complete message to RIB */
3427
0
    bgp_zebra_update(bgp, afi, safi,
3428
0
         ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
3429
0
    return;
3430
0
  }
3431
3432
0
  thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
3433
3434
0
  thread_info->afi = afi;
3435
0
  thread_info->safi = safi;
3436
0
  thread_info->bgp = bgp;
3437
3438
  /* If there are more routes to be processed, start the
3439
   * selection timer
3440
   */
3441
0
  event_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3442
0
      BGP_ROUTE_SELECT_DELAY,
3443
0
      &bgp->gr_info[afi][safi].t_route_select);
3444
0
}
3445
3446
static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
3447
0
{
3448
0
  struct bgp_process_queue *pqnode = data;
3449
0
  struct bgp *bgp = pqnode->bgp;
3450
0
  struct bgp_table *table;
3451
0
  struct bgp_dest *dest;
3452
3453
  /* eoiu marker */
3454
0
  if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3455
0
    bgp_process_main_one(bgp, NULL, 0, 0);
3456
    /* should always have dedicated wq call */
3457
0
    assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
3458
0
    return WQ_SUCCESS;
3459
0
  }
3460
3461
0
  while (!STAILQ_EMPTY(&pqnode->pqueue)) {
3462
0
    dest = STAILQ_FIRST(&pqnode->pqueue);
3463
0
    STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
3464
0
    STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3465
0
    table = bgp_dest_table(dest);
3466
    /* note, new DESTs may be added as part of processing */
3467
0
    bgp_process_main_one(bgp, dest, table->afi, table->safi);
3468
3469
0
    bgp_dest_unlock_node(dest);
3470
0
    bgp_table_unlock(table);
3471
0
  }
3472
3473
0
  return WQ_SUCCESS;
3474
0
}
3475
3476
static void bgp_processq_del(struct work_queue *wq, void *data)
3477
0
{
3478
0
  struct bgp_process_queue *pqnode = data;
3479
3480
0
  bgp_unlock(pqnode->bgp);
3481
3482
0
  XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
3483
0
}
3484
3485
void bgp_process_queue_init(struct bgp *bgp)
3486
1
{
3487
1
  if (!bgp->process_queue) {
3488
1
    char name[BUFSIZ];
3489
3490
1
    snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3491
1
    bgp->process_queue = work_queue_new(bm->master, name);
3492
1
  }
3493
3494
1
  bgp->process_queue->spec.workfunc = &bgp_process_wq;
3495
1
  bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3496
1
  bgp->process_queue->spec.max_retries = 0;
3497
1
  bgp->process_queue->spec.hold = 50;
3498
  /* Use a higher yield value of 50ms for main queue processing */
3499
1
  bgp->process_queue->spec.yield = 50 * 1000L;
3500
1
}
3501
3502
static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
3503
0
{
3504
0
  struct bgp_process_queue *pqnode;
3505
3506
0
  pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3507
0
       sizeof(struct bgp_process_queue));
3508
3509
  /* unlocked in bgp_processq_del */
3510
0
  pqnode->bgp = bgp_lock(bgp);
3511
0
  STAILQ_INIT(&pqnode->pqueue);
3512
3513
0
  return pqnode;
3514
0
}
3515
3516
void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
3517
0
{
3518
0
#define ARBITRARY_PROCESS_QLEN    10000
3519
0
  struct work_queue *wq = bgp->process_queue;
3520
0
  struct bgp_process_queue *pqnode;
3521
0
  int pqnode_reuse = 0;
3522
3523
  /* already scheduled for processing? */
3524
0
  if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
3525
0
    return;
3526
3527
  /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3528
   * the workqueue
3529
   */
3530
0
  if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3531
0
    if (BGP_DEBUG(update, UPDATE_OUT))
3532
0
      zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3533
0
           dest);
3534
0
    return;
3535
0
  }
3536
3537
0
  if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3538
0
    if (BGP_DEBUG(update, UPDATE_OUT))
3539
0
      zlog_debug(
3540
0
        "Soft reconfigure table in progress for route %p",
3541
0
        dest);
3542
0
    return;
3543
0
  }
3544
3545
0
  if (wq == NULL)
3546
0
    return;
3547
3548
  /* Add route nodes to an existing work queue item until reaching the
3549
     limit only if is from the same BGP view and it's not an EOIU marker
3550
   */
3551
0
  if (work_queue_item_count(wq)) {
3552
0
    struct work_queue_item *item = work_queue_last_item(wq);
3553
0
    pqnode = item->data;
3554
3555
0
    if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3556
0
        || pqnode->bgp != bgp
3557
0
        || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
3558
0
      pqnode = bgp_processq_alloc(bgp);
3559
0
    else
3560
0
      pqnode_reuse = 1;
3561
0
  } else
3562
0
    pqnode = bgp_processq_alloc(bgp);
3563
  /* all unlocked in bgp_process_wq */
3564
0
  bgp_table_lock(bgp_dest_table(dest));
3565
3566
0
  SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3567
0
  bgp_dest_lock_node(dest);
3568
3569
  /* can't be enqueued twice */
3570
0
  assert(STAILQ_NEXT(dest, pq) == NULL);
3571
0
  STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
3572
0
  pqnode->queued++;
3573
3574
0
  if (!pqnode_reuse)
3575
0
    work_queue_add(wq, pqnode);
3576
3577
0
  return;
3578
0
}
3579
3580
void bgp_add_eoiu_mark(struct bgp *bgp)
3581
0
{
3582
0
  struct bgp_process_queue *pqnode;
3583
3584
0
  if (bgp->process_queue == NULL)
3585
0
    return;
3586
3587
0
  pqnode = bgp_processq_alloc(bgp);
3588
3589
0
  SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
3590
0
  work_queue_add(bgp->process_queue, pqnode);
3591
0
}
3592
3593
static void bgp_maximum_prefix_restart_timer(struct event *thread)
3594
0
{
3595
0
  struct peer *peer;
3596
0
3597
0
  peer = EVENT_ARG(thread);
3598
0
  peer->t_pmax_restart = NULL;
3599
0
3600
0
  if (bgp_debug_neighbor_events(peer))
3601
0
    zlog_debug(
3602
0
      "%s Maximum-prefix restart timer expired, restore peering",
3603
0
      peer->host);
3604
0
3605
0
  if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
3606
0
    zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
3607
0
}
3608
3609
static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3610
            safi_t safi)
3611
0
{
3612
0
  uint32_t count = 0;
3613
0
  bool filtered = false;
3614
0
  struct bgp_dest *dest;
3615
0
  struct bgp_adj_in *ain;
3616
0
  struct attr attr = {};
3617
0
  struct bgp_table *table = peer->bgp->rib[afi][safi];
3618
3619
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3620
0
    for (ain = dest->adj_in; ain; ain = ain->next) {
3621
0
      const struct prefix *rn_p = bgp_dest_get_prefix(dest);
3622
3623
0
      attr = *ain->attr;
3624
3625
0
      if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3626
0
          == FILTER_DENY)
3627
0
        filtered = true;
3628
3629
0
      if (bgp_input_modifier(
3630
0
            peer, rn_p, &attr, afi, safi,
3631
0
            ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3632
0
            NULL, 0, NULL)
3633
0
          == RMAP_DENY)
3634
0
        filtered = true;
3635
3636
0
      if (filtered)
3637
0
        count++;
3638
3639
0
      bgp_attr_flush(&attr);
3640
0
    }
3641
0
  }
3642
3643
0
  return count;
3644
0
}
3645
3646
bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3647
         int always)
3648
0
{
3649
0
  iana_afi_t pkt_afi;
3650
0
  iana_safi_t pkt_safi;
3651
0
  uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3652
0
              PEER_FLAG_MAX_PREFIX_FORCE))
3653
0
          ? bgp_filtered_routes_count(peer, afi, safi)
3654
0
              + peer->pcount[afi][safi]
3655
0
          : peer->pcount[afi][safi];
3656
3657
0
  if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3658
0
    return false;
3659
3660
0
  if (pcount > peer->pmax[afi][safi]) {
3661
0
    if (CHECK_FLAG(peer->af_sflags[afi][safi],
3662
0
             PEER_STATUS_PREFIX_LIMIT)
3663
0
        && !always)
3664
0
      return false;
3665
3666
0
    zlog_info(
3667
0
      "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3668
0
      get_afi_safi_str(afi, safi, false), peer, pcount,
3669
0
      peer->pmax[afi][safi]);
3670
0
    SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3671
3672
0
    if (CHECK_FLAG(peer->af_flags[afi][safi],
3673
0
             PEER_FLAG_MAX_PREFIX_WARNING))
3674
0
      return false;
3675
3676
    /* Convert AFI, SAFI to values for packet. */
3677
0
    pkt_afi = afi_int2iana(afi);
3678
0
    pkt_safi = safi_int2iana(safi);
3679
0
    {
3680
0
      uint8_t ndata[7];
3681
3682
0
      ndata[0] = (pkt_afi >> 8);
3683
0
      ndata[1] = pkt_afi;
3684
0
      ndata[2] = pkt_safi;
3685
0
      ndata[3] = (peer->pmax[afi][safi] >> 24);
3686
0
      ndata[4] = (peer->pmax[afi][safi] >> 16);
3687
0
      ndata[5] = (peer->pmax[afi][safi] >> 8);
3688
0
      ndata[6] = (peer->pmax[afi][safi]);
3689
3690
0
      SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3691
0
      bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3692
0
              BGP_NOTIFY_CEASE_MAX_PREFIX,
3693
0
              ndata, 7);
3694
0
    }
3695
3696
    /* Dynamic peers will just close their connection. */
3697
0
    if (peer_dynamic_neighbor(peer))
3698
0
      return true;
3699
3700
    /* restart timer start */
3701
0
    if (peer->pmax_restart[afi][safi]) {
3702
0
      peer->v_pmax_restart =
3703
0
        peer->pmax_restart[afi][safi] * 60;
3704
3705
0
      if (bgp_debug_neighbor_events(peer))
3706
0
        zlog_debug(
3707
0
          "%pBP Maximum-prefix restart timer started for %d secs",
3708
0
          peer, peer->v_pmax_restart);
3709
3710
0
      BGP_TIMER_ON(peer->t_pmax_restart,
3711
0
             bgp_maximum_prefix_restart_timer,
3712
0
             peer->v_pmax_restart);
3713
0
    }
3714
3715
0
    return true;
3716
0
  } else
3717
0
    UNSET_FLAG(peer->af_sflags[afi][safi],
3718
0
         PEER_STATUS_PREFIX_LIMIT);
3719
3720
0
  if (pcount
3721
0
      > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3722
0
    if (CHECK_FLAG(peer->af_sflags[afi][safi],
3723
0
             PEER_STATUS_PREFIX_THRESHOLD)
3724
0
        && !always)
3725
0
      return false;
3726
3727
0
    zlog_info(
3728
0
      "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3729
0
      get_afi_safi_str(afi, safi, false), peer, pcount,
3730
0
      peer->pmax[afi][safi]);
3731
0
    SET_FLAG(peer->af_sflags[afi][safi],
3732
0
       PEER_STATUS_PREFIX_THRESHOLD);
3733
0
  } else
3734
0
    UNSET_FLAG(peer->af_sflags[afi][safi],
3735
0
         PEER_STATUS_PREFIX_THRESHOLD);
3736
0
  return false;
3737
0
}
3738
3739
/* Unconditionally remove the route from the RIB, without taking
3740
 * damping into consideration (eg, because the session went down)
3741
 */
3742
void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
3743
        struct peer *peer, afi_t afi, safi_t safi)
3744
0
{
3745
3746
0
  struct bgp *bgp = NULL;
3747
0
  bool delete_route = false;
3748
3749
0
  bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3750
0
        safi);
3751
3752
0
  if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3753
0
    bgp_path_info_delete(dest, pi); /* keep historical info */
3754
3755
    /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3756
     * flag
3757
     */
3758
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3759
0
      delete_route = true;
3760
0
    else if (bgp_dest_set_defer_flag(dest, true) < 0)
3761
0
      delete_route = true;
3762
0
    if (delete_route) {
3763
0
      if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3764
0
        UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3765
0
        bgp = pi->peer->bgp;
3766
0
        bgp->gr_info[afi][safi].gr_deferred--;
3767
0
      }
3768
0
    }
3769
0
  }
3770
3771
0
  hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3772
0
  bgp_process(peer->bgp, dest, afi, safi);
3773
0
}
3774
3775
static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
3776
           struct peer *peer, afi_t afi, safi_t safi,
3777
           struct prefix_rd *prd)
3778
0
{
3779
0
  const struct prefix *p = bgp_dest_get_prefix(dest);
3780
3781
  /* apply dampening, if result is suppressed, we'll be retaining
3782
   * the bgp_path_info in the RIB for historical reference.
3783
   */
3784
0
  if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3785
0
      && peer->sort == BGP_PEER_EBGP)
3786
0
    if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3787
0
        == BGP_DAMP_SUPPRESSED) {
3788
0
      bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3789
0
            safi);
3790
0
      return;
3791
0
    }
3792
3793
0
#ifdef ENABLE_BGP_VNC
3794
0
  if (safi == SAFI_MPLS_VPN) {
3795
0
    struct bgp_dest *pdest = NULL;
3796
0
    struct bgp_table *table = NULL;
3797
3798
0
    pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3799
0
             (struct prefix *)prd);
3800
0
    if (bgp_dest_has_bgp_path_info_data(pdest)) {
3801
0
      table = bgp_dest_get_bgp_table_info(pdest);
3802
3803
0
      vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3804
0
        peer->bgp, prd, table, p, pi);
3805
0
    }
3806
0
    bgp_dest_unlock_node(pdest);
3807
0
  }
3808
0
  if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3809
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3810
3811
0
      vnc_import_bgp_del_route(peer->bgp, p, pi);
3812
0
      vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
3813
0
    }
3814
0
  }
3815
0
#endif
3816
3817
  /* If this is an EVPN route, process for un-import. */
3818
0
  if (safi == SAFI_EVPN)
3819
0
    bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
3820
3821
0
  bgp_rib_remove(dest, pi, peer, afi, safi);
3822
0
}
3823
3824
struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3825
        struct peer *peer, struct attr *attr,
3826
        struct bgp_dest *dest)
3827
0
{
3828
0
  struct bgp_path_info *new;
3829
3830
  /* Make new BGP info. */
3831
0
  new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
3832
0
  new->type = type;
3833
0
  new->instance = instance;
3834
0
  new->sub_type = sub_type;
3835
0
  new->peer = peer;
3836
0
  new->attr = attr;
3837
0
  new->uptime = monotime(NULL);
3838
0
  new->net = dest;
3839
0
  return new;
3840
0
}
3841
3842
/* Check if received nexthop is valid or not. */
3843
bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3844
        uint8_t type, uint8_t stype, struct attr *attr,
3845
        struct bgp_dest *dest)
3846
2.27k
{
3847
2.27k
  bool ret = false;
3848
2.27k
  bool is_bgp_static_route =
3849
2.27k
    (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3850
2.27k
                       : false;
3851
3852
  /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3853
   * as good.
3854
   */
3855
2.27k
  if (bgp->allow_martian)
3856
0
    return false;
3857
3858
  /*
3859
   * Only validated for unicast and multicast currently.
3860
   * Also valid for EVPN where the nexthop is an IP address.
3861
   * If we are a bgp static route being checked then there is
3862
   * no need to check to see if the nexthop is martian as
3863
   * that it should be ok.
3864
   */
3865
2.27k
  if (is_bgp_static_route ||
3866
2.27k
      (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3867
0
    return false;
3868
3869
  /* If NEXT_HOP is present, validate it. */
3870
2.27k
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3871
593
    if (attr->nexthop.s_addr == INADDR_ANY ||
3872
520
        !ipv4_unicast_valid(&attr->nexthop) ||
3873
273
        bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3874
320
      return true;
3875
593
  }
3876
3877
  /* If MP_NEXTHOP is present, validate it. */
3878
  /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3879
   * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3880
   * it is not an IPv6 link-local address.
3881
   *
3882
   * If we receive an UPDATE with nexthop length set to 32 bytes
3883
   * we shouldn't discard an UPDATE if it's set to (::).
3884
   * The link-local (2st) is validated along the code path later.
3885
   */
3886
1.95k
  if (attr->mp_nexthop_len) {
3887
1.95k
    switch (attr->mp_nexthop_len) {
3888
572
    case BGP_ATTR_NHLEN_IPV4:
3889
1.75k
    case BGP_ATTR_NHLEN_VPNV4:
3890
1.75k
      ret = (attr->mp_nexthop_global_in.s_addr ==
3891
1.75k
               INADDR_ANY ||
3892
1.48k
             !ipv4_unicast_valid(
3893
1.48k
               &attr->mp_nexthop_global_in) ||
3894
0
             bgp_nexthop_self(bgp, afi, type, stype, attr,
3895
0
            dest));
3896
1.75k
      break;
3897
3898
199
    case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3899
199
    case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3900
199
      ret = (IN6_IS_ADDR_UNSPECIFIED(
3901
199
          &attr->mp_nexthop_global)
3902
199
             || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3903
199
             || IN6_IS_ADDR_MULTICAST(
3904
199
               &attr->mp_nexthop_global)
3905
0
             || bgp_nexthop_self(bgp, afi, type, stype, attr,
3906
0
               dest));
3907
199
      break;
3908
0
    case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3909
0
      ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3910
0
             || IN6_IS_ADDR_MULTICAST(
3911
0
               &attr->mp_nexthop_global)
3912
0
             || bgp_nexthop_self(bgp, afi, type, stype, attr,
3913
0
               dest));
3914
0
      break;
3915
3916
0
    default:
3917
0
      ret = true;
3918
0
      break;
3919
1.95k
    }
3920
1.95k
  }
3921
3922
1.95k
  return ret;
3923
1.95k
}
3924
3925
static void bgp_attr_add_no_export_community(struct attr *attr)
3926
458
{
3927
458
  struct community *old;
3928
458
  struct community *new;
3929
458
  struct community *merge;
3930
458
  struct community *no_export;
3931
3932
458
  old = bgp_attr_get_community(attr);
3933
458
  no_export = community_str2com("no-export");
3934
3935
458
  assert(no_export);
3936
3937
458
  if (old) {
3938
458
    merge = community_merge(community_dup(old), no_export);
3939
3940
458
    if (!old->refcnt)
3941
0
      community_free(&old);
3942
3943
458
    new = community_uniq_sort(merge);
3944
458
    community_free(&merge);
3945
458
  } else {
3946
0
    new = community_dup(no_export);
3947
0
  }
3948
3949
458
  community_free(&no_export);
3950
3951
458
  bgp_attr_set_community(attr, new);
3952
458
}
3953
3954
static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3955
         struct attr *attr, const struct prefix *prefix,
3956
         int *sub_type)
3957
0
{
3958
0
  struct listnode *node, *nnode;
3959
0
  struct bgp *bgp;
3960
0
  bool accept_own_found = false;
3961
3962
0
  if (safi != SAFI_MPLS_VPN)
3963
0
    return false;
3964
3965
  /* Processing of the ACCEPT_OWN community is enabled by configuration */
3966
0
  if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3967
0
    return false;
3968
3969
  /* The route in question carries the ACCEPT_OWN community */
3970
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3971
0
    struct community *comm = bgp_attr_get_community(attr);
3972
3973
0
    if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3974
0
      accept_own_found = true;
3975
0
  }
3976
3977
  /* The route in question is targeted to one or more destination VRFs
3978
   * on the router (as determined by inspecting the Route Target(s)).
3979
   */
3980
0
  for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3981
0
    if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3982
0
      continue;
3983
3984
0
    if (accept_own_found &&
3985
0
        ecommunity_include(
3986
0
          bgp->vpn_policy[afi]
3987
0
            .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3988
0
          bgp_attr_get_ecommunity(attr))) {
3989
0
      if (bgp_debug_update(peer, prefix, NULL, 1))
3990
0
        zlog_debug(
3991
0
          "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3992
0
          peer, prefix);
3993
3994
      /* Treat this route as imported, because it's leaked
3995
       * already from another VRF, and we got an updated
3996
       * version from route-reflector with ACCEPT_OWN
3997
       * community.
3998
       */
3999
0
      *sub_type = BGP_ROUTE_IMPORTED;
4000
4001
0
      return true;
4002
0
    }
4003
0
  }
4004
4005
0
  return false;
4006
0
}
4007
4008
void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4009
    struct attr *attr, afi_t afi, safi_t safi, int type,
4010
    int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4011
    uint32_t num_labels, int soft_reconfig,
4012
    struct bgp_route_evpn *evpn)
4013
2.42k
{
4014
2.42k
  int ret;
4015
2.42k
  int aspath_loop_count = 0;
4016
2.42k
  struct bgp_dest *dest;
4017
2.42k
  struct bgp *bgp;
4018
2.42k
  struct attr new_attr;
4019
2.42k
  struct attr *attr_new;
4020
2.42k
  struct bgp_path_info *pi;
4021
2.42k
  struct bgp_path_info *new = NULL;
4022
2.42k
  struct bgp_path_info_extra *extra;
4023
2.42k
  const char *reason;
4024
2.42k
  char pfx_buf[BGP_PRD_PATH_STRLEN];
4025
2.42k
  int connected = 0;
4026
2.42k
  int do_loop_check = 1;
4027
2.42k
  int has_valid_label = 0;
4028
2.42k
  afi_t nh_afi;
4029
2.42k
  bool force_evpn_import = false;
4030
2.42k
  safi_t orig_safi = safi;
4031
2.42k
  bool leak_success = true;
4032
2.42k
  int allowas_in = 0;
4033
4034
2.42k
  if (frrtrace_enabled(frr_bgp, process_update)) {
4035
0
    char pfxprint[PREFIX2STR_BUFFER];
4036
4037
0
    prefix2str(p, pfxprint, sizeof(pfxprint));
4038
0
    frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4039
0
       afi, safi, attr);
4040
0
  }
4041
4042
2.42k
#ifdef ENABLE_BGP_VNC
4043
2.42k
  int vnc_implicit_withdraw = 0;
4044
2.42k
#endif
4045
2.42k
  int same_attr = 0;
4046
2.42k
  const struct prefix *bgp_nht_param_prefix;
4047
4048
  /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4049
2.42k
  if (orig_safi == SAFI_LABELED_UNICAST)
4050
0
    safi = SAFI_UNICAST;
4051
4052
2.42k
  memset(&new_attr, 0, sizeof(new_attr));
4053
2.42k
  new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4054
2.42k
  new_attr.label = MPLS_INVALID_LABEL;
4055
4056
2.42k
  bgp = peer->bgp;
4057
2.42k
  dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4058
  /* TODO: Check to see if we can get rid of "is_valid_label" */
4059
2.42k
  if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4060
122
    has_valid_label = (num_labels > 0) ? 1 : 0;
4061
2.30k
  else
4062
2.30k
    has_valid_label = bgp_is_valid_label(label);
4063
4064
2.42k
  if (has_valid_label)
4065
118
    assert(label != NULL);
4066
4067
4068
  /* When peer's soft reconfiguration enabled.  Record input packet in
4069
     Adj-RIBs-In.  */
4070
2.42k
  if (!soft_reconfig &&
4071
2.42k
      CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) &&
4072
0
      peer != bgp->peer_self) {
4073
    /*
4074
     * If the trigger is not from soft_reconfig and if
4075
     * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
4076
     * will not be interned. In which case, it is ok to update the
4077
     * attr->evpn_overlay, so that, this can be stored in adj_in.
4078
     */
4079
0
    if ((afi == AFI_L2VPN) && evpn) {
4080
0
      memcpy(&attr->evpn_overlay, evpn,
4081
0
             sizeof(struct bgp_route_evpn));
4082
0
    }
4083
0
    bgp_adj_in_set(dest, peer, attr, addpath_id);
4084
0
  }
4085
4086
  /* Update permitted loop count */
4087
2.42k
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4088
0
    allowas_in = peer->allowas_in[afi][safi];
4089
4090
  /* Check previously received route. */
4091
2.42k
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4092
0
    if (pi->peer == peer && pi->type == type
4093
0
        && pi->sub_type == sub_type
4094
0
        && pi->addpath_rx_id == addpath_id)
4095
0
      break;
4096
4097
  /* AS path local-as loop check. */
4098
2.42k
  if (peer->change_local_as) {
4099
0
    if (allowas_in)
4100
0
      aspath_loop_count = allowas_in;
4101
0
    else if (!CHECK_FLAG(peer->flags,
4102
0
             PEER_FLAG_LOCAL_AS_NO_PREPEND))
4103
0
      aspath_loop_count = 1;
4104
4105
0
    if (aspath_loop_check(attr->aspath, peer->change_local_as)
4106
0
        > aspath_loop_count) {
4107
0
      peer->stat_pfx_aspath_loop++;
4108
0
      reason = "as-path contains our own AS;";
4109
0
      goto filtered;
4110
0
    }
4111
0
  }
4112
4113
  /* If the peer is configured for "allowas-in origin" and the last ASN in
4114
   * the
4115
   * as-path is our ASN then we do not need to call aspath_loop_check
4116
   */
4117
2.42k
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4118
0
    if (aspath_get_last_as(attr->aspath) == bgp->as)
4119
0
      do_loop_check = 0;
4120
4121
2.42k
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4122
0
    bgp_nht_param_prefix = NULL;
4123
2.42k
  else
4124
2.42k
    bgp_nht_param_prefix = p;
4125
4126
  /* AS path loop check. */
4127
2.42k
  if (do_loop_check) {
4128
2.42k
    if (aspath_loop_check(attr->aspath, bgp->as) >
4129
2.42k
        peer->allowas_in[afi][safi]) {
4130
0
      peer->stat_pfx_aspath_loop++;
4131
0
      reason = "as-path contains our own AS;";
4132
0
      goto filtered;
4133
0
    }
4134
2.42k
  }
4135
4136
  /* If we're a CONFED we need to loop check the CONFED ID too */
4137
2.42k
  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4138
0
    if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4139
0
        peer->allowas_in[afi][safi]) {
4140
0
      peer->stat_pfx_aspath_loop++;
4141
0
      reason = "as-path contains our own confed AS;";
4142
0
      goto filtered;
4143
0
    }
4144
4145
  /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4146
   * enabled, then take care of that too.
4147
   */
4148
2.42k
  bool accept_own = false;
4149
4150
2.42k
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4151
191
      && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
4152
0
    accept_own =
4153
0
      bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4154
0
    if (!accept_own) {
4155
0
      peer->stat_pfx_originator_loop++;
4156
0
      reason = "originator is us;";
4157
0
      goto filtered;
4158
0
    }
4159
0
  }
4160
4161
  /* Route reflector cluster ID check.  */
4162
2.42k
  if (bgp_cluster_filter(peer, attr)) {
4163
0
    peer->stat_pfx_cluster_loop++;
4164
0
    reason = "reflected from the same cluster;";
4165
0
    goto filtered;
4166
0
  }
4167
4168
  /* Apply incoming filter.  */
4169
2.42k
  if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
4170
0
    peer->stat_pfx_filter++;
4171
0
    reason = "filter;";
4172
0
    goto filtered;
4173
0
  }
4174
4175
  /* If the route has Node Target Extended Communities, check
4176
   * if it's allowed to be installed locally.
4177
   */
4178
2.42k
  if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4179
270
    struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
4180
4181
270
    if (ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
4182
270
              ECOMMUNITY_NODE_TARGET) &&
4183
206
        !ecommunity_node_target_match(ecomm, &peer->local_id)) {
4184
156
      reason =
4185
156
        "Node-Target Extended Communities do not contain own BGP Identifier;";
4186
156
      goto filtered;
4187
156
    }
4188
270
  }
4189
4190
  /* RFC 8212 to prevent route leaks.
4191
   * This specification intends to improve this situation by requiring the
4192
   * explicit configuration of both BGP Import and Export Policies for any
4193
   * External BGP (EBGP) session such as customers, peers, or
4194
   * confederation boundaries for all enabled address families. Through
4195
   * codification of the aforementioned requirement, operators will
4196
   * benefit from consistent behavior across different BGP
4197
   * implementations.
4198
   */
4199
2.27k
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
4200
0
    if (!bgp_inbound_policy_exists(peer,
4201
0
                 &peer->filter[afi][safi])) {
4202
0
      reason = "inbound policy missing";
4203
0
      if (monotime_since(&bgp->ebgprequirespolicywarning,
4204
0
             NULL) > FIFTEENMINUTE2USEC ||
4205
0
          bgp->ebgprequirespolicywarning.tv_sec == 0) {
4206
0
        zlog_warn(
4207
0
          "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4208
0
        monotime(&bgp->ebgprequirespolicywarning);
4209
0
      }
4210
0
      goto filtered;
4211
0
    }
4212
4213
  /* draft-ietf-idr-deprecate-as-set-confed-set
4214
   * Filter routes having AS_SET or AS_CONFED_SET in the path.
4215
   * Eventually, This document (if approved) updates RFC 4271
4216
   * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4217
   * and obsoletes RFC 6472.
4218
   */
4219
2.27k
  if (peer->bgp->reject_as_sets)
4220
0
    if (aspath_check_as_sets(attr->aspath)) {
4221
0
      reason =
4222
0
        "as-path contains AS_SET or AS_CONFED_SET type;";
4223
0
      goto filtered;
4224
0
    }
4225
4226
2.27k
  new_attr = *attr;
4227
  /*
4228
   * If bgp_update is called with soft_reconfig set then
4229
   * attr is interned. In this case, do not overwrite the
4230
   * attr->evpn_overlay with evpn directly. Instead memcpy
4231
   * evpn to new_atr.evpn_overlay before it is interned.
4232
   */
4233
2.27k
  if (soft_reconfig && (afi == AFI_L2VPN) && evpn)
4234
0
    memcpy(&new_attr.evpn_overlay, evpn,
4235
0
           sizeof(struct bgp_route_evpn));
4236
4237
  /* Apply incoming route-map.
4238
   * NB: new_attr may now contain newly allocated values from route-map
4239
   * "set"
4240
   * commands, so we need bgp_attr_flush in the error paths, until we
4241
   * intern
4242
   * the attr (which takes over the memory references) */
4243
2.27k
  if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
4244
2.27k
             num_labels, dest)
4245
2.27k
      == RMAP_DENY) {
4246
0
    peer->stat_pfx_filter++;
4247
0
    reason = "route-map;";
4248
0
    bgp_attr_flush(&new_attr);
4249
0
    goto filtered;
4250
0
  }
4251
4252
2.27k
  if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
4253
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4254
      /* remove from RIB previous entry */
4255
0
      bgp_zebra_withdraw(p, pi, bgp, safi);
4256
0
  }
4257
4258
2.27k
  if (peer->sort == BGP_PEER_EBGP) {
4259
4260
    /* rfc7999:
4261
     * A BGP speaker receiving an announcement tagged with the
4262
     * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4263
     * NO_EXPORT community as defined in RFC1997, or a
4264
     * similar community, to prevent propagation of the
4265
     * prefix outside the local AS. The community to prevent
4266
     * propagation SHOULD be chosen according to the operator's
4267
     * routing policy.
4268
     */
4269
2.27k
    if (bgp_attr_get_community(&new_attr) &&
4270
1.28k
        community_include(bgp_attr_get_community(&new_attr),
4271
1.28k
              COMMUNITY_BLACKHOLE))
4272
458
      bgp_attr_add_no_export_community(&new_attr);
4273
4274
    /* If we receive the graceful-shutdown community from an eBGP
4275
     * peer we must lower local-preference */
4276
2.27k
    if (bgp_attr_get_community(&new_attr) &&
4277
1.28k
        community_include(bgp_attr_get_community(&new_attr),
4278
1.28k
              COMMUNITY_GSHUT)) {
4279
182
      new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4280
182
      new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4281
4282
      /* If graceful-shutdown is configured globally or
4283
       * per neighbor, then add the GSHUT community to
4284
       * all paths received from eBGP peers. */
4285
2.09k
    } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4286
2.09k
         CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
4287
0
      bgp_attr_add_gshut_community(&new_attr);
4288
2.27k
  }
4289
4290
  /* next hop check.  */
4291
2.27k
  if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4292
2.27k
      bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4293
2.27k
               &new_attr, dest)) {
4294
2.27k
    peer->stat_pfx_nh_invalid++;
4295
2.27k
    reason = "martian or self next-hop;";
4296
2.27k
    bgp_attr_flush(&new_attr);
4297
2.27k
    goto filtered;
4298
2.27k
  }
4299
4300
0
  if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
4301
0
    peer->stat_pfx_nh_invalid++;
4302
0
    reason = "self mac;";
4303
0
    bgp_attr_flush(&new_attr);
4304
0
    goto filtered;
4305
0
  }
4306
4307
0
  if (bgp_check_role_applicability(afi, safi) &&
4308
0
      bgp_otc_filter(peer, &new_attr)) {
4309
0
    reason = "failing otc validation";
4310
0
    bgp_attr_flush(&new_attr);
4311
0
    goto filtered;
4312
0
  }
4313
4314
  /* If neighbor soo is configured, tag all incoming routes with
4315
   * this SoO tag and then filter out advertisements in
4316
   * subgroup_announce_check() if it matches the configured SoO
4317
   * on the other peer.
4318
   */
4319
0
  if (peer->soo[afi][safi]) {
4320
0
    struct ecommunity *old_ecomm =
4321
0
      bgp_attr_get_ecommunity(&new_attr);
4322
0
    struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4323
0
    struct ecommunity *new_ecomm;
4324
4325
0
    if (old_ecomm) {
4326
0
      new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4327
0
                 ecomm_soo);
4328
4329
0
      if (!old_ecomm->refcnt)
4330
0
        ecommunity_free(&old_ecomm);
4331
0
    } else {
4332
0
      new_ecomm = ecommunity_dup(ecomm_soo);
4333
0
    }
4334
4335
0
    bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4336
0
  }
4337
4338
0
  attr_new = bgp_attr_intern(&new_attr);
4339
4340
  /* If the update is implicit withdraw. */
4341
0
  if (pi) {
4342
0
    pi->uptime = monotime(NULL);
4343
0
    same_attr = attrhash_cmp(pi->attr, attr_new);
4344
4345
0
    hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4346
4347
    /* Same attribute comes in. */
4348
0
    if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
4349
0
        && same_attr
4350
0
        && (!has_valid_label
4351
0
      || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
4352
0
          num_labels * sizeof(mpls_label_t))
4353
0
           == 0)) {
4354
0
      if (CHECK_FLAG(bgp->af_flags[afi][safi],
4355
0
               BGP_CONFIG_DAMPENING)
4356
0
          && peer->sort == BGP_PEER_EBGP
4357
0
          && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4358
0
        if (bgp_debug_update(peer, p, NULL, 1)) {
4359
0
          bgp_debug_rdpfxpath2str(
4360
0
            afi, safi, prd, p, label,
4361
0
            num_labels, addpath_id ? 1 : 0,
4362
0
            addpath_id, evpn, pfx_buf,
4363
0
            sizeof(pfx_buf));
4364
0
          zlog_debug("%pBP rcvd %s", peer,
4365
0
               pfx_buf);
4366
0
        }
4367
4368
0
        if (bgp_damp_update(pi, dest, afi, safi)
4369
0
            != BGP_DAMP_SUPPRESSED) {
4370
0
          bgp_aggregate_increment(bgp, p, pi, afi,
4371
0
                safi);
4372
0
          bgp_process(bgp, dest, afi, safi);
4373
0
        }
4374
0
      } else /* Duplicate - odd */
4375
0
      {
4376
0
        if (bgp_debug_update(peer, p, NULL, 1)) {
4377
0
          if (!peer->rcvd_attr_printed) {
4378
0
            zlog_debug(
4379
0
              "%pBP rcvd UPDATE w/ attr: %s",
4380
0
              peer,
4381
0
              peer->rcvd_attr_str);
4382
0
            peer->rcvd_attr_printed = 1;
4383
0
          }
4384
4385
0
          bgp_debug_rdpfxpath2str(
4386
0
            afi, safi, prd, p, label,
4387
0
            num_labels, addpath_id ? 1 : 0,
4388
0
            addpath_id, evpn, pfx_buf,
4389
0
            sizeof(pfx_buf));
4390
0
          zlog_debug(
4391
0
            "%pBP rcvd %s...duplicate ignored",
4392
0
            peer, pfx_buf);
4393
0
        }
4394
4395
        /* graceful restart STALE flag unset. */
4396
0
        if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
4397
0
          bgp_path_info_unset_flag(
4398
0
            dest, pi, BGP_PATH_STALE);
4399
0
          bgp_dest_set_defer_flag(dest, false);
4400
0
          bgp_process(bgp, dest, afi, safi);
4401
0
        }
4402
0
      }
4403
4404
0
      bgp_dest_unlock_node(dest);
4405
0
      bgp_attr_unintern(&attr_new);
4406
4407
0
      return;
4408
0
    }
4409
4410
    /* Withdraw/Announce before we fully processed the withdraw */
4411
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
4412
0
      if (bgp_debug_update(peer, p, NULL, 1)) {
4413
0
        bgp_debug_rdpfxpath2str(
4414
0
          afi, safi, prd, p, label, num_labels,
4415
0
          addpath_id ? 1 : 0, addpath_id, evpn,
4416
0
          pfx_buf, sizeof(pfx_buf));
4417
0
        zlog_debug(
4418
0
          "%pBP rcvd %s, flapped quicker than processing",
4419
0
          peer, pfx_buf);
4420
0
      }
4421
4422
0
      bgp_path_info_restore(dest, pi);
4423
4424
      /*
4425
       * If the BGP_PATH_REMOVED flag is set, then EVPN
4426
       * routes would have been unimported already when a
4427
       * prior BGP withdraw processing happened. Such routes
4428
       * need to be imported again, so flag accordingly.
4429
       */
4430
0
      force_evpn_import = true;
4431
0
    } else {
4432
      /* implicit withdraw, decrement aggregate and pcount
4433
       * here. only if update is accepted, they'll increment
4434
       * below.
4435
       */
4436
0
      bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4437
0
    }
4438
4439
    /* Received Logging. */
4440
0
    if (bgp_debug_update(peer, p, NULL, 1)) {
4441
0
      bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4442
0
            num_labels, addpath_id ? 1 : 0,
4443
0
            addpath_id, evpn, pfx_buf,
4444
0
            sizeof(pfx_buf));
4445
0
      zlog_debug("%pBP rcvd %s", peer, pfx_buf);
4446
0
    }
4447
4448
    /* graceful restart STALE flag unset. */
4449
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
4450
0
      bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4451
0
      bgp_dest_set_defer_flag(dest, false);
4452
0
    }
4453
4454
    /* The attribute is changed. */
4455
0
    bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
4456
4457
    /* Update bgp route dampening information.  */
4458
0
    if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
4459
0
        && peer->sort == BGP_PEER_EBGP) {
4460
      /* This is implicit withdraw so we should update
4461
         dampening
4462
         information.  */
4463
0
      if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
4464
0
        bgp_damp_withdraw(pi, dest, afi, safi, 1);
4465
0
    }
4466
0
#ifdef ENABLE_BGP_VNC
4467
0
    if (safi == SAFI_MPLS_VPN) {
4468
0
      struct bgp_dest *pdest = NULL;
4469
0
      struct bgp_table *table = NULL;
4470
4471
0
      pdest = bgp_node_get(bgp->rib[afi][safi],
4472
0
               (struct prefix *)prd);
4473
0
      if (bgp_dest_has_bgp_path_info_data(pdest)) {
4474
0
        table = bgp_dest_get_bgp_table_info(pdest);
4475
4476
0
        vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4477
0
          bgp, prd, table, p, pi);
4478
0
      }
4479
0
      bgp_dest_unlock_node(pdest);
4480
0
    }
4481
0
    if ((afi == AFI_IP || afi == AFI_IP6)
4482
0
        && (safi == SAFI_UNICAST)) {
4483
0
      if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
4484
        /*
4485
         * Implicit withdraw case.
4486
         */
4487
0
        ++vnc_implicit_withdraw;
4488
0
        vnc_import_bgp_del_route(bgp, p, pi);
4489
0
        vnc_import_bgp_exterior_del_route(bgp, p, pi);
4490
0
      }
4491
0
    }
4492
0
#endif
4493
4494
    /* Special handling for EVPN update of an existing route. If the
4495
     * extended community attribute has changed, we need to
4496
     * un-import
4497
     * the route using its existing extended community. It will be
4498
     * subsequently processed for import with the new extended
4499
     * community.
4500
     */
4501
0
    if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4502
0
        && !same_attr) {
4503
0
      if ((pi->attr->flag
4504
0
           & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4505
0
          && (attr_new->flag
4506
0
        & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4507
0
        int cmp;
4508
4509
0
        cmp = ecommunity_cmp(
4510
0
          bgp_attr_get_ecommunity(pi->attr),
4511
0
          bgp_attr_get_ecommunity(attr_new));
4512
0
        if (!cmp) {
4513
0
          if (bgp_debug_update(peer, p, NULL, 1))
4514
0
            zlog_debug(
4515
0
              "Change in EXT-COMM, existing %s new %s",
4516
0
              ecommunity_str(
4517
0
                bgp_attr_get_ecommunity(
4518
0
                  pi->attr)),
4519
0
              ecommunity_str(
4520
0
                bgp_attr_get_ecommunity(
4521
0
                  attr_new)));
4522
0
          if (safi == SAFI_EVPN)
4523
0
            bgp_evpn_unimport_route(
4524
0
              bgp, afi, safi, p, pi);
4525
0
          else /* SAFI_MPLS_VPN */
4526
0
            vpn_leak_to_vrf_withdraw(pi);
4527
0
        }
4528
0
      }
4529
0
    }
4530
4531
    /* Update to new attribute.  */
4532
0
    bgp_attr_unintern(&pi->attr);
4533
0
    pi->attr = attr_new;
4534
4535
    /* Update MPLS label */
4536
0
    if (has_valid_label) {
4537
0
      extra = bgp_path_info_extra_get(pi);
4538
0
      if (extra->label != label) {
4539
0
        memcpy(&extra->label, label,
4540
0
               num_labels * sizeof(mpls_label_t));
4541
0
        extra->num_labels = num_labels;
4542
0
      }
4543
0
      if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4544
0
        bgp_set_valid_label(&extra->label[0]);
4545
0
    }
4546
4547
    /* Update SRv6 SID */
4548
0
    if (attr->srv6_l3vpn) {
4549
0
      extra = bgp_path_info_extra_get(pi);
4550
0
      if (sid_diff(&extra->sid[0].sid,
4551
0
             &attr->srv6_l3vpn->sid)) {
4552
0
        sid_copy(&extra->sid[0].sid,
4553
0
           &attr->srv6_l3vpn->sid);
4554
0
        extra->num_sids = 1;
4555
4556
0
        extra->sid[0].loc_block_len = 0;
4557
0
        extra->sid[0].loc_node_len = 0;
4558
0
        extra->sid[0].func_len = 0;
4559
0
        extra->sid[0].arg_len = 0;
4560
0
        extra->sid[0].transposition_len = 0;
4561
0
        extra->sid[0].transposition_offset = 0;
4562
4563
0
        if (attr->srv6_l3vpn->loc_block_len != 0) {
4564
0
          extra->sid[0].loc_block_len =
4565
0
            attr->srv6_l3vpn->loc_block_len;
4566
0
          extra->sid[0].loc_node_len =
4567
0
            attr->srv6_l3vpn->loc_node_len;
4568
0
          extra->sid[0].func_len =
4569
0
            attr->srv6_l3vpn->func_len;
4570
0
          extra->sid[0].arg_len =
4571
0
            attr->srv6_l3vpn->arg_len;
4572
0
          extra->sid[0].transposition_len =
4573
0
            attr->srv6_l3vpn
4574
0
              ->transposition_len;
4575
0
          extra->sid[0].transposition_offset =
4576
0
            attr->srv6_l3vpn
4577
0
              ->transposition_offset;
4578
0
        }
4579
0
      }
4580
0
    } else if (attr->srv6_vpn) {
4581
0
      extra = bgp_path_info_extra_get(pi);
4582
0
      if (sid_diff(&extra->sid[0].sid,
4583
0
             &attr->srv6_vpn->sid)) {
4584
0
        sid_copy(&extra->sid[0].sid,
4585
0
           &attr->srv6_vpn->sid);
4586
0
        extra->num_sids = 1;
4587
0
      }
4588
0
    }
4589
4590
0
#ifdef ENABLE_BGP_VNC
4591
0
    if ((afi == AFI_IP || afi == AFI_IP6)
4592
0
        && (safi == SAFI_UNICAST)) {
4593
0
      if (vnc_implicit_withdraw) {
4594
        /*
4595
         * Add back the route with its new attributes
4596
         * (e.g., nexthop).
4597
         * The route is still selected, until the route
4598
         * selection
4599
         * queued by bgp_process actually runs. We have
4600
         * to make this
4601
         * update to the VNC side immediately to avoid
4602
         * racing against
4603
         * configuration changes (e.g., route-map
4604
         * changes) which
4605
         * trigger re-importation of the entire RIB.
4606
         */
4607
0
        vnc_import_bgp_add_route(bgp, p, pi);
4608
0
        vnc_import_bgp_exterior_add_route(bgp, p, pi);
4609
0
      }
4610
0
    }
4611
0
#endif
4612
4613
    /* Update bgp route dampening information.  */
4614
0
    if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
4615
0
        && peer->sort == BGP_PEER_EBGP) {
4616
      /* Now we do normal update dampening.  */
4617
0
      ret = bgp_damp_update(pi, dest, afi, safi);
4618
0
      if (ret == BGP_DAMP_SUPPRESSED) {
4619
0
        bgp_dest_unlock_node(dest);
4620
0
        return;
4621
0
      }
4622
0
    }
4623
4624
    /* Nexthop reachability check - for unicast and
4625
     * labeled-unicast.. */
4626
0
    if (((afi == AFI_IP || afi == AFI_IP6)
4627
0
        && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4628
0
        || (safi == SAFI_EVPN &&
4629
0
      bgp_evpn_is_prefix_nht_supported(p))) {
4630
0
      if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4631
0
          && peer->ttl == BGP_DEFAULT_TTL
4632
0
          && !CHECK_FLAG(peer->flags,
4633
0
             PEER_FLAG_DISABLE_CONNECTED_CHECK)
4634
0
          && !CHECK_FLAG(bgp->flags,
4635
0
             BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4636
0
        connected = 1;
4637
0
      else
4638
0
        connected = 0;
4639
4640
0
      struct bgp *bgp_nexthop = bgp;
4641
4642
0
      if (pi->extra && pi->extra->bgp_orig)
4643
0
        bgp_nexthop = pi->extra->bgp_orig;
4644
4645
0
      nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4646
4647
0
      if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4648
0
                safi, pi, NULL, connected,
4649
0
                bgp_nht_param_prefix) ||
4650
0
          CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4651
0
        bgp_path_info_set_flag(dest, pi,
4652
0
                   BGP_PATH_VALID);
4653
0
      else {
4654
0
        if (BGP_DEBUG(nht, NHT)) {
4655
0
          zlog_debug("%s(%pI4): NH unresolved",
4656
0
               __func__,
4657
0
               (in_addr_t *)&attr_new->nexthop);
4658
0
        }
4659
0
        bgp_path_info_unset_flag(dest, pi,
4660
0
               BGP_PATH_VALID);
4661
0
      }
4662
0
    } else {
4663
0
      if (accept_own)
4664
0
        bgp_path_info_set_flag(dest, pi,
4665
0
                   BGP_PATH_ACCEPT_OWN);
4666
4667
0
      bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
4668
0
    }
4669
4670
0
#ifdef ENABLE_BGP_VNC
4671
0
    if (safi == SAFI_MPLS_VPN) {
4672
0
      struct bgp_dest *pdest = NULL;
4673
0
      struct bgp_table *table = NULL;
4674
4675
0
      pdest = bgp_node_get(bgp->rib[afi][safi],
4676
0
               (struct prefix *)prd);
4677
0
      if (bgp_dest_has_bgp_path_info_data(pdest)) {
4678
0
        table = bgp_dest_get_bgp_table_info(pdest);
4679
4680
0
        vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4681
0
          bgp, prd, table, p, pi);
4682
0
      }
4683
0
      bgp_dest_unlock_node(pdest);
4684
0
    }
4685
0
#endif
4686
4687
    /* If this is an EVPN route and some attribute has changed,
4688
     * or we are explicitly told to perform a route import, process
4689
     * route for import. If the extended community has changed, we
4690
     * would
4691
     * have done the un-import earlier and the import would result
4692
     * in the
4693
     * route getting injected into appropriate L2 VNIs. If it is
4694
     * just
4695
     * some other attribute change, the import will result in
4696
     * updating
4697
     * the attributes for the route in the VNI(s).
4698
     */
4699
0
    if (safi == SAFI_EVPN &&
4700
0
        (!same_attr || force_evpn_import) &&
4701
0
        CHECK_FLAG(pi->flags, BGP_PATH_VALID))
4702
0
      bgp_evpn_import_route(bgp, afi, safi, p, pi);
4703
4704
    /* Process change. */
4705
0
    bgp_aggregate_increment(bgp, p, pi, afi, safi);
4706
4707
0
    bgp_process(bgp, dest, afi, safi);
4708
0
    bgp_dest_unlock_node(dest);
4709
4710
0
    if (SAFI_UNICAST == safi
4711
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4712
0
      || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4713
4714
0
      vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
4715
0
    }
4716
0
    if ((SAFI_MPLS_VPN == safi)
4717
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4718
0
      leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
4719
0
    }
4720
4721
0
#ifdef ENABLE_BGP_VNC
4722
0
    if (SAFI_MPLS_VPN == safi) {
4723
0
      mpls_label_t label_decoded = decode_label(label);
4724
4725
0
      rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4726
0
             type, sub_type, &label_decoded);
4727
0
    }
4728
0
    if (SAFI_ENCAP == safi) {
4729
0
      rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4730
0
             type, sub_type, NULL);
4731
0
    }
4732
0
#endif
4733
0
    if ((safi == SAFI_MPLS_VPN) &&
4734
0
        !CHECK_FLAG(bgp->af_flags[afi][safi],
4735
0
        BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4736
0
        !leak_success) {
4737
0
      bgp_unlink_nexthop(pi);
4738
0
      bgp_path_info_delete(dest, pi);
4739
0
    }
4740
0
    return;
4741
0
  } // End of implicit withdraw
4742
4743
  /* Received Logging. */
4744
0
  if (bgp_debug_update(peer, p, NULL, 1)) {
4745
0
    if (!peer->rcvd_attr_printed) {
4746
0
      zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
4747
0
           peer->rcvd_attr_str);
4748
0
      peer->rcvd_attr_printed = 1;
4749
0
    }
4750
4751
0
    bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4752
0
          addpath_id ? 1 : 0, addpath_id, evpn,
4753
0
          pfx_buf, sizeof(pfx_buf));
4754
0
    zlog_debug("%pBP rcvd %s", peer, pfx_buf);
4755
0
  }
4756
4757
  /* Make new BGP info. */
4758
0
  new = info_make(type, sub_type, 0, peer, attr_new, dest);
4759
4760
  /* Update MPLS label */
4761
0
  if (has_valid_label) {
4762
0
    extra = bgp_path_info_extra_get(new);
4763
0
    if (extra->label != label) {
4764
0
      memcpy(&extra->label, label,
4765
0
             num_labels * sizeof(mpls_label_t));
4766
0
      extra->num_labels = num_labels;
4767
0
    }
4768
0
    if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4769
0
      bgp_set_valid_label(&extra->label[0]);
4770
0
  }
4771
4772
  /* Update SRv6 SID */
4773
0
  if (safi == SAFI_MPLS_VPN) {
4774
0
    extra = bgp_path_info_extra_get(new);
4775
0
    if (attr->srv6_l3vpn) {
4776
0
      sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
4777
0
      extra->num_sids = 1;
4778
4779
0
      extra->sid[0].loc_block_len =
4780
0
        attr->srv6_l3vpn->loc_block_len;
4781
0
      extra->sid[0].loc_node_len =
4782
0
        attr->srv6_l3vpn->loc_node_len;
4783
0
      extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4784
0
      extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4785
0
      extra->sid[0].transposition_len =
4786
0
        attr->srv6_l3vpn->transposition_len;
4787
0
      extra->sid[0].transposition_offset =
4788
0
        attr->srv6_l3vpn->transposition_offset;
4789
0
    } else if (attr->srv6_vpn) {
4790
0
      sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
4791
0
      extra->num_sids = 1;
4792
0
    }
4793
0
  }
4794
4795
  /* Nexthop reachability check. */
4796
0
  if (((afi == AFI_IP || afi == AFI_IP6)
4797
0
      && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4798
0
      || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
4799
0
    if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4800
0
        && peer->ttl == BGP_DEFAULT_TTL
4801
0
        && !CHECK_FLAG(peer->flags,
4802
0
           PEER_FLAG_DISABLE_CONNECTED_CHECK)
4803
0
        && !CHECK_FLAG(bgp->flags,
4804
0
           BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4805
0
      connected = 1;
4806
0
    else
4807
0
      connected = 0;
4808
4809
0
    nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4810
4811
0
    if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
4812
0
              connected, bgp_nht_param_prefix) ||
4813
0
        CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4814
0
      bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4815
0
    else {
4816
0
      if (BGP_DEBUG(nht, NHT))
4817
0
        zlog_debug("%s(%pI4): NH unresolved", __func__,
4818
0
             &attr_new->nexthop);
4819
0
      bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
4820
0
    }
4821
0
  } else {
4822
0
    if (accept_own)
4823
0
      bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4824
4825
0
    bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4826
0
  }
4827
4828
  /* If maximum prefix count is configured and current prefix
4829
   * count exeed it.
4830
   */
4831
0
  if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4832
0
    reason = "maximum-prefix overflow";
4833
0
    bgp_attr_flush(&new_attr);
4834
0
    goto filtered;
4835
0
  }
4836
4837
  /* Addpath ID */
4838
0
  new->addpath_rx_id = addpath_id;
4839
4840
  /* Increment prefix */
4841
0
  bgp_aggregate_increment(bgp, p, new, afi, safi);
4842
4843
  /* Register new BGP information. */
4844
0
  bgp_path_info_add(dest, new);
4845
4846
  /* route_node_get lock */
4847
0
  bgp_dest_unlock_node(dest);
4848
4849
0
#ifdef ENABLE_BGP_VNC
4850
0
  if (safi == SAFI_MPLS_VPN) {
4851
0
    struct bgp_dest *pdest = NULL;
4852
0
    struct bgp_table *table = NULL;
4853
4854
0
    pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4855
0
    if (bgp_dest_has_bgp_path_info_data(pdest)) {
4856
0
      table = bgp_dest_get_bgp_table_info(pdest);
4857
4858
0
      vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4859
0
        bgp, prd, table, p, new);
4860
0
    }
4861
0
    bgp_dest_unlock_node(pdest);
4862
0
  }
4863
0
#endif
4864
4865
  /* If this is an EVPN route, process for import. */
4866
0
  if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
4867
0
    bgp_evpn_import_route(bgp, afi, safi, p, new);
4868
4869
0
  hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4870
4871
  /* Process change. */
4872
0
  bgp_process(bgp, dest, afi, safi);
4873
4874
0
  if (SAFI_UNICAST == safi
4875
0
      && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4876
0
    || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4877
0
    vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4878
0
  }
4879
0
  if ((SAFI_MPLS_VPN == safi)
4880
0
      && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4881
0
    leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
4882
0
  }
4883
0
#ifdef ENABLE_BGP_VNC
4884
0
  if (SAFI_MPLS_VPN == safi) {
4885
0
    mpls_label_t label_decoded = decode_label(label);
4886
4887
0
    rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4888
0
           sub_type, &label_decoded);
4889
0
  }
4890
0
  if (SAFI_ENCAP == safi) {
4891
0
    rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4892
0
           sub_type, NULL);
4893
0
  }
4894
0
#endif
4895
0
  if ((safi == SAFI_MPLS_VPN) &&
4896
0
      !CHECK_FLAG(bgp->af_flags[afi][safi],
4897
0
      BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4898
0
      !leak_success) {
4899
0
    bgp_unlink_nexthop(new);
4900
0
    bgp_path_info_delete(dest, new);
4901
0
  }
4902
4903
0
  return;
4904
4905
/* This BGP update is filtered.  Log the reason then update BGP
4906
   entry.  */
4907
2.42k
filtered:
4908
2.42k
  if (new) {
4909
0
    bgp_unlink_nexthop(new);
4910
0
    bgp_path_info_delete(dest, new);
4911
0
    bgp_path_info_extra_free(&new->extra);
4912
0
    XFREE(MTYPE_BGP_ROUTE, new);
4913
0
  }
4914
4915
2.42k
  hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4916
4917
2.42k
  if (bgp_debug_update(peer, p, NULL, 1)) {
4918
0
    if (!peer->rcvd_attr_printed) {
4919
0
      zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
4920
0
           peer->rcvd_attr_str);
4921
0
      peer->rcvd_attr_printed = 1;
4922
0
    }
4923
4924
0
    bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4925
0
          addpath_id ? 1 : 0, addpath_id, evpn,
4926
0
          pfx_buf, sizeof(pfx_buf));
4927
0
    zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4928
0
         peer, pfx_buf, reason);
4929
0
  }
4930
4931
2.42k
  if (pi) {
4932
    /* If this is an EVPN route, un-import it as it is now filtered.
4933
     */
4934
0
    if (safi == SAFI_EVPN)
4935
0
      bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
4936
4937
0
    if (SAFI_UNICAST == safi
4938
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4939
0
      || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4940
4941
0
      vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4942
0
    }
4943
0
    if ((SAFI_MPLS_VPN == safi)
4944
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4945
4946
0
      vpn_leak_to_vrf_withdraw(pi);
4947
0
    }
4948
4949
0
    bgp_rib_remove(dest, pi, peer, afi, safi);
4950
0
  }
4951
4952
2.42k
  bgp_dest_unlock_node(dest);
4953
4954
2.42k
#ifdef ENABLE_BGP_VNC
4955
  /*
4956
   * Filtered update is treated as an implicit withdrawal (see
4957
   * bgp_rib_remove()
4958
   * a few lines above)
4959
   */
4960
2.42k
  if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4961
0
    rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4962
0
             0);
4963
0
  }
4964
2.42k
#endif
4965
4966
2.42k
  return;
4967
0
}
4968
4969
void bgp_withdraw(struct peer *peer, const struct prefix *p,
4970
      uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4971
      int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4972
      uint32_t num_labels, struct bgp_route_evpn *evpn)
4973
689
{
4974
689
  struct bgp *bgp;
4975
689
  char pfx_buf[BGP_PRD_PATH_STRLEN];
4976
689
  struct bgp_dest *dest;
4977
689
  struct bgp_path_info *pi;
4978
4979
689
#ifdef ENABLE_BGP_VNC
4980
689
  if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4981
110
    rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4982
110
             0);
4983
110
  }
4984
689
#endif
4985
4986
689
  bgp = peer->bgp;
4987
4988
  /* Lookup node. */
4989
689
  dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4990
4991
  /* If peer is soft reconfiguration enabled.  Record input packet for
4992
   * further calculation.
4993
   *
4994
   * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4995
   * routes that are filtered.  This tanks out Quagga RS pretty badly due
4996
   * to
4997
   * the iteration over all RS clients.
4998
   * Since we need to remove the entry from adj_in anyway, do that first
4999
   * and
5000
   * if there was no entry, we don't need to do anything more.
5001
   */
5002
689
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
5003
0
      && peer != bgp->peer_self)
5004
0
    if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
5005
0
      peer->stat_pfx_dup_withdraw++;
5006
5007
0
      if (bgp_debug_update(peer, p, NULL, 1)) {
5008
0
        bgp_debug_rdpfxpath2str(
5009
0
          afi, safi, prd, p, label, num_labels,
5010
0
          addpath_id ? 1 : 0, addpath_id, NULL,
5011
0
          pfx_buf, sizeof(pfx_buf));
5012
0
        zlog_debug(
5013
0
          "%s withdrawing route %s not in adj-in",
5014
0
          peer->host, pfx_buf);
5015
0
      }
5016
0
      bgp_dest_unlock_node(dest);
5017
0
      return;
5018
0
    }
5019
5020
  /* Lookup withdrawn route. */
5021
689
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5022
0
    if (pi->peer == peer && pi->type == type
5023
0
        && pi->sub_type == sub_type
5024
0
        && pi->addpath_rx_id == addpath_id)
5025
0
      break;
5026
5027
  /* Logging. */
5028
689
  if (bgp_debug_update(peer, p, NULL, 1)) {
5029
0
    bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
5030
0
          addpath_id ? 1 : 0, addpath_id, NULL,
5031
0
          pfx_buf, sizeof(pfx_buf));
5032
0
    zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
5033
0
         pfx_buf);
5034
0
  }
5035
5036
  /* Withdraw specified route from routing table. */
5037
689
  if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
5038
0
    bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
5039
0
    if (SAFI_UNICAST == safi
5040
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5041
0
      || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5042
0
      vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
5043
0
    }
5044
0
    if ((SAFI_MPLS_VPN == safi)
5045
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5046
5047
0
      vpn_leak_to_vrf_withdraw(pi);
5048
0
    }
5049
689
  } else if (bgp_debug_update(peer, p, NULL, 1)) {
5050
0
    bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
5051
0
          addpath_id ? 1 : 0, addpath_id, NULL,
5052
0
          pfx_buf, sizeof(pfx_buf));
5053
0
    zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5054
0
  }
5055
5056
  /* Unlock bgp_node_get() lock. */
5057
689
  bgp_dest_unlock_node(dest);
5058
5059
689
  return;
5060
689
}
5061
5062
void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5063
         int withdraw)
5064
0
{
5065
0
  struct update_subgroup *subgrp;
5066
0
  subgrp = peer_subgroup(peer, afi, safi);
5067
0
  subgroup_default_originate(subgrp, withdraw);
5068
0
}
5069
5070
5071
/*
5072
 * bgp_stop_announce_route_timer
5073
 */
5074
void bgp_stop_announce_route_timer(struct peer_af *paf)
5075
0
{
5076
0
  if (!paf->t_announce_route)
5077
0
    return;
5078
5079
0
  EVENT_OFF(paf->t_announce_route);
5080
0
}
5081
5082
/*
5083
 * bgp_announce_route_timer_expired
5084
 *
5085
 * Callback that is invoked when the route announcement timer for a
5086
 * peer_af expires.
5087
 */
5088
static void bgp_announce_route_timer_expired(struct event *t)
5089
0
{
5090
0
  struct peer_af *paf;
5091
0
  struct peer *peer;
5092
0
5093
0
  paf = EVENT_ARG(t);
5094
0
  peer = paf->peer;
5095
0
5096
0
  if (!peer_established(peer))
5097
0
    return;
5098
0
5099
0
  if (!peer->afc_nego[paf->afi][paf->safi])
5100
0
    return;
5101
0
5102
0
  peer_af_announce_route(paf, 1);
5103
0
5104
0
  /* Notify BGP conditional advertisement scanner percess */
5105
0
  peer->advmap_config_change[paf->afi][paf->safi] = true;
5106
0
}
5107
5108
/*
5109
 * bgp_announce_route
5110
 *
5111
 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5112
 *
5113
 * if force is true we will force an update even if the update
5114
 * limiting code is attempted to kick in.
5115
 */
5116
void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
5117
36
{
5118
36
  struct peer_af *paf;
5119
36
  struct update_subgroup *subgrp;
5120
5121
36
  paf = peer_af_find(peer, afi, safi);
5122
36
  if (!paf)
5123
21
    return;
5124
15
  subgrp = PAF_SUBGRP(paf);
5125
5126
  /*
5127
   * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5128
   * or a refresh has already been triggered.
5129
   */
5130
15
  if (!subgrp || paf->t_announce_route)
5131
15
    return;
5132
5133
0
  if (force)
5134
0
    SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5135
5136
  /*
5137
   * Start a timer to stagger/delay the announce. This serves
5138
   * two purposes - announcement can potentially be combined for
5139
   * multiple peers and the announcement doesn't happen in the
5140
   * vty context.
5141
   */
5142
0
  event_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5143
0
           (subgrp->peer_count == 1)
5144
0
             ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5145
0
             : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5146
0
           &paf->t_announce_route);
5147
0
}
5148
5149
/*
5150
 * Announce routes from all AF tables to a peer.
5151
 *
5152
 * This should ONLY be called when there is a need to refresh the
5153
 * routes to the peer based on a policy change for this peer alone
5154
 * or a route refresh request received from the peer.
5155
 * The operation will result in splitting the peer from its existing
5156
 * subgroups and putting it in new subgroups.
5157
 */
5158
void bgp_announce_route_all(struct peer *peer)
5159
0
{
5160
0
  afi_t afi;
5161
0
  safi_t safi;
5162
5163
0
  FOREACH_AFI_SAFI (afi, safi)
5164
0
    bgp_announce_route(peer, afi, safi, false);
5165
0
}
5166
5167
/* Flag or unflag bgp_dest to determine whether it should be treated by
5168
 * bgp_soft_reconfig_table_task.
5169
 * Flag if flag is true. Unflag if flag is false.
5170
 */
5171
static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5172
0
{
5173
0
  struct bgp_dest *dest;
5174
0
  struct bgp_adj_in *ain;
5175
5176
0
  if (!table)
5177
0
    return;
5178
5179
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5180
0
    for (ain = dest->adj_in; ain; ain = ain->next) {
5181
0
      if (ain->peer != NULL)
5182
0
        break;
5183
0
    }
5184
0
    if (flag && ain != NULL && ain->peer != NULL)
5185
0
      SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5186
0
    else
5187
0
      UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5188
0
  }
5189
0
}
5190
5191
static void bgp_soft_reconfig_table_update(struct peer *peer,
5192
             struct bgp_dest *dest,
5193
             struct bgp_adj_in *ain, afi_t afi,
5194
             safi_t safi, struct prefix_rd *prd)
5195
0
{
5196
0
  struct bgp_path_info *pi;
5197
0
  uint32_t num_labels = 0;
5198
0
  mpls_label_t *label_pnt = NULL;
5199
0
  struct bgp_route_evpn evpn;
5200
5201
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5202
0
    if (pi->peer == peer)
5203
0
      break;
5204
5205
0
  if (pi && pi->extra)
5206
0
    num_labels = pi->extra->num_labels;
5207
0
  if (num_labels)
5208
0
    label_pnt = &pi->extra->label[0];
5209
0
  if (pi)
5210
0
    memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5211
0
           sizeof(evpn));
5212
0
  else
5213
0
    memset(&evpn, 0, sizeof(evpn));
5214
5215
0
  bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5216
0
       ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5217
0
       label_pnt, num_labels, 1, &evpn);
5218
0
}
5219
5220
static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5221
            struct bgp_table *table,
5222
            struct prefix_rd *prd)
5223
0
{
5224
0
  struct bgp_dest *dest;
5225
0
  struct bgp_adj_in *ain;
5226
5227
0
  if (!table)
5228
0
    table = peer->bgp->rib[afi][safi];
5229
5230
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5231
0
    for (ain = dest->adj_in; ain; ain = ain->next) {
5232
0
      if (ain->peer != peer)
5233
0
        continue;
5234
5235
0
      bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5236
0
                   safi, prd);
5237
0
    }
5238
0
}
5239
5240
/* Do soft reconfig table per bgp table.
5241
 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5242
 * when BGP_NODE_SOFT_RECONFIG is set,
5243
 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5244
 * Schedule a new thread to continue the job.
5245
 * Without splitting the full job into several part,
5246
 * vtysh waits for the job to finish before responding to a BGP command
5247
 */
5248
static void bgp_soft_reconfig_table_task(struct event *thread)
5249
0
{
5250
0
  uint32_t iter, max_iter;
5251
0
  struct bgp_dest *dest;
5252
0
  struct bgp_adj_in *ain;
5253
0
  struct peer *peer;
5254
0
  struct bgp_table *table;
5255
0
  struct prefix_rd *prd;
5256
0
  struct listnode *node, *nnode;
5257
0
5258
0
  table = EVENT_ARG(thread);
5259
0
  prd = NULL;
5260
0
5261
0
  max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5262
0
  if (table->soft_reconfig_init) {
5263
0
    /* first call of the function with a new srta structure.
5264
0
     * Don't do any treatment this time on nodes
5265
0
     * in order vtysh to respond quickly
5266
0
     */
5267
0
    max_iter = 0;
5268
0
  }
5269
0
5270
0
  for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5271
0
       dest = bgp_route_next(dest)) {
5272
0
    if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5273
0
      continue;
5274
0
5275
0
    UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5276
0
5277
0
    for (ain = dest->adj_in; ain; ain = ain->next) {
5278
0
      for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5279
0
                 nnode, peer)) {
5280
0
        if (ain->peer != peer)
5281
0
          continue;
5282
0
5283
0
        bgp_soft_reconfig_table_update(
5284
0
          peer, dest, ain, table->afi,
5285
0
          table->safi, prd);
5286
0
        iter++;
5287
0
      }
5288
0
    }
5289
0
  }
5290
0
5291
0
  /* we're either starting the initial iteration,
5292
0
   * or we're going to continue an ongoing iteration
5293
0
   */
5294
0
  if (dest || table->soft_reconfig_init) {
5295
0
    table->soft_reconfig_init = false;
5296
0
    event_add_event(bm->master, bgp_soft_reconfig_table_task, table,
5297
0
        0, &table->soft_reconfig_thread);
5298
0
    return;
5299
0
  }
5300
0
  /* we're done, clean up the background iteration context info and
5301
0
  schedule route annoucement
5302
0
  */
5303
0
  for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5304
0
    listnode_delete(table->soft_reconfig_peers, peer);
5305
0
    bgp_announce_route(peer, table->afi, table->safi, false);
5306
0
  }
5307
0
5308
0
  list_delete(&table->soft_reconfig_peers);
5309
0
}
5310
5311
5312
/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5313
 * and peer.
5314
 * - bgp cannot be NULL
5315
 * - if table and peer are NULL, cancel all threads within the bgp instance
5316
 * - if table is NULL and peer is not,
5317
 * remove peer in all threads within the bgp instance
5318
 * - if peer is NULL, cancel all threads matching table within the bgp instance
5319
 */
5320
void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5321
           const struct bgp_table *table,
5322
           const struct peer *peer)
5323
0
{
5324
0
  struct peer *npeer;
5325
0
  struct listnode *node, *nnode;
5326
0
  int afi, safi;
5327
0
  struct bgp_table *ntable;
5328
5329
0
  if (!bgp)
5330
0
    return;
5331
5332
0
  FOREACH_AFI_SAFI (afi, safi) {
5333
0
    ntable = bgp->rib[afi][safi];
5334
0
    if (!ntable)
5335
0
      continue;
5336
0
    if (table && table != ntable)
5337
0
      continue;
5338
5339
0
    for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5340
0
               npeer)) {
5341
0
      if (peer && peer != npeer)
5342
0
        continue;
5343
0
      listnode_delete(ntable->soft_reconfig_peers, npeer);
5344
0
    }
5345
5346
0
    if (!ntable->soft_reconfig_peers
5347
0
        || !list_isempty(ntable->soft_reconfig_peers))
5348
0
      continue;
5349
5350
0
    list_delete(&ntable->soft_reconfig_peers);
5351
0
    bgp_soft_reconfig_table_flag(ntable, false);
5352
0
    EVENT_OFF(ntable->soft_reconfig_thread);
5353
0
  }
5354
0
}
5355
5356
/*
5357
 * Returns false if the peer is not configured for soft reconfig in
5358
 */
5359
bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
5360
0
{
5361
0
  struct bgp_dest *dest;
5362
0
  struct bgp_table *table;
5363
0
  struct listnode *node, *nnode;
5364
0
  struct peer *npeer;
5365
0
  struct peer_af *paf;
5366
5367
0
  if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5368
0
    return false;
5369
5370
0
  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
5371
0
      && (safi != SAFI_EVPN)) {
5372
0
    table = peer->bgp->rib[afi][safi];
5373
0
    if (!table)
5374
0
      return true;
5375
5376
0
    table->soft_reconfig_init = true;
5377
5378
0
    if (!table->soft_reconfig_peers)
5379
0
      table->soft_reconfig_peers = list_new();
5380
0
    npeer = NULL;
5381
    /* add peer to the table soft_reconfig_peers if not already
5382
     * there
5383
     */
5384
0
    for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5385
0
               npeer)) {
5386
0
      if (peer == npeer)
5387
0
        break;
5388
0
    }
5389
0
    if (peer != npeer)
5390
0
      listnode_add(table->soft_reconfig_peers, peer);
5391
5392
    /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5393
     * on table would start back at the beginning.
5394
     */
5395
0
    bgp_soft_reconfig_table_flag(table, true);
5396
5397
0
    if (!table->soft_reconfig_thread)
5398
0
      event_add_event(bm->master,
5399
0
          bgp_soft_reconfig_table_task, table, 0,
5400
0
          &table->soft_reconfig_thread);
5401
    /* Cancel bgp_announce_route_timer_expired threads.
5402
     * bgp_announce_route_timer_expired threads have been scheduled
5403
     * to announce routes as soon as the soft_reconfigure process
5404
     * finishes.
5405
     * In this case, soft_reconfigure is also scheduled by using
5406
     * a thread but is planned after the
5407
     * bgp_announce_route_timer_expired threads. It means that,
5408
     * without cancelling the threads, the route announcement task
5409
     * would run before the soft reconfiguration one. That would
5410
     * useless and would block vtysh during several seconds. Route
5411
     * announcements are rescheduled as soon as the soft_reconfigure
5412
     * process finishes.
5413
     */
5414
0
    paf = peer_af_find(peer, afi, safi);
5415
0
    if (paf)
5416
0
      bgp_stop_announce_route_timer(paf);
5417
0
  } else
5418
0
    for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5419
0
         dest = bgp_route_next(dest)) {
5420
0
      table = bgp_dest_get_bgp_table_info(dest);
5421
5422
0
      if (table == NULL)
5423
0
        continue;
5424
5425
0
      const struct prefix *p = bgp_dest_get_prefix(dest);
5426
0
      struct prefix_rd prd;
5427
5428
0
      prd.family = AF_UNSPEC;
5429
0
      prd.prefixlen = 64;
5430
0
      memcpy(&prd.val, p->u.val, 8);
5431
5432
0
      bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
5433
0
    }
5434
5435
0
  return true;
5436
0
}
5437
5438
5439
struct bgp_clear_node_queue {
5440
  struct bgp_dest *dest;
5441
};
5442
5443
static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
5444
0
{
5445
0
  struct bgp_clear_node_queue *cnq = data;
5446
0
  struct bgp_dest *dest = cnq->dest;
5447
0
  struct peer *peer = wq->spec.data;
5448
0
  struct bgp_path_info *pi;
5449
0
  struct bgp *bgp;
5450
0
  afi_t afi = bgp_dest_table(dest)->afi;
5451
0
  safi_t safi = bgp_dest_table(dest)->safi;
5452
5453
0
  assert(dest && peer);
5454
0
  bgp = peer->bgp;
5455
5456
  /* It is possible that we have multiple paths for a prefix from a peer
5457
   * if that peer is using AddPath.
5458
   */
5459
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
5460
0
    if (pi->peer != peer)
5461
0
      continue;
5462
5463
    /* graceful restart STALE flag set. */
5464
0
    if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5465
0
          && peer->nsf[afi][safi])
5466
0
         || CHECK_FLAG(peer->af_sflags[afi][safi],
5467
0
           PEER_STATUS_ENHANCED_REFRESH))
5468
0
        && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5469
0
        && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
5470
0
      bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
5471
0
    else {
5472
      /* If this is an EVPN route, process for
5473
       * un-import. */
5474
0
      if (safi == SAFI_EVPN)
5475
0
        bgp_evpn_unimport_route(
5476
0
          bgp, afi, safi,
5477
0
          bgp_dest_get_prefix(dest), pi);
5478
      /* Handle withdraw for VRF route-leaking and L3VPN */
5479
0
      if (SAFI_UNICAST == safi
5480
0
          && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
5481
0
        bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5482
0
        vpn_leak_from_vrf_withdraw(bgp_get_default(),
5483
0
                 bgp, pi);
5484
0
      }
5485
0
      if (SAFI_MPLS_VPN == safi &&
5486
0
          bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5487
0
        vpn_leak_to_vrf_withdraw(pi);
5488
0
      }
5489
5490
0
      bgp_rib_remove(dest, pi, peer, afi, safi);
5491
0
    }
5492
0
  }
5493
0
  return WQ_SUCCESS;
5494
0
}
5495
5496
static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
5497
0
{
5498
0
  struct bgp_clear_node_queue *cnq = data;
5499
0
  struct bgp_dest *dest = cnq->dest;
5500
0
  struct bgp_table *table = bgp_dest_table(dest);
5501
5502
0
  bgp_dest_unlock_node(dest);
5503
0
  bgp_table_unlock(table);
5504
0
  XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
5505
0
}
5506
5507
static void bgp_clear_node_complete(struct work_queue *wq)
5508
0
{
5509
0
  struct peer *peer = wq->spec.data;
5510
5511
  /* Tickle FSM to start moving again */
5512
0
  BGP_EVENT_ADD(peer, Clearing_Completed);
5513
5514
0
  peer_unlock(peer); /* bgp_clear_route */
5515
0
}
5516
5517
static void bgp_clear_node_queue_init(struct peer *peer)
5518
1
{
5519
1
  char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5520
5521
1
  snprintf(wname, sizeof(wname), "clear %s", peer->host);
5522
1
#undef CLEAR_QUEUE_NAME_LEN
5523
5524
1
  peer->clear_node_queue = work_queue_new(bm->master, wname);
5525
1
  peer->clear_node_queue->spec.hold = 10;
5526
1
  peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5527
1
  peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5528
1
  peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5529
1
  peer->clear_node_queue->spec.max_retries = 0;
5530
5531
  /* we only 'lock' this peer reference when the queue is actually active
5532
   */
5533
1
  peer->clear_node_queue->spec.data = peer;
5534
1
}
5535
5536
static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5537
          struct bgp_table *table)
5538
10
{
5539
10
  struct bgp_dest *dest;
5540
10
  int force = peer->bgp->process_queue ? 0 : 1;
5541
5542
10
  if (!table)
5543
3
    table = peer->bgp->rib[afi][safi];
5544
5545
  /* If still no table => afi/safi isn't configured at all or smth. */
5546
10
  if (!table)
5547
0
    return;
5548
5549
10
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5550
0
    struct bgp_path_info *pi, *next;
5551
0
    struct bgp_adj_in *ain;
5552
0
    struct bgp_adj_in *ain_next;
5553
5554
    /* XXX:TODO: This is suboptimal, every non-empty route_node is
5555
     * queued for every clearing peer, regardless of whether it is
5556
     * relevant to the peer at hand.
5557
     *
5558
     * Overview: There are 3 different indices which need to be
5559
     * scrubbed, potentially, when a peer is removed:
5560
     *
5561
     * 1 peer's routes visible via the RIB (ie accepted routes)
5562
     * 2 peer's routes visible by the (optional) peer's adj-in index
5563
     * 3 other routes visible by the peer's adj-out index
5564
     *
5565
     * 3 there is no hurry in scrubbing, once the struct peer is
5566
     * removed from bgp->peer, we could just GC such deleted peer's
5567
     * adj-outs at our leisure.
5568
     *
5569
     * 1 and 2 must be 'scrubbed' in some way, at least made
5570
     * invisible via RIB index before peer session is allowed to be
5571
     * brought back up. So one needs to know when such a 'search' is
5572
     * complete.
5573
     *
5574
     * Ideally:
5575
     *
5576
     * - there'd be a single global queue or a single RIB walker
5577
     * - rather than tracking which route_nodes still need to be
5578
     *   examined on a peer basis, we'd track which peers still
5579
     *   aren't cleared
5580
     *
5581
     * Given that our per-peer prefix-counts now should be reliable,
5582
     * this may actually be achievable. It doesn't seem to be a huge
5583
     * problem at this time,
5584
     *
5585
     * It is possible that we have multiple paths for a prefix from
5586
     * a peer
5587
     * if that peer is using AddPath.
5588
     */
5589
0
    ain = dest->adj_in;
5590
0
    while (ain) {
5591
0
      ain_next = ain->next;
5592
5593
0
      if (ain->peer == peer)
5594
0
        bgp_adj_in_remove(dest, ain);
5595
5596
0
      ain = ain_next;
5597
0
    }
5598
5599
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5600
0
      next = pi->next;
5601
0
      if (pi->peer != peer)
5602
0
        continue;
5603
5604
0
      if (force)
5605
0
        bgp_path_info_reap(dest, pi);
5606
0
      else {
5607
0
        struct bgp_clear_node_queue *cnq;
5608
5609
        /* both unlocked in bgp_clear_node_queue_del */
5610
0
        bgp_table_lock(bgp_dest_table(dest));
5611
0
        bgp_dest_lock_node(dest);
5612
0
        cnq = XCALLOC(
5613
0
          MTYPE_BGP_CLEAR_NODE_QUEUE,
5614
0
          sizeof(struct bgp_clear_node_queue));
5615
0
        cnq->dest = dest;
5616
0
        work_queue_add(peer->clear_node_queue, cnq);
5617
0
        break;
5618
0
      }
5619
0
    }
5620
0
  }
5621
10
  return;
5622
10
}
5623
5624
void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5625
4
{
5626
4
  struct bgp_dest *dest;
5627
4
  struct bgp_table *table;
5628
5629
4
  if (peer->clear_node_queue == NULL)
5630
1
    bgp_clear_node_queue_init(peer);
5631
5632
  /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5633
   * Idle until it receives a Clearing_Completed event. This protects
5634
   * against peers which flap faster than we can we clear, which could
5635
   * lead to:
5636
   *
5637
   * a) race with routes from the new session being installed before
5638
   *    clear_route_node visits the node (to delete the route of that
5639
   *    peer)
5640
   * b) resource exhaustion, clear_route_node likely leads to an entry
5641
   *    on the process_main queue. Fast-flapping could cause that queue
5642
   *    to grow and grow.
5643
   */
5644
5645
  /* lock peer in assumption that clear-node-queue will get nodes; if so,
5646
   * the unlock will happen upon work-queue completion; other wise, the
5647
   * unlock happens at the end of this function.
5648
   */
5649
4
  if (!peer->clear_node_queue->thread)
5650
4
    peer_lock(peer);
5651
5652
4
  if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5653
3
    bgp_clear_route_table(peer, afi, safi, NULL);
5654
1
  else
5655
14
    for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5656
13
         dest = bgp_route_next(dest)) {
5657
13
      table = bgp_dest_get_bgp_table_info(dest);
5658
13
      if (!table)
5659
6
        continue;
5660
5661
7
      bgp_clear_route_table(peer, afi, safi, table);
5662
7
    }
5663
5664
  /* unlock if no nodes got added to the clear-node-queue. */
5665
4
  if (!peer->clear_node_queue->thread)
5666
4
    peer_unlock(peer);
5667
4
}
5668
5669
void bgp_clear_route_all(struct peer *peer)
5670
0
{
5671
0
  afi_t afi;
5672
0
  safi_t safi;
5673
5674
0
  FOREACH_AFI_SAFI (afi, safi)
5675
0
    bgp_clear_route(peer, afi, safi);
5676
5677
0
#ifdef ENABLE_BGP_VNC
5678
0
  rfapiProcessPeerDown(peer);
5679
0
#endif
5680
0
}
5681
5682
void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
5683
0
{
5684
0
  struct bgp_table *table;
5685
0
  struct bgp_dest *dest;
5686
0
  struct bgp_adj_in *ain;
5687
0
  struct bgp_adj_in *ain_next;
5688
5689
0
  table = peer->bgp->rib[afi][safi];
5690
5691
  /* It is possible that we have multiple paths for a prefix from a peer
5692
   * if that peer is using AddPath.
5693
   */
5694
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5695
0
    ain = dest->adj_in;
5696
5697
0
    while (ain) {
5698
0
      ain_next = ain->next;
5699
5700
0
      if (ain->peer == peer)
5701
0
        bgp_adj_in_remove(dest, ain);
5702
5703
0
      ain = ain_next;
5704
0
    }
5705
0
  }
5706
0
}
5707
5708
/* If any of the routes from the peer have been marked with the NO_LLGR
5709
 * community, either as sent by the peer, or as the result of a configured
5710
 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5711
 * operation of [RFC4271].
5712
 */
5713
void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5714
0
{
5715
0
  struct bgp_dest *dest;
5716
0
  struct bgp_path_info *pi;
5717
0
  struct bgp_table *table;
5718
5719
0
  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5720
0
    for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5721
0
         dest = bgp_route_next(dest)) {
5722
0
      struct bgp_dest *rm;
5723
5724
      /* look for neighbor in tables */
5725
0
      table = bgp_dest_get_bgp_table_info(dest);
5726
0
      if (!table)
5727
0
        continue;
5728
5729
0
      for (rm = bgp_table_top(table); rm;
5730
0
           rm = bgp_route_next(rm))
5731
0
        for (pi = bgp_dest_get_bgp_path_info(rm); pi;
5732
0
             pi = pi->next) {
5733
0
          if (pi->peer != peer)
5734
0
            continue;
5735
0
          if (CHECK_FLAG(
5736
0
                peer->af_sflags[afi][safi],
5737
0
                PEER_STATUS_LLGR_WAIT) &&
5738
0
              bgp_attr_get_community(pi->attr) &&
5739
0
              !community_include(
5740
0
                bgp_attr_get_community(
5741
0
                  pi->attr),
5742
0
                COMMUNITY_NO_LLGR))
5743
0
            continue;
5744
0
          if (!CHECK_FLAG(pi->flags,
5745
0
              BGP_PATH_STALE))
5746
0
            continue;
5747
5748
          /*
5749
           * If this is VRF leaked route
5750
           * process for withdraw.
5751
           */
5752
0
          if (pi->sub_type ==
5753
0
                BGP_ROUTE_IMPORTED &&
5754
0
              peer->bgp->inst_type ==
5755
0
                BGP_INSTANCE_TYPE_DEFAULT)
5756
0
            vpn_leak_to_vrf_withdraw(pi);
5757
5758
0
          bgp_rib_remove(rm, pi, peer, afi, safi);
5759
0
          break;
5760
0
        }
5761
0
    }
5762
0
  } else {
5763
0
    for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5764
0
         dest = bgp_route_next(dest))
5765
0
      for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5766
0
           pi = pi->next) {
5767
0
        if (pi->peer != peer)
5768
0
          continue;
5769
0
        if (CHECK_FLAG(peer->af_sflags[afi][safi],
5770
0
                 PEER_STATUS_LLGR_WAIT) &&
5771
0
            bgp_attr_get_community(pi->attr) &&
5772
0
            !community_include(
5773
0
              bgp_attr_get_community(pi->attr),
5774
0
              COMMUNITY_NO_LLGR))
5775
0
          continue;
5776
0
        if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
5777
0
          continue;
5778
0
        if (safi == SAFI_UNICAST &&
5779
0
            (peer->bgp->inst_type ==
5780
0
               BGP_INSTANCE_TYPE_VRF ||
5781
0
             peer->bgp->inst_type ==
5782
0
               BGP_INSTANCE_TYPE_DEFAULT))
5783
0
          vpn_leak_from_vrf_withdraw(
5784
0
            bgp_get_default(), peer->bgp,
5785
0
            pi);
5786
5787
0
        bgp_rib_remove(dest, pi, peer, afi, safi);
5788
0
        break;
5789
0
      }
5790
0
  }
5791
0
}
5792
5793
void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5794
18
{
5795
18
  struct bgp_dest *dest, *ndest;
5796
18
  struct bgp_path_info *pi;
5797
18
  struct bgp_table *table;
5798
5799
18
  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5800
334
    for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5801
326
         dest = bgp_route_next(dest)) {
5802
326
      table = bgp_dest_get_bgp_table_info(dest);
5803
326
      if (!table)
5804
162
        continue;
5805
5806
164
      for (ndest = bgp_table_top(table); ndest;
5807
164
           ndest = bgp_route_next(ndest)) {
5808
0
        for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5809
0
             pi = pi->next) {
5810
0
          if (pi->peer != peer)
5811
0
            continue;
5812
5813
0
          if ((CHECK_FLAG(
5814
0
                peer->af_sflags[afi][safi],
5815
0
                PEER_STATUS_ENHANCED_REFRESH))
5816
0
              && !CHECK_FLAG(pi->flags,
5817
0
                 BGP_PATH_STALE)
5818
0
              && !CHECK_FLAG(
5819
0
                   pi->flags,
5820
0
                   BGP_PATH_UNUSEABLE)) {
5821
0
            if (bgp_debug_neighbor_events(
5822
0
                  peer))
5823
0
              zlog_debug(
5824
0
                "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5825
0
                peer,
5826
0
                afi2str(afi),
5827
0
                safi2str(safi),
5828
0
                bgp_dest_get_prefix(
5829
0
                  ndest));
5830
5831
0
            bgp_path_info_set_flag(
5832
0
              ndest, pi,
5833
0
              BGP_PATH_STALE);
5834
0
          }
5835
0
        }
5836
0
      }
5837
164
    }
5838
10
  } else {
5839
10
    for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5840
10
         dest = bgp_route_next(dest)) {
5841
0
      for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5842
0
           pi = pi->next) {
5843
0
        if (pi->peer != peer)
5844
0
          continue;
5845
5846
0
        if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5847
0
            PEER_STATUS_ENHANCED_REFRESH))
5848
0
            && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5849
0
            && !CHECK_FLAG(pi->flags,
5850
0
               BGP_PATH_UNUSEABLE)) {
5851
0
          if (bgp_debug_neighbor_events(peer))
5852
0
            zlog_debug(
5853
0
              "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5854
0
              peer, afi2str(afi),
5855
0
              safi2str(safi),
5856
0
              bgp_dest_get_prefix(
5857
0
                dest));
5858
5859
0
          bgp_path_info_set_flag(dest, pi,
5860
0
                     BGP_PATH_STALE);
5861
0
        }
5862
0
      }
5863
0
    }
5864
10
  }
5865
18
}
5866
5867
bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5868
0
{
5869
0
  if (peer->sort == BGP_PEER_IBGP)
5870
0
    return true;
5871
5872
0
  if (peer->sort == BGP_PEER_EBGP
5873
0
      && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5874
0
    || FILTER_LIST_OUT_NAME(filter)
5875
0
    || DISTRIBUTE_OUT_NAME(filter)))
5876
0
    return true;
5877
0
  return false;
5878
0
}
5879
5880
bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5881
0
{
5882
0
  if (peer->sort == BGP_PEER_IBGP)
5883
0
    return true;
5884
5885
0
  if (peer->sort == BGP_PEER_EBGP
5886
0
      && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5887
0
    || FILTER_LIST_IN_NAME(filter)
5888
0
    || DISTRIBUTE_IN_NAME(filter)))
5889
0
    return true;
5890
0
  return false;
5891
0
}
5892
5893
static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5894
            safi_t safi)
5895
0
{
5896
0
  struct bgp_dest *dest;
5897
0
  struct bgp_path_info *pi;
5898
0
  struct bgp_path_info *next;
5899
5900
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5901
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5902
0
      const struct prefix *p = bgp_dest_get_prefix(dest);
5903
5904
0
      next = pi->next;
5905
5906
      /* Unimport EVPN routes from VRFs */
5907
0
      if (safi == SAFI_EVPN)
5908
0
        bgp_evpn_unimport_route(bgp, AFI_L2VPN,
5909
0
              SAFI_EVPN, p, pi);
5910
5911
0
      if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5912
0
          && pi->type == ZEBRA_ROUTE_BGP
5913
0
          && (pi->sub_type == BGP_ROUTE_NORMAL
5914
0
        || pi->sub_type == BGP_ROUTE_AGGREGATE
5915
0
        || pi->sub_type == BGP_ROUTE_IMPORTED)) {
5916
5917
0
        if (bgp_fibupd_safi(safi))
5918
0
          bgp_zebra_withdraw(p, pi, bgp, safi);
5919
0
      }
5920
5921
0
      bgp_path_info_reap(dest, pi);
5922
0
    }
5923
0
}
5924
5925
/* Delete all kernel routes. */
5926
void bgp_cleanup_routes(struct bgp *bgp)
5927
0
{
5928
0
  afi_t afi;
5929
0
  struct bgp_dest *dest;
5930
0
  struct bgp_table *table;
5931
5932
0
  for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5933
0
    if (afi == AFI_L2VPN)
5934
0
      continue;
5935
0
    bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5936
0
          SAFI_UNICAST);
5937
    /*
5938
     * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5939
     */
5940
0
    if (afi != AFI_L2VPN) {
5941
0
      safi_t safi;
5942
0
      safi = SAFI_MPLS_VPN;
5943
0
      for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5944
0
           dest = bgp_route_next(dest)) {
5945
0
        table = bgp_dest_get_bgp_table_info(dest);
5946
0
        if (table != NULL) {
5947
0
          bgp_cleanup_table(bgp, table, safi);
5948
0
          bgp_table_finish(&table);
5949
0
          bgp_dest_set_bgp_table_info(dest, NULL);
5950
0
          bgp_dest_unlock_node(dest);
5951
0
        }
5952
0
      }
5953
0
      safi = SAFI_ENCAP;
5954
0
      for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5955
0
           dest = bgp_route_next(dest)) {
5956
0
        table = bgp_dest_get_bgp_table_info(dest);
5957
0
        if (table != NULL) {
5958
0
          bgp_cleanup_table(bgp, table, safi);
5959
0
          bgp_table_finish(&table);
5960
0
          bgp_dest_set_bgp_table_info(dest, NULL);
5961
0
          bgp_dest_unlock_node(dest);
5962
0
        }
5963
0
      }
5964
0
    }
5965
0
  }
5966
0
  for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5967
0
       dest = bgp_route_next(dest)) {
5968
0
    table = bgp_dest_get_bgp_table_info(dest);
5969
0
    if (table != NULL) {
5970
0
      bgp_cleanup_table(bgp, table, SAFI_EVPN);
5971
0
      bgp_table_finish(&table);
5972
0
      bgp_dest_set_bgp_table_info(dest, NULL);
5973
0
      bgp_dest_unlock_node(dest);
5974
0
    }
5975
0
  }
5976
0
}
5977
5978
void bgp_reset(void)
5979
0
{
5980
0
  vty_reset();
5981
0
  bgp_zclient_reset();
5982
0
  access_list_reset();
5983
0
  prefix_list_reset();
5984
0
}
5985
5986
bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
5987
245
{
5988
245
  return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5989
245
    && CHECK_FLAG(peer->af_cap[afi][safi],
5990
245
            PEER_CAP_ADDPATH_AF_TX_RCV));
5991
245
}
5992
5993
/* Parse NLRI stream.  Withdraw NLRI is recognized by NULL attr
5994
   value. */
5995
int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5996
          struct bgp_nlri *packet)
5997
86
{
5998
86
  uint8_t *pnt;
5999
86
  uint8_t *lim;
6000
86
  struct prefix p;
6001
86
  int psize;
6002
86
  afi_t afi;
6003
86
  safi_t safi;
6004
86
  bool addpath_capable;
6005
86
  uint32_t addpath_id;
6006
6007
86
  pnt = packet->nlri;
6008
86
  lim = pnt + packet->length;
6009
86
  afi = packet->afi;
6010
86
  safi = packet->safi;
6011
86
  addpath_id = 0;
6012
86
  addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
6013
6014
  /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6015
     syntactic validity.  If the field is syntactically incorrect,
6016
     then the Error Subcode is set to Invalid Network Field. */
6017
2.80k
  for (; pnt < lim; pnt += psize) {
6018
    /* Clear prefix structure. */
6019
2.79k
    memset(&p, 0, sizeof(p));
6020
6021
2.79k
    if (addpath_capable) {
6022
6023
      /* When packet overflow occurs return immediately. */
6024
2.79k
      if (pnt + BGP_ADDPATH_ID_LEN >= lim)
6025
19
        return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
6026
6027
2.77k
      memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
6028
2.77k
      addpath_id = ntohl(addpath_id);
6029
2.77k
      pnt += BGP_ADDPATH_ID_LEN;
6030
2.77k
    }
6031
6032
    /* Fetch prefix length. */
6033
2.77k
    p.prefixlen = *pnt++;
6034
    /* afi/safi validity already verified by caller,
6035
     * bgp_update_receive */
6036
2.77k
    p.family = afi2family(afi);
6037
6038
    /* Prefix length check. */
6039
2.77k
    if (p.prefixlen > prefix_blen(&p) * 8) {
6040
59
      flog_err(
6041
59
        EC_BGP_UPDATE_RCV,
6042
59
        "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6043
59
        peer->host, p.prefixlen, packet->afi);
6044
59
      return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
6045
59
    }
6046
6047
    /* Packet size overflow check. */
6048
2.71k
    psize = PSIZE(p.prefixlen);
6049
6050
    /* When packet overflow occur return immediately. */
6051
2.71k
    if (pnt + psize > lim) {
6052
1
      flog_err(
6053
1
        EC_BGP_UPDATE_RCV,
6054
1
        "%s [Error] Update packet error (prefix length %d overflows packet)",
6055
1
        peer->host, p.prefixlen);
6056
1
      return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
6057
1
    }
6058
6059
    /* Defensive coding, double-check the psize fits in a struct
6060
     * prefix for the v4 and v6 afi's and unicast/multicast */
6061
2.71k
    if (psize > (ssize_t)sizeof(p.u.val)) {
6062
0
      flog_err(
6063
0
        EC_BGP_UPDATE_RCV,
6064
0
        "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6065
0
        peer->host, p.prefixlen, sizeof(p.u.val));
6066
0
      return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
6067
0
    }
6068
6069
    /* Fetch prefix from NLRI packet. */
6070
2.71k
    memcpy(p.u.val, pnt, psize);
6071
6072
    /* Check address. */
6073
2.71k
    if (afi == AFI_IP && safi == SAFI_UNICAST) {
6074
2.71k
      if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6075
        /* From RFC4271 Section 6.3:
6076
         *
6077
         * If a prefix in the NLRI field is semantically
6078
         * incorrect
6079
         * (e.g., an unexpected multicast IP address),
6080
         * an error SHOULD
6081
         * be logged locally, and the prefix SHOULD be
6082
         * ignored.
6083
         */
6084
2
        flog_err(
6085
2
          EC_BGP_UPDATE_RCV,
6086
2
          "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6087
2
          peer->host, &p.u.prefix4);
6088
2
        continue;
6089
2
      }
6090
2.71k
    }
6091
6092
    /* Check address. */
6093
2.71k
    if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6094
0
      if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6095
0
        flog_err(
6096
0
          EC_BGP_UPDATE_RCV,
6097
0
          "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6098
0
          peer->host, &p.u.prefix6);
6099
6100
0
        continue;
6101
0
      }
6102
0
      if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
6103
0
        flog_err(
6104
0
          EC_BGP_UPDATE_RCV,
6105
0
          "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6106
0
          peer->host, &p.u.prefix6);
6107
6108
0
        continue;
6109
0
      }
6110
0
    }
6111
6112
    /* Normal process. */
6113
2.71k
    if (attr)
6114
2.30k
      bgp_update(peer, &p, addpath_id, attr, afi, safi,
6115
2.30k
           ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6116
2.30k
           NULL, 0, 0, NULL);
6117
407
    else
6118
407
      bgp_withdraw(peer, &p, addpath_id, afi, safi,
6119
407
             ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6120
407
             NULL, 0, NULL);
6121
6122
    /* Do not send BGP notification twice when maximum-prefix count
6123
     * overflow. */
6124
2.71k
    if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6125
0
      return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6126
2.71k
  }
6127
6128
  /* Packet length consistency check. */
6129
7
  if (pnt != lim) {
6130
0
    flog_err(
6131
0
      EC_BGP_UPDATE_RCV,
6132
0
      "%s [Error] Update packet error (prefix length mismatch with total length)",
6133
0
      peer->host);
6134
0
    return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
6135
0
  }
6136
6137
7
  return BGP_NLRI_PARSE_OK;
6138
7
}
6139
6140
static struct bgp_static *bgp_static_new(void)
6141
0
{
6142
0
  return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
6143
0
}
6144
6145
static void bgp_static_free(struct bgp_static *bgp_static)
6146
0
{
6147
0
  XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6148
0
  route_map_counter_decrement(bgp_static->rmap.map);
6149
6150
0
  if (bgp_static->prd_pretty)
6151
0
    XFREE(MTYPE_BGP, bgp_static->prd_pretty);
6152
0
  XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
6153
0
  XFREE(MTYPE_BGP_STATIC, bgp_static);
6154
0
}
6155
6156
void bgp_static_update(struct bgp *bgp, const struct prefix *p,
6157
           struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6158
0
{
6159
0
  struct bgp_dest *dest;
6160
0
  struct bgp_path_info *pi;
6161
0
  struct bgp_path_info *new;
6162
0
  struct bgp_path_info rmap_path;
6163
0
  struct attr attr;
6164
0
  struct attr *attr_new;
6165
0
  route_map_result_t ret;
6166
0
#ifdef ENABLE_BGP_VNC
6167
0
  int vnc_implicit_withdraw = 0;
6168
0
#endif
6169
6170
0
  assert(bgp_static);
6171
6172
0
  dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
6173
6174
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
6175
6176
0
  attr.nexthop = bgp_static->igpnexthop;
6177
0
  attr.med = bgp_static->igpmetric;
6178
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6179
6180
0
  if (afi == AFI_IP)
6181
0
    attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6182
6183
0
  if (bgp_static->igpmetric)
6184
0
    bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6185
6186
0
  if (bgp_static->atomic)
6187
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6188
6189
  /* Store label index, if required. */
6190
0
  if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6191
0
    attr.label_index = bgp_static->label_index;
6192
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6193
0
  }
6194
6195
  /* Apply route-map. */
6196
0
  if (bgp_static->rmap.name) {
6197
0
    struct attr attr_tmp = attr;
6198
6199
0
    memset(&rmap_path, 0, sizeof(rmap_path));
6200
0
    rmap_path.peer = bgp->peer_self;
6201
0
    rmap_path.attr = &attr_tmp;
6202
6203
0
    SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
6204
6205
0
    ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
6206
6207
0
    bgp->peer_self->rmap_type = 0;
6208
6209
0
    if (ret == RMAP_DENYMATCH) {
6210
      /* Free uninterned attribute. */
6211
0
      bgp_attr_flush(&attr_tmp);
6212
6213
      /* Unintern original. */
6214
0
      aspath_unintern(&attr.aspath);
6215
0
      bgp_static_withdraw(bgp, p, afi, safi);
6216
0
      bgp_dest_unlock_node(dest);
6217
0
      return;
6218
0
    }
6219
6220
0
    if (bgp_in_graceful_shutdown(bgp))
6221
0
      bgp_attr_add_gshut_community(&attr_tmp);
6222
6223
0
    attr_new = bgp_attr_intern(&attr_tmp);
6224
0
  } else {
6225
6226
0
    if (bgp_in_graceful_shutdown(bgp))
6227
0
      bgp_attr_add_gshut_community(&attr);
6228
6229
0
    attr_new = bgp_attr_intern(&attr);
6230
0
  }
6231
6232
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6233
0
    if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6234
0
        && pi->sub_type == BGP_ROUTE_STATIC)
6235
0
      break;
6236
6237
0
  if (pi) {
6238
0
    if (attrhash_cmp(pi->attr, attr_new)
6239
0
        && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
6240
0
        && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
6241
0
      bgp_dest_unlock_node(dest);
6242
0
      bgp_attr_unintern(&attr_new);
6243
0
      aspath_unintern(&attr.aspath);
6244
0
      return;
6245
0
    } else {
6246
      /* The attribute is changed. */
6247
0
      bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
6248
6249
      /* Rewrite BGP route information. */
6250
0
      if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
6251
0
        bgp_path_info_restore(dest, pi);
6252
0
      else
6253
0
        bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6254
0
#ifdef ENABLE_BGP_VNC
6255
0
      if ((afi == AFI_IP || afi == AFI_IP6)
6256
0
          && (safi == SAFI_UNICAST)) {
6257
0
        if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
6258
          /*
6259
           * Implicit withdraw case.
6260
           * We have to do this before pi is
6261
           * changed
6262
           */
6263
0
          ++vnc_implicit_withdraw;
6264
0
          vnc_import_bgp_del_route(bgp, p, pi);
6265
0
          vnc_import_bgp_exterior_del_route(
6266
0
            bgp, p, pi);
6267
0
        }
6268
0
      }
6269
0
#endif
6270
0
      bgp_attr_unintern(&pi->attr);
6271
0
      pi->attr = attr_new;
6272
0
      pi->uptime = monotime(NULL);
6273
0
#ifdef ENABLE_BGP_VNC
6274
0
      if ((afi == AFI_IP || afi == AFI_IP6)
6275
0
          && (safi == SAFI_UNICAST)) {
6276
0
        if (vnc_implicit_withdraw) {
6277
0
          vnc_import_bgp_add_route(bgp, p, pi);
6278
0
          vnc_import_bgp_exterior_add_route(
6279
0
            bgp, p, pi);
6280
0
        }
6281
0
      }
6282
0
#endif
6283
6284
      /* Nexthop reachability check. */
6285
0
      if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
6286
0
          && (safi == SAFI_UNICAST
6287
0
        || safi == SAFI_LABELED_UNICAST)) {
6288
6289
0
        struct bgp *bgp_nexthop = bgp;
6290
6291
0
        if (pi->extra && pi->extra->bgp_orig)
6292
0
          bgp_nexthop = pi->extra->bgp_orig;
6293
6294
0
        if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
6295
0
                  afi, safi, pi, NULL,
6296
0
                  0, p))
6297
0
          bgp_path_info_set_flag(dest, pi,
6298
0
                     BGP_PATH_VALID);
6299
0
        else {
6300
0
          if (BGP_DEBUG(nht, NHT)) {
6301
0
            char buf1[INET6_ADDRSTRLEN];
6302
0
            inet_ntop(p->family,
6303
0
                &p->u.prefix, buf1,
6304
0
                sizeof(buf1));
6305
0
            zlog_debug(
6306
0
              "%s(%s): Route not in table, not advertising",
6307
0
              __func__, buf1);
6308
0
          }
6309
0
          bgp_path_info_unset_flag(
6310
0
            dest, pi, BGP_PATH_VALID);
6311
0
        }
6312
0
      } else {
6313
        /* Delete the NHT structure if any, if we're
6314
         * toggling between
6315
         * enabling/disabling import check. We
6316
         * deregister the route
6317
         * from NHT to avoid overloading NHT and the
6318
         * process interaction
6319
         */
6320
0
        bgp_unlink_nexthop(pi);
6321
0
        bgp_path_info_set_flag(dest, pi,
6322
0
                   BGP_PATH_VALID);
6323
0
      }
6324
      /* Process change. */
6325
0
      bgp_aggregate_increment(bgp, p, pi, afi, safi);
6326
0
      bgp_process(bgp, dest, afi, safi);
6327
6328
0
      if (SAFI_UNICAST == safi
6329
0
          && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6330
0
        || bgp->inst_type
6331
0
             == BGP_INSTANCE_TYPE_DEFAULT)) {
6332
0
        vpn_leak_from_vrf_update(bgp_get_default(), bgp,
6333
0
               pi);
6334
0
      }
6335
6336
0
      bgp_dest_unlock_node(dest);
6337
0
      aspath_unintern(&attr.aspath);
6338
0
      return;
6339
0
    }
6340
0
  }
6341
6342
  /* Make new BGP info. */
6343
0
  new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
6344
0
      attr_new, dest);
6345
  /* Nexthop reachability check. */
6346
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
6347
0
      && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
6348
0
    if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6349
0
              p))
6350
0
      bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
6351
0
    else {
6352
0
      if (BGP_DEBUG(nht, NHT)) {
6353
0
        char buf1[INET6_ADDRSTRLEN];
6354
6355
0
        inet_ntop(p->family, &p->u.prefix, buf1,
6356
0
            sizeof(buf1));
6357
0
        zlog_debug(
6358
0
          "%s(%s): Route not in table, not advertising",
6359
0
          __func__, buf1);
6360
0
      }
6361
0
      bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
6362
0
    }
6363
0
  } else {
6364
    /* Delete the NHT structure if any, if we're toggling between
6365
     * enabling/disabling import check. We deregister the route
6366
     * from NHT to avoid overloading NHT and the process interaction
6367
     */
6368
0
    bgp_unlink_nexthop(new);
6369
6370
0
    bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
6371
0
  }
6372
6373
  /* Aggregate address increment. */
6374
0
  bgp_aggregate_increment(bgp, p, new, afi, safi);
6375
6376
  /* Register new BGP information. */
6377
0
  bgp_path_info_add(dest, new);
6378
6379
  /* route_node_get lock */
6380
0
  bgp_dest_unlock_node(dest);
6381
6382
  /* Process change. */
6383
0
  bgp_process(bgp, dest, afi, safi);
6384
6385
0
  if (SAFI_UNICAST == safi
6386
0
      && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6387
0
    || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6388
0
    vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6389
0
  }
6390
6391
  /* Unintern original. */
6392
0
  aspath_unintern(&attr.aspath);
6393
0
}
6394
6395
void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
6396
       safi_t safi)
6397
0
{
6398
0
  struct bgp_dest *dest;
6399
0
  struct bgp_path_info *pi;
6400
6401
0
  dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
6402
6403
  /* Check selected route and self inserted route. */
6404
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6405
0
    if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6406
0
        && pi->sub_type == BGP_ROUTE_STATIC)
6407
0
      break;
6408
6409
  /* Withdraw static BGP route from routing table. */
6410
0
  if (pi) {
6411
0
    if (SAFI_UNICAST == safi
6412
0
        && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6413
0
      || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6414
0
      vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
6415
0
    }
6416
0
    bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6417
0
    bgp_unlink_nexthop(pi);
6418
0
    bgp_path_info_delete(dest, pi);
6419
0
    bgp_process(bgp, dest, afi, safi);
6420
0
  }
6421
6422
  /* Unlock bgp_node_lookup. */
6423
0
  bgp_dest_unlock_node(dest);
6424
0
}
6425
6426
/*
6427
 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6428
 */
6429
static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
6430
             afi_t afi, safi_t safi,
6431
             struct prefix_rd *prd)
6432
0
{
6433
0
  struct bgp_dest *dest;
6434
0
  struct bgp_path_info *pi;
6435
6436
0
  dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
6437
6438
  /* Check selected route and self inserted route. */
6439
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6440
0
    if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6441
0
        && pi->sub_type == BGP_ROUTE_STATIC)
6442
0
      break;
6443
6444
  /* Withdraw static BGP route from routing table. */
6445
0
  if (pi) {
6446
0
#ifdef ENABLE_BGP_VNC
6447
0
    rfapiProcessWithdraw(
6448
0
      pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
6449
0
      1); /* Kill, since it is an administrative change */
6450
0
#endif
6451
0
    if (SAFI_MPLS_VPN == safi
6452
0
        && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6453
0
      vpn_leak_to_vrf_withdraw(pi);
6454
0
    }
6455
0
    bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6456
0
    bgp_path_info_delete(dest, pi);
6457
0
    bgp_process(bgp, dest, afi, safi);
6458
0
  }
6459
6460
  /* Unlock bgp_node_lookup. */
6461
0
  bgp_dest_unlock_node(dest);
6462
0
}
6463
6464
static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
6465
           struct bgp_static *bgp_static, afi_t afi,
6466
           safi_t safi)
6467
0
{
6468
0
  struct bgp_dest *dest;
6469
0
  struct bgp_path_info *new;
6470
0
  struct attr *attr_new;
6471
0
  struct attr attr = {0};
6472
0
  struct bgp_path_info *pi;
6473
0
#ifdef ENABLE_BGP_VNC
6474
0
  mpls_label_t label = 0;
6475
0
#endif
6476
0
  uint32_t num_labels = 0;
6477
6478
0
  assert(bgp_static);
6479
6480
0
  if (bgp_static->label != MPLS_INVALID_LABEL)
6481
0
    num_labels = 1;
6482
0
  dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6483
0
        &bgp_static->prd);
6484
6485
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
6486
6487
0
  attr.nexthop = bgp_static->igpnexthop;
6488
0
  attr.med = bgp_static->igpmetric;
6489
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6490
6491
0
  if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6492
0
      || (safi == SAFI_ENCAP)) {
6493
0
    if (afi == AFI_IP) {
6494
0
      attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6495
0
      attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6496
0
    }
6497
0
  }
6498
0
  if (afi == AFI_L2VPN) {
6499
0
    if (bgp_static->gatewayIp.family == AF_INET) {
6500
0
      SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6501
0
      memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
6502
0
             &bgp_static->gatewayIp.u.prefix4,
6503
0
             IPV4_MAX_BYTELEN);
6504
0
    } else if (bgp_static->gatewayIp.family == AF_INET6) {
6505
0
      SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6506
0
      memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
6507
0
             &bgp_static->gatewayIp.u.prefix6,
6508
0
             IPV6_MAX_BYTELEN);
6509
0
    }
6510
0
    memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
6511
0
    if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6512
0
      struct bgp_encap_type_vxlan bet;
6513
0
      memset(&bet, 0, sizeof(bet));
6514
0
      bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
6515
0
      bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6516
0
    }
6517
0
    if (bgp_static->router_mac) {
6518
0
      bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6519
0
    }
6520
0
  }
6521
  /* Apply route-map. */
6522
0
  if (bgp_static->rmap.name) {
6523
0
    struct attr attr_tmp = attr;
6524
0
    struct bgp_path_info rmap_path;
6525
0
    route_map_result_t ret;
6526
6527
0
    rmap_path.peer = bgp->peer_self;
6528
0
    rmap_path.attr = &attr_tmp;
6529
6530
0
    SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
6531
6532
0
    ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
6533
6534
0
    bgp->peer_self->rmap_type = 0;
6535
6536
0
    if (ret == RMAP_DENYMATCH) {
6537
      /* Free uninterned attribute. */
6538
0
      bgp_attr_flush(&attr_tmp);
6539
6540
      /* Unintern original. */
6541
0
      aspath_unintern(&attr.aspath);
6542
0
      bgp_static_withdraw_safi(bgp, p, afi, safi,
6543
0
             &bgp_static->prd);
6544
0
      bgp_dest_unlock_node(dest);
6545
0
      return;
6546
0
    }
6547
6548
0
    attr_new = bgp_attr_intern(&attr_tmp);
6549
0
  } else {
6550
0
    attr_new = bgp_attr_intern(&attr);
6551
0
  }
6552
6553
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6554
0
    if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6555
0
        && pi->sub_type == BGP_ROUTE_STATIC)
6556
0
      break;
6557
6558
0
  if (pi) {
6559
0
    if (attrhash_cmp(pi->attr, attr_new)
6560
0
        && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
6561
0
      bgp_dest_unlock_node(dest);
6562
0
      bgp_attr_unintern(&attr_new);
6563
0
      aspath_unintern(&attr.aspath);
6564
0
      return;
6565
0
    } else {
6566
      /* The attribute is changed. */
6567
0
      bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
6568
6569
      /* Rewrite BGP route information. */
6570
0
      if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
6571
0
        bgp_path_info_restore(dest, pi);
6572
0
      else
6573
0
        bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6574
0
      bgp_attr_unintern(&pi->attr);
6575
0
      pi->attr = attr_new;
6576
0
      pi->uptime = monotime(NULL);
6577
0
#ifdef ENABLE_BGP_VNC
6578
0
      if (pi->extra)
6579
0
        label = decode_label(&pi->extra->label[0]);
6580
0
#endif
6581
6582
      /* Process change. */
6583
0
      bgp_aggregate_increment(bgp, p, pi, afi, safi);
6584
0
      bgp_process(bgp, dest, afi, safi);
6585
6586
0
      if (SAFI_MPLS_VPN == safi
6587
0
          && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6588
0
        vpn_leak_to_vrf_update(bgp, pi,
6589
0
                   &bgp_static->prd);
6590
0
      }
6591
0
#ifdef ENABLE_BGP_VNC
6592
0
      rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6593
0
             pi->attr, afi, safi, pi->type,
6594
0
             pi->sub_type, &label);
6595
0
#endif
6596
0
      bgp_dest_unlock_node(dest);
6597
0
      aspath_unintern(&attr.aspath);
6598
0
      return;
6599
0
    }
6600
0
  }
6601
6602
6603
  /* Make new BGP info. */
6604
0
  new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
6605
0
      attr_new, dest);
6606
0
  SET_FLAG(new->flags, BGP_PATH_VALID);
6607
0
  bgp_path_info_extra_get(new);
6608
0
  if (num_labels) {
6609
0
    new->extra->label[0] = bgp_static->label;
6610
0
    new->extra->num_labels = num_labels;
6611
0
  }
6612
0
#ifdef ENABLE_BGP_VNC
6613
0
  label = decode_label(&bgp_static->label);
6614
0
#endif
6615
6616
  /* Aggregate address increment. */
6617
0
  bgp_aggregate_increment(bgp, p, new, afi, safi);
6618
6619
  /* Register new BGP information. */
6620
0
  bgp_path_info_add(dest, new);
6621
  /* route_node_get lock */
6622
0
  bgp_dest_unlock_node(dest);
6623
6624
  /* Process change. */
6625
0
  bgp_process(bgp, dest, afi, safi);
6626
6627
0
  if (SAFI_MPLS_VPN == safi
6628
0
      && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6629
0
    vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
6630
0
  }
6631
0
#ifdef ENABLE_BGP_VNC
6632
0
  rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6633
0
         safi, new->type, new->sub_type, &label);
6634
0
#endif
6635
6636
  /* Unintern original. */
6637
0
  aspath_unintern(&attr.aspath);
6638
0
}
6639
6640
/* Configure static BGP network.  When user don't run zebra, static
6641
   route should be installed as valid.  */
6642
static int bgp_static_set(struct vty *vty, const char *negate,
6643
        const char *ip_str, afi_t afi, safi_t safi,
6644
        const char *rmap, int backdoor, uint32_t label_index)
6645
0
{
6646
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
6647
0
  int ret;
6648
0
  struct prefix p;
6649
0
  struct bgp_static *bgp_static;
6650
0
  struct bgp_dest *dest;
6651
0
  uint8_t need_update = 0;
6652
6653
  /* Convert IP prefix string to struct prefix. */
6654
0
  ret = str2prefix(ip_str, &p);
6655
0
  if (!ret) {
6656
0
    vty_out(vty, "%% Malformed prefix\n");
6657
0
    return CMD_WARNING_CONFIG_FAILED;
6658
0
  }
6659
0
  if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6660
0
    vty_out(vty, "%% Malformed prefix (link-local address)\n");
6661
0
    return CMD_WARNING_CONFIG_FAILED;
6662
0
  }
6663
6664
0
  apply_mask(&p);
6665
6666
0
  if (negate) {
6667
6668
    /* Set BGP static route configuration. */
6669
0
    dest = bgp_node_lookup(bgp->route[afi][safi], &p);
6670
6671
0
    if (!dest) {
6672
0
      vty_out(vty, "%% Can't find static route specified\n");
6673
0
      return CMD_WARNING_CONFIG_FAILED;
6674
0
    }
6675
6676
0
    bgp_static = bgp_dest_get_bgp_static_info(dest);
6677
6678
0
    if ((label_index != BGP_INVALID_LABEL_INDEX)
6679
0
        && (label_index != bgp_static->label_index)) {
6680
0
      vty_out(vty,
6681
0
        "%% label-index doesn't match static route\n");
6682
0
      bgp_dest_unlock_node(dest);
6683
0
      return CMD_WARNING_CONFIG_FAILED;
6684
0
    }
6685
6686
0
    if ((rmap && bgp_static->rmap.name)
6687
0
        && strcmp(rmap, bgp_static->rmap.name)) {
6688
0
      vty_out(vty,
6689
0
        "%% route-map name doesn't match static route\n");
6690
0
      bgp_dest_unlock_node(dest);
6691
0
      return CMD_WARNING_CONFIG_FAILED;
6692
0
    }
6693
6694
    /* Update BGP RIB. */
6695
0
    if (!bgp_static->backdoor)
6696
0
      bgp_static_withdraw(bgp, &p, afi, safi);
6697
6698
    /* Clear configuration. */
6699
0
    bgp_static_free(bgp_static);
6700
0
    bgp_dest_set_bgp_static_info(dest, NULL);
6701
0
    bgp_dest_unlock_node(dest);
6702
0
    bgp_dest_unlock_node(dest);
6703
0
  } else {
6704
6705
    /* Set BGP static route configuration. */
6706
0
    dest = bgp_node_get(bgp->route[afi][safi], &p);
6707
0
    bgp_static = bgp_dest_get_bgp_static_info(dest);
6708
0
    if (bgp_static) {
6709
      /* Configuration change. */
6710
      /* Label index cannot be changed. */
6711
0
      if (bgp_static->label_index != label_index) {
6712
0
        vty_out(vty, "%% cannot change label-index\n");
6713
0
        bgp_dest_unlock_node(dest);
6714
0
        return CMD_WARNING_CONFIG_FAILED;
6715
0
      }
6716
6717
      /* Check previous routes are installed into BGP.  */
6718
0
      if (bgp_static->valid
6719
0
          && bgp_static->backdoor != backdoor)
6720
0
        need_update = 1;
6721
6722
0
      bgp_static->backdoor = backdoor;
6723
6724
0
      if (rmap) {
6725
0
        XFREE(MTYPE_ROUTE_MAP_NAME,
6726
0
              bgp_static->rmap.name);
6727
0
        route_map_counter_decrement(
6728
0
          bgp_static->rmap.map);
6729
0
        bgp_static->rmap.name =
6730
0
          XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6731
0
        bgp_static->rmap.map =
6732
0
          route_map_lookup_by_name(rmap);
6733
0
        route_map_counter_increment(
6734
0
          bgp_static->rmap.map);
6735
0
      } else {
6736
0
        XFREE(MTYPE_ROUTE_MAP_NAME,
6737
0
              bgp_static->rmap.name);
6738
0
        route_map_counter_decrement(
6739
0
          bgp_static->rmap.map);
6740
0
        bgp_static->rmap.map = NULL;
6741
0
        bgp_static->valid = 0;
6742
0
      }
6743
0
      bgp_dest_unlock_node(dest);
6744
0
    } else {
6745
      /* New configuration. */
6746
0
      bgp_static = bgp_static_new();
6747
0
      bgp_static->backdoor = backdoor;
6748
0
      bgp_static->valid = 0;
6749
0
      bgp_static->igpmetric = 0;
6750
0
      bgp_static->igpnexthop.s_addr = INADDR_ANY;
6751
0
      bgp_static->label_index = label_index;
6752
6753
0
      if (rmap) {
6754
0
        XFREE(MTYPE_ROUTE_MAP_NAME,
6755
0
              bgp_static->rmap.name);
6756
0
        route_map_counter_decrement(
6757
0
          bgp_static->rmap.map);
6758
0
        bgp_static->rmap.name =
6759
0
          XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6760
0
        bgp_static->rmap.map =
6761
0
          route_map_lookup_by_name(rmap);
6762
0
        route_map_counter_increment(
6763
0
          bgp_static->rmap.map);
6764
0
      }
6765
0
      bgp_dest_set_bgp_static_info(dest, bgp_static);
6766
0
    }
6767
6768
0
    bgp_static->valid = 1;
6769
0
    if (need_update)
6770
0
      bgp_static_withdraw(bgp, &p, afi, safi);
6771
6772
0
    if (!bgp_static->backdoor)
6773
0
      bgp_static_update(bgp, &p, bgp_static, afi, safi);
6774
0
  }
6775
6776
0
  return CMD_SUCCESS;
6777
0
}
6778
6779
void bgp_static_add(struct bgp *bgp)
6780
0
{
6781
0
  afi_t afi;
6782
0
  safi_t safi;
6783
0
  struct bgp_dest *dest;
6784
0
  struct bgp_dest *rm;
6785
0
  struct bgp_table *table;
6786
0
  struct bgp_static *bgp_static;
6787
6788
0
  SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6789
0
  FOREACH_AFI_SAFI (afi, safi)
6790
0
    for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6791
0
         dest = bgp_route_next(dest)) {
6792
0
      if (!bgp_dest_has_bgp_path_info_data(dest))
6793
0
        continue;
6794
6795
0
      if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6796
0
          || (safi == SAFI_EVPN)) {
6797
0
        table = bgp_dest_get_bgp_table_info(dest);
6798
6799
0
        for (rm = bgp_table_top(table); rm;
6800
0
             rm = bgp_route_next(rm)) {
6801
0
          bgp_static =
6802
0
            bgp_dest_get_bgp_static_info(
6803
0
              rm);
6804
0
          bgp_static_update_safi(
6805
0
            bgp, bgp_dest_get_prefix(rm),
6806
0
            bgp_static, afi, safi);
6807
0
        }
6808
0
      } else {
6809
0
        bgp_static_update(
6810
0
          bgp, bgp_dest_get_prefix(dest),
6811
0
          bgp_dest_get_bgp_static_info(dest), afi,
6812
0
          safi);
6813
0
      }
6814
0
    }
6815
0
  UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6816
0
}
6817
6818
/* Called from bgp_delete().  Delete all static routes from the BGP
6819
   instance. */
6820
void bgp_static_delete(struct bgp *bgp)
6821
0
{
6822
0
  afi_t afi;
6823
0
  safi_t safi;
6824
0
  struct bgp_dest *dest;
6825
0
  struct bgp_dest *rm;
6826
0
  struct bgp_table *table;
6827
0
  struct bgp_static *bgp_static;
6828
6829
0
  FOREACH_AFI_SAFI (afi, safi)
6830
0
    for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6831
0
         dest = bgp_route_next(dest)) {
6832
0
      if (!bgp_dest_has_bgp_path_info_data(dest))
6833
0
        continue;
6834
6835
0
      if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6836
0
          || (safi == SAFI_EVPN)) {
6837
0
        table = bgp_dest_get_bgp_table_info(dest);
6838
6839
0
        for (rm = bgp_table_top(table); rm;
6840
0
             rm = bgp_route_next(rm)) {
6841
0
          bgp_static =
6842
0
            bgp_dest_get_bgp_static_info(
6843
0
              rm);
6844
0
          if (!bgp_static)
6845
0
            continue;
6846
6847
0
          bgp_static_withdraw_safi(
6848
0
            bgp, bgp_dest_get_prefix(rm),
6849
0
            AFI_IP, safi,
6850
0
            (struct prefix_rd *)
6851
0
              bgp_dest_get_prefix(
6852
0
                dest));
6853
0
          bgp_static_free(bgp_static);
6854
0
          bgp_dest_set_bgp_static_info(rm,
6855
0
                     NULL);
6856
0
          bgp_dest_unlock_node(rm);
6857
0
        }
6858
0
      } else {
6859
0
        bgp_static = bgp_dest_get_bgp_static_info(dest);
6860
0
        bgp_static_withdraw(bgp,
6861
0
                bgp_dest_get_prefix(dest),
6862
0
                afi, safi);
6863
0
        bgp_static_free(bgp_static);
6864
0
        bgp_dest_set_bgp_static_info(dest, NULL);
6865
0
        bgp_dest_unlock_node(dest);
6866
0
      }
6867
0
    }
6868
0
}
6869
6870
void bgp_static_redo_import_check(struct bgp *bgp)
6871
0
{
6872
0
  afi_t afi;
6873
0
  safi_t safi;
6874
0
  struct bgp_dest *dest;
6875
0
  struct bgp_dest *rm;
6876
0
  struct bgp_table *table;
6877
0
  struct bgp_static *bgp_static;
6878
6879
  /* Use this flag to force reprocessing of the route */
6880
0
  SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6881
0
  FOREACH_AFI_SAFI (afi, safi) {
6882
0
    for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6883
0
         dest = bgp_route_next(dest)) {
6884
0
      if (!bgp_dest_has_bgp_path_info_data(dest))
6885
0
        continue;
6886
6887
0
      if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6888
0
          || (safi == SAFI_EVPN)) {
6889
0
        table = bgp_dest_get_bgp_table_info(dest);
6890
6891
0
        for (rm = bgp_table_top(table); rm;
6892
0
             rm = bgp_route_next(rm)) {
6893
0
          bgp_static =
6894
0
            bgp_dest_get_bgp_static_info(
6895
0
              rm);
6896
0
          bgp_static_update_safi(
6897
0
            bgp, bgp_dest_get_prefix(rm),
6898
0
            bgp_static, afi, safi);
6899
0
        }
6900
0
      } else {
6901
0
        bgp_static = bgp_dest_get_bgp_static_info(dest);
6902
0
        bgp_static_update(bgp,
6903
0
              bgp_dest_get_prefix(dest),
6904
0
              bgp_static, afi, safi);
6905
0
      }
6906
0
    }
6907
0
  }
6908
0
  UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6909
0
}
6910
6911
static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6912
                safi_t safi)
6913
0
{
6914
0
  struct bgp_table *table;
6915
0
  struct bgp_dest *dest;
6916
0
  struct bgp_path_info *pi;
6917
6918
  /* Do not install the aggregate route if BGP is in the
6919
   * process of termination.
6920
   */
6921
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6922
0
      || (bgp->peer_self == NULL))
6923
0
    return;
6924
6925
0
  table = bgp->rib[afi][safi];
6926
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6927
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6928
0
      if (pi->peer == bgp->peer_self
6929
0
          && ((pi->type == ZEBRA_ROUTE_BGP
6930
0
         && pi->sub_type == BGP_ROUTE_STATIC)
6931
0
        || (pi->type != ZEBRA_ROUTE_BGP
6932
0
            && pi->sub_type
6933
0
                 == BGP_ROUTE_REDISTRIBUTE))) {
6934
0
        bgp_aggregate_decrement(
6935
0
          bgp, bgp_dest_get_prefix(dest), pi, afi,
6936
0
          safi);
6937
0
        bgp_unlink_nexthop(pi);
6938
0
        bgp_path_info_delete(dest, pi);
6939
0
        bgp_process(bgp, dest, afi, safi);
6940
0
      }
6941
0
    }
6942
0
  }
6943
0
}
6944
6945
/*
6946
 * Purge all networks and redistributed routes from routing table.
6947
 * Invoked upon the instance going down.
6948
 */
6949
void bgp_purge_static_redist_routes(struct bgp *bgp)
6950
0
{
6951
0
  afi_t afi;
6952
0
  safi_t safi;
6953
6954
0
  FOREACH_AFI_SAFI (afi, safi)
6955
0
    bgp_purge_af_static_redist_routes(bgp, afi, safi);
6956
0
}
6957
6958
/*
6959
 * gpz 110624
6960
 * Currently this is used to set static routes for VPN and ENCAP.
6961
 * I think it can probably be factored with bgp_static_set.
6962
 */
6963
int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6964
      const char *ip_str, const char *rd_str,
6965
      const char *label_str, const char *rmap_str,
6966
      int evpn_type, const char *esi, const char *gwip,
6967
      const char *ethtag, const char *routermac)
6968
0
{
6969
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
6970
0
  int ret;
6971
0
  struct prefix p;
6972
0
  struct prefix_rd prd;
6973
0
  struct bgp_dest *pdest;
6974
0
  struct bgp_dest *dest;
6975
0
  struct bgp_table *table;
6976
0
  struct bgp_static *bgp_static;
6977
0
  mpls_label_t label = MPLS_INVALID_LABEL;
6978
0
  struct prefix gw_ip;
6979
6980
  /* validate ip prefix */
6981
0
  ret = str2prefix(ip_str, &p);
6982
0
  if (!ret) {
6983
0
    vty_out(vty, "%% Malformed prefix\n");
6984
0
    return CMD_WARNING_CONFIG_FAILED;
6985
0
  }
6986
0
  apply_mask(&p);
6987
0
  if ((afi == AFI_L2VPN)
6988
0
      && (bgp_build_evpn_prefix(evpn_type,
6989
0
              ethtag != NULL ? atol(ethtag) : 0, &p))) {
6990
0
    vty_out(vty, "%% L2VPN prefix could not be forged\n");
6991
0
    return CMD_WARNING_CONFIG_FAILED;
6992
0
  }
6993
6994
0
  ret = str2prefix_rd(rd_str, &prd);
6995
0
  if (!ret) {
6996
0
    vty_out(vty, "%% Malformed rd\n");
6997
0
    return CMD_WARNING_CONFIG_FAILED;
6998
0
  }
6999
7000
0
  if (label_str) {
7001
0
    unsigned long label_val;
7002
0
    label_val = strtoul(label_str, NULL, 10);
7003
0
    encode_label(label_val, &label);
7004
0
  }
7005
7006
0
  if (safi == SAFI_EVPN) {
7007
0
    if (esi && str2esi(esi, NULL) == 0) {
7008
0
      vty_out(vty, "%% Malformed ESI\n");
7009
0
      return CMD_WARNING_CONFIG_FAILED;
7010
0
    }
7011
0
    if (routermac && prefix_str2mac(routermac, NULL) == 0) {
7012
0
      vty_out(vty, "%% Malformed Router MAC\n");
7013
0
      return CMD_WARNING_CONFIG_FAILED;
7014
0
    }
7015
0
    if (gwip) {
7016
0
      memset(&gw_ip, 0, sizeof(gw_ip));
7017
0
      ret = str2prefix(gwip, &gw_ip);
7018
0
      if (!ret) {
7019
0
        vty_out(vty, "%% Malformed GatewayIp\n");
7020
0
        return CMD_WARNING_CONFIG_FAILED;
7021
0
      }
7022
0
      if ((gw_ip.family == AF_INET
7023
0
           && is_evpn_prefix_ipaddr_v6(
7024
0
          (struct prefix_evpn *)&p))
7025
0
          || (gw_ip.family == AF_INET6
7026
0
        && is_evpn_prefix_ipaddr_v4(
7027
0
             (struct prefix_evpn *)&p))) {
7028
0
        vty_out(vty,
7029
0
          "%% GatewayIp family differs with IP prefix\n");
7030
0
        return CMD_WARNING_CONFIG_FAILED;
7031
0
      }
7032
0
    }
7033
0
  }
7034
0
  pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7035
0
  if (!bgp_dest_has_bgp_path_info_data(pdest))
7036
0
    bgp_dest_set_bgp_table_info(pdest,
7037
0
              bgp_table_init(bgp, afi, safi));
7038
0
  table = bgp_dest_get_bgp_table_info(pdest);
7039
7040
0
  dest = bgp_node_get(table, &p);
7041
7042
0
  if (bgp_dest_has_bgp_path_info_data(dest)) {
7043
0
    vty_out(vty, "%% Same network configuration exists\n");
7044
0
    bgp_dest_unlock_node(dest);
7045
0
  } else {
7046
    /* New configuration. */
7047
0
    bgp_static = bgp_static_new();
7048
0
    bgp_static->backdoor = 0;
7049
0
    bgp_static->valid = 0;
7050
0
    bgp_static->igpmetric = 0;
7051
0
    bgp_static->igpnexthop.s_addr = INADDR_ANY;
7052
0
    bgp_static->label = label;
7053
0
    bgp_static->prd = prd;
7054
7055
0
    bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
7056
7057
0
    if (rmap_str) {
7058
0
      XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
7059
0
      route_map_counter_decrement(bgp_static->rmap.map);
7060
0
      bgp_static->rmap.name =
7061
0
        XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7062
0
      bgp_static->rmap.map =
7063
0
        route_map_lookup_by_name(rmap_str);
7064
0
      route_map_counter_increment(bgp_static->rmap.map);
7065
0
    }
7066
7067
0
    if (safi == SAFI_EVPN) {
7068
0
      if (esi) {
7069
0
        bgp_static->eth_s_id =
7070
0
          XCALLOC(MTYPE_ATTR,
7071
0
            sizeof(esi_t));
7072
0
        str2esi(esi, bgp_static->eth_s_id);
7073
0
      }
7074
0
      if (routermac) {
7075
0
        bgp_static->router_mac =
7076
0
          XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
7077
0
        (void)prefix_str2mac(routermac,
7078
0
                 bgp_static->router_mac);
7079
0
      }
7080
0
      if (gwip)
7081
0
        prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7082
0
    }
7083
0
    bgp_dest_set_bgp_static_info(dest, bgp_static);
7084
7085
0
    bgp_static->valid = 1;
7086
0
    bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7087
0
  }
7088
7089
0
  return CMD_SUCCESS;
7090
0
}
7091
7092
/* Configure static BGP network. */
7093
int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7094
        const char *ip_str, const char *rd_str,
7095
        const char *label_str, int evpn_type, const char *esi,
7096
        const char *gwip, const char *ethtag)
7097
0
{
7098
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
7099
0
  int ret;
7100
0
  struct prefix p;
7101
0
  struct prefix_rd prd;
7102
0
  struct bgp_dest *pdest;
7103
0
  struct bgp_dest *dest;
7104
0
  struct bgp_table *table;
7105
0
  struct bgp_static *bgp_static;
7106
0
  mpls_label_t label = MPLS_INVALID_LABEL;
7107
7108
  /* Convert IP prefix string to struct prefix. */
7109
0
  ret = str2prefix(ip_str, &p);
7110
0
  if (!ret) {
7111
0
    vty_out(vty, "%% Malformed prefix\n");
7112
0
    return CMD_WARNING_CONFIG_FAILED;
7113
0
  }
7114
0
  apply_mask(&p);
7115
0
  if ((afi == AFI_L2VPN)
7116
0
      && (bgp_build_evpn_prefix(evpn_type,
7117
0
              ethtag != NULL ? atol(ethtag) : 0, &p))) {
7118
0
    vty_out(vty, "%% L2VPN prefix could not be forged\n");
7119
0
    return CMD_WARNING_CONFIG_FAILED;
7120
0
  }
7121
0
  ret = str2prefix_rd(rd_str, &prd);
7122
0
  if (!ret) {
7123
0
    vty_out(vty, "%% Malformed rd\n");
7124
0
    return CMD_WARNING_CONFIG_FAILED;
7125
0
  }
7126
7127
0
  if (label_str) {
7128
0
    unsigned long label_val;
7129
0
    label_val = strtoul(label_str, NULL, 10);
7130
0
    encode_label(label_val, &label);
7131
0
  }
7132
7133
0
  pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7134
0
  if (!bgp_dest_has_bgp_path_info_data(pdest))
7135
0
    bgp_dest_set_bgp_table_info(pdest,
7136
0
              bgp_table_init(bgp, afi, safi));
7137
0
  else
7138
0
    bgp_dest_unlock_node(pdest);
7139
0
  table = bgp_dest_get_bgp_table_info(pdest);
7140
7141
0
  dest = bgp_node_lookup(table, &p);
7142
7143
0
  if (dest) {
7144
0
    bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
7145
7146
0
    bgp_static = bgp_dest_get_bgp_static_info(dest);
7147
0
    bgp_static_free(bgp_static);
7148
0
    bgp_dest_set_bgp_static_info(dest, NULL);
7149
0
    bgp_dest_unlock_node(dest);
7150
0
    bgp_dest_unlock_node(dest);
7151
0
  } else
7152
0
    vty_out(vty, "%% Can't find the route\n");
7153
7154
0
  return CMD_SUCCESS;
7155
0
}
7156
7157
static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7158
           const char *rmap_name)
7159
0
{
7160
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
7161
0
  struct bgp_rmap *rmap;
7162
7163
0
  rmap = &bgp->table_map[afi][safi];
7164
0
  if (rmap_name) {
7165
0
    XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
7166
0
    route_map_counter_decrement(rmap->map);
7167
0
    rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7168
0
    rmap->map = route_map_lookup_by_name(rmap_name);
7169
0
    route_map_counter_increment(rmap->map);
7170
0
  } else {
7171
0
    XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
7172
0
    route_map_counter_decrement(rmap->map);
7173
0
    rmap->map = NULL;
7174
0
  }
7175
7176
0
  if (bgp_fibupd_safi(safi))
7177
0
    bgp_zebra_announce_table(bgp, afi, safi);
7178
7179
0
  return CMD_SUCCESS;
7180
0
}
7181
7182
static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7183
             const char *rmap_name)
7184
0
{
7185
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
7186
0
  struct bgp_rmap *rmap;
7187
7188
0
  rmap = &bgp->table_map[afi][safi];
7189
0
  XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
7190
0
  route_map_counter_decrement(rmap->map);
7191
0
  rmap->map = NULL;
7192
7193
0
  if (bgp_fibupd_safi(safi))
7194
0
    bgp_zebra_announce_table(bgp, afi, safi);
7195
7196
0
  return CMD_SUCCESS;
7197
0
}
7198
7199
void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
7200
        safi_t safi)
7201
0
{
7202
0
  if (bgp->table_map[afi][safi].name) {
7203
0
    vty_out(vty, "  table-map %s\n",
7204
0
      bgp->table_map[afi][safi].name);
7205
0
  }
7206
0
}
7207
7208
DEFUN (bgp_table_map,
7209
       bgp_table_map_cmd,
7210
       "table-map WORD",
7211
       "BGP table to RIB route download filter\n"
7212
       "Name of the route map\n")
7213
0
{
7214
0
  int idx_word = 1;
7215
0
  return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7216
0
         argv[idx_word]->arg);
7217
0
}
7218
DEFUN (no_bgp_table_map,
7219
       no_bgp_table_map_cmd,
7220
       "no table-map WORD",
7221
       NO_STR
7222
       "BGP table to RIB route download filter\n"
7223
       "Name of the route map\n")
7224
0
{
7225
0
  int idx_word = 2;
7226
0
  return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7227
0
           argv[idx_word]->arg);
7228
0
}
7229
7230
DEFPY(bgp_network,
7231
  bgp_network_cmd,
7232
  "[no] network \
7233
  <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7234
  [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7235
  backdoor$backdoor}]",
7236
  NO_STR
7237
  "Specify a network to announce via BGP\n"
7238
  "IPv4 prefix\n"
7239
  "Network number\n"
7240
  "Network mask\n"
7241
  "Network mask\n"
7242
  "Route-map to modify the attributes\n"
7243
  "Name of the route map\n"
7244
  "Label index to associate with the prefix\n"
7245
  "Label index value\n"
7246
  "Specify a BGP backdoor route\n")
7247
0
{
7248
0
  char addr_prefix_str[BUFSIZ];
7249
7250
0
  if (address_str) {
7251
0
    int ret;
7252
7253
0
    ret = netmask_str2prefix_str(address_str, netmask_str,
7254
0
               addr_prefix_str,
7255
0
               sizeof(addr_prefix_str));
7256
0
    if (!ret) {
7257
0
      vty_out(vty, "%% Inconsistent address and mask\n");
7258
0
      return CMD_WARNING_CONFIG_FAILED;
7259
0
    }
7260
0
  }
7261
7262
0
  return bgp_static_set(
7263
0
    vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7264
0
    bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7265
0
    label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
7266
0
}
7267
7268
DEFPY(ipv6_bgp_network,
7269
  ipv6_bgp_network_cmd,
7270
  "[no] network X:X::X:X/M$prefix \
7271
  [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7272
  NO_STR
7273
  "Specify a network to announce via BGP\n"
7274
  "IPv6 prefix\n"
7275
  "Route-map to modify the attributes\n"
7276
  "Name of the route map\n"
7277
  "Label index to associate with the prefix\n"
7278
  "Label index value\n")
7279
0
{
7280
0
  return bgp_static_set(
7281
0
    vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7282
0
    label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
7283
0
}
7284
7285
static struct bgp_aggregate *bgp_aggregate_new(void)
7286
0
{
7287
0
  return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
7288
0
}
7289
7290
void bgp_aggregate_free(struct bgp_aggregate *aggregate)
7291
0
{
7292
0
  XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7293
0
  route_map_counter_decrement(aggregate->suppress_map);
7294
0
  XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7295
0
  route_map_counter_decrement(aggregate->rmap.map);
7296
0
  XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7297
0
}
7298
7299
/**
7300
 * Helper function to avoid repeated code: prepare variables for a
7301
 * `route_map_apply` call.
7302
 *
7303
 * \returns `true` on route map match, otherwise `false`.
7304
 */
7305
static bool aggr_suppress_map_test(struct bgp *bgp,
7306
           struct bgp_aggregate *aggregate,
7307
           struct bgp_path_info *pi)
7308
0
{
7309
0
  const struct prefix *p = bgp_dest_get_prefix(pi->net);
7310
0
  route_map_result_t rmr = RMAP_DENYMATCH;
7311
0
  struct bgp_path_info rmap_path = {};
7312
0
  struct attr attr = {};
7313
7314
  /* No route map entries created, just don't match. */
7315
0
  if (aggregate->suppress_map == NULL)
7316
0
    return false;
7317
7318
  /* Call route map matching and return result. */
7319
0
  attr.aspath = aspath_empty(bgp->asnotation);
7320
0
  rmap_path.peer = bgp->peer_self;
7321
0
  rmap_path.attr = &attr;
7322
7323
0
  SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
7324
0
  rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
7325
0
  bgp->peer_self->rmap_type = 0;
7326
7327
0
  bgp_attr_flush(&attr);
7328
0
  aspath_unintern(&attr.aspath);
7329
7330
0
  return rmr == RMAP_PERMITMATCH;
7331
0
}
7332
7333
/** Test whether the aggregation has suppressed this path or not. */
7334
static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7335
         struct bgp_path_info *pi)
7336
0
{
7337
0
  if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7338
0
    return false;
7339
7340
0
  return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7341
0
}
7342
7343
/**
7344
 * Suppress this path and keep the reference.
7345
 *
7346
 * \returns `true` if needs processing otherwise `false`.
7347
 */
7348
static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7349
             struct bgp_path_info *pi)
7350
0
{
7351
0
  struct bgp_path_info_extra *pie;
7352
7353
  /* Path is already suppressed by this aggregation. */
7354
0
  if (aggr_suppress_exists(aggregate, pi))
7355
0
    return false;
7356
7357
0
  pie = bgp_path_info_extra_get(pi);
7358
7359
  /* This is the first suppression, allocate memory and list it. */
7360
0
  if (pie->aggr_suppressors == NULL)
7361
0
    pie->aggr_suppressors = list_new();
7362
7363
0
  listnode_add(pie->aggr_suppressors, aggregate);
7364
7365
  /* Only mark for processing if suppressed. */
7366
0
  if (listcount(pie->aggr_suppressors) == 1) {
7367
0
    if (BGP_DEBUG(update, UPDATE_OUT))
7368
0
      zlog_debug("aggregate-address suppressing: %pFX",
7369
0
           bgp_dest_get_prefix(pi->net));
7370
7371
0
    bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7372
0
    return true;
7373
0
  }
7374
7375
0
  return false;
7376
0
}
7377
7378
/**
7379
 * Unsuppress this path and remove the reference.
7380
 *
7381
 * \returns `true` if needs processing otherwise `false`.
7382
 */
7383
static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7384
         struct bgp_path_info *pi)
7385
0
{
7386
  /* Path wasn't suppressed. */
7387
0
  if (!aggr_suppress_exists(aggregate, pi))
7388
0
    return false;
7389
7390
0
  listnode_delete(pi->extra->aggr_suppressors, aggregate);
7391
7392
  /* Unsuppress and free extra memory if last item. */
7393
0
  if (listcount(pi->extra->aggr_suppressors) == 0) {
7394
0
    if (BGP_DEBUG(update, UPDATE_OUT))
7395
0
      zlog_debug("aggregate-address unsuppressing: %pFX",
7396
0
           bgp_dest_get_prefix(pi->net));
7397
7398
0
    list_delete(&pi->extra->aggr_suppressors);
7399
0
    bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7400
0
    return true;
7401
0
  }
7402
7403
0
  return false;
7404
0
}
7405
7406
static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7407
            struct aspath *aspath,
7408
            struct community *comm,
7409
            struct ecommunity *ecomm,
7410
            struct lcommunity *lcomm)
7411
0
{
7412
0
  static struct aspath *ae = NULL;
7413
0
  enum asnotation_mode asnotation;
7414
7415
0
  asnotation = bgp_get_asnotation(NULL);
7416
7417
0
  if (!aspath)
7418
0
    ae = aspath_empty(asnotation);
7419
7420
0
  if (!pi)
7421
0
    return false;
7422
7423
0
  if (origin != pi->attr->origin)
7424
0
    return false;
7425
7426
0
  if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
7427
0
    return false;
7428
7429
0
  if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
7430
0
    return false;
7431
7432
0
  if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
7433
0
    return false;
7434
7435
0
  if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
7436
0
    return false;
7437
7438
0
  if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7439
0
    return false;
7440
7441
0
  return true;
7442
0
}
7443
7444
static void bgp_aggregate_install(
7445
  struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7446
  uint8_t origin, struct aspath *aspath, struct community *community,
7447
  struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7448
  uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
7449
0
{
7450
0
  struct bgp_dest *dest;
7451
0
  struct bgp_table *table;
7452
0
  struct bgp_path_info *pi, *orig, *new;
7453
0
  struct attr *attr;
7454
7455
0
  table = bgp->rib[afi][safi];
7456
7457
0
  dest = bgp_node_get(table, p);
7458
7459
0
  for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
7460
0
    if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7461
0
        && pi->sub_type == BGP_ROUTE_AGGREGATE)
7462
0
      break;
7463
7464
  /*
7465
   * If we have paths with different MEDs, then don't install
7466
   * (or uninstall) the aggregate route.
7467
   */
7468
0
  if (aggregate->match_med && aggregate->med_mismatched)
7469
0
    goto uninstall_aggregate_route;
7470
7471
0
  if (aggregate->count > 0) {
7472
    /*
7473
     * If the aggregate information has not changed
7474
     * no need to re-install it again.
7475
     */
7476
0
    if (pi && bgp_aggregate_info_same(pi, origin, aspath, community,
7477
0
              ecommunity, lcommunity)) {
7478
0
      bgp_dest_unlock_node(dest);
7479
7480
0
      if (aspath)
7481
0
        aspath_free(aspath);
7482
0
      if (community)
7483
0
        community_free(&community);
7484
0
      if (ecommunity)
7485
0
        ecommunity_free(&ecommunity);
7486
0
      if (lcommunity)
7487
0
        lcommunity_free(&lcommunity);
7488
7489
0
      return;
7490
0
    }
7491
7492
    /*
7493
     * Mark the old as unusable
7494
     */
7495
0
    if (pi)
7496
0
      bgp_path_info_delete(dest, pi);
7497
7498
0
    attr = bgp_attr_aggregate_intern(
7499
0
      bgp, origin, aspath, community, ecommunity, lcommunity,
7500
0
      aggregate, atomic_aggregate, p);
7501
7502
0
    if (!attr) {
7503
0
      aspath_free(aspath);
7504
0
      community_free(&community);
7505
0
      ecommunity_free(&ecommunity);
7506
0
      lcommunity_free(&lcommunity);
7507
0
      bgp_dest_unlock_node(dest);
7508
0
      bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
7509
0
      if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7510
0
        zlog_debug("%s: %pFX null attribute", __func__,
7511
0
             p);
7512
0
      return;
7513
0
    }
7514
7515
0
    new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
7516
0
        bgp->peer_self, attr, dest);
7517
7518
0
    SET_FLAG(new->flags, BGP_PATH_VALID);
7519
7520
0
    bgp_path_info_add(dest, new);
7521
0
    bgp_process(bgp, dest, afi, safi);
7522
0
  } else {
7523
0
  uninstall_aggregate_route:
7524
0
    for (pi = orig; pi; pi = pi->next)
7525
0
      if (pi->peer == bgp->peer_self
7526
0
          && pi->type == ZEBRA_ROUTE_BGP
7527
0
          && pi->sub_type == BGP_ROUTE_AGGREGATE)
7528
0
        break;
7529
7530
    /* Withdraw static BGP route from routing table. */
7531
0
    if (pi) {
7532
0
      bgp_path_info_delete(dest, pi);
7533
0
      bgp_process(bgp, dest, afi, safi);
7534
0
    }
7535
0
  }
7536
7537
0
  bgp_dest_unlock_node(dest);
7538
0
}
7539
7540
/**
7541
 * Check if the current path has different MED than other known paths.
7542
 *
7543
 * \returns `true` if the MED matched the others else `false`.
7544
 */
7545
static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7546
            struct bgp *bgp, struct bgp_path_info *pi)
7547
0
{
7548
0
  uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7549
7550
  /* This is the first route being analyzed. */
7551
0
  if (!aggregate->med_initialized) {
7552
0
    aggregate->med_initialized = true;
7553
0
    aggregate->med_mismatched = false;
7554
0
    aggregate->med_matched_value = cur_med;
7555
0
  } else {
7556
    /* Check if routes with different MED showed up. */
7557
0
    if (cur_med != aggregate->med_matched_value)
7558
0
      aggregate->med_mismatched = true;
7559
0
  }
7560
7561
0
  return !aggregate->med_mismatched;
7562
0
}
7563
7564
/**
7565
 * Initializes and tests all routes in the aggregate address path for MED
7566
 * values.
7567
 *
7568
 * \returns `true` if all MEDs are the same otherwise `false`.
7569
 */
7570
static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7571
               struct bgp *bgp, const struct prefix *p,
7572
               afi_t afi, safi_t safi)
7573
0
{
7574
0
  struct bgp_table *table = bgp->rib[afi][safi];
7575
0
  const struct prefix *dest_p;
7576
0
  struct bgp_dest *dest, *top;
7577
0
  struct bgp_path_info *pi;
7578
0
  bool med_matched = true;
7579
7580
0
  aggregate->med_initialized = false;
7581
7582
0
  top = bgp_node_get(table, p);
7583
0
  for (dest = bgp_node_get(table, p); dest;
7584
0
       dest = bgp_route_next_until(dest, top)) {
7585
0
    dest_p = bgp_dest_get_prefix(dest);
7586
0
    if (dest_p->prefixlen <= p->prefixlen)
7587
0
      continue;
7588
7589
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7590
0
      if (BGP_PATH_HOLDDOWN(pi))
7591
0
        continue;
7592
0
      if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7593
0
        continue;
7594
0
      if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7595
0
        med_matched = false;
7596
0
        break;
7597
0
      }
7598
0
    }
7599
0
    if (!med_matched)
7600
0
      break;
7601
0
  }
7602
0
  bgp_dest_unlock_node(top);
7603
7604
0
  return med_matched;
7605
0
}
7606
7607
/**
7608
 * Toggles the route suppression status for this aggregate address
7609
 * configuration.
7610
 */
7611
void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7612
             struct bgp *bgp, const struct prefix *p,
7613
             afi_t afi, safi_t safi, bool suppress)
7614
0
{
7615
0
  struct bgp_table *table = bgp->rib[afi][safi];
7616
0
  const struct prefix *dest_p;
7617
0
  struct bgp_dest *dest, *top;
7618
0
  struct bgp_path_info *pi;
7619
0
  bool toggle_suppression;
7620
7621
  /* We've found a different MED we must revert any suppressed routes. */
7622
0
  top = bgp_node_get(table, p);
7623
0
  for (dest = bgp_node_get(table, p); dest;
7624
0
       dest = bgp_route_next_until(dest, top)) {
7625
0
    dest_p = bgp_dest_get_prefix(dest);
7626
0
    if (dest_p->prefixlen <= p->prefixlen)
7627
0
      continue;
7628
7629
0
    toggle_suppression = false;
7630
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7631
0
      if (BGP_PATH_HOLDDOWN(pi))
7632
0
        continue;
7633
0
      if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7634
0
        continue;
7635
7636
      /* We are toggling suppression back. */
7637
0
      if (suppress) {
7638
        /* Suppress route if not suppressed already. */
7639
0
        if (aggr_suppress_path(aggregate, pi))
7640
0
          toggle_suppression = true;
7641
0
        continue;
7642
0
      }
7643
7644
      /* Install route if there is no more suppression. */
7645
0
      if (aggr_unsuppress_path(aggregate, pi))
7646
0
        toggle_suppression = true;
7647
0
    }
7648
7649
0
    if (toggle_suppression)
7650
0
      bgp_process(bgp, dest, afi, safi);
7651
0
  }
7652
0
  bgp_dest_unlock_node(top);
7653
0
}
7654
7655
/**
7656
 * Aggregate address MED matching incremental test: this function is called
7657
 * when the initial aggregation occurred and we are only testing a single
7658
 * new path.
7659
 *
7660
 * In addition to testing and setting the MED validity it also installs back
7661
 * suppressed routes (if summary is configured).
7662
 *
7663
 * Must not be called in `bgp_aggregate_route`.
7664
 */
7665
static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7666
             struct bgp *bgp, const struct prefix *p,
7667
             afi_t afi, safi_t safi,
7668
             struct bgp_path_info *pi)
7669
0
{
7670
  /* MED matching disabled. */
7671
0
  if (!aggregate->match_med)
7672
0
    return;
7673
7674
  /* Aggregation with different MED, recheck if we have got equal MEDs
7675
   * now.
7676
   */
7677
0
  if (aggregate->med_mismatched &&
7678
0
      bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7679
0
      aggregate->summary_only)
7680
0
    bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7681
0
            true);
7682
0
  else
7683
0
    bgp_aggregate_med_match(aggregate, bgp, pi);
7684
7685
  /* No mismatches, just quit. */
7686
0
  if (!aggregate->med_mismatched)
7687
0
    return;
7688
7689
  /* Route summarization is disabled. */
7690
0
  if (!aggregate->summary_only)
7691
0
    return;
7692
7693
0
  bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7694
0
}
7695
7696
/* Update an aggregate as routes are added/removed from the BGP table */
7697
bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7698
       safi_t safi, struct bgp_aggregate *aggregate)
7699
0
{
7700
0
  struct bgp_table *table;
7701
0
  struct bgp_dest *top;
7702
0
  struct bgp_dest *dest;
7703
0
  uint8_t origin;
7704
0
  struct aspath *aspath = NULL;
7705
0
  struct community *community = NULL;
7706
0
  struct ecommunity *ecommunity = NULL;
7707
0
  struct lcommunity *lcommunity = NULL;
7708
0
  struct bgp_path_info *pi;
7709
0
  unsigned long match = 0;
7710
0
  uint8_t atomic_aggregate = 0;
7711
7712
  /* If the bgp instance is being deleted or self peer is deleted
7713
   * then do not create aggregate route
7714
   */
7715
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
7716
0
      bgp->peer_self == NULL)
7717
0
    return false;
7718
7719
  /* Initialize and test routes for MED difference. */
7720
0
  if (aggregate->match_med)
7721
0
    bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7722
7723
  /*
7724
   * Reset aggregate count: we might've been called from route map
7725
   * update so in that case we must retest all more specific routes.
7726
   *
7727
   * \see `bgp_route_map_process_update`.
7728
   */
7729
0
  aggregate->count = 0;
7730
0
  aggregate->incomplete_origin_count = 0;
7731
0
  aggregate->incomplete_origin_count = 0;
7732
0
  aggregate->egp_origin_count = 0;
7733
7734
  /* ORIGIN attribute: If at least one route among routes that are
7735
     aggregated has ORIGIN with the value INCOMPLETE, then the
7736
     aggregated route must have the ORIGIN attribute with the value
7737
     INCOMPLETE. Otherwise, if at least one route among routes that
7738
     are aggregated has ORIGIN with the value EGP, then the aggregated
7739
     route must have the origin attribute with the value EGP. In all
7740
     other case the value of the ORIGIN attribute of the aggregated
7741
     route is INTERNAL. */
7742
0
  origin = BGP_ORIGIN_IGP;
7743
7744
0
  table = bgp->rib[afi][safi];
7745
7746
0
  top = bgp_node_get(table, p);
7747
0
  for (dest = bgp_node_get(table, p); dest;
7748
0
       dest = bgp_route_next_until(dest, top)) {
7749
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7750
7751
0
    if (dest_p->prefixlen <= p->prefixlen)
7752
0
      continue;
7753
7754
    /* If suppress fib is enabled and route not installed
7755
     * in FIB, skip the route
7756
     */
7757
0
    if (!bgp_check_advertise(bgp, dest))
7758
0
      continue;
7759
7760
0
    match = 0;
7761
7762
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7763
0
      if (BGP_PATH_HOLDDOWN(pi))
7764
0
        continue;
7765
7766
0
      if (pi->attr->flag
7767
0
          & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7768
0
        atomic_aggregate = 1;
7769
7770
0
      if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7771
0
        continue;
7772
7773
      /*
7774
       * summary-only aggregate route suppress
7775
       * aggregated route announcements.
7776
       *
7777
       * MED matching:
7778
       * Don't create summaries if MED didn't match
7779
       * otherwise neither the specific routes and the
7780
       * aggregation will be announced.
7781
       */
7782
0
      if (aggregate->summary_only
7783
0
          && AGGREGATE_MED_VALID(aggregate)) {
7784
0
        if (aggr_suppress_path(aggregate, pi))
7785
0
          match++;
7786
0
      }
7787
7788
      /*
7789
       * Suppress more specific routes that match the route
7790
       * map results.
7791
       *
7792
       * MED matching:
7793
       * Don't suppress routes if MED matching is enabled and
7794
       * it mismatched otherwise we might end up with no
7795
       * routes for this path.
7796
       */
7797
0
      if (aggregate->suppress_map_name
7798
0
          && AGGREGATE_MED_VALID(aggregate)
7799
0
          && aggr_suppress_map_test(bgp, aggregate, pi)) {
7800
0
        if (aggr_suppress_path(aggregate, pi))
7801
0
          match++;
7802
0
      }
7803
7804
0
      aggregate->count++;
7805
7806
      /*
7807
                        * If at least one route among routes that are
7808
                        * aggregated has ORIGIN with the value INCOMPLETE,
7809
                        * then the aggregated route MUST have the ORIGIN
7810
                        * attribute with the value INCOMPLETE.  Otherwise, if
7811
                        * at least one route among routes that are aggregated
7812
                        * has ORIGIN with the value EGP, then the aggregated
7813
                        * route MUST have the ORIGIN attribute with the value
7814
                        * EGP.
7815
                        */
7816
0
      switch (pi->attr->origin) {
7817
0
      case BGP_ORIGIN_INCOMPLETE:
7818
0
        aggregate->incomplete_origin_count++;
7819
0
      break;
7820
0
      case BGP_ORIGIN_EGP:
7821
0
        aggregate->egp_origin_count++;
7822
0
      break;
7823
0
      default:
7824
        /*Do nothing.
7825
         */
7826
0
      break;
7827
0
      }
7828
7829
0
      if (!aggregate->as_set)
7830
0
        continue;
7831
7832
      /*
7833
       * as-set aggregate route generate origin, as path,
7834
       * and community aggregation.
7835
       */
7836
      /* Compute aggregate route's as-path.
7837
       */
7838
0
      bgp_compute_aggregate_aspath_hash(aggregate,
7839
0
                pi->attr->aspath);
7840
7841
      /* Compute aggregate route's community.
7842
       */
7843
0
      if (bgp_attr_get_community(pi->attr))
7844
0
        bgp_compute_aggregate_community_hash(
7845
0
          aggregate,
7846
0
          bgp_attr_get_community(pi->attr));
7847
7848
      /* Compute aggregate route's extended community.
7849
       */
7850
0
      if (bgp_attr_get_ecommunity(pi->attr))
7851
0
        bgp_compute_aggregate_ecommunity_hash(
7852
0
          aggregate,
7853
0
          bgp_attr_get_ecommunity(pi->attr));
7854
7855
      /* Compute aggregate route's large community.
7856
       */
7857
0
      if (bgp_attr_get_lcommunity(pi->attr))
7858
0
        bgp_compute_aggregate_lcommunity_hash(
7859
0
          aggregate,
7860
0
          bgp_attr_get_lcommunity(pi->attr));
7861
0
    }
7862
0
    if (match)
7863
0
      bgp_process(bgp, dest, afi, safi);
7864
0
  }
7865
0
  if (aggregate->as_set) {
7866
0
    bgp_compute_aggregate_aspath_val(aggregate);
7867
0
    bgp_compute_aggregate_community_val(aggregate);
7868
0
    bgp_compute_aggregate_ecommunity_val(aggregate);
7869
0
    bgp_compute_aggregate_lcommunity_val(aggregate);
7870
0
  }
7871
7872
7873
0
  bgp_dest_unlock_node(top);
7874
7875
7876
0
  if (aggregate->incomplete_origin_count > 0)
7877
0
    origin = BGP_ORIGIN_INCOMPLETE;
7878
0
  else if (aggregate->egp_origin_count > 0)
7879
0
    origin = BGP_ORIGIN_EGP;
7880
7881
0
  if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7882
0
    origin = aggregate->origin;
7883
7884
0
  if (aggregate->as_set) {
7885
0
    if (aggregate->aspath)
7886
      /* Retrieve aggregate route's as-path.
7887
       */
7888
0
      aspath = aspath_dup(aggregate->aspath);
7889
7890
0
    if (aggregate->community)
7891
      /* Retrieve aggregate route's community.
7892
       */
7893
0
      community = community_dup(aggregate->community);
7894
7895
0
    if (aggregate->ecommunity)
7896
      /* Retrieve aggregate route's ecommunity.
7897
       */
7898
0
      ecommunity = ecommunity_dup(aggregate->ecommunity);
7899
7900
0
    if (aggregate->lcommunity)
7901
      /* Retrieve aggregate route's lcommunity.
7902
       */
7903
0
      lcommunity = lcommunity_dup(aggregate->lcommunity);
7904
0
  }
7905
7906
0
  bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
7907
0
            ecommunity, lcommunity, atomic_aggregate,
7908
0
            aggregate);
7909
7910
0
  return true;
7911
0
}
7912
7913
void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7914
        safi_t safi, struct bgp_aggregate *aggregate)
7915
0
{
7916
0
  struct bgp_table *table;
7917
0
  struct bgp_dest *top;
7918
0
  struct bgp_dest *dest;
7919
0
  struct bgp_path_info *pi;
7920
0
  unsigned long match;
7921
7922
0
  table = bgp->rib[afi][safi];
7923
7924
  /* If routes exists below this node, generate aggregate routes. */
7925
0
  top = bgp_node_get(table, p);
7926
0
  for (dest = bgp_node_get(table, p); dest;
7927
0
       dest = bgp_route_next_until(dest, top)) {
7928
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7929
7930
0
    if (dest_p->prefixlen <= p->prefixlen)
7931
0
      continue;
7932
0
    match = 0;
7933
7934
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7935
0
      if (BGP_PATH_HOLDDOWN(pi))
7936
0
        continue;
7937
7938
0
      if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7939
0
        continue;
7940
7941
      /*
7942
       * This route is suppressed: attempt to unsuppress it.
7943
       *
7944
       * `aggr_unsuppress_path` will fail if this particular
7945
       * aggregate route was not the suppressor.
7946
       */
7947
0
      if (pi->extra && pi->extra->aggr_suppressors &&
7948
0
          listcount(pi->extra->aggr_suppressors)) {
7949
0
        if (aggr_unsuppress_path(aggregate, pi))
7950
0
          match++;
7951
0
      }
7952
7953
0
      aggregate->count--;
7954
7955
0
      if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7956
0
        aggregate->incomplete_origin_count--;
7957
0
      else if (pi->attr->origin == BGP_ORIGIN_EGP)
7958
0
        aggregate->egp_origin_count--;
7959
7960
0
      if (aggregate->as_set) {
7961
        /* Remove as-path from aggregate.
7962
         */
7963
0
        bgp_remove_aspath_from_aggregate_hash(
7964
0
              aggregate,
7965
0
              pi->attr->aspath);
7966
7967
0
        if (bgp_attr_get_community(pi->attr))
7968
          /* Remove community from aggregate.
7969
           */
7970
0
          bgp_remove_comm_from_aggregate_hash(
7971
0
            aggregate,
7972
0
            bgp_attr_get_community(
7973
0
              pi->attr));
7974
7975
0
        if (bgp_attr_get_ecommunity(pi->attr))
7976
          /* Remove ecommunity from aggregate.
7977
           */
7978
0
          bgp_remove_ecomm_from_aggregate_hash(
7979
0
            aggregate,
7980
0
            bgp_attr_get_ecommunity(
7981
0
              pi->attr));
7982
7983
0
        if (bgp_attr_get_lcommunity(pi->attr))
7984
          /* Remove lcommunity from aggregate.
7985
           */
7986
0
          bgp_remove_lcomm_from_aggregate_hash(
7987
0
            aggregate,
7988
0
            bgp_attr_get_lcommunity(
7989
0
              pi->attr));
7990
0
      }
7991
0
    }
7992
7993
    /* If this node was suppressed, process the change. */
7994
0
    if (match)
7995
0
      bgp_process(bgp, dest, afi, safi);
7996
0
  }
7997
0
  if (aggregate->as_set) {
7998
0
    aspath_free(aggregate->aspath);
7999
0
    aggregate->aspath = NULL;
8000
0
    if (aggregate->community)
8001
0
      community_free(&aggregate->community);
8002
0
    if (aggregate->ecommunity)
8003
0
      ecommunity_free(&aggregate->ecommunity);
8004
0
    if (aggregate->lcommunity)
8005
0
      lcommunity_free(&aggregate->lcommunity);
8006
0
  }
8007
8008
0
  bgp_dest_unlock_node(top);
8009
0
}
8010
8011
static void bgp_add_route_to_aggregate(struct bgp *bgp,
8012
               const struct prefix *aggr_p,
8013
               struct bgp_path_info *pinew, afi_t afi,
8014
               safi_t safi,
8015
               struct bgp_aggregate *aggregate)
8016
0
{
8017
0
  uint8_t origin;
8018
0
  struct aspath *aspath = NULL;
8019
0
  uint8_t atomic_aggregate = 0;
8020
0
  struct community *community = NULL;
8021
0
  struct ecommunity *ecommunity = NULL;
8022
0
  struct lcommunity *lcommunity = NULL;
8023
8024
  /* If the bgp instance is being deleted or self peer is deleted
8025
   * then do not create aggregate route
8026
   */
8027
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8028
0
      || (bgp->peer_self == NULL))
8029
0
    return;
8030
8031
  /* ORIGIN attribute: If at least one route among routes that are
8032
   * aggregated has ORIGIN with the value INCOMPLETE, then the
8033
   * aggregated route must have the ORIGIN attribute with the value
8034
   * INCOMPLETE. Otherwise, if at least one route among routes that
8035
   * are aggregated has ORIGIN with the value EGP, then the aggregated
8036
   * route must have the origin attribute with the value EGP. In all
8037
   * other case the value of the ORIGIN attribute of the aggregated
8038
   * route is INTERNAL.
8039
   */
8040
0
  origin = BGP_ORIGIN_IGP;
8041
8042
0
  aggregate->count++;
8043
8044
  /*
8045
   * This must be called before `summary` check to avoid
8046
   * "suppressing" twice.
8047
   */
8048
0
  if (aggregate->match_med)
8049
0
    bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
8050
0
           pinew);
8051
8052
0
  if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8053
0
    aggr_suppress_path(aggregate, pinew);
8054
8055
0
  if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8056
0
      && aggr_suppress_map_test(bgp, aggregate, pinew))
8057
0
    aggr_suppress_path(aggregate, pinew);
8058
8059
0
  switch (pinew->attr->origin) {
8060
0
  case BGP_ORIGIN_INCOMPLETE:
8061
0
    aggregate->incomplete_origin_count++;
8062
0
  break;
8063
0
  case BGP_ORIGIN_EGP:
8064
0
    aggregate->egp_origin_count++;
8065
0
  break;
8066
0
  default:
8067
    /* Do nothing.
8068
     */
8069
0
  break;
8070
0
  }
8071
8072
0
  if (aggregate->incomplete_origin_count > 0)
8073
0
    origin = BGP_ORIGIN_INCOMPLETE;
8074
0
  else if (aggregate->egp_origin_count > 0)
8075
0
    origin = BGP_ORIGIN_EGP;
8076
8077
0
  if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8078
0
    origin = aggregate->origin;
8079
8080
0
  if (aggregate->as_set) {
8081
    /* Compute aggregate route's as-path.
8082
     */
8083
0
    bgp_compute_aggregate_aspath(aggregate,
8084
0
               pinew->attr->aspath);
8085
8086
    /* Compute aggregate route's community.
8087
     */
8088
0
    if (bgp_attr_get_community(pinew->attr))
8089
0
      bgp_compute_aggregate_community(
8090
0
        aggregate, bgp_attr_get_community(pinew->attr));
8091
8092
    /* Compute aggregate route's extended community.
8093
     */
8094
0
    if (bgp_attr_get_ecommunity(pinew->attr))
8095
0
      bgp_compute_aggregate_ecommunity(
8096
0
        aggregate,
8097
0
        bgp_attr_get_ecommunity(pinew->attr));
8098
8099
    /* Compute aggregate route's large community.
8100
     */
8101
0
    if (bgp_attr_get_lcommunity(pinew->attr))
8102
0
      bgp_compute_aggregate_lcommunity(
8103
0
        aggregate,
8104
0
        bgp_attr_get_lcommunity(pinew->attr));
8105
8106
    /* Retrieve aggregate route's as-path.
8107
     */
8108
0
    if (aggregate->aspath)
8109
0
      aspath = aspath_dup(aggregate->aspath);
8110
8111
    /* Retrieve aggregate route's community.
8112
     */
8113
0
    if (aggregate->community)
8114
0
      community = community_dup(aggregate->community);
8115
8116
    /* Retrieve aggregate route's ecommunity.
8117
     */
8118
0
    if (aggregate->ecommunity)
8119
0
      ecommunity = ecommunity_dup(aggregate->ecommunity);
8120
8121
    /* Retrieve aggregate route's lcommunity.
8122
     */
8123
0
    if (aggregate->lcommunity)
8124
0
      lcommunity = lcommunity_dup(aggregate->lcommunity);
8125
0
  }
8126
8127
0
  bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8128
0
            aspath, community, ecommunity,
8129
0
            lcommunity, atomic_aggregate, aggregate);
8130
0
}
8131
8132
static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8133
              safi_t safi,
8134
              struct bgp_path_info *pi,
8135
              struct bgp_aggregate *aggregate,
8136
              const struct prefix *aggr_p)
8137
0
{
8138
0
  uint8_t origin;
8139
0
  struct aspath *aspath = NULL;
8140
0
  uint8_t atomic_aggregate = 0;
8141
0
  struct community *community = NULL;
8142
0
  struct ecommunity *ecommunity = NULL;
8143
0
  struct lcommunity *lcommunity = NULL;
8144
0
  unsigned long match = 0;
8145
8146
  /* If the bgp instance is being deleted or self peer is deleted
8147
   * then do not create aggregate route
8148
   */
8149
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8150
0
      || (bgp->peer_self == NULL))
8151
0
    return;
8152
8153
0
  if (BGP_PATH_HOLDDOWN(pi))
8154
0
    return;
8155
8156
0
  if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8157
0
    return;
8158
8159
0
  if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8160
0
    if (aggr_unsuppress_path(aggregate, pi))
8161
0
      match++;
8162
8163
0
  if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8164
0
      && aggr_suppress_map_test(bgp, aggregate, pi))
8165
0
    if (aggr_unsuppress_path(aggregate, pi))
8166
0
      match++;
8167
8168
  /*
8169
   * This must be called after `summary`, `suppress-map` check to avoid
8170
   * "unsuppressing" twice.
8171
   */
8172
0
  if (aggregate->match_med)
8173
0
    bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
8174
8175
0
  if (aggregate->count > 0)
8176
0
    aggregate->count--;
8177
8178
0
  if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8179
0
    aggregate->incomplete_origin_count--;
8180
0
  else if (pi->attr->origin == BGP_ORIGIN_EGP)
8181
0
    aggregate->egp_origin_count--;
8182
8183
0
  if (aggregate->as_set) {
8184
    /* Remove as-path from aggregate.
8185
     */
8186
0
    bgp_remove_aspath_from_aggregate(aggregate,
8187
0
             pi->attr->aspath);
8188
8189
0
    if (bgp_attr_get_community(pi->attr))
8190
      /* Remove community from aggregate.
8191
       */
8192
0
      bgp_remove_community_from_aggregate(
8193
0
        aggregate, bgp_attr_get_community(pi->attr));
8194
8195
0
    if (bgp_attr_get_ecommunity(pi->attr))
8196
      /* Remove ecommunity from aggregate.
8197
       */
8198
0
      bgp_remove_ecommunity_from_aggregate(
8199
0
        aggregate, bgp_attr_get_ecommunity(pi->attr));
8200
8201
0
    if (bgp_attr_get_lcommunity(pi->attr))
8202
      /* Remove lcommunity from aggregate.
8203
       */
8204
0
      bgp_remove_lcommunity_from_aggregate(
8205
0
        aggregate, bgp_attr_get_lcommunity(pi->attr));
8206
0
  }
8207
8208
  /* If this node was suppressed, process the change. */
8209
0
  if (match)
8210
0
    bgp_process(bgp, pi->net, afi, safi);
8211
8212
0
  origin = BGP_ORIGIN_IGP;
8213
0
  if (aggregate->incomplete_origin_count > 0)
8214
0
    origin = BGP_ORIGIN_INCOMPLETE;
8215
0
  else if (aggregate->egp_origin_count > 0)
8216
0
    origin = BGP_ORIGIN_EGP;
8217
8218
0
  if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8219
0
    origin = aggregate->origin;
8220
8221
0
  if (aggregate->as_set) {
8222
    /* Retrieve aggregate route's as-path.
8223
     */
8224
0
    if (aggregate->aspath)
8225
0
      aspath = aspath_dup(aggregate->aspath);
8226
8227
    /* Retrieve aggregate route's community.
8228
     */
8229
0
    if (aggregate->community)
8230
0
      community = community_dup(aggregate->community);
8231
8232
    /* Retrieve aggregate route's ecommunity.
8233
     */
8234
0
    if (aggregate->ecommunity)
8235
0
      ecommunity = ecommunity_dup(aggregate->ecommunity);
8236
8237
    /* Retrieve aggregate route's lcommunity.
8238
     */
8239
0
    if (aggregate->lcommunity)
8240
0
      lcommunity = lcommunity_dup(aggregate->lcommunity);
8241
0
  }
8242
8243
0
  bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8244
0
            aspath, community, ecommunity,
8245
0
            lcommunity, atomic_aggregate, aggregate);
8246
0
}
8247
8248
void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
8249
           struct bgp_path_info *pi, afi_t afi, safi_t safi)
8250
0
{
8251
0
  struct bgp_dest *child;
8252
0
  struct bgp_dest *dest;
8253
0
  struct bgp_aggregate *aggregate;
8254
0
  struct bgp_table *table;
8255
8256
0
  table = bgp->aggregate[afi][safi];
8257
8258
  /* No aggregates configured. */
8259
0
  if (bgp_table_top_nolock(table) == NULL)
8260
0
    return;
8261
8262
0
  if (p->prefixlen == 0)
8263
0
    return;
8264
8265
0
  if (BGP_PATH_HOLDDOWN(pi))
8266
0
    return;
8267
8268
  /* If suppress fib is enabled and route not installed
8269
   * in FIB, do not update the aggregate route
8270
   */
8271
0
  if (!bgp_check_advertise(bgp, pi->net))
8272
0
    return;
8273
8274
0
  child = bgp_node_get(table, p);
8275
8276
  /* Aggregate address configuration check. */
8277
0
  for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8278
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
8279
8280
0
    aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8281
0
    if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8282
0
      bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
8283
0
               aggregate);
8284
0
    }
8285
0
  }
8286
0
  bgp_dest_unlock_node(child);
8287
0
}
8288
8289
void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
8290
           struct bgp_path_info *del, afi_t afi, safi_t safi)
8291
0
{
8292
0
  struct bgp_dest *child;
8293
0
  struct bgp_dest *dest;
8294
0
  struct bgp_aggregate *aggregate;
8295
0
  struct bgp_table *table;
8296
8297
0
  table = bgp->aggregate[afi][safi];
8298
8299
  /* No aggregates configured. */
8300
0
  if (bgp_table_top_nolock(table) == NULL)
8301
0
    return;
8302
8303
0
  if (p->prefixlen == 0)
8304
0
    return;
8305
8306
0
  child = bgp_node_get(table, p);
8307
8308
  /* Aggregate address configuration check. */
8309
0
  for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8310
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
8311
8312
0
    aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8313
0
    if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8314
0
      bgp_remove_route_from_aggregate(bgp, afi, safi, del,
8315
0
              aggregate, dest_p);
8316
0
    }
8317
0
  }
8318
0
  bgp_dest_unlock_node(child);
8319
0
}
8320
8321
/* Aggregate route attribute. */
8322
#define AGGREGATE_SUMMARY_ONLY 1
8323
0
#define AGGREGATE_AS_SET       1
8324
0
#define AGGREGATE_AS_UNSET     0
8325
8326
static const char *bgp_origin2str(uint8_t origin)
8327
0
{
8328
0
  switch (origin) {
8329
0
  case BGP_ORIGIN_IGP:
8330
0
    return "igp";
8331
0
  case BGP_ORIGIN_EGP:
8332
0
    return "egp";
8333
0
  case BGP_ORIGIN_INCOMPLETE:
8334
0
    return "incomplete";
8335
0
  }
8336
0
  return "n/a";
8337
0
}
8338
8339
static const char *bgp_rpki_validation2str(enum rpki_states v_state)
8340
0
{
8341
0
  switch (v_state) {
8342
0
  case RPKI_NOT_BEING_USED:
8343
0
    return "not used";
8344
0
  case RPKI_VALID:
8345
0
    return "valid";
8346
0
  case RPKI_NOTFOUND:
8347
0
    return "not found";
8348
0
  case RPKI_INVALID:
8349
0
    return "invalid";
8350
0
  }
8351
8352
0
  assert(!"We should never get here this is a dev escape");
8353
0
  return "ERROR";
8354
0
}
8355
8356
static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8357
             afi_t afi, safi_t safi)
8358
0
{
8359
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
8360
0
  int ret;
8361
0
  struct prefix p;
8362
0
  struct bgp_dest *dest;
8363
0
  struct bgp_aggregate *aggregate;
8364
8365
  /* Convert string to prefix structure. */
8366
0
  ret = str2prefix(prefix_str, &p);
8367
0
  if (!ret) {
8368
0
    vty_out(vty, "Malformed prefix\n");
8369
0
    return CMD_WARNING_CONFIG_FAILED;
8370
0
  }
8371
0
  apply_mask(&p);
8372
8373
  /* Old configuration check. */
8374
0
  dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
8375
0
  if (!dest) {
8376
0
    vty_out(vty,
8377
0
      "%% There is no aggregate-address configuration.\n");
8378
0
    return CMD_WARNING_CONFIG_FAILED;
8379
0
  }
8380
8381
0
  aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8382
0
  bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8383
0
  bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8384
0
            NULL, NULL,  0, aggregate);
8385
8386
  /* Unlock aggregate address configuration. */
8387
0
  bgp_dest_set_bgp_aggregate_info(dest, NULL);
8388
8389
0
  bgp_free_aggregate_info(aggregate);
8390
0
  bgp_dest_unlock_node(dest);
8391
0
  bgp_dest_unlock_node(dest);
8392
8393
0
  return CMD_SUCCESS;
8394
0
}
8395
8396
static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8397
           safi_t safi, const char *rmap,
8398
           uint8_t summary_only, uint8_t as_set,
8399
           uint8_t origin, bool match_med,
8400
           const char *suppress_map)
8401
0
{
8402
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
8403
0
  int ret;
8404
0
  struct prefix p;
8405
0
  struct bgp_dest *dest;
8406
0
  struct bgp_aggregate *aggregate;
8407
0
  uint8_t as_set_new = as_set;
8408
8409
0
  if (suppress_map && summary_only) {
8410
0
    vty_out(vty,
8411
0
      "'summary-only' and 'suppress-map' can't be used at the same time\n");
8412
0
    return CMD_WARNING_CONFIG_FAILED;
8413
0
  }
8414
8415
  /* Convert string to prefix structure. */
8416
0
  ret = str2prefix(prefix_str, &p);
8417
0
  if (!ret) {
8418
0
    vty_out(vty, "Malformed prefix\n");
8419
0
    return CMD_WARNING_CONFIG_FAILED;
8420
0
  }
8421
0
  apply_mask(&p);
8422
8423
0
  if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8424
0
      (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8425
0
    vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8426
0
      prefix_str);
8427
0
    return CMD_WARNING_CONFIG_FAILED;
8428
0
  }
8429
8430
  /* Old configuration check. */
8431
0
  dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
8432
0
  aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8433
8434
0
  if (aggregate) {
8435
0
    vty_out(vty, "There is already same aggregate network.\n");
8436
    /* try to remove the old entry */
8437
0
    ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
8438
0
    if (ret) {
8439
0
      vty_out(vty, "Error deleting aggregate.\n");
8440
0
      bgp_dest_unlock_node(dest);
8441
0
      return CMD_WARNING_CONFIG_FAILED;
8442
0
    }
8443
0
  }
8444
8445
  /* Make aggregate address structure. */
8446
0
  aggregate = bgp_aggregate_new();
8447
0
  aggregate->summary_only = summary_only;
8448
0
  aggregate->match_med = match_med;
8449
8450
  /* Network operators MUST NOT locally generate any new
8451
   * announcements containing AS_SET or AS_CONFED_SET. If they have
8452
   * announced routes with AS_SET or AS_CONFED_SET in them, then they
8453
   * SHOULD withdraw those routes and re-announce routes for the
8454
   * aggregate or component prefixes (i.e., the more-specific routes
8455
   * subsumed by the previously aggregated route) without AS_SET
8456
   * or AS_CONFED_SET in the updates.
8457
   */
8458
0
  if (bgp->reject_as_sets) {
8459
0
    if (as_set == AGGREGATE_AS_SET) {
8460
0
      as_set_new = AGGREGATE_AS_UNSET;
8461
0
      zlog_warn(
8462
0
        "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8463
0
        __func__);
8464
0
      vty_out(vty,
8465
0
        "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8466
0
    }
8467
0
  }
8468
8469
0
  aggregate->as_set = as_set_new;
8470
0
  aggregate->safi = safi;
8471
  /* Override ORIGIN attribute if defined.
8472
   * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8473
   * to IGP which is not what rfc4271 says.
8474
   * This enables the same behavior, optionally.
8475
   */
8476
0
  aggregate->origin = origin;
8477
8478
0
  if (rmap) {
8479
0
    XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8480
0
    route_map_counter_decrement(aggregate->rmap.map);
8481
0
    aggregate->rmap.name =
8482
0
      XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8483
0
    aggregate->rmap.map = route_map_lookup_by_name(rmap);
8484
0
    route_map_counter_increment(aggregate->rmap.map);
8485
0
  }
8486
8487
0
  if (suppress_map) {
8488
0
    XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8489
0
    route_map_counter_decrement(aggregate->suppress_map);
8490
8491
0
    aggregate->suppress_map_name =
8492
0
      XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8493
0
    aggregate->suppress_map =
8494
0
      route_map_lookup_by_name(aggregate->suppress_map_name);
8495
0
    route_map_counter_increment(aggregate->suppress_map);
8496
0
  }
8497
8498
0
  bgp_dest_set_bgp_aggregate_info(dest, aggregate);
8499
8500
  /* Aggregate address insert into BGP routing table. */
8501
0
  if (!bgp_aggregate_route(bgp, &p, afi, safi, aggregate)) {
8502
0
    bgp_aggregate_free(aggregate);
8503
0
    bgp_dest_unlock_node(dest);
8504
0
  }
8505
8506
0
  return CMD_SUCCESS;
8507
0
}
8508
8509
DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8510
      "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8511
      "as-set$as_set_s"
8512
      "|summary-only$summary_only"
8513
      "|route-map RMAP_NAME$rmap_name"
8514
      "|origin <egp|igp|incomplete>$origin_s"
8515
      "|matching-MED-only$match_med"
8516
      "|suppress-map RMAP_NAME$suppress_map"
8517
      "}]",
8518
      NO_STR
8519
      "Configure BGP aggregate entries\n"
8520
      "Aggregate prefix\n"
8521
      "Aggregate address\n"
8522
      "Aggregate mask\n"
8523
      "Generate AS set path information\n"
8524
      "Filter more specific routes from updates\n"
8525
      "Apply route map to aggregate network\n"
8526
      "Route map name\n"
8527
      "BGP origin code\n"
8528
      "Remote EGP\n"
8529
      "Local IGP\n"
8530
      "Unknown heritage\n"
8531
      "Only aggregate routes with matching MED\n"
8532
      "Suppress the selected more specific routes\n"
8533
      "Route map with the route selectors\n")
8534
0
{
8535
0
  const char *prefix_s = NULL;
8536
0
  safi_t safi = bgp_node_safi(vty);
8537
0
  uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8538
0
  int as_set = AGGREGATE_AS_UNSET;
8539
0
  char prefix_buf[PREFIX2STR_BUFFER];
8540
8541
0
  if (addr_str) {
8542
0
    if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8543
0
             sizeof(prefix_buf))
8544
0
        == 0) {
8545
0
      vty_out(vty, "%% Inconsistent address and mask\n");
8546
0
      return CMD_WARNING_CONFIG_FAILED;
8547
0
    }
8548
0
    prefix_s = prefix_buf;
8549
0
  } else
8550
0
    prefix_s = prefix_str;
8551
8552
0
  if (origin_s) {
8553
0
    if (strcmp(origin_s, "egp") == 0)
8554
0
      origin = BGP_ORIGIN_EGP;
8555
0
    else if (strcmp(origin_s, "igp") == 0)
8556
0
      origin = BGP_ORIGIN_IGP;
8557
0
    else if (strcmp(origin_s, "incomplete") == 0)
8558
0
      origin = BGP_ORIGIN_INCOMPLETE;
8559
0
  }
8560
8561
0
  if (as_set_s)
8562
0
    as_set = AGGREGATE_AS_SET;
8563
8564
  /* Handle configuration removal, otherwise installation. */
8565
0
  if (no)
8566
0
    return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8567
8568
0
  return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8569
0
         summary_only != NULL, as_set, origin,
8570
0
         match_med != NULL, suppress_map);
8571
0
}
8572
8573
void bgp_free_aggregate_info(struct bgp_aggregate *aggregate)
8574
0
{
8575
0
  if (aggregate->community)
8576
0
    community_free(&aggregate->community);
8577
8578
0
  hash_clean_and_free(&aggregate->community_hash,
8579
0
          bgp_aggr_community_remove);
8580
8581
0
  if (aggregate->ecommunity)
8582
0
    ecommunity_free(&aggregate->ecommunity);
8583
8584
0
  hash_clean_and_free(&aggregate->ecommunity_hash,
8585
0
          bgp_aggr_ecommunity_remove);
8586
8587
0
  if (aggregate->lcommunity)
8588
0
    lcommunity_free(&aggregate->lcommunity);
8589
8590
0
  hash_clean_and_free(&aggregate->lcommunity_hash,
8591
0
          bgp_aggr_lcommunity_remove);
8592
8593
0
  if (aggregate->aspath)
8594
0
    aspath_free(aggregate->aspath);
8595
8596
0
  hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
8597
8598
0
  bgp_aggregate_free(aggregate);
8599
0
}
8600
8601
DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8602
      "[no] aggregate-address X:X::X:X/M$prefix [{"
8603
      "as-set$as_set_s"
8604
      "|summary-only$summary_only"
8605
      "|route-map RMAP_NAME$rmap_name"
8606
      "|origin <egp|igp|incomplete>$origin_s"
8607
      "|matching-MED-only$match_med"
8608
      "|suppress-map RMAP_NAME$suppress_map"
8609
      "}]",
8610
      NO_STR
8611
      "Configure BGP aggregate entries\n"
8612
      "Aggregate prefix\n"
8613
      "Generate AS set path information\n"
8614
      "Filter more specific routes from updates\n"
8615
      "Apply route map to aggregate network\n"
8616
      "Route map name\n"
8617
      "BGP origin code\n"
8618
      "Remote EGP\n"
8619
      "Local IGP\n"
8620
      "Unknown heritage\n"
8621
      "Only aggregate routes with matching MED\n"
8622
      "Suppress the selected more specific routes\n"
8623
      "Route map with the route selectors\n")
8624
0
{
8625
0
  uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8626
0
  int as_set = AGGREGATE_AS_UNSET;
8627
8628
0
  if (origin_s) {
8629
0
    if (strcmp(origin_s, "egp") == 0)
8630
0
      origin = BGP_ORIGIN_EGP;
8631
0
    else if (strcmp(origin_s, "igp") == 0)
8632
0
      origin = BGP_ORIGIN_IGP;
8633
0
    else if (strcmp(origin_s, "incomplete") == 0)
8634
0
      origin = BGP_ORIGIN_INCOMPLETE;
8635
0
  }
8636
8637
0
  if (as_set_s)
8638
0
    as_set = AGGREGATE_AS_SET;
8639
8640
  /* Handle configuration removal, otherwise installation. */
8641
0
  if (no)
8642
0
    return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8643
0
             SAFI_UNICAST);
8644
8645
0
  return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8646
0
         rmap_name, summary_only != NULL, as_set,
8647
0
         origin, match_med != NULL, suppress_map);
8648
0
}
8649
8650
/* Redistribute route treatment. */
8651
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
8652
        const union g_addr *nexthop, ifindex_t ifindex,
8653
        enum nexthop_types_t nhtype, uint8_t distance,
8654
        enum blackhole_type bhtype, uint32_t metric,
8655
        uint8_t type, unsigned short instance,
8656
        route_tag_t tag)
8657
0
{
8658
0
  struct bgp_path_info *new;
8659
0
  struct bgp_path_info *bpi;
8660
0
  struct bgp_path_info rmap_path;
8661
0
  struct bgp_dest *bn;
8662
0
  struct attr attr;
8663
0
  struct attr *new_attr;
8664
0
  afi_t afi;
8665
0
  route_map_result_t ret;
8666
0
  struct bgp_redist *red;
8667
8668
0
  if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
8669
0
      bgp->peer_self == NULL)
8670
0
    return;
8671
8672
  /* Make default attribute. */
8673
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
8674
  /*
8675
   * This must not be NULL to satisfy Coverity SA
8676
   */
8677
0
  assert(attr.aspath);
8678
8679
0
  if (p->family == AF_INET6)
8680
0
    UNSET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
8681
8682
0
  switch (nhtype) {
8683
0
  case NEXTHOP_TYPE_IFINDEX:
8684
0
    switch (p->family) {
8685
0
    case AF_INET:
8686
0
      attr.nexthop.s_addr = INADDR_ANY;
8687
0
      attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8688
0
      attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
8689
0
      break;
8690
0
    case AF_INET6:
8691
0
      memset(&attr.mp_nexthop_global, 0,
8692
0
             sizeof(attr.mp_nexthop_global));
8693
0
      attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8694
0
      break;
8695
0
    }
8696
0
    break;
8697
0
  case NEXTHOP_TYPE_IPV4:
8698
0
  case NEXTHOP_TYPE_IPV4_IFINDEX:
8699
0
    attr.nexthop = nexthop->ipv4;
8700
0
    attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8701
0
    attr.mp_nexthop_global_in = nexthop->ipv4;
8702
0
    break;
8703
0
  case NEXTHOP_TYPE_IPV6:
8704
0
  case NEXTHOP_TYPE_IPV6_IFINDEX:
8705
0
    attr.mp_nexthop_global = nexthop->ipv6;
8706
0
    attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8707
0
    break;
8708
0
  case NEXTHOP_TYPE_BLACKHOLE:
8709
0
    switch (p->family) {
8710
0
    case AF_INET:
8711
0
      attr.nexthop.s_addr = INADDR_ANY;
8712
0
      attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8713
0
      attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
8714
0
      break;
8715
0
    case AF_INET6:
8716
0
      memset(&attr.mp_nexthop_global, 0,
8717
0
             sizeof(attr.mp_nexthop_global));
8718
0
      attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8719
0
      break;
8720
0
    }
8721
0
    attr.bh_type = bhtype;
8722
0
    break;
8723
0
  }
8724
0
  attr.nh_type = nhtype;
8725
0
  attr.nh_ifindex = ifindex;
8726
8727
0
  attr.med = metric;
8728
0
  attr.distance = distance;
8729
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8730
0
  attr.tag = tag;
8731
8732
0
  if (metric)
8733
0
    bgp_attr_set_aigp_metric(&attr, metric);
8734
8735
0
  afi = family2afi(p->family);
8736
8737
0
  red = bgp_redist_lookup(bgp, afi, type, instance);
8738
0
  if (red) {
8739
0
    struct attr attr_new;
8740
8741
    /* Copy attribute for modification. */
8742
0
    attr_new = attr;
8743
8744
0
    if (red->redist_metric_flag) {
8745
0
      attr_new.med = red->redist_metric;
8746
0
      bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8747
0
    }
8748
8749
    /* Apply route-map. */
8750
0
    if (red->rmap.name) {
8751
0
      memset(&rmap_path, 0, sizeof(rmap_path));
8752
0
      rmap_path.peer = bgp->peer_self;
8753
0
      rmap_path.attr = &attr_new;
8754
8755
0
      SET_FLAG(bgp->peer_self->rmap_type,
8756
0
         PEER_RMAP_TYPE_REDISTRIBUTE);
8757
8758
0
      ret = route_map_apply(red->rmap.map, p, &rmap_path);
8759
8760
0
      bgp->peer_self->rmap_type = 0;
8761
8762
0
      if (ret == RMAP_DENYMATCH) {
8763
        /* Free uninterned attribute. */
8764
0
        bgp_attr_flush(&attr_new);
8765
8766
        /* Unintern original. */
8767
0
        aspath_unintern(&attr.aspath);
8768
0
        bgp_redistribute_delete(bgp, p, type, instance);
8769
0
        return;
8770
0
      }
8771
0
    }
8772
8773
0
    if (bgp_in_graceful_shutdown(bgp))
8774
0
      bgp_attr_add_gshut_community(&attr_new);
8775
8776
0
    bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8777
0
              SAFI_UNICAST, p, NULL);
8778
8779
0
    new_attr = bgp_attr_intern(&attr_new);
8780
8781
0
    for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
8782
0
      if (bpi->peer == bgp->peer_self
8783
0
          && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
8784
0
        break;
8785
8786
0
    if (bpi) {
8787
      /* Ensure the (source route) type is updated. */
8788
0
      bpi->type = type;
8789
0
      if (attrhash_cmp(bpi->attr, new_attr)
8790
0
          && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
8791
0
        bgp_attr_unintern(&new_attr);
8792
0
        aspath_unintern(&attr.aspath);
8793
0
        bgp_dest_unlock_node(bn);
8794
0
        return;
8795
0
      } else {
8796
        /* The attribute is changed. */
8797
0
        bgp_path_info_set_flag(bn, bpi,
8798
0
                   BGP_PATH_ATTR_CHANGED);
8799
8800
        /* Rewrite BGP route information. */
8801
0
        if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8802
0
          bgp_path_info_restore(bn, bpi);
8803
0
        else
8804
0
          bgp_aggregate_decrement(
8805
0
            bgp, p, bpi, afi, SAFI_UNICAST);
8806
0
        bgp_attr_unintern(&bpi->attr);
8807
0
        bpi->attr = new_attr;
8808
0
        bpi->uptime = monotime(NULL);
8809
8810
        /* Process change. */
8811
0
        bgp_aggregate_increment(bgp, p, bpi, afi,
8812
0
              SAFI_UNICAST);
8813
0
        bgp_process(bgp, bn, afi, SAFI_UNICAST);
8814
0
        bgp_dest_unlock_node(bn);
8815
0
        aspath_unintern(&attr.aspath);
8816
8817
0
        if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8818
0
            || (bgp->inst_type
8819
0
          == BGP_INSTANCE_TYPE_DEFAULT)) {
8820
8821
0
          vpn_leak_from_vrf_update(
8822
0
            bgp_get_default(), bgp, bpi);
8823
0
        }
8824
0
        return;
8825
0
      }
8826
0
    }
8827
8828
0
    new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8829
0
        bgp->peer_self, new_attr, bn);
8830
0
    SET_FLAG(new->flags, BGP_PATH_VALID);
8831
8832
0
    bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
8833
0
    bgp_path_info_add(bn, new);
8834
0
    bgp_dest_unlock_node(bn);
8835
0
    SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
8836
0
    bgp_process(bgp, bn, afi, SAFI_UNICAST);
8837
8838
0
    if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8839
0
        || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8840
8841
0
      vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8842
0
    }
8843
0
  }
8844
8845
  /* Unintern original. */
8846
0
  aspath_unintern(&attr.aspath);
8847
0
}
8848
8849
void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8850
           unsigned short instance)
8851
0
{
8852
0
  afi_t afi;
8853
0
  struct bgp_dest *dest;
8854
0
  struct bgp_path_info *pi;
8855
0
  struct bgp_redist *red;
8856
8857
0
  afi = family2afi(p->family);
8858
8859
0
  red = bgp_redist_lookup(bgp, afi, type, instance);
8860
0
  if (red) {
8861
0
    dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8862
0
          SAFI_UNICAST, p, NULL);
8863
8864
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8865
0
      if (pi->peer == bgp->peer_self && pi->type == type)
8866
0
        break;
8867
8868
0
    if (pi) {
8869
0
      if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8870
0
          || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8871
8872
0
        vpn_leak_from_vrf_withdraw(bgp_get_default(),
8873
0
                 bgp, pi);
8874
0
      }
8875
0
      bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
8876
0
      bgp_path_info_delete(dest, pi);
8877
0
      bgp_process(bgp, dest, afi, SAFI_UNICAST);
8878
0
    }
8879
0
    bgp_dest_unlock_node(dest);
8880
0
  }
8881
0
}
8882
8883
/* Withdraw specified route type's route. */
8884
void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
8885
             unsigned short instance)
8886
0
{
8887
0
  struct bgp_dest *dest;
8888
0
  struct bgp_path_info *pi;
8889
0
  struct bgp_table *table;
8890
8891
0
  table = bgp->rib[afi][SAFI_UNICAST];
8892
8893
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8894
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8895
0
      if (pi->peer == bgp->peer_self && pi->type == type
8896
0
          && pi->instance == instance)
8897
0
        break;
8898
8899
0
    if (pi) {
8900
0
      if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8901
0
          || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8902
8903
0
        vpn_leak_from_vrf_withdraw(bgp_get_default(),
8904
0
                 bgp, pi);
8905
0
      }
8906
0
      bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
8907
0
            pi, afi, SAFI_UNICAST);
8908
0
      bgp_path_info_delete(dest, pi);
8909
0
      if (!CHECK_FLAG(bgp->flags,
8910
0
          BGP_FLAG_DELETE_IN_PROGRESS))
8911
0
        bgp_process(bgp, dest, afi, SAFI_UNICAST);
8912
0
      else
8913
0
        bgp_path_info_reap(dest, pi);
8914
0
    }
8915
0
  }
8916
0
}
8917
8918
/* Static function to display route. */
8919
static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8920
        struct vty *vty, json_object *json, bool wide)
8921
0
{
8922
0
  int len = 0;
8923
0
  char buf[INET6_ADDRSTRLEN];
8924
8925
0
  if (p->family == AF_INET) {
8926
0
    if (!json) {
8927
0
      len = vty_out(vty, "%pFX", p);
8928
0
    } else {
8929
0
      json_object_string_add(json, "prefix",
8930
0
                 inet_ntop(p->family,
8931
0
               &p->u.prefix, buf,
8932
0
               sizeof(buf)));
8933
0
      json_object_int_add(json, "prefixLen", p->prefixlen);
8934
0
      json_object_string_addf(json, "network", "%pFX", p);
8935
0
      json_object_int_add(json, "version", dest->version);
8936
0
    }
8937
0
  } else if (p->family == AF_ETHERNET) {
8938
0
    len = vty_out(vty, "%pFX", p);
8939
0
  } else if (p->family == AF_EVPN) {
8940
0
    if (!json)
8941
0
      len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
8942
0
    else
8943
0
      bgp_evpn_route2json((struct prefix_evpn *)p, json);
8944
0
  } else if (p->family == AF_FLOWSPEC) {
8945
0
    route_vty_out_flowspec(vty, p, NULL,
8946
0
             json ?
8947
0
             NLRI_STRING_FORMAT_JSON_SIMPLE :
8948
0
             NLRI_STRING_FORMAT_MIN, json);
8949
0
  } else {
8950
0
    if (!json)
8951
0
      len = vty_out(vty, "%pFX", p);
8952
0
    else {
8953
0
      json_object_string_add(json, "prefix",
8954
0
                 inet_ntop(p->family,
8955
0
               &p->u.prefix, buf,
8956
0
               sizeof(buf)));
8957
0
      json_object_int_add(json, "prefixLen", p->prefixlen);
8958
0
      json_object_string_addf(json, "network", "%pFX", p);
8959
0
      json_object_int_add(json, "version", dest->version);
8960
0
    }
8961
0
  }
8962
8963
0
  if (!json) {
8964
0
    len = wide ? (45 - len) : (17 - len);
8965
0
    if (len < 1)
8966
0
      vty_out(vty, "\n%*s", 20, " ");
8967
0
    else
8968
0
      vty_out(vty, "%*s", len, " ");
8969
0
  }
8970
0
}
8971
8972
enum bgp_display_type {
8973
  normal_list,
8974
};
8975
8976
const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8977
0
{
8978
0
  switch (reason) {
8979
0
  case bgp_path_selection_none:
8980
0
    return "Nothing to Select";
8981
0
  case bgp_path_selection_first:
8982
0
    return "First path received";
8983
0
  case bgp_path_selection_evpn_sticky_mac:
8984
0
    return "EVPN Sticky Mac";
8985
0
  case bgp_path_selection_evpn_seq:
8986
0
    return "EVPN sequence number";
8987
0
  case bgp_path_selection_evpn_lower_ip:
8988
0
    return "EVPN lower IP";
8989
0
  case bgp_path_selection_evpn_local_path:
8990
0
    return "EVPN local ES path";
8991
0
  case bgp_path_selection_evpn_non_proxy:
8992
0
    return "EVPN non proxy";
8993
0
  case bgp_path_selection_weight:
8994
0
    return "Weight";
8995
0
  case bgp_path_selection_local_pref:
8996
0
    return "Local Pref";
8997
0
  case bgp_path_selection_accept_own:
8998
0
    return "Accept Own";
8999
0
  case bgp_path_selection_local_route:
9000
0
    return "Local Route";
9001
0
  case bgp_path_selection_aigp:
9002
0
    return "AIGP";
9003
0
  case bgp_path_selection_confed_as_path:
9004
0
    return "Confederation based AS Path";
9005
0
  case bgp_path_selection_as_path:
9006
0
    return "AS Path";
9007
0
  case bgp_path_selection_origin:
9008
0
    return "Origin";
9009
0
  case bgp_path_selection_med:
9010
0
    return "MED";
9011
0
  case bgp_path_selection_peer:
9012
0
    return "Peer Type";
9013
0
  case bgp_path_selection_confed:
9014
0
    return "Confed Peer Type";
9015
0
  case bgp_path_selection_igp_metric:
9016
0
    return "IGP Metric";
9017
0
  case bgp_path_selection_older:
9018
0
    return "Older Path";
9019
0
  case bgp_path_selection_router_id:
9020
0
    return "Router ID";
9021
0
  case bgp_path_selection_cluster_length:
9022
0
    return "Cluster length";
9023
0
  case bgp_path_selection_stale:
9024
0
    return "Path Staleness";
9025
0
  case bgp_path_selection_local_configured:
9026
0
    return "Locally configured route";
9027
0
  case bgp_path_selection_neighbor_ip:
9028
0
    return "Neighbor IP";
9029
0
  case bgp_path_selection_default:
9030
0
    return "Nothing left to compare";
9031
0
  }
9032
0
  return "Invalid (internal error)";
9033
0
}
9034
9035
/* Print the short form route status for a bgp_path_info */
9036
static void route_vty_short_status_out(struct vty *vty,
9037
               struct bgp_path_info *path,
9038
               const struct prefix *p,
9039
               json_object *json_path)
9040
0
{
9041
0
  enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9042
9043
0
  if (json_path) {
9044
9045
    /* Route status display. */
9046
0
    if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
9047
0
      json_object_boolean_true_add(json_path, "removed");
9048
9049
0
    if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
9050
0
      json_object_boolean_true_add(json_path, "stale");
9051
9052
0
    if (path->extra && bgp_path_suppressed(path))
9053
0
      json_object_boolean_true_add(json_path, "suppressed");
9054
9055
0
    if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9056
0
        && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9057
0
      json_object_boolean_true_add(json_path, "valid");
9058
9059
    /* Selected */
9060
0
    if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9061
0
      json_object_boolean_true_add(json_path, "history");
9062
9063
0
    if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
9064
0
      json_object_boolean_true_add(json_path, "damped");
9065
9066
0
    if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9067
0
      json_object_boolean_true_add(json_path, "bestpath");
9068
0
      json_object_string_add(json_path, "selectionReason",
9069
0
                 bgp_path_selection_reason2str(
9070
0
                   path->net->reason));
9071
0
    }
9072
9073
0
    if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
9074
0
      json_object_boolean_true_add(json_path, "multipath");
9075
9076
    /* Internal route. */
9077
0
    if ((path->peer->as)
9078
0
        && (path->peer->as == path->peer->local_as))
9079
0
      json_object_string_add(json_path, "pathFrom",
9080
0
                 "internal");
9081
0
    else
9082
0
      json_object_string_add(json_path, "pathFrom",
9083
0
                 "external");
9084
9085
0
    return;
9086
0
  }
9087
9088
  /* RPKI validation state */
9089
0
  rpki_state =
9090
0
    hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9091
9092
0
  if (rpki_state == RPKI_VALID)
9093
0
    vty_out(vty, "V");
9094
0
  else if (rpki_state == RPKI_INVALID)
9095
0
    vty_out(vty, "I");
9096
0
  else if (rpki_state == RPKI_NOTFOUND)
9097
0
    vty_out(vty, "N");
9098
0
  else
9099
0
    vty_out(vty, " ");
9100
9101
  /* Route status display. */
9102
0
  if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
9103
0
    vty_out(vty, "R");
9104
0
  else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
9105
0
    vty_out(vty, "S");
9106
0
  else if (bgp_path_suppressed(path))
9107
0
    vty_out(vty, "s");
9108
0
  else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9109
0
     && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9110
0
    vty_out(vty, "*");
9111
0
  else
9112
0
    vty_out(vty, " ");
9113
9114
  /* Selected */
9115
0
  if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9116
0
    vty_out(vty, "h");
9117
0
  else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
9118
0
    vty_out(vty, "d");
9119
0
  else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
9120
0
    vty_out(vty, ">");
9121
0
  else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
9122
0
    vty_out(vty, "=");
9123
0
  else
9124
0
    vty_out(vty, " ");
9125
9126
  /* Internal route. */
9127
0
  if (path->peer && (path->peer->as)
9128
0
      && (path->peer->as == path->peer->local_as))
9129
0
    vty_out(vty, "i");
9130
0
  else
9131
0
    vty_out(vty, " ");
9132
0
}
9133
9134
static char *bgp_nexthop_hostname(struct peer *peer,
9135
          struct bgp_nexthop_cache *bnc)
9136
0
{
9137
0
  if (peer->hostname
9138
0
      && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
9139
0
    return peer->hostname;
9140
0
  return NULL;
9141
0
}
9142
9143
/* called from terminal list command */
9144
void route_vty_out(struct vty *vty, const struct prefix *p,
9145
       struct bgp_path_info *path, int display, safi_t safi,
9146
       json_object *json_paths, bool wide)
9147
0
{
9148
0
  int len;
9149
0
  struct attr *attr = path->attr;
9150
0
  json_object *json_path = NULL;
9151
0
  json_object *json_nexthops = NULL;
9152
0
  json_object *json_nexthop_global = NULL;
9153
0
  json_object *json_nexthop_ll = NULL;
9154
0
  json_object *json_ext_community = NULL;
9155
0
  char vrf_id_str[VRF_NAMSIZ] = {0};
9156
0
  bool nexthop_self =
9157
0
    CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9158
0
  bool nexthop_othervrf = false;
9159
0
  vrf_id_t nexthop_vrfid = VRF_DEFAULT;
9160
0
  const char *nexthop_vrfname = VRF_DEFAULT_NAME;
9161
0
  char *nexthop_hostname =
9162
0
    bgp_nexthop_hostname(path->peer, path->nexthop);
9163
0
  char esi_buf[ESI_STR_LEN];
9164
9165
0
  if (json_paths)
9166
0
    json_path = json_object_new_object();
9167
9168
  /* short status lead text */
9169
0
  route_vty_short_status_out(vty, path, p, json_path);
9170
9171
0
  if (!json_paths) {
9172
    /* print prefix and mask */
9173
0
    if (!display)
9174
0
      route_vty_out_route(path->net, p, vty, json_path, wide);
9175
0
    else
9176
0
      vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9177
0
  } else {
9178
0
    route_vty_out_route(path->net, p, vty, json_path, wide);
9179
0
  }
9180
9181
  /*
9182
   * If vrf id of nexthop is different from that of prefix,
9183
   * set up printable string to append
9184
   */
9185
0
  if (path->extra && path->extra->bgp_orig) {
9186
0
    const char *self = "";
9187
9188
0
    if (nexthop_self)
9189
0
      self = "<";
9190
9191
0
    nexthop_othervrf = true;
9192
0
    nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9193
9194
0
    if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9195
0
      snprintf(vrf_id_str, sizeof(vrf_id_str),
9196
0
        "@%s%s", VRFID_NONE_STR, self);
9197
0
    else
9198
0
      snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9199
0
         path->extra->bgp_orig->vrf_id, self);
9200
9201
0
    if (path->extra->bgp_orig->inst_type
9202
0
        != BGP_INSTANCE_TYPE_DEFAULT)
9203
9204
0
      nexthop_vrfname = path->extra->bgp_orig->name;
9205
0
  } else {
9206
0
    const char *self = "";
9207
9208
0
    if (nexthop_self)
9209
0
      self = "<";
9210
9211
0
    snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9212
0
  }
9213
9214
  /*
9215
   * For ENCAP and EVPN routes, nexthop address family is not
9216
   * neccessarily the same as the prefix address family.
9217
   * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9218
   * EVPN routes are also exchanged with a MP nexthop. Currently,
9219
   * this
9220
   * is only IPv4, the value will be present in either
9221
   * attr->nexthop or
9222
   * attr->mp_nexthop_global_in
9223
   */
9224
0
  if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
9225
0
    char nexthop[128];
9226
0
    int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9227
9228
0
    switch (af) {
9229
0
    case AF_INET:
9230
0
      snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9231
0
           &attr->mp_nexthop_global_in);
9232
0
      break;
9233
0
    case AF_INET6:
9234
0
      snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9235
0
           &attr->mp_nexthop_global);
9236
0
      break;
9237
0
    default:
9238
0
      snprintf(nexthop, sizeof(nexthop), "?");
9239
0
      break;
9240
0
    }
9241
9242
0
    if (json_paths) {
9243
0
      json_nexthop_global = json_object_new_object();
9244
9245
0
      json_object_string_add(json_nexthop_global, "ip",
9246
0
                 nexthop);
9247
9248
0
      if (path->peer->hostname)
9249
0
        json_object_string_add(json_nexthop_global,
9250
0
                   "hostname",
9251
0
                   path->peer->hostname);
9252
9253
0
      json_object_string_add(json_nexthop_global, "afi",
9254
0
                 (af == AF_INET) ? "ipv4"
9255
0
                     : "ipv6");
9256
0
      json_object_boolean_true_add(json_nexthop_global,
9257
0
                 "used");
9258
0
    } else {
9259
0
      if (nexthop_hostname)
9260
0
        len = vty_out(vty, "%s(%s)%s", nexthop,
9261
0
                nexthop_hostname, vrf_id_str);
9262
0
      else
9263
0
        len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9264
9265
0
      len = wide ? (41 - len) : (16 - len);
9266
0
      if (len < 1)
9267
0
        vty_out(vty, "\n%*s", 36, " ");
9268
0
      else
9269
0
        vty_out(vty, "%*s", len, " ");
9270
0
    }
9271
0
  } else if (safi == SAFI_EVPN) {
9272
0
    if (json_paths) {
9273
0
      json_nexthop_global = json_object_new_object();
9274
9275
0
      json_object_string_addf(json_nexthop_global, "ip",
9276
0
            "%pI4",
9277
0
            &attr->mp_nexthop_global_in);
9278
9279
0
      if (path->peer->hostname)
9280
0
        json_object_string_add(json_nexthop_global,
9281
0
                   "hostname",
9282
0
                   path->peer->hostname);
9283
9284
0
      json_object_string_add(json_nexthop_global, "afi",
9285
0
                 "ipv4");
9286
0
      json_object_boolean_true_add(json_nexthop_global,
9287
0
                 "used");
9288
0
    } else {
9289
0
      if (nexthop_hostname)
9290
0
        len = vty_out(vty, "%pI4(%s)%s",
9291
0
                &attr->mp_nexthop_global_in,
9292
0
                nexthop_hostname, vrf_id_str);
9293
0
      else
9294
0
        len = vty_out(vty, "%pI4%s",
9295
0
                &attr->mp_nexthop_global_in,
9296
0
                vrf_id_str);
9297
9298
0
      len = wide ? (41 - len) : (16 - len);
9299
0
      if (len < 1)
9300
0
        vty_out(vty, "\n%*s", 36, " ");
9301
0
      else
9302
0
        vty_out(vty, "%*s", len, " ");
9303
0
    }
9304
0
  } else if (safi == SAFI_FLOWSPEC) {
9305
0
    if (attr->nexthop.s_addr != INADDR_ANY) {
9306
0
      if (json_paths) {
9307
0
        json_nexthop_global = json_object_new_object();
9308
9309
0
        json_object_string_add(json_nexthop_global,
9310
0
                   "afi", "ipv4");
9311
0
        json_object_string_addf(json_nexthop_global,
9312
0
              "ip", "%pI4",
9313
0
              &attr->nexthop);
9314
9315
0
        if (path->peer->hostname)
9316
0
          json_object_string_add(
9317
0
            json_nexthop_global, "hostname",
9318
0
            path->peer->hostname);
9319
9320
0
        json_object_boolean_true_add(
9321
0
              json_nexthop_global,
9322
0
                   "used");
9323
0
      } else {
9324
0
        if (nexthop_hostname)
9325
0
          len = vty_out(vty, "%pI4(%s)%s",
9326
0
                  &attr->nexthop,
9327
0
                  nexthop_hostname,
9328
0
                  vrf_id_str);
9329
0
        else
9330
0
          len = vty_out(vty, "%pI4%s",
9331
0
                  &attr->nexthop,
9332
0
                  vrf_id_str);
9333
9334
0
        len = wide ? (41 - len) : (16 - len);
9335
0
        if (len < 1)
9336
0
          vty_out(vty, "\n%*s", 36, " ");
9337
0
        else
9338
0
          vty_out(vty, "%*s", len, " ");
9339
0
      }
9340
0
    }
9341
0
  } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9342
0
    if (json_paths) {
9343
0
      json_nexthop_global = json_object_new_object();
9344
9345
0
      json_object_string_addf(json_nexthop_global, "ip",
9346
0
            "%pI4", &attr->nexthop);
9347
9348
0
      if (path->peer->hostname)
9349
0
        json_object_string_add(json_nexthop_global,
9350
0
                   "hostname",
9351
0
                   path->peer->hostname);
9352
9353
0
      json_object_string_add(json_nexthop_global, "afi",
9354
0
                 "ipv4");
9355
0
      json_object_boolean_true_add(json_nexthop_global,
9356
0
                 "used");
9357
0
    } else {
9358
0
      if (nexthop_hostname)
9359
0
        len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9360
0
                nexthop_hostname, vrf_id_str);
9361
0
      else
9362
0
        len = vty_out(vty, "%pI4%s", &attr->nexthop,
9363
0
                vrf_id_str);
9364
9365
0
      len = wide ? (41 - len) : (16 - len);
9366
0
      if (len < 1)
9367
0
        vty_out(vty, "\n%*s", 36, " ");
9368
0
      else
9369
0
        vty_out(vty, "%*s", len, " ");
9370
0
    }
9371
0
  }
9372
9373
  /* IPv6 Next Hop */
9374
0
  else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9375
0
    if (json_paths) {
9376
0
      json_nexthop_global = json_object_new_object();
9377
0
      json_object_string_addf(json_nexthop_global, "ip",
9378
0
            "%pI6",
9379
0
            &attr->mp_nexthop_global);
9380
9381
0
      if (path->peer->hostname)
9382
0
        json_object_string_add(json_nexthop_global,
9383
0
                   "hostname",
9384
0
                   path->peer->hostname);
9385
9386
0
      json_object_string_add(json_nexthop_global, "afi",
9387
0
                 "ipv6");
9388
0
      json_object_string_add(json_nexthop_global, "scope",
9389
0
                 "global");
9390
9391
      /* We display both LL & GL if both have been
9392
       * received */
9393
0
      if ((attr->mp_nexthop_len
9394
0
           == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9395
0
          || (path->peer->conf_if)) {
9396
0
        json_nexthop_ll = json_object_new_object();
9397
0
        json_object_string_addf(
9398
0
          json_nexthop_ll, "ip", "%pI6",
9399
0
          &attr->mp_nexthop_local);
9400
9401
0
        if (path->peer->hostname)
9402
0
          json_object_string_add(
9403
0
            json_nexthop_ll, "hostname",
9404
0
            path->peer->hostname);
9405
9406
0
        json_object_string_add(json_nexthop_ll, "afi",
9407
0
                   "ipv6");
9408
0
        json_object_string_add(json_nexthop_ll, "scope",
9409
0
                   "link-local");
9410
9411
0
        if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9412
0
               &attr->mp_nexthop_local)
9413
0
             != 0)
9414
0
            && !attr->mp_nexthop_prefer_global)
9415
0
          json_object_boolean_true_add(
9416
0
            json_nexthop_ll, "used");
9417
0
        else
9418
0
          json_object_boolean_true_add(
9419
0
            json_nexthop_global, "used");
9420
0
      } else
9421
0
        json_object_boolean_true_add(
9422
0
          json_nexthop_global, "used");
9423
0
    } else {
9424
      /* Display LL if LL/Global both in table unless
9425
       * prefer-global is set */
9426
0
      if (((attr->mp_nexthop_len
9427
0
            == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9428
0
           && !attr->mp_nexthop_prefer_global)
9429
0
          || (path->peer->conf_if)) {
9430
0
        if (path->peer->conf_if) {
9431
0
          len = vty_out(vty, "%s",
9432
0
                  path->peer->conf_if);
9433
          /* len of IPv6 addr + max len of def
9434
           * ifname */
9435
0
          len = wide ? (41 - len) : (16 - len);
9436
9437
0
          if (len < 1)
9438
0
            vty_out(vty, "\n%*s", 36, " ");
9439
0
          else
9440
0
            vty_out(vty, "%*s", len, " ");
9441
0
        } else {
9442
0
          if (nexthop_hostname)
9443
0
            len = vty_out(
9444
0
              vty, "%pI6(%s)%s",
9445
0
              &attr->mp_nexthop_local,
9446
0
              nexthop_hostname,
9447
0
              vrf_id_str);
9448
0
          else
9449
0
            len = vty_out(
9450
0
              vty, "%pI6%s",
9451
0
              &attr->mp_nexthop_local,
9452
0
              vrf_id_str);
9453
9454
0
          len = wide ? (41 - len) : (16 - len);
9455
9456
0
          if (len < 1)
9457
0
            vty_out(vty, "\n%*s", 36, " ");
9458
0
          else
9459
0
            vty_out(vty, "%*s", len, " ");
9460
0
        }
9461
0
      } else {
9462
0
        if (nexthop_hostname)
9463
0
          len = vty_out(vty, "%pI6(%s)%s",
9464
0
                  &attr->mp_nexthop_global,
9465
0
                  nexthop_hostname,
9466
0
                  vrf_id_str);
9467
0
        else
9468
0
          len = vty_out(vty, "%pI6%s",
9469
0
                  &attr->mp_nexthop_global,
9470
0
                  vrf_id_str);
9471
9472
0
        len = wide ? (41 - len) : (16 - len);
9473
9474
0
        if (len < 1)
9475
0
          vty_out(vty, "\n%*s", 36, " ");
9476
0
        else
9477
0
          vty_out(vty, "%*s", len, " ");
9478
0
      }
9479
0
    }
9480
0
  }
9481
9482
  /* MED/Metric */
9483
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9484
0
    if (json_paths)
9485
0
      json_object_int_add(json_path, "metric", attr->med);
9486
0
    else if (wide)
9487
0
      vty_out(vty, "%7u", attr->med);
9488
0
    else
9489
0
      vty_out(vty, "%10u", attr->med);
9490
0
  else if (!json_paths) {
9491
0
    if (wide)
9492
0
      vty_out(vty, "%*s", 7, " ");
9493
0
    else
9494
0
      vty_out(vty, "%*s", 10, " ");
9495
0
  }
9496
9497
  /* Local Pref */
9498
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9499
0
    if (json_paths)
9500
0
      json_object_int_add(json_path, "locPrf",
9501
0
              attr->local_pref);
9502
0
    else
9503
0
      vty_out(vty, "%7u", attr->local_pref);
9504
0
  else if (!json_paths)
9505
0
    vty_out(vty, "       ");
9506
9507
0
  if (json_paths)
9508
0
    json_object_int_add(json_path, "weight", attr->weight);
9509
0
  else
9510
0
    vty_out(vty, "%7u ", attr->weight);
9511
9512
0
  if (json_paths)
9513
0
    json_object_string_addf(json_path, "peerId", "%pSU",
9514
0
          &path->peer->su);
9515
9516
  /* Print aspath */
9517
0
  if (attr->aspath) {
9518
0
    if (json_paths)
9519
0
      json_object_string_add(json_path, "path",
9520
0
                 attr->aspath->str);
9521
0
    else
9522
0
      aspath_print_vty(vty, attr->aspath);
9523
0
  }
9524
9525
  /* Print origin */
9526
0
  if (json_paths)
9527
0
    json_object_string_add(json_path, "origin",
9528
0
               bgp_origin_long_str[attr->origin]);
9529
0
  else
9530
0
    vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9531
9532
0
  if (json_paths) {
9533
0
    if (bgp_evpn_is_esi_valid(&attr->esi)) {
9534
0
      json_object_string_add(json_path, "esi",
9535
0
          esi_to_str(&attr->esi,
9536
0
          esi_buf, sizeof(esi_buf)));
9537
0
    }
9538
0
    if (safi == SAFI_EVPN &&
9539
0
        attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9540
0
      json_ext_community = json_object_new_object();
9541
0
      json_object_string_add(
9542
0
        json_ext_community, "string",
9543
0
        bgp_attr_get_ecommunity(attr)->str);
9544
0
      json_object_object_add(json_path,
9545
0
                 "extendedCommunity",
9546
0
                 json_ext_community);
9547
0
    }
9548
9549
0
    if (nexthop_self)
9550
0
      json_object_boolean_true_add(json_path,
9551
0
        "announceNexthopSelf");
9552
0
    if (nexthop_othervrf) {
9553
0
      json_object_string_add(json_path, "nhVrfName",
9554
0
        nexthop_vrfname);
9555
9556
0
      json_object_int_add(json_path, "nhVrfId",
9557
0
        ((nexthop_vrfid == VRF_UNKNOWN)
9558
0
          ? -1
9559
0
          : (int)nexthop_vrfid));
9560
0
    }
9561
0
  }
9562
9563
0
  if (json_paths) {
9564
0
    if (json_nexthop_global || json_nexthop_ll) {
9565
0
      json_nexthops = json_object_new_array();
9566
9567
0
      if (json_nexthop_global)
9568
0
        json_object_array_add(json_nexthops,
9569
0
                  json_nexthop_global);
9570
9571
0
      if (json_nexthop_ll)
9572
0
        json_object_array_add(json_nexthops,
9573
0
                  json_nexthop_ll);
9574
9575
0
      json_object_object_add(json_path, "nexthops",
9576
0
                 json_nexthops);
9577
0
    }
9578
9579
0
    json_object_array_add(json_paths, json_path);
9580
0
  } else {
9581
0
    vty_out(vty, "\n");
9582
9583
0
    if (safi == SAFI_EVPN) {
9584
0
      if (bgp_evpn_is_esi_valid(&attr->esi)) {
9585
        /* XXX - add these params to the json out */
9586
0
        vty_out(vty, "%*s", 20, " ");
9587
0
        vty_out(vty, "ESI:%s",
9588
0
          esi_to_str(&attr->esi, esi_buf,
9589
0
               sizeof(esi_buf)));
9590
9591
0
        vty_out(vty, "\n");
9592
0
      }
9593
0
      if (attr->flag &
9594
0
        ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9595
0
        vty_out(vty, "%*s", 20, " ");
9596
0
        vty_out(vty, "%s\n",
9597
0
          bgp_attr_get_ecommunity(attr)->str);
9598
0
      }
9599
0
    }
9600
9601
0
#ifdef ENABLE_BGP_VNC
9602
    /* prints an additional line, indented, with VNC info, if
9603
     * present */
9604
0
    if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9605
0
      rfapi_vty_out_vncinfo(vty, p, path, safi);
9606
0
#endif
9607
0
  }
9608
0
}
9609
9610
/* called from terminal list command */
9611
void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9612
           const struct prefix *p, struct attr *attr, safi_t safi,
9613
           bool use_json, json_object *json_ar, bool wide)
9614
0
{
9615
0
  json_object *json_status = NULL;
9616
0
  json_object *json_net = NULL;
9617
0
  int len;
9618
0
  char buff[BUFSIZ];
9619
9620
  /* Route status display. */
9621
0
  if (use_json) {
9622
0
    json_status = json_object_new_object();
9623
0
    json_net = json_object_new_object();
9624
0
  } else {
9625
0
    vty_out(vty, " *");
9626
0
    vty_out(vty, ">");
9627
0
    vty_out(vty, " ");
9628
0
  }
9629
9630
  /* print prefix and mask */
9631
0
  if (use_json) {
9632
0
    if (safi == SAFI_EVPN)
9633
0
      bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9634
0
    else if (p->family == AF_INET || p->family == AF_INET6) {
9635
0
      json_object_string_add(
9636
0
        json_net, "addrPrefix",
9637
0
        inet_ntop(p->family, &p->u.prefix, buff,
9638
0
        BUFSIZ));
9639
0
      json_object_int_add(json_net, "prefixLen",
9640
0
        p->prefixlen);
9641
0
      json_object_string_addf(json_net, "network", "%pFX", p);
9642
0
    }
9643
0
  } else
9644
0
    route_vty_out_route(dest, p, vty, NULL, wide);
9645
9646
  /* Print attribute */
9647
0
  if (attr) {
9648
0
    if (use_json) {
9649
0
      if (p->family == AF_INET &&
9650
0
          (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9651
0
           !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9652
0
        if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
9653
0
          json_object_string_addf(
9654
0
            json_net, "nextHop", "%pI4",
9655
0
            &attr->mp_nexthop_global_in);
9656
0
        else
9657
0
          json_object_string_addf(
9658
0
            json_net, "nextHop", "%pI4",
9659
0
            &attr->nexthop);
9660
0
      } else if (p->family == AF_INET6 ||
9661
0
           BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9662
0
        json_object_string_addf(
9663
0
          json_net, "nextHopGlobal", "%pI6",
9664
0
          &attr->mp_nexthop_global);
9665
0
      } else if (p->family == AF_EVPN &&
9666
0
           !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9667
0
        json_object_string_addf(
9668
0
          json_net, "nextHop", "%pI4",
9669
0
          &attr->mp_nexthop_global_in);
9670
0
      }
9671
9672
0
      if (attr->flag
9673
0
          & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9674
0
        json_object_int_add(json_net, "metric",
9675
0
                attr->med);
9676
9677
0
      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9678
0
        json_object_int_add(json_net, "locPrf",
9679
0
                attr->local_pref);
9680
9681
0
      json_object_int_add(json_net, "weight", attr->weight);
9682
9683
      /* Print aspath */
9684
0
      if (attr->aspath)
9685
0
        json_object_string_add(json_net, "path",
9686
0
                   attr->aspath->str);
9687
9688
      /* Print origin */
9689
#if CONFDATE > 20231208
9690
CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9691
#endif
9692
0
      json_object_string_add(json_net, "bgpOriginCode",
9693
0
                 bgp_origin_str[attr->origin]);
9694
0
      json_object_string_add(
9695
0
        json_net, "origin",
9696
0
        bgp_origin_long_str[attr->origin]);
9697
0
    } else {
9698
0
      if (p->family == AF_INET &&
9699
0
          (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9700
0
           safi == SAFI_EVPN ||
9701
0
           !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9702
0
        if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9703
0
            || safi == SAFI_EVPN)
9704
0
          vty_out(vty, "%-16pI4",
9705
0
            &attr->mp_nexthop_global_in);
9706
0
        else if (wide)
9707
0
          vty_out(vty, "%-41pI4", &attr->nexthop);
9708
0
        else
9709
0
          vty_out(vty, "%-16pI4", &attr->nexthop);
9710
0
      } else if (p->family == AF_INET6 ||
9711
0
           BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9712
0
        len = vty_out(vty, "%pI6",
9713
0
                &attr->mp_nexthop_global);
9714
0
        len = wide ? (41 - len) : (16 - len);
9715
0
        if (len < 1)
9716
0
          vty_out(vty, "\n%*s", 36, " ");
9717
0
        else
9718
0
          vty_out(vty, "%*s", len, " ");
9719
0
      }
9720
0
      if (attr->flag
9721
0
          & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9722
0
        if (wide)
9723
0
          vty_out(vty, "%7u", attr->med);
9724
0
        else
9725
0
          vty_out(vty, "%10u", attr->med);
9726
0
      else if (wide)
9727
0
        vty_out(vty, "       ");
9728
0
      else
9729
0
        vty_out(vty, "          ");
9730
9731
0
      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9732
0
        vty_out(vty, "%7u", attr->local_pref);
9733
0
      else
9734
0
        vty_out(vty, "       ");
9735
9736
0
      vty_out(vty, "%7u ", attr->weight);
9737
9738
      /* Print aspath */
9739
0
      if (attr->aspath)
9740
0
        aspath_print_vty(vty, attr->aspath);
9741
9742
      /* Print origin */
9743
0
      vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9744
0
    }
9745
0
  }
9746
0
  if (use_json) {
9747
0
    struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9748
9749
#if CONFDATE > 20231208
9750
CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9751
#endif
9752
0
    json_object_boolean_true_add(json_status, "*");
9753
0
    json_object_boolean_true_add(json_status, ">");
9754
0
    json_object_boolean_true_add(json_net, "valid");
9755
0
    json_object_boolean_true_add(json_net, "best");
9756
9757
0
    if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
9758
0
      json_object_boolean_true_add(json_status, "=");
9759
0
      json_object_boolean_true_add(json_net, "multipath");
9760
0
    }
9761
0
    json_object_object_add(json_net, "appliedStatusSymbols",
9762
0
               json_status);
9763
0
    json_object_object_addf(json_ar, json_net, "%pFX", p);
9764
0
  } else
9765
0
    vty_out(vty, "\n");
9766
0
}
9767
9768
void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9769
           struct bgp_path_info *path, int display, safi_t safi,
9770
           json_object *json)
9771
0
{
9772
0
  json_object *json_out = NULL;
9773
0
  struct attr *attr;
9774
0
  mpls_label_t label = MPLS_INVALID_LABEL;
9775
9776
0
  if (!path->extra)
9777
0
    return;
9778
9779
0
  if (json)
9780
0
    json_out = json_object_new_object();
9781
9782
  /* short status lead text */
9783
0
  route_vty_short_status_out(vty, path, p, json_out);
9784
9785
  /* print prefix and mask */
9786
0
  if (json == NULL) {
9787
0
    if (!display)
9788
0
      route_vty_out_route(path->net, p, vty, NULL, false);
9789
0
    else
9790
0
      vty_out(vty, "%*s", 17, " ");
9791
0
  }
9792
9793
  /* Print attribute */
9794
0
  attr = path->attr;
9795
0
  if (((p->family == AF_INET) &&
9796
0
       ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9797
0
      (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9798
0
      (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9799
0
    if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9800
0
        || safi == SAFI_EVPN) {
9801
0
      if (json)
9802
0
        json_object_string_addf(
9803
0
          json_out, "mpNexthopGlobalIn", "%pI4",
9804
0
          &attr->mp_nexthop_global_in);
9805
0
      else
9806
0
        vty_out(vty, "%-16pI4",
9807
0
          &attr->mp_nexthop_global_in);
9808
0
    } else {
9809
0
      if (json)
9810
0
        json_object_string_addf(json_out, "nexthop",
9811
0
              "%pI4", &attr->nexthop);
9812
0
      else
9813
0
        vty_out(vty, "%-16pI4", &attr->nexthop);
9814
0
    }
9815
0
  } else if (((p->family == AF_INET6) &&
9816
0
        ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9817
0
       (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9818
0
       (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9819
0
    char buf_a[512];
9820
9821
0
    if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9822
0
      if (json)
9823
0
        json_object_string_addf(
9824
0
          json_out, "mpNexthopGlobalIn", "%pI6",
9825
0
          &attr->mp_nexthop_global);
9826
0
      else
9827
0
        vty_out(vty, "%s",
9828
0
          inet_ntop(AF_INET6,
9829
0
              &attr->mp_nexthop_global,
9830
0
              buf_a, sizeof(buf_a)));
9831
0
    } else if (attr->mp_nexthop_len
9832
0
         == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9833
0
      snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9834
0
           &attr->mp_nexthop_global,
9835
0
           &attr->mp_nexthop_local);
9836
0
      if (json)
9837
0
        json_object_string_add(json_out,
9838
0
                   "mpNexthopGlobalLocal",
9839
0
                   buf_a);
9840
0
      else
9841
0
        vty_out(vty, "%s", buf_a);
9842
0
    }
9843
0
  }
9844
9845
0
  label = decode_label(&path->extra->label[0]);
9846
9847
0
  if (bgp_is_valid_label(&label)) {
9848
0
    if (json) {
9849
0
      json_object_int_add(json_out, "notag", label);
9850
0
      json_object_array_add(json, json_out);
9851
0
    } else {
9852
0
      vty_out(vty, "notag/%d", label);
9853
0
      vty_out(vty, "\n");
9854
0
    }
9855
0
  } else if (!json)
9856
0
    vty_out(vty, "\n");
9857
0
}
9858
9859
void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9860
         struct bgp_path_info *path, int display,
9861
         json_object *json_paths)
9862
0
{
9863
0
  struct attr *attr;
9864
0
  json_object *json_path = NULL;
9865
0
  json_object *json_nexthop = NULL;
9866
0
  json_object *json_overlay = NULL;
9867
9868
0
  if (!path->extra)
9869
0
    return;
9870
9871
0
  if (json_paths) {
9872
0
    json_path = json_object_new_object();
9873
0
    json_overlay = json_object_new_object();
9874
0
    json_nexthop = json_object_new_object();
9875
0
  }
9876
9877
  /* short status lead text */
9878
0
  route_vty_short_status_out(vty, path, p, json_path);
9879
9880
  /* print prefix and mask */
9881
0
  if (!display)
9882
0
    route_vty_out_route(path->net, p, vty, json_path, false);
9883
0
  else
9884
0
    vty_out(vty, "%*s", 17, " ");
9885
9886
  /* Print attribute */
9887
0
  attr = path->attr;
9888
0
  int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9889
9890
0
  switch (af) {
9891
0
  case AF_INET:
9892
0
    if (!json_path) {
9893
0
      vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
9894
0
    } else {
9895
0
      json_object_string_addf(json_nexthop, "ip", "%pI4",
9896
0
            &attr->mp_nexthop_global_in);
9897
9898
0
      json_object_string_add(json_nexthop, "afi", "ipv4");
9899
9900
0
      json_object_object_add(json_path, "nexthop",
9901
0
                 json_nexthop);
9902
0
    }
9903
0
    break;
9904
0
  case AF_INET6:
9905
0
    if (!json_path) {
9906
0
      vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9907
0
        &attr->mp_nexthop_local);
9908
0
    } else {
9909
0
      json_object_string_addf(json_nexthop, "ipv6Global",
9910
0
            "%pI6",
9911
0
            &attr->mp_nexthop_global);
9912
9913
0
      json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9914
0
            "%pI6",
9915
0
            &attr->mp_nexthop_local);
9916
9917
0
      json_object_string_add(json_nexthop, "afi", "ipv6");
9918
9919
0
      json_object_object_add(json_path, "nexthop",
9920
0
                 json_nexthop);
9921
0
    }
9922
0
    break;
9923
0
  default:
9924
0
    if (!json_path) {
9925
0
      vty_out(vty, "?");
9926
0
    } else {
9927
0
      json_object_string_add(json_nexthop, "error",
9928
0
                 "Unsupported address-family");
9929
0
    }
9930
0
  }
9931
9932
0
  const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9933
9934
0
  if (!json_path)
9935
0
    vty_out(vty, "/%pIA", &eo->gw_ip);
9936
0
  else
9937
0
    json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
9938
9939
0
  if (bgp_attr_get_ecommunity(attr)) {
9940
0
    char *mac = NULL;
9941
0
    struct ecommunity_val *routermac = ecommunity_lookup(
9942
0
      bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
9943
0
      ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9944
9945
0
    if (routermac)
9946
0
      mac = ecom_mac2str((char *)routermac->val);
9947
0
    if (mac) {
9948
0
      if (!json_path) {
9949
0
        vty_out(vty, "/%s", mac);
9950
0
      } else {
9951
0
        json_object_string_add(json_overlay, "rmac",
9952
0
                   mac);
9953
0
      }
9954
0
      XFREE(MTYPE_TMP, mac);
9955
0
    }
9956
0
  }
9957
9958
0
  if (!json_path) {
9959
0
    vty_out(vty, "\n");
9960
0
  } else {
9961
0
    json_object_object_add(json_path, "overlay", json_overlay);
9962
9963
0
    json_object_array_add(json_paths, json_path);
9964
0
  }
9965
0
}
9966
9967
/* dampening route */
9968
static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9969
             struct bgp_path_info *path, int display,
9970
             afi_t afi, safi_t safi, bool use_json,
9971
             json_object *json_paths)
9972
0
{
9973
0
  struct attr *attr = path->attr;
9974
0
  int len;
9975
0
  char timebuf[BGP_UPTIME_LEN];
9976
0
  json_object *json_path = NULL;
9977
9978
0
  if (use_json)
9979
0
    json_path = json_object_new_object();
9980
9981
  /* short status lead text */
9982
0
  route_vty_short_status_out(vty, path, p, json_path);
9983
9984
  /* print prefix and mask */
9985
0
  if (!use_json) {
9986
0
    if (!display)
9987
0
      route_vty_out_route(path->net, p, vty, NULL, false);
9988
0
    else
9989
0
      vty_out(vty, "%*s", 17, " ");
9990
9991
0
    len = vty_out(vty, "%s", path->peer->host);
9992
0
    len = 17 - len;
9993
9994
0
    if (len < 1)
9995
0
      vty_out(vty, "\n%*s", 34, " ");
9996
0
    else
9997
0
      vty_out(vty, "%*s", len, " ");
9998
9999
0
    vty_out(vty, "%s ",
10000
0
      bgp_damp_reuse_time_vty(vty, path, timebuf,
10001
0
            BGP_UPTIME_LEN, afi, safi,
10002
0
            use_json, NULL));
10003
10004
0
    if (attr->aspath)
10005
0
      aspath_print_vty(vty, attr->aspath);
10006
10007
0
    vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10008
10009
0
    vty_out(vty, "\n");
10010
0
  } else {
10011
0
    bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
10012
0
          safi, use_json, json_path);
10013
10014
0
    if (attr->aspath)
10015
0
      json_object_string_add(json_path, "asPath",
10016
0
                 attr->aspath->str);
10017
10018
0
    json_object_string_add(json_path, "origin",
10019
0
               bgp_origin_str[attr->origin]);
10020
0
    json_object_string_add(json_path, "peerHost", path->peer->host);
10021
10022
0
    json_object_array_add(json_paths, json_path);
10023
0
  }
10024
0
}
10025
10026
/* flap route */
10027
static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10028
             struct bgp_path_info *path, int display,
10029
             afi_t afi, safi_t safi, bool use_json,
10030
             json_object *json_paths)
10031
0
{
10032
0
  struct attr *attr = path->attr;
10033
0
  struct bgp_damp_info *bdi;
10034
0
  char timebuf[BGP_UPTIME_LEN];
10035
0
  int len;
10036
0
  json_object *json_path = NULL;
10037
10038
0
  if (!path->extra)
10039
0
    return;
10040
10041
0
  if (use_json)
10042
0
    json_path = json_object_new_object();
10043
10044
0
  bdi = path->extra->damp_info;
10045
10046
  /* short status lead text */
10047
0
  route_vty_short_status_out(vty, path, p, json_path);
10048
10049
0
  if (!use_json) {
10050
0
    if (!display)
10051
0
      route_vty_out_route(path->net, p, vty, NULL, false);
10052
0
    else
10053
0
      vty_out(vty, "%*s", 17, " ");
10054
10055
0
    len = vty_out(vty, "%s", path->peer->host);
10056
0
    len = 16 - len;
10057
0
    if (len < 1)
10058
0
      vty_out(vty, "\n%*s", 33, " ");
10059
0
    else
10060
0
      vty_out(vty, "%*s", len, " ");
10061
10062
0
    len = vty_out(vty, "%d", bdi->flap);
10063
0
    len = 5 - len;
10064
0
    if (len < 1)
10065
0
      vty_out(vty, " ");
10066
0
    else
10067
0
      vty_out(vty, "%*s", len, " ");
10068
10069
0
    vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10070
0
            BGP_UPTIME_LEN, 0, NULL));
10071
10072
0
    if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10073
0
        && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10074
0
      vty_out(vty, "%s ",
10075
0
        bgp_damp_reuse_time_vty(vty, path, timebuf,
10076
0
              BGP_UPTIME_LEN, afi,
10077
0
              safi, use_json, NULL));
10078
0
    else
10079
0
      vty_out(vty, "%*s ", 8, " ");
10080
10081
0
    if (attr->aspath)
10082
0
      aspath_print_vty(vty, attr->aspath);
10083
10084
0
    vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10085
10086
0
    vty_out(vty, "\n");
10087
0
  } else {
10088
0
    json_object_string_add(json_path, "peerHost", path->peer->host);
10089
0
    json_object_int_add(json_path, "bdiFlap", bdi->flap);
10090
10091
0
    peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10092
0
          json_path);
10093
10094
0
    if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10095
0
        && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10096
0
      bgp_damp_reuse_time_vty(vty, path, timebuf,
10097
0
            BGP_UPTIME_LEN, afi, safi,
10098
0
            use_json, json_path);
10099
10100
0
    if (attr->aspath)
10101
0
      json_object_string_add(json_path, "asPath",
10102
0
                 attr->aspath->str);
10103
10104
0
    json_object_string_add(json_path, "origin",
10105
0
               bgp_origin_str[attr->origin]);
10106
10107
0
    json_object_array_add(json_paths, json_path);
10108
0
  }
10109
0
}
10110
10111
static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10112
          int *first, const char *header,
10113
          json_object *json_adv_to)
10114
0
{
10115
0
  json_object *json_peer = NULL;
10116
10117
0
  if (json_adv_to) {
10118
    /* 'advertised-to' is a dictionary of peers we have advertised
10119
     * this
10120
     * prefix too.  The key is the peer's IP or swpX, the value is
10121
     * the
10122
     * hostname if we know it and "" if not.
10123
     */
10124
0
    json_peer = json_object_new_object();
10125
10126
0
    if (peer->hostname)
10127
0
      json_object_string_add(json_peer, "hostname",
10128
0
                 peer->hostname);
10129
10130
0
    if (peer->conf_if)
10131
0
      json_object_object_add(json_adv_to, peer->conf_if,
10132
0
                 json_peer);
10133
0
    else
10134
0
      json_object_object_addf(json_adv_to, json_peer, "%pSU",
10135
0
            &peer->su);
10136
0
  } else {
10137
0
    if (*first) {
10138
0
      vty_out(vty, "%s", header);
10139
0
      *first = 0;
10140
0
    }
10141
10142
0
    if (peer->hostname
10143
0
        && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
10144
0
      if (peer->conf_if)
10145
0
        vty_out(vty, " %s(%s)", peer->hostname,
10146
0
          peer->conf_if);
10147
0
      else
10148
0
        vty_out(vty, " %s(%pSU)", peer->hostname,
10149
0
          &peer->su);
10150
0
    } else {
10151
0
      if (peer->conf_if)
10152
0
        vty_out(vty, " %s", peer->conf_if);
10153
0
      else
10154
0
        vty_out(vty, " %pSU", &peer->su);
10155
0
    }
10156
0
  }
10157
0
}
10158
10159
static void route_vty_out_tx_ids(struct vty *vty,
10160
         struct bgp_addpath_info_data *d)
10161
0
{
10162
0
  int i;
10163
10164
0
  for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10165
0
    vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10166
0
      d->addpath_tx_id[i],
10167
0
      i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10168
0
  }
10169
0
}
10170
10171
static void route_vty_out_detail_es_info(struct vty *vty,
10172
           struct bgp_path_info *pi,
10173
           struct attr *attr,
10174
           json_object *json_path)
10175
0
{
10176
0
  char esi_buf[ESI_STR_LEN];
10177
0
  bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10178
0
  bool peer_router = !!CHECK_FLAG(attr->es_flags,
10179
0
      ATTR_ES_PEER_ROUTER);
10180
0
  bool peer_active = !!CHECK_FLAG(attr->es_flags,
10181
0
      ATTR_ES_PEER_ACTIVE);
10182
0
  bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10183
0
      ATTR_ES_PEER_PROXY);
10184
0
  esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10185
0
  if (json_path) {
10186
0
    json_object *json_es_info = NULL;
10187
10188
0
    json_object_string_add(
10189
0
        json_path, "esi",
10190
0
        esi_buf);
10191
0
    if (es_local || bgp_evpn_attr_is_sync(attr)) {
10192
0
      json_es_info = json_object_new_object();
10193
0
      if (es_local)
10194
0
        json_object_boolean_true_add(
10195
0
            json_es_info, "localEs");
10196
0
      if (peer_active)
10197
0
        json_object_boolean_true_add(
10198
0
            json_es_info, "peerActive");
10199
0
      if (peer_proxy)
10200
0
        json_object_boolean_true_add(
10201
0
            json_es_info, "peerProxy");
10202
0
      if (peer_router)
10203
0
        json_object_boolean_true_add(
10204
0
            json_es_info, "peerRouter");
10205
0
      if (attr->mm_sync_seqnum)
10206
0
        json_object_int_add(
10207
0
            json_es_info, "peerSeq",
10208
0
            attr->mm_sync_seqnum);
10209
0
      json_object_object_add(
10210
0
          json_path, "es_info",
10211
0
          json_es_info);
10212
0
    }
10213
0
  } else {
10214
0
    if (bgp_evpn_attr_is_sync(attr))
10215
0
      vty_out(vty,
10216
0
          "      ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10217
0
          esi_buf,
10218
0
          es_local ? "local-es":"",
10219
0
          peer_proxy ? "proxy " : "",
10220
0
          peer_active ? "active ":"",
10221
0
          peer_router ? "router ":"",
10222
0
          attr->mm_sync_seqnum);
10223
0
    else
10224
0
      vty_out(vty, "      ESI %s %s\n",
10225
0
          esi_buf,
10226
0
          es_local ? "local-es":"");
10227
0
  }
10228
0
}
10229
10230
void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
10231
        const struct prefix *p, struct bgp_path_info *path,
10232
        afi_t afi, safi_t safi,
10233
        enum rpki_states rpki_curr_state,
10234
        json_object *json_paths)
10235
0
{
10236
0
  char buf[INET6_ADDRSTRLEN];
10237
0
  char tag_buf[30];
10238
0
  struct attr *attr = path->attr;
10239
0
  time_t tbuf;
10240
0
  json_object *json_bestpath = NULL;
10241
0
  json_object *json_cluster_list = NULL;
10242
0
  json_object *json_cluster_list_list = NULL;
10243
0
  json_object *json_ext_community = NULL;
10244
0
  json_object *json_last_update = NULL;
10245
0
  json_object *json_pmsi = NULL;
10246
0
  json_object *json_nexthop_global = NULL;
10247
0
  json_object *json_nexthop_ll = NULL;
10248
0
  json_object *json_nexthops = NULL;
10249
0
  json_object *json_path = NULL;
10250
0
  json_object *json_peer = NULL;
10251
0
  json_object *json_string = NULL;
10252
0
  json_object *json_adv_to = NULL;
10253
0
  int first = 0;
10254
0
  struct listnode *node, *nnode;
10255
0
  struct peer *peer;
10256
0
  bool addpath_capable;
10257
0
  int has_adj;
10258
0
  unsigned int first_as;
10259
0
  bool nexthop_self =
10260
0
    CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
10261
0
  int i;
10262
0
  char *nexthop_hostname =
10263
0
    bgp_nexthop_hostname(path->peer, path->nexthop);
10264
0
  uint32_t ttl = 0;
10265
0
  uint32_t bos = 0;
10266
0
  uint32_t exp = 0;
10267
0
  mpls_label_t label = MPLS_INVALID_LABEL;
10268
0
  tag_buf[0] = '\0';
10269
0
  struct bgp_path_info *bpi_ultimate =
10270
0
    bgp_get_imported_bpi_ultimate(path);
10271
10272
0
  if (json_paths) {
10273
0
    json_path = json_object_new_object();
10274
0
    json_peer = json_object_new_object();
10275
0
    json_nexthop_global = json_object_new_object();
10276
0
  }
10277
10278
0
  if (safi == SAFI_EVPN) {
10279
0
    if (!json_paths)
10280
0
      vty_out(vty, "  Route %pFX", p);
10281
0
  }
10282
10283
0
  if (path->extra) {
10284
0
    if (path->extra && path->extra->num_labels) {
10285
0
      bgp_evpn_label2str(path->extra->label,
10286
0
             path->extra->num_labels, tag_buf,
10287
0
             sizeof(tag_buf));
10288
0
    }
10289
0
    if (safi == SAFI_EVPN) {
10290
0
      if (!json_paths) {
10291
0
        if (tag_buf[0] != '\0')
10292
0
          vty_out(vty, " VNI %s", tag_buf);
10293
0
      } else {
10294
0
        if (tag_buf[0])
10295
0
          json_object_string_add(json_path, "vni",
10296
0
                     tag_buf);
10297
0
      }
10298
0
    }
10299
0
  }
10300
10301
0
  if (safi == SAFI_EVPN
10302
0
      && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10303
0
    char gwip_buf[INET6_ADDRSTRLEN];
10304
10305
0
    ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10306
0
         sizeof(gwip_buf));
10307
10308
0
    if (json_paths)
10309
0
      json_object_string_add(json_path, "gatewayIP",
10310
0
                 gwip_buf);
10311
0
    else
10312
0
      vty_out(vty, " Gateway IP %s", gwip_buf);
10313
0
  }
10314
10315
0
  if (safi == SAFI_EVPN && !json_path)
10316
0
    vty_out(vty, "\n");
10317
10318
10319
0
  if (path->extra && path->extra->parent && !json_paths) {
10320
0
    struct bgp_path_info *parent_ri;
10321
0
    struct bgp_dest *dest, *pdest;
10322
10323
0
    parent_ri = (struct bgp_path_info *)path->extra->parent;
10324
0
    dest = parent_ri->net;
10325
0
    if (dest && dest->pdest) {
10326
0
      pdest = dest->pdest;
10327
0
      if (is_pi_family_evpn(parent_ri)) {
10328
0
        vty_out(vty, "  Imported from ");
10329
0
        vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
10330
0
          (struct prefix_rd *)bgp_dest_get_prefix(
10331
0
            pdest));
10332
0
        vty_out(vty, ":%pFX, VNI %s",
10333
0
          (struct prefix_evpn *)
10334
0
            bgp_dest_get_prefix(dest),
10335
0
          tag_buf);
10336
0
        if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
10337
0
          vty_out(vty, ", L3NHG %s",
10338
0
            CHECK_FLAG(
10339
0
              attr->es_flags,
10340
0
              ATTR_ES_L3_NHG_ACTIVE)
10341
0
              ? "active"
10342
0
              : "inactive");
10343
0
        vty_out(vty, "\n");
10344
10345
0
      } else {
10346
0
        vty_out(vty, "  Imported from ");
10347
0
        vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
10348
0
          (struct prefix_rd *)bgp_dest_get_prefix(
10349
0
            pdest));
10350
0
        vty_out(vty, ":%pFX\n",
10351
0
          (struct prefix_evpn *)
10352
0
            bgp_dest_get_prefix(dest));
10353
0
      }
10354
0
    }
10355
0
  }
10356
10357
  /* Line1 display AS-path, Aggregator */
10358
0
  if (attr->aspath) {
10359
0
    if (json_paths) {
10360
0
      if (!attr->aspath->json)
10361
0
        aspath_str_update(attr->aspath, true);
10362
0
      json_object_lock(attr->aspath->json);
10363
0
      json_object_object_add(json_path, "aspath",
10364
0
                 attr->aspath->json);
10365
0
    } else {
10366
0
      if (attr->aspath->segments)
10367
0
        vty_out(vty, "  %s", attr->aspath->str);
10368
0
      else
10369
0
        vty_out(vty, "  Local");
10370
0
    }
10371
0
  }
10372
10373
0
  if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10374
0
    if (json_paths)
10375
0
      json_object_boolean_true_add(json_path, "removed");
10376
0
    else
10377
0
      vty_out(vty, ", (removed)");
10378
0
  }
10379
10380
0
  if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10381
0
    if (json_paths)
10382
0
      json_object_boolean_true_add(json_path, "stale");
10383
0
    else
10384
0
      vty_out(vty, ", (stale)");
10385
0
  }
10386
10387
0
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10388
0
    if (json_paths) {
10389
0
      json_object_int_add(json_path, "aggregatorAs",
10390
0
              attr->aggregator_as);
10391
0
      json_object_string_addf(json_path, "aggregatorId",
10392
0
            "%pI4", &attr->aggregator_addr);
10393
0
    } else {
10394
0
      vty_out(vty, ", (aggregated by %u %pI4)",
10395
0
        attr->aggregator_as, &attr->aggregator_addr);
10396
0
    }
10397
0
  }
10398
10399
0
  if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10400
0
           PEER_FLAG_REFLECTOR_CLIENT)) {
10401
0
    if (json_paths)
10402
0
      json_object_boolean_true_add(json_path,
10403
0
                 "rxedFromRrClient");
10404
0
    else
10405
0
      vty_out(vty, ", (Received from a RR-client)");
10406
0
  }
10407
10408
0
  if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10409
0
           PEER_FLAG_RSERVER_CLIENT)) {
10410
0
    if (json_paths)
10411
0
      json_object_boolean_true_add(json_path,
10412
0
                 "rxedFromRsClient");
10413
0
    else
10414
0
      vty_out(vty, ", (Received from a RS-client)");
10415
0
  }
10416
10417
0
  if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10418
0
    if (json_paths)
10419
0
      json_object_boolean_true_add(json_path,
10420
0
                 "dampeningHistoryEntry");
10421
0
    else
10422
0
      vty_out(vty, ", (history entry)");
10423
0
  } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10424
0
    if (json_paths)
10425
0
      json_object_boolean_true_add(json_path,
10426
0
                 "dampeningSuppressed");
10427
0
    else
10428
0
      vty_out(vty, ", (suppressed due to dampening)");
10429
0
  }
10430
10431
0
  if (!json_paths)
10432
0
    vty_out(vty, "\n");
10433
10434
  /* Line2 display Next-hop, Neighbor, Router-id */
10435
  /* Display the nexthop */
10436
10437
0
  if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10438
0
       p->family == AF_EVPN) &&
10439
0
      (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10440
0
       !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
10441
0
    if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10442
0
        || safi == SAFI_EVPN) {
10443
0
      if (json_paths) {
10444
0
        json_object_string_addf(
10445
0
          json_nexthop_global, "ip", "%pI4",
10446
0
          &attr->mp_nexthop_global_in);
10447
10448
0
        if (path->peer->hostname)
10449
0
          json_object_string_add(
10450
0
            json_nexthop_global, "hostname",
10451
0
            path->peer->hostname);
10452
0
      } else {
10453
0
        if (nexthop_hostname)
10454
0
          vty_out(vty, "    %pI4(%s)",
10455
0
            &attr->mp_nexthop_global_in,
10456
0
            nexthop_hostname);
10457
0
        else
10458
0
          vty_out(vty, "    %pI4",
10459
0
            &attr->mp_nexthop_global_in);
10460
0
      }
10461
0
    } else {
10462
0
      if (json_paths) {
10463
0
        json_object_string_addf(json_nexthop_global,
10464
0
              "ip", "%pI4",
10465
0
              &attr->nexthop);
10466
10467
0
        if (path->peer->hostname)
10468
0
          json_object_string_add(
10469
0
            json_nexthop_global, "hostname",
10470
0
            path->peer->hostname);
10471
0
      } else {
10472
0
        if (nexthop_hostname)
10473
0
          vty_out(vty, "    %pI4(%s)",
10474
0
            &attr->nexthop,
10475
0
            nexthop_hostname);
10476
0
        else
10477
0
          vty_out(vty, "    %pI4",
10478
0
            &attr->nexthop);
10479
0
      }
10480
0
    }
10481
10482
0
    if (json_paths)
10483
0
      json_object_string_add(json_nexthop_global, "afi",
10484
0
                 "ipv4");
10485
0
  } else {
10486
0
    if (json_paths) {
10487
0
      json_object_string_addf(json_nexthop_global, "ip",
10488
0
            "%pI6",
10489
0
            &attr->mp_nexthop_global);
10490
10491
0
      if (path->peer->hostname)
10492
0
        json_object_string_add(json_nexthop_global,
10493
0
                   "hostname",
10494
0
                   path->peer->hostname);
10495
10496
0
      json_object_string_add(json_nexthop_global, "afi",
10497
0
                 "ipv6");
10498
0
      json_object_string_add(json_nexthop_global, "scope",
10499
0
                 "global");
10500
0
    } else {
10501
0
      if (nexthop_hostname)
10502
0
        vty_out(vty, "    %pI6(%s)",
10503
0
          &attr->mp_nexthop_global,
10504
0
          nexthop_hostname);
10505
0
      else
10506
0
        vty_out(vty, "    %pI6",
10507
0
          &attr->mp_nexthop_global);
10508
0
    }
10509
0
  }
10510
10511
  /* Display the IGP cost or 'inaccessible' */
10512
0
  if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
10513
0
    bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10514
10515
0
    if (json_paths) {
10516
0
      json_object_boolean_false_add(json_nexthop_global,
10517
0
                  "accessible");
10518
0
      json_object_boolean_add(json_nexthop_global,
10519
0
            "importCheckEnabled", import);
10520
0
    } else {
10521
0
      vty_out(vty, " (inaccessible%s)",
10522
0
        import ? ", import-check enabled" : "");
10523
0
    }
10524
0
  } else {
10525
0
    if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
10526
0
      if (json_paths)
10527
0
        json_object_int_add(
10528
0
          json_nexthop_global, "metric",
10529
0
          bpi_ultimate->extra->igpmetric);
10530
0
      else
10531
0
        vty_out(vty, " (metric %u)",
10532
0
          bpi_ultimate->extra->igpmetric);
10533
0
    }
10534
10535
    /* IGP cost is 0, display this only for json */
10536
0
    else {
10537
0
      if (json_paths)
10538
0
        json_object_int_add(json_nexthop_global,
10539
0
                "metric", 0);
10540
0
    }
10541
10542
0
    if (json_paths)
10543
0
      json_object_boolean_true_add(json_nexthop_global,
10544
0
                 "accessible");
10545
0
  }
10546
10547
  /* Display peer "from" output */
10548
  /* This path was originated locally */
10549
0
  if (path->peer == bgp->peer_self) {
10550
10551
0
    if (safi == SAFI_EVPN || (p->family == AF_INET &&
10552
0
            !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
10553
0
      if (json_paths)
10554
0
        json_object_string_add(json_peer, "peerId",
10555
0
                   "0.0.0.0");
10556
0
      else
10557
0
        vty_out(vty, " from 0.0.0.0 ");
10558
0
    } else {
10559
0
      if (json_paths)
10560
0
        json_object_string_add(json_peer, "peerId",
10561
0
                   "::");
10562
0
      else
10563
0
        vty_out(vty, " from :: ");
10564
0
    }
10565
10566
0
    if (json_paths)
10567
0
      json_object_string_addf(json_peer, "routerId", "%pI4",
10568
0
            &bgp->router_id);
10569
0
    else
10570
0
      vty_out(vty, "(%pI4)", &bgp->router_id);
10571
0
  }
10572
10573
  /* We RXed this path from one of our peers */
10574
0
  else {
10575
10576
0
    if (json_paths) {
10577
0
      json_object_string_addf(json_peer, "peerId", "%pSU",
10578
0
            &path->peer->su);
10579
0
      json_object_string_addf(json_peer, "routerId", "%pI4",
10580
0
            &path->peer->remote_id);
10581
10582
0
      if (path->peer->hostname)
10583
0
        json_object_string_add(json_peer, "hostname",
10584
0
                   path->peer->hostname);
10585
10586
0
      if (path->peer->domainname)
10587
0
        json_object_string_add(json_peer, "domainname",
10588
0
                   path->peer->domainname);
10589
10590
0
      if (path->peer->conf_if)
10591
0
        json_object_string_add(json_peer, "interface",
10592
0
                   path->peer->conf_if);
10593
0
    } else {
10594
0
      if (path->peer->conf_if) {
10595
0
        if (path->peer->hostname
10596
0
            && CHECK_FLAG(path->peer->bgp->flags,
10597
0
              BGP_FLAG_SHOW_HOSTNAME))
10598
0
          vty_out(vty, " from %s(%s)",
10599
0
            path->peer->hostname,
10600
0
            path->peer->conf_if);
10601
0
        else
10602
0
          vty_out(vty, " from %s",
10603
0
            path->peer->conf_if);
10604
0
      } else {
10605
0
        if (path->peer->hostname
10606
0
            && CHECK_FLAG(path->peer->bgp->flags,
10607
0
              BGP_FLAG_SHOW_HOSTNAME))
10608
0
          vty_out(vty, " from %s(%s)",
10609
0
            path->peer->hostname,
10610
0
            path->peer->host);
10611
0
        else
10612
0
          vty_out(vty, " from %pSU",
10613
0
            &path->peer->su);
10614
0
      }
10615
10616
0
      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10617
0
        vty_out(vty, " (%pI4)", &attr->originator_id);
10618
0
      else
10619
0
        vty_out(vty, " (%pI4)", &path->peer->remote_id);
10620
0
    }
10621
0
  }
10622
10623
  /*
10624
   * Note when vrfid of nexthop is different from that of prefix
10625
   */
10626
0
  if (path->extra && path->extra->bgp_orig) {
10627
0
    vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
10628
10629
0
    if (json_paths) {
10630
0
      const char *vn;
10631
10632
0
      if (path->extra->bgp_orig->inst_type
10633
0
          == BGP_INSTANCE_TYPE_DEFAULT)
10634
0
        vn = VRF_DEFAULT_NAME;
10635
0
      else
10636
0
        vn = path->extra->bgp_orig->name;
10637
10638
0
      json_object_string_add(json_path, "nhVrfName", vn);
10639
10640
0
      if (nexthop_vrfid == VRF_UNKNOWN) {
10641
0
        json_object_int_add(json_path, "nhVrfId", -1);
10642
0
      } else {
10643
0
        json_object_int_add(json_path, "nhVrfId",
10644
0
                (int)nexthop_vrfid);
10645
0
      }
10646
0
    } else {
10647
0
      if (nexthop_vrfid == VRF_UNKNOWN)
10648
0
        vty_out(vty, " vrf ?");
10649
0
      else {
10650
0
        struct vrf *vrf;
10651
10652
0
        vrf = vrf_lookup_by_id(nexthop_vrfid);
10653
0
        vty_out(vty, " vrf %s(%u)",
10654
0
          VRF_LOGNAME(vrf), nexthop_vrfid);
10655
0
      }
10656
0
    }
10657
0
  }
10658
10659
0
  if (nexthop_self) {
10660
0
    if (json_paths) {
10661
0
      json_object_boolean_true_add(json_path,
10662
0
                 "announceNexthopSelf");
10663
0
    } else {
10664
0
      vty_out(vty, " announce-nh-self");
10665
0
    }
10666
0
  }
10667
10668
0
  if (!json_paths)
10669
0
    vty_out(vty, "\n");
10670
10671
  /* display the link-local nexthop */
10672
0
  if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10673
0
    if (json_paths) {
10674
0
      json_nexthop_ll = json_object_new_object();
10675
0
      json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10676
0
            &attr->mp_nexthop_local);
10677
10678
0
      if (path->peer->hostname)
10679
0
        json_object_string_add(json_nexthop_ll,
10680
0
                   "hostname",
10681
0
                   path->peer->hostname);
10682
10683
0
      json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10684
0
      json_object_string_add(json_nexthop_ll, "scope",
10685
0
                 "link-local");
10686
10687
0
      json_object_boolean_true_add(json_nexthop_ll,
10688
0
                 "accessible");
10689
10690
0
      if (!attr->mp_nexthop_prefer_global)
10691
0
        json_object_boolean_true_add(json_nexthop_ll,
10692
0
                   "used");
10693
0
      else
10694
0
        json_object_boolean_true_add(
10695
0
          json_nexthop_global, "used");
10696
0
    } else {
10697
0
      vty_out(vty, "    (%s) %s\n",
10698
0
        inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10699
0
            buf, INET6_ADDRSTRLEN),
10700
0
        attr->mp_nexthop_prefer_global
10701
0
          ? "(prefer-global)"
10702
0
          : "(used)");
10703
0
    }
10704
0
  }
10705
  /* If we do not have a link-local nexthop then we must flag the
10706
     global as "used" */
10707
0
  else {
10708
0
    if (json_paths)
10709
0
      json_object_boolean_true_add(json_nexthop_global,
10710
0
                 "used");
10711
0
  }
10712
10713
0
  if (safi == SAFI_EVPN &&
10714
0
      bgp_evpn_is_esi_valid(&attr->esi)) {
10715
0
    route_vty_out_detail_es_info(vty, path, attr, json_path);
10716
0
  }
10717
10718
  /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10719
   * Int/Ext/Local, Atomic, best */
10720
0
  if (json_paths)
10721
0
    json_object_string_add(json_path, "origin",
10722
0
               bgp_origin_long_str[attr->origin]);
10723
0
  else
10724
0
    vty_out(vty, "      Origin %s",
10725
0
      bgp_origin_long_str[attr->origin]);
10726
10727
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
10728
0
    if (json_paths)
10729
0
      json_object_int_add(json_path, "metric", attr->med);
10730
0
    else
10731
0
      vty_out(vty, ", metric %u", attr->med);
10732
0
  }
10733
10734
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10735
0
    if (json_paths)
10736
0
      json_object_int_add(json_path, "locPrf",
10737
0
              attr->local_pref);
10738
0
    else
10739
0
      vty_out(vty, ", localpref %u", attr->local_pref);
10740
0
  }
10741
10742
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10743
0
    if (json_paths)
10744
0
      json_object_int_add(json_path, "aigpMetric",
10745
0
              bgp_attr_get_aigp_metric(attr));
10746
0
    else
10747
0
      vty_out(vty, ", aigp-metric %" PRIu64,
10748
0
        bgp_attr_get_aigp_metric(attr));
10749
0
  }
10750
10751
0
  if (attr->weight != 0) {
10752
0
    if (json_paths)
10753
0
      json_object_int_add(json_path, "weight", attr->weight);
10754
0
    else
10755
0
      vty_out(vty, ", weight %u", attr->weight);
10756
0
  }
10757
10758
0
  if (attr->tag != 0) {
10759
0
    if (json_paths)
10760
0
      json_object_int_add(json_path, "tag", attr->tag);
10761
0
    else
10762
0
      vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10763
0
  }
10764
10765
0
  if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10766
0
    if (json_paths)
10767
0
      json_object_boolean_false_add(json_path, "valid");
10768
0
    else
10769
0
      vty_out(vty, ", invalid");
10770
0
  } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10771
0
    if (json_paths)
10772
0
      json_object_boolean_true_add(json_path, "valid");
10773
0
    else
10774
0
      vty_out(vty, ", valid");
10775
0
  }
10776
10777
0
  if (json_paths)
10778
0
    json_object_int_add(json_path, "version", bn->version);
10779
10780
0
  if (path->peer != bgp->peer_self) {
10781
0
    if (path->peer->as == path->peer->local_as) {
10782
0
      if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10783
0
        if (json_paths)
10784
0
          json_object_string_add(
10785
0
            json_peer, "type",
10786
0
            "confed-internal");
10787
0
        else
10788
0
          vty_out(vty, ", confed-internal");
10789
0
      } else {
10790
0
        if (json_paths)
10791
0
          json_object_string_add(
10792
0
            json_peer, "type", "internal");
10793
0
        else
10794
0
          vty_out(vty, ", internal");
10795
0
      }
10796
0
    } else {
10797
0
      if (bgp_confederation_peers_check(bgp,
10798
0
                path->peer->as)) {
10799
0
        if (json_paths)
10800
0
          json_object_string_add(
10801
0
            json_peer, "type",
10802
0
            "confed-external");
10803
0
        else
10804
0
          vty_out(vty, ", confed-external");
10805
0
      } else {
10806
0
        if (json_paths)
10807
0
          json_object_string_add(
10808
0
            json_peer, "type", "external");
10809
0
        else
10810
0
          vty_out(vty, ", external");
10811
0
      }
10812
0
    }
10813
0
  } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10814
0
    if (json_paths) {
10815
0
      json_object_boolean_true_add(json_path, "aggregated");
10816
0
      json_object_boolean_true_add(json_path, "local");
10817
0
    } else {
10818
0
      vty_out(vty, ", aggregated, local");
10819
0
    }
10820
0
  } else if (path->type != ZEBRA_ROUTE_BGP) {
10821
0
    if (json_paths)
10822
0
      json_object_boolean_true_add(json_path, "sourced");
10823
0
    else
10824
0
      vty_out(vty, ", sourced");
10825
0
  } else {
10826
0
    if (json_paths) {
10827
0
      json_object_boolean_true_add(json_path, "sourced");
10828
0
      json_object_boolean_true_add(json_path, "local");
10829
0
    } else {
10830
0
      vty_out(vty, ", sourced, local");
10831
0
    }
10832
0
  }
10833
10834
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
10835
0
    if (json_paths)
10836
0
      json_object_boolean_true_add(json_path,
10837
0
                 "atomicAggregate");
10838
0
    else
10839
0
      vty_out(vty, ", atomic-aggregate");
10840
0
  }
10841
10842
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10843
0
    if (json_paths)
10844
0
      json_object_int_add(json_path, "otc", attr->otc);
10845
0
    else
10846
0
      vty_out(vty, ", otc %u", attr->otc);
10847
0
  }
10848
10849
0
  if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10850
0
      || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10851
0
    && bgp_path_info_mpath_count(path))) {
10852
0
    if (json_paths)
10853
0
      json_object_boolean_true_add(json_path, "multipath");
10854
0
    else
10855
0
      vty_out(vty, ", multipath");
10856
0
  }
10857
10858
  // Mark the bestpath(s)
10859
0
  if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10860
0
    first_as = aspath_get_first_as(attr->aspath);
10861
10862
0
    if (json_paths) {
10863
0
      if (!json_bestpath)
10864
0
        json_bestpath = json_object_new_object();
10865
0
      json_object_int_add(json_bestpath, "bestpathFromAs",
10866
0
              first_as);
10867
0
    } else {
10868
0
      if (first_as)
10869
0
        vty_out(vty, ", bestpath-from-AS %u", first_as);
10870
0
      else
10871
0
        vty_out(vty, ", bestpath-from-AS Local");
10872
0
    }
10873
0
  }
10874
10875
0
  if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10876
0
    if (json_paths) {
10877
0
      if (!json_bestpath)
10878
0
        json_bestpath = json_object_new_object();
10879
0
      json_object_boolean_true_add(json_bestpath, "overall");
10880
0
      json_object_string_add(
10881
0
        json_bestpath, "selectionReason",
10882
0
        bgp_path_selection_reason2str(bn->reason));
10883
0
    } else {
10884
0
      vty_out(vty, ", best");
10885
0
      vty_out(vty, " (%s)",
10886
0
        bgp_path_selection_reason2str(bn->reason));
10887
0
    }
10888
0
  }
10889
10890
0
  if (rpki_curr_state != RPKI_NOT_BEING_USED) {
10891
0
    if (json_paths)
10892
0
      json_object_string_add(
10893
0
        json_path, "rpkiValidationState",
10894
0
        bgp_rpki_validation2str(rpki_curr_state));
10895
0
    else
10896
0
      vty_out(vty, ", rpki validation-state: %s",
10897
0
        bgp_rpki_validation2str(rpki_curr_state));
10898
0
  }
10899
10900
0
  if (json_bestpath)
10901
0
    json_object_object_add(json_path, "bestpath", json_bestpath);
10902
10903
0
  if (!json_paths)
10904
0
    vty_out(vty, "\n");
10905
10906
  /* Line 4 display Community */
10907
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
10908
0
    if (json_paths) {
10909
0
      if (!bgp_attr_get_community(attr)->json)
10910
0
        community_str(bgp_attr_get_community(attr),
10911
0
                true, true);
10912
0
      json_object_lock(bgp_attr_get_community(attr)->json);
10913
0
      json_object_object_add(
10914
0
        json_path, "community",
10915
0
        bgp_attr_get_community(attr)->json);
10916
0
    } else {
10917
0
      vty_out(vty, "      Community: %s\n",
10918
0
        bgp_attr_get_community(attr)->str);
10919
0
    }
10920
0
  }
10921
10922
  /* Line 5 display Extended-community */
10923
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10924
0
    if (json_paths) {
10925
0
      json_ext_community = json_object_new_object();
10926
0
      json_object_string_add(
10927
0
        json_ext_community, "string",
10928
0
        bgp_attr_get_ecommunity(attr)->str);
10929
0
      json_object_object_add(json_path, "extendedCommunity",
10930
0
                 json_ext_community);
10931
0
    } else {
10932
0
      vty_out(vty, "      Extended Community: %s\n",
10933
0
        bgp_attr_get_ecommunity(attr)->str);
10934
0
    }
10935
0
  }
10936
10937
  /* Line 6 display Large community */
10938
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10939
0
    if (json_paths) {
10940
0
      if (!bgp_attr_get_lcommunity(attr)->json)
10941
0
        lcommunity_str(bgp_attr_get_lcommunity(attr),
10942
0
                 true, true);
10943
0
      json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10944
0
      json_object_object_add(
10945
0
        json_path, "largeCommunity",
10946
0
        bgp_attr_get_lcommunity(attr)->json);
10947
0
    } else {
10948
0
      vty_out(vty, "      Large Community: %s\n",
10949
0
        bgp_attr_get_lcommunity(attr)->str);
10950
0
    }
10951
0
  }
10952
10953
  /* Line 7 display Originator, Cluster-id */
10954
0
  if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10955
0
      || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
10956
0
    char buf[BUFSIZ] = {0};
10957
10958
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
10959
0
      if (json_paths)
10960
0
        json_object_string_addf(json_path,
10961
0
              "originatorId", "%pI4",
10962
0
              &attr->originator_id);
10963
0
      else
10964
0
        vty_out(vty, "      Originator: %pI4",
10965
0
          &attr->originator_id);
10966
0
    }
10967
10968
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10969
0
      struct cluster_list *cluster =
10970
0
        bgp_attr_get_cluster(attr);
10971
0
      int i;
10972
10973
0
      if (json_paths) {
10974
0
        json_cluster_list = json_object_new_object();
10975
0
        json_cluster_list_list =
10976
0
          json_object_new_array();
10977
10978
0
        for (i = 0; i < cluster->length / 4; i++) {
10979
0
          json_string = json_object_new_string(
10980
0
            inet_ntop(AF_INET,
10981
0
                &cluster->list[i],
10982
0
                buf, sizeof(buf)));
10983
0
          json_object_array_add(
10984
0
            json_cluster_list_list,
10985
0
            json_string);
10986
0
        }
10987
10988
        /*
10989
         * struct cluster_list does not have
10990
         * "str" variable like aspath and community
10991
         * do.  Add this someday if someone asks
10992
         * for it.
10993
         * json_object_string_add(json_cluster_list,
10994
         * "string", cluster->str);
10995
         */
10996
0
        json_object_object_add(json_cluster_list,
10997
0
                   "list",
10998
0
                   json_cluster_list_list);
10999
0
        json_object_object_add(json_path, "clusterList",
11000
0
                   json_cluster_list);
11001
0
      } else {
11002
0
        vty_out(vty, ", Cluster list: ");
11003
11004
0
        for (i = 0; i < cluster->length / 4; i++) {
11005
0
          vty_out(vty, "%pI4 ",
11006
0
            &cluster->list[i]);
11007
0
        }
11008
0
      }
11009
0
    }
11010
11011
0
    if (!json_paths)
11012
0
      vty_out(vty, "\n");
11013
0
  }
11014
11015
0
  if (path->extra && path->extra->damp_info)
11016
0
    bgp_damp_info_vty(vty, path, afi, safi, json_path);
11017
11018
  /* Remote Label */
11019
0
  if (path->extra && bgp_is_valid_label(&path->extra->label[0])
11020
0
      && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
11021
0
    mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
11022
0
        &bos);
11023
11024
0
    if (json_paths)
11025
0
      json_object_int_add(json_path, "remoteLabel", label);
11026
0
    else
11027
0
      vty_out(vty, "      Remote label: %d\n", label);
11028
0
  }
11029
11030
  /* Remote SID */
11031
0
  if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
11032
0
    if (json_paths)
11033
0
      json_object_string_addf(json_path, "remoteSid", "%pI6",
11034
0
            &path->extra->sid[0].sid);
11035
0
    else
11036
0
      vty_out(vty, "      Remote SID: %pI6\n",
11037
0
        &path->extra->sid[0].sid);
11038
0
  }
11039
11040
  /* Label Index */
11041
0
  if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11042
0
    if (json_paths)
11043
0
      json_object_int_add(json_path, "labelIndex",
11044
0
              attr->label_index);
11045
0
    else
11046
0
      vty_out(vty, "      Label Index: %d\n",
11047
0
        attr->label_index);
11048
0
  }
11049
11050
  /* Line 8 display Addpath IDs */
11051
0
  if (path->addpath_rx_id
11052
0
      || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11053
0
    if (json_paths) {
11054
0
      json_object_int_add(json_path, "addpathRxId",
11055
0
              path->addpath_rx_id);
11056
11057
      /* Keep backwards compatibility with the old API
11058
       * by putting TX All's ID in the old field
11059
       */
11060
0
      json_object_int_add(
11061
0
        json_path, "addpathTxId",
11062
0
        path->tx_addpath
11063
0
          .addpath_tx_id[BGP_ADDPATH_ALL]);
11064
11065
      /* ... but create a specific field for each
11066
       * strategy
11067
       */
11068
0
      for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11069
0
        json_object_int_add(
11070
0
          json_path,
11071
0
          bgp_addpath_names(i)->id_json_name,
11072
0
          path->tx_addpath.addpath_tx_id[i]);
11073
0
      }
11074
0
    } else {
11075
0
      vty_out(vty, "      AddPath ID: RX %u, ",
11076
0
        path->addpath_rx_id);
11077
11078
0
      route_vty_out_tx_ids(vty, &path->tx_addpath);
11079
0
    }
11080
0
  }
11081
11082
  /* If we used addpath to TX a non-bestpath we need to display
11083
   * "Advertised to" on a path-by-path basis
11084
   */
11085
0
  if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11086
0
    first = 1;
11087
11088
0
    for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11089
0
      addpath_capable =
11090
0
        bgp_addpath_encode_tx(peer, afi, safi);
11091
0
      has_adj = bgp_adj_out_lookup(
11092
0
        peer, path->net,
11093
0
        bgp_addpath_id_for_peer(peer, afi, safi,
11094
0
              &path->tx_addpath));
11095
11096
0
      if ((addpath_capable && has_adj)
11097
0
          || (!addpath_capable && has_adj
11098
0
        && CHECK_FLAG(path->flags,
11099
0
                BGP_PATH_SELECTED))) {
11100
0
        if (json_path && !json_adv_to)
11101
0
          json_adv_to = json_object_new_object();
11102
11103
0
        route_vty_out_advertised_to(
11104
0
          vty, peer, &first,
11105
0
          "      Advertised to:", json_adv_to);
11106
0
      }
11107
0
    }
11108
11109
0
    if (json_path) {
11110
0
      if (json_adv_to) {
11111
0
        json_object_object_add(
11112
0
          json_path, "advertisedTo", json_adv_to);
11113
0
      }
11114
0
    } else {
11115
0
      if (!first) {
11116
0
        vty_out(vty, "\n");
11117
0
      }
11118
0
    }
11119
0
  }
11120
11121
  /* Line 9 display Uptime */
11122
0
  tbuf = time(NULL) - (monotime(NULL) - path->uptime);
11123
0
  if (json_paths) {
11124
0
    json_last_update = json_object_new_object();
11125
0
    json_object_int_add(json_last_update, "epoch", tbuf);
11126
0
    json_object_string_add(json_last_update, "string",
11127
0
               ctime(&tbuf));
11128
0
    json_object_object_add(json_path, "lastUpdate",
11129
0
               json_last_update);
11130
0
  } else
11131
0
    vty_out(vty, "      Last update: %s", ctime(&tbuf));
11132
11133
  /* Line 10 display PMSI tunnel attribute, if present */
11134
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
11135
0
    const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11136
0
               bgp_attr_get_pmsi_tnl_type(attr),
11137
0
               PMSI_TNLTYPE_STR_DEFAULT);
11138
11139
0
    if (json_paths) {
11140
0
      json_pmsi = json_object_new_object();
11141
0
      json_object_string_add(json_pmsi, "tunnelType", str);
11142
0
      json_object_int_add(json_pmsi, "label",
11143
0
              label2vni(&attr->label));
11144
0
      json_object_object_add(json_path, "pmsi", json_pmsi);
11145
0
    } else
11146
0
      vty_out(vty, "      PMSI Tunnel Type: %s, label: %d\n",
11147
0
        str, label2vni(&attr->label));
11148
0
  }
11149
11150
0
  if (path->peer->t_gr_restart &&
11151
0
      CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11152
0
    unsigned long gr_remaining =
11153
0
      event_timer_remain_second(path->peer->t_gr_restart);
11154
11155
0
    if (json_paths) {
11156
0
      json_object_int_add(json_path,
11157
0
              "gracefulRestartSecondsRemaining",
11158
0
              gr_remaining);
11159
0
    } else
11160
0
      vty_out(vty,
11161
0
        "      Time until Graceful Restart stale route deleted: %lu\n",
11162
0
        gr_remaining);
11163
0
  }
11164
11165
0
  if (path->peer->t_llgr_stale[afi][safi] &&
11166
0
      bgp_attr_get_community(attr) &&
11167
0
      community_include(bgp_attr_get_community(attr),
11168
0
            COMMUNITY_LLGR_STALE)) {
11169
0
    unsigned long llgr_remaining = event_timer_remain_second(
11170
0
      path->peer->t_llgr_stale[afi][safi]);
11171
11172
0
    if (json_paths) {
11173
0
      json_object_int_add(json_path, "llgrSecondsRemaining",
11174
0
              llgr_remaining);
11175
0
    } else
11176
0
      vty_out(vty,
11177
0
        "      Time until Long-lived stale route deleted: %lu\n",
11178
0
        llgr_remaining);
11179
0
  }
11180
11181
  /* Output some debug about internal state of the dest flags */
11182
0
  if (json_paths) {
11183
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11184
0
      json_object_boolean_true_add(json_path, "processScheduled");
11185
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11186
0
      json_object_boolean_true_add(json_path, "userCleared");
11187
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11188
0
      json_object_boolean_true_add(json_path, "labelChanged");
11189
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11190
0
      json_object_boolean_true_add(json_path, "registeredForLabel");
11191
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11192
0
      json_object_boolean_true_add(json_path, "selectDefered");
11193
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11194
0
      json_object_boolean_true_add(json_path, "fibInstalled");
11195
0
    if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11196
0
      json_object_boolean_true_add(json_path, "fibPending");
11197
11198
0
    if (json_nexthop_global || json_nexthop_ll) {
11199
0
      json_nexthops = json_object_new_array();
11200
11201
0
      if (json_nexthop_global)
11202
0
        json_object_array_add(json_nexthops,
11203
0
                  json_nexthop_global);
11204
11205
0
      if (json_nexthop_ll)
11206
0
        json_object_array_add(json_nexthops,
11207
0
                  json_nexthop_ll);
11208
11209
0
      json_object_object_add(json_path, "nexthops",
11210
0
                 json_nexthops);
11211
0
    }
11212
11213
0
    json_object_object_add(json_path, "peer", json_peer);
11214
0
    json_object_array_add(json_paths, json_path);
11215
0
  }
11216
0
}
11217
11218
#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11219
0
#define BGP_SHOW_DAMP_HEADER "   Network          From             Reuse    Path\n"
11220
0
#define BGP_SHOW_FLAP_HEADER "   Network          From            Flaps Duration Reuse    Path\n"
11221
11222
static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
11223
         afi_t afi, safi_t safi, enum bgp_show_type type,
11224
         bool use_json);
11225
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11226
            const char *comstr, int exact, afi_t afi,
11227
            safi_t safi, uint16_t show_flags);
11228
11229
static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
11230
        struct bgp_table *table, enum bgp_show_type type,
11231
        void *output_arg, const char *rd, int is_last,
11232
        unsigned long *output_cum, unsigned long *total_cum,
11233
        unsigned long *json_header_depth, uint16_t show_flags,
11234
        enum rpki_states rpki_target_state)
11235
0
{
11236
0
  struct bgp_path_info *pi;
11237
0
  struct bgp_dest *dest;
11238
0
  bool header = true;
11239
0
  bool json_detail_header = false;
11240
0
  int display;
11241
0
  unsigned long output_count = 0;
11242
0
  unsigned long total_count = 0;
11243
0
  struct prefix *p;
11244
0
  json_object *json_paths = NULL;
11245
0
  int first = 1;
11246
0
  bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11247
0
  bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11248
0
  bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11249
0
  bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
11250
0
  bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
11251
11252
0
  if (output_cum && *output_cum != 0)
11253
0
    header = false;
11254
11255
0
  if (use_json && !*json_header_depth) {
11256
0
    if (all)
11257
0
      *json_header_depth = 1;
11258
0
    else {
11259
0
      vty_out(vty, "{\n");
11260
0
      *json_header_depth = 2;
11261
0
    }
11262
0
    vty_out(vty,
11263
0
      " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11264
0
      ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11265
0
      " \"localAS\": ",
11266
0
      bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
11267
0
      bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
11268
0
        ? VRF_DEFAULT_NAME
11269
0
        : bgp->name,
11270
0
      table->version, &bgp->router_id,
11271
0
      bgp->default_local_pref);
11272
0
    if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11273
0
        ((bgp->asnotation == ASNOTATION_DOT) &&
11274
0
         (bgp->as < UINT16_MAX)))
11275
0
      vty_out(vty, "%u", bgp->as);
11276
0
    else {
11277
0
      vty_out(vty, "\"");
11278
0
      vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11279
0
      vty_out(vty, "\"");
11280
0
    }
11281
0
    vty_out(vty, ",\n \"routes\": { ");
11282
0
    if (rd) {
11283
0
      vty_out(vty, " \"routeDistinguishers\" : {");
11284
0
      ++*json_header_depth;
11285
0
    }
11286
0
  }
11287
11288
0
  if (use_json && rd) {
11289
0
    vty_out(vty, " \"%s\" : { ", rd);
11290
0
  }
11291
11292
  /* Check for 'json detail', where we need header output once per dest */
11293
0
  if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
11294
0
      type != bgp_show_type_damp_neighbor &&
11295
0
      type != bgp_show_type_flap_statistics &&
11296
0
      type != bgp_show_type_flap_neighbor)
11297
0
    json_detail_header = true;
11298
11299
  /* Start processing of routes. */
11300
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11301
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11302
0
    enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
11303
0
    bool json_detail_header_used = false;
11304
11305
0
    pi = bgp_dest_get_bgp_path_info(dest);
11306
0
    if (pi == NULL)
11307
0
      continue;
11308
11309
0
    display = 0;
11310
0
    if (use_json)
11311
0
      json_paths = json_object_new_array();
11312
0
    else
11313
0
      json_paths = NULL;
11314
11315
0
    for (; pi; pi = pi->next) {
11316
0
      struct community *picomm = NULL;
11317
11318
0
      picomm = bgp_attr_get_community(pi->attr);
11319
11320
0
      total_count++;
11321
11322
0
      if (type == bgp_show_type_prefix_version) {
11323
0
        uint32_t version =
11324
0
          strtoul(output_arg, NULL, 10);
11325
0
        if (dest->version < version)
11326
0
          continue;
11327
0
      }
11328
11329
0
      if (type == bgp_show_type_community_alias) {
11330
0
        char *alias = output_arg;
11331
0
        char **communities;
11332
0
        int num;
11333
0
        bool found = false;
11334
11335
0
        if (picomm) {
11336
0
          frrstr_split(picomm->str, " ",
11337
0
                 &communities, &num);
11338
0
          for (int i = 0; i < num; i++) {
11339
0
            const char *com2alias =
11340
0
              bgp_community2alias(
11341
0
                communities[i]);
11342
0
            if (!found
11343
0
                && strcmp(alias, com2alias)
11344
0
                     == 0)
11345
0
              found = true;
11346
0
            XFREE(MTYPE_TMP,
11347
0
                  communities[i]);
11348
0
          }
11349
0
          XFREE(MTYPE_TMP, communities);
11350
0
        }
11351
11352
0
        if (!found &&
11353
0
            bgp_attr_get_lcommunity(pi->attr)) {
11354
0
          frrstr_split(bgp_attr_get_lcommunity(
11355
0
                   pi->attr)
11356
0
                   ->str,
11357
0
                 " ", &communities, &num);
11358
0
          for (int i = 0; i < num; i++) {
11359
0
            const char *com2alias =
11360
0
              bgp_community2alias(
11361
0
                communities[i]);
11362
0
            if (!found
11363
0
                && strcmp(alias, com2alias)
11364
0
                     == 0)
11365
0
              found = true;
11366
0
            XFREE(MTYPE_TMP,
11367
0
                  communities[i]);
11368
0
          }
11369
0
          XFREE(MTYPE_TMP, communities);
11370
0
        }
11371
11372
0
        if (!found)
11373
0
          continue;
11374
0
      }
11375
11376
0
      if (type == bgp_show_type_rpki) {
11377
0
        if (dest_p->family == AF_INET
11378
0
            || dest_p->family == AF_INET6)
11379
0
          rpki_curr_state = hook_call(
11380
0
            bgp_rpki_prefix_status,
11381
0
            pi->peer, pi->attr, dest_p);
11382
0
        if (rpki_target_state != RPKI_NOT_BEING_USED
11383
0
            && rpki_curr_state != rpki_target_state)
11384
0
          continue;
11385
0
      }
11386
11387
0
      if (type == bgp_show_type_flap_statistics
11388
0
          || type == bgp_show_type_flap_neighbor
11389
0
          || type == bgp_show_type_dampend_paths
11390
0
          || type == bgp_show_type_damp_neighbor) {
11391
0
        if (!(pi->extra && pi->extra->damp_info))
11392
0
          continue;
11393
0
      }
11394
0
      if (type == bgp_show_type_regexp) {
11395
0
        regex_t *regex = output_arg;
11396
11397
0
        if (bgp_regexec(regex, pi->attr->aspath)
11398
0
            == REG_NOMATCH)
11399
0
          continue;
11400
0
      }
11401
0
      if (type == bgp_show_type_prefix_list) {
11402
0
        struct prefix_list *plist = output_arg;
11403
11404
0
        if (prefix_list_apply(plist, dest_p)
11405
0
            != PREFIX_PERMIT)
11406
0
          continue;
11407
0
      }
11408
0
      if (type == bgp_show_type_access_list) {
11409
0
        struct access_list *alist = output_arg;
11410
11411
0
        if (access_list_apply(alist, dest_p) !=
11412
0
            FILTER_PERMIT)
11413
0
          continue;
11414
0
      }
11415
0
      if (type == bgp_show_type_filter_list) {
11416
0
        struct as_list *as_list = output_arg;
11417
11418
0
        if (as_list_apply(as_list, pi->attr->aspath)
11419
0
            != AS_FILTER_PERMIT)
11420
0
          continue;
11421
0
      }
11422
0
      if (type == bgp_show_type_route_map) {
11423
0
        struct route_map *rmap = output_arg;
11424
0
        struct bgp_path_info path;
11425
0
        struct bgp_path_info_extra extra;
11426
0
        struct attr dummy_attr = {};
11427
0
        route_map_result_t ret;
11428
11429
0
        dummy_attr = *pi->attr;
11430
11431
0
        prep_for_rmap_apply(&path, &extra, dest, pi,
11432
0
                pi->peer, &dummy_attr);
11433
11434
0
        ret = route_map_apply(rmap, dest_p, &path);
11435
0
        bgp_attr_flush(&dummy_attr);
11436
0
        if (ret == RMAP_DENYMATCH)
11437
0
          continue;
11438
0
      }
11439
0
      if (type == bgp_show_type_neighbor
11440
0
          || type == bgp_show_type_flap_neighbor
11441
0
          || type == bgp_show_type_damp_neighbor) {
11442
0
        union sockunion *su = output_arg;
11443
11444
0
        if (pi->peer == NULL
11445
0
            || pi->peer->su_remote == NULL
11446
0
            || !sockunion_same(pi->peer->su_remote, su))
11447
0
          continue;
11448
0
      }
11449
0
      if (type == bgp_show_type_cidr_only) {
11450
0
        uint32_t destination;
11451
11452
0
        destination = ntohl(dest_p->u.prefix4.s_addr);
11453
0
        if (IN_CLASSC(destination)
11454
0
            && dest_p->prefixlen == 24)
11455
0
          continue;
11456
0
        if (IN_CLASSB(destination)
11457
0
            && dest_p->prefixlen == 16)
11458
0
          continue;
11459
0
        if (IN_CLASSA(destination)
11460
0
            && dest_p->prefixlen == 8)
11461
0
          continue;
11462
0
      }
11463
0
      if (type == bgp_show_type_prefix_longer) {
11464
0
        p = output_arg;
11465
0
        if (!prefix_match(p, dest_p))
11466
0
          continue;
11467
0
      }
11468
0
      if (type == bgp_show_type_community_all) {
11469
0
        if (!picomm)
11470
0
          continue;
11471
0
      }
11472
0
      if (type == bgp_show_type_community) {
11473
0
        struct community *com = output_arg;
11474
11475
0
        if (!picomm || !community_match(picomm, com))
11476
0
          continue;
11477
0
      }
11478
0
      if (type == bgp_show_type_community_exact) {
11479
0
        struct community *com = output_arg;
11480
11481
0
        if (!picomm || !community_cmp(picomm, com))
11482
0
          continue;
11483
0
      }
11484
0
      if (type == bgp_show_type_community_list) {
11485
0
        struct community_list *list = output_arg;
11486
11487
0
        if (!community_list_match(picomm, list))
11488
0
          continue;
11489
0
      }
11490
0
      if (type == bgp_show_type_community_list_exact) {
11491
0
        struct community_list *list = output_arg;
11492
11493
0
        if (!community_list_exact_match(picomm, list))
11494
0
          continue;
11495
0
      }
11496
0
      if (type == bgp_show_type_lcommunity) {
11497
0
        struct lcommunity *lcom = output_arg;
11498
11499
0
        if (!bgp_attr_get_lcommunity(pi->attr) ||
11500
0
            !lcommunity_match(
11501
0
              bgp_attr_get_lcommunity(pi->attr),
11502
0
              lcom))
11503
0
          continue;
11504
0
      }
11505
11506
0
      if (type == bgp_show_type_lcommunity_exact) {
11507
0
        struct lcommunity *lcom = output_arg;
11508
11509
0
        if (!bgp_attr_get_lcommunity(pi->attr) ||
11510
0
            !lcommunity_cmp(
11511
0
              bgp_attr_get_lcommunity(pi->attr),
11512
0
              lcom))
11513
0
          continue;
11514
0
      }
11515
0
      if (type == bgp_show_type_lcommunity_list) {
11516
0
        struct community_list *list = output_arg;
11517
11518
0
        if (!lcommunity_list_match(
11519
0
              bgp_attr_get_lcommunity(pi->attr),
11520
0
              list))
11521
0
          continue;
11522
0
      }
11523
0
      if (type
11524
0
          == bgp_show_type_lcommunity_list_exact) {
11525
0
        struct community_list *list = output_arg;
11526
11527
0
        if (!lcommunity_list_exact_match(
11528
0
              bgp_attr_get_lcommunity(pi->attr),
11529
0
              list))
11530
0
          continue;
11531
0
      }
11532
0
      if (type == bgp_show_type_lcommunity_all) {
11533
0
        if (!bgp_attr_get_lcommunity(pi->attr))
11534
0
          continue;
11535
0
      }
11536
0
      if (type == bgp_show_type_dampend_paths
11537
0
          || type == bgp_show_type_damp_neighbor) {
11538
0
        if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11539
0
            || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11540
0
          continue;
11541
0
      }
11542
0
      if (type == bgp_show_type_self_originated) {
11543
0
        if (pi->peer != bgp->peer_self)
11544
0
          continue;
11545
0
      }
11546
11547
0
      if (!use_json && header) {
11548
0
        vty_out(vty,
11549
0
          "BGP table version is %" PRIu64
11550
0
          ", local router ID is %pI4, vrf id ",
11551
0
          table->version, &bgp->router_id);
11552
0
        if (bgp->vrf_id == VRF_UNKNOWN)
11553
0
          vty_out(vty, "%s", VRFID_NONE_STR);
11554
0
        else
11555
0
          vty_out(vty, "%u", bgp->vrf_id);
11556
0
        vty_out(vty, "\n");
11557
0
        vty_out(vty, "Default local pref %u, ",
11558
0
          bgp->default_local_pref);
11559
0
        vty_out(vty, "local AS ");
11560
0
        vty_out(vty, ASN_FORMAT(bgp->asnotation),
11561
0
          &bgp->as);
11562
0
        vty_out(vty, "\n");
11563
0
        if (!detail_routes) {
11564
0
          vty_out(vty, BGP_SHOW_SCODE_HEADER);
11565
0
          vty_out(vty, BGP_SHOW_NCODE_HEADER);
11566
0
          vty_out(vty, BGP_SHOW_OCODE_HEADER);
11567
0
          vty_out(vty, BGP_SHOW_RPKI_HEADER);
11568
0
        }
11569
0
        if (type == bgp_show_type_dampend_paths
11570
0
            || type == bgp_show_type_damp_neighbor)
11571
0
          vty_out(vty, BGP_SHOW_DAMP_HEADER);
11572
0
        else if (type == bgp_show_type_flap_statistics
11573
0
           || type == bgp_show_type_flap_neighbor)
11574
0
          vty_out(vty, BGP_SHOW_FLAP_HEADER);
11575
0
        else if (!detail_routes)
11576
0
          vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11577
0
                 : BGP_SHOW_HEADER));
11578
0
        header = false;
11579
11580
0
      }
11581
0
      if (rd != NULL && !display && !output_count) {
11582
0
        if (!use_json)
11583
0
          vty_out(vty,
11584
0
            "Route Distinguisher: %s\n",
11585
0
            rd);
11586
0
      }
11587
0
      if (type == bgp_show_type_dampend_paths
11588
0
          || type == bgp_show_type_damp_neighbor)
11589
0
        damp_route_vty_out(vty, dest_p, pi, display,
11590
0
               AFI_IP, safi, use_json,
11591
0
               json_paths);
11592
0
      else if (type == bgp_show_type_flap_statistics
11593
0
         || type == bgp_show_type_flap_neighbor)
11594
0
        flap_route_vty_out(vty, dest_p, pi, display,
11595
0
               AFI_IP, safi, use_json,
11596
0
               json_paths);
11597
0
      else {
11598
0
        if (detail_routes || detail_json) {
11599
0
          const struct prefix_rd *prd = NULL;
11600
11601
0
          if (dest->pdest)
11602
0
            prd = bgp_rd_from_dest(
11603
0
              dest->pdest, safi);
11604
11605
0
          if (!use_json)
11606
0
            route_vty_out_detail_header(
11607
0
              vty, bgp, dest,
11608
0
              bgp_dest_get_prefix(
11609
0
                dest),
11610
0
              prd, table->afi, safi,
11611
0
              NULL, false);
11612
11613
0
          route_vty_out_detail(
11614
0
            vty, bgp, dest, dest_p, pi,
11615
0
            family2afi(dest_p->family),
11616
0
            safi, RPKI_NOT_BEING_USED,
11617
0
            json_paths);
11618
0
        } else {
11619
0
          route_vty_out(vty, dest_p, pi, display,
11620
0
                  safi, json_paths, wide);
11621
0
        }
11622
0
      }
11623
0
      display++;
11624
0
    }
11625
11626
0
    if (display) {
11627
0
      output_count++;
11628
0
      if (!use_json)
11629
0
        continue;
11630
11631
      /* encode prefix */
11632
0
      if (dest_p->family == AF_FLOWSPEC) {
11633
0
        char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11634
11635
11636
0
        bgp_fs_nlri_get_string(
11637
0
          (unsigned char *)
11638
0
            dest_p->u.prefix_flowspec.ptr,
11639
0
          dest_p->u.prefix_flowspec.prefixlen,
11640
0
          retstr, NLRI_STRING_FORMAT_MIN, NULL,
11641
0
          family2afi(dest_p->u
11642
0
               .prefix_flowspec.family));
11643
0
        if (first)
11644
0
          vty_out(vty, "\"%s/%d\": ", retstr,
11645
0
            dest_p->u.prefix_flowspec
11646
0
              .prefixlen);
11647
0
        else
11648
0
          vty_out(vty, ",\"%s/%d\": ", retstr,
11649
0
            dest_p->u.prefix_flowspec
11650
0
              .prefixlen);
11651
0
      } else {
11652
0
        if (first)
11653
0
          vty_out(vty, "\"%pFX\": ", dest_p);
11654
0
        else
11655
0
          vty_out(vty, ",\"%pFX\": ", dest_p);
11656
0
      }
11657
11658
      /* This is used for 'json detail' vty keywords.
11659
       *
11660
       * In plain 'json' the per-prefix header is encoded
11661
       * as a standalone dictionary in the first json_paths
11662
       * array element:
11663
       * "<prefix>": [{header}, {path-1}, {path-N}]
11664
       * (which is confusing and borderline broken)
11665
       *
11666
       * For 'json detail' this changes the value
11667
       * of each prefix-key to be a dictionary where each
11668
       * header item has its own key, and json_paths is
11669
       * tucked under the "paths" key:
11670
       * "<prefix>": {
11671
       *   "<header-key-1>": <header-val-1>,
11672
       *   "<header-key-N>": <header-val-N>,
11673
       *   "paths": [{path-1}, {path-N}]
11674
       * }
11675
       */
11676
0
      if (json_detail_header && json_paths != NULL) {
11677
0
        const struct prefix_rd *prd;
11678
11679
        /* Start per-prefix dictionary */
11680
0
        vty_out(vty, "{\n");
11681
11682
0
        prd = bgp_rd_from_dest(dest, safi);
11683
11684
0
        route_vty_out_detail_header(
11685
0
          vty, bgp, dest,
11686
0
          bgp_dest_get_prefix(dest), prd,
11687
0
          table->afi, safi, json_paths, true);
11688
11689
0
        vty_out(vty, "\"paths\": ");
11690
0
        json_detail_header_used = true;
11691
0
      }
11692
11693
      /*
11694
       * We are using no_pretty here because under
11695
       * extremely high settings( say lots and lots of
11696
       * routes with lots and lots of ways to reach
11697
       * that route via different paths ) this can
11698
       * save several minutes of output when FRR
11699
       * is run on older cpu's or more underperforming
11700
       * routers out there
11701
       */
11702
0
      vty_json_no_pretty(vty, json_paths);
11703
11704
      /* End per-prefix dictionary */
11705
0
      if (json_detail_header_used)
11706
0
        vty_out(vty, "} ");
11707
11708
0
      json_paths = NULL;
11709
0
      first = 0;
11710
0
    } else
11711
0
      json_object_free(json_paths);
11712
0
  }
11713
11714
0
  if (output_cum) {
11715
0
    output_count += *output_cum;
11716
0
    *output_cum = output_count;
11717
0
  }
11718
0
  if (total_cum) {
11719
0
    total_count += *total_cum;
11720
0
    *total_cum = total_count;
11721
0
  }
11722
0
  if (use_json) {
11723
0
    if (rd) {
11724
0
      vty_out(vty, " }%s ", (is_last ? "" : ","));
11725
0
    }
11726
0
    if (is_last) {
11727
0
      unsigned long i;
11728
0
      for (i = 0; i < *json_header_depth; ++i)
11729
0
        vty_out(vty, " } ");
11730
0
      if (!all)
11731
0
        vty_out(vty, "\n");
11732
0
    }
11733
0
  } else {
11734
0
    if (is_last) {
11735
      /* No route is displayed */
11736
0
      if (output_count == 0) {
11737
0
        if (type == bgp_show_type_normal)
11738
0
          vty_out(vty,
11739
0
            "No BGP prefixes displayed, %ld exist\n",
11740
0
            total_count);
11741
0
      } else
11742
0
        vty_out(vty,
11743
0
          "\nDisplayed  %ld routes and %ld total paths\n",
11744
0
          output_count, total_count);
11745
0
    }
11746
0
  }
11747
11748
0
  return CMD_SUCCESS;
11749
0
}
11750
11751
int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11752
          struct bgp_table *table, struct prefix_rd *prd_match,
11753
          enum bgp_show_type type, void *output_arg,
11754
          uint16_t show_flags)
11755
0
{
11756
0
  struct bgp_dest *dest, *next;
11757
0
  unsigned long output_cum = 0;
11758
0
  unsigned long total_cum = 0;
11759
0
  unsigned long json_header_depth = 0;
11760
0
  struct bgp_table *itable;
11761
0
  bool show_msg;
11762
0
  bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11763
11764
0
  show_msg = (!use_json && type == bgp_show_type_normal);
11765
11766
0
  for (dest = bgp_table_top(table); dest; dest = next) {
11767
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11768
11769
0
    next = bgp_route_next(dest);
11770
0
    if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
11771
0
      continue;
11772
11773
0
    itable = bgp_dest_get_bgp_table_info(dest);
11774
0
    if (itable != NULL) {
11775
0
      struct prefix_rd prd;
11776
0
      char rd[RD_ADDRSTRLEN];
11777
11778
0
      memcpy(&prd, dest_p, sizeof(struct prefix_rd));
11779
0
      prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
11780
0
      bgp_show_table(vty, bgp, safi, itable, type, output_arg,
11781
0
               rd, next == NULL, &output_cum,
11782
0
               &total_cum, &json_header_depth,
11783
0
               show_flags, RPKI_NOT_BEING_USED);
11784
0
      if (next == NULL)
11785
0
        show_msg = false;
11786
0
    }
11787
0
  }
11788
0
  if (show_msg) {
11789
0
    if (output_cum == 0)
11790
0
      vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11791
0
        total_cum);
11792
0
    else
11793
0
      vty_out(vty,
11794
0
        "\nDisplayed  %ld routes and %ld total paths\n",
11795
0
        output_cum, total_cum);
11796
0
  } else {
11797
0
    if (use_json && output_cum == 0)
11798
0
      vty_out(vty, "{}\n");
11799
0
  }
11800
0
  return CMD_SUCCESS;
11801
0
}
11802
11803
static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
11804
        enum bgp_show_type type, void *output_arg,
11805
        uint16_t show_flags, enum rpki_states rpki_target_state)
11806
0
{
11807
0
  struct bgp_table *table;
11808
0
  unsigned long json_header_depth = 0;
11809
0
  bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11810
11811
0
  if (bgp == NULL) {
11812
0
    bgp = bgp_get_default();
11813
0
  }
11814
11815
0
  if (bgp == NULL) {
11816
0
    if (!use_json)
11817
0
      vty_out(vty, "No BGP process is configured\n");
11818
0
    else
11819
0
      vty_out(vty, "{}\n");
11820
0
    return CMD_WARNING;
11821
0
  }
11822
11823
  /* Labeled-unicast routes live in the unicast table. */
11824
0
  if (safi == SAFI_LABELED_UNICAST)
11825
0
    safi = SAFI_UNICAST;
11826
11827
0
  table = bgp->rib[afi][safi];
11828
  /* use MPLS and ENCAP specific shows until they are merged */
11829
0
  if (safi == SAFI_MPLS_VPN) {
11830
0
    return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11831
0
           output_arg, show_flags);
11832
0
  }
11833
11834
0
  if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11835
0
    return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11836
0
                 output_arg, use_json,
11837
0
                 1, NULL, NULL);
11838
0
  }
11839
11840
0
  if (safi == SAFI_EVPN)
11841
0
    return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11842
11843
0
  return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
11844
0
            NULL, NULL, &json_header_depth, show_flags,
11845
0
            rpki_target_state);
11846
0
}
11847
11848
static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
11849
                safi_t safi, uint16_t show_flags)
11850
0
{
11851
0
  struct listnode *node, *nnode;
11852
0
  struct bgp *bgp;
11853
0
  int is_first = 1;
11854
0
  bool route_output = false;
11855
0
  bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11856
11857
0
  if (use_json)
11858
0
    vty_out(vty, "{\n");
11859
11860
0
  for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
11861
0
    route_output = true;
11862
0
    if (use_json) {
11863
0
      if (!is_first)
11864
0
        vty_out(vty, ",\n");
11865
0
      else
11866
0
        is_first = 0;
11867
11868
0
      vty_out(vty, "\"%s\":",
11869
0
        (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11870
0
          ? VRF_DEFAULT_NAME
11871
0
          : bgp->name);
11872
0
    } else {
11873
0
      vty_out(vty, "\nInstance %s:\n",
11874
0
        (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11875
0
          ? VRF_DEFAULT_NAME
11876
0
          : bgp->name);
11877
0
    }
11878
0
    bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
11879
0
       show_flags, RPKI_NOT_BEING_USED);
11880
0
  }
11881
11882
0
  if (use_json)
11883
0
    vty_out(vty, "}\n");
11884
0
  else if (!route_output)
11885
0
    vty_out(vty, "%% BGP instance not found\n");
11886
0
}
11887
11888
/* Header of detailed BGP route information */
11889
void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
11890
         struct bgp_dest *dest, const struct prefix *p,
11891
         const struct prefix_rd *prd, afi_t afi,
11892
         safi_t safi, json_object *json,
11893
         bool incremental_print)
11894
0
{
11895
0
  struct bgp_path_info *pi;
11896
0
  struct peer *peer;
11897
0
  struct listnode *node, *nnode;
11898
0
  char buf1[RD_ADDRSTRLEN];
11899
0
  int count = 0;
11900
0
  int best = 0;
11901
0
  int suppress = 0;
11902
0
  int accept_own = 0;
11903
0
  int route_filter_translated_v4 = 0;
11904
0
  int route_filter_v4 = 0;
11905
0
  int route_filter_translated_v6 = 0;
11906
0
  int route_filter_v6 = 0;
11907
0
  int llgr_stale = 0;
11908
0
  int no_llgr = 0;
11909
0
  int accept_own_nexthop = 0;
11910
0
  int blackhole = 0;
11911
0
  int no_export = 0;
11912
0
  int no_advertise = 0;
11913
0
  int local_as = 0;
11914
0
  int no_peer = 0;
11915
0
  int first = 1;
11916
0
  int has_valid_label = 0;
11917
0
  mpls_label_t label = 0;
11918
0
  json_object *json_adv_to = NULL;
11919
0
  uint32_t ttl = 0;
11920
0
  uint32_t bos = 0;
11921
0
  uint32_t exp = 0;
11922
11923
0
  mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
11924
11925
0
  has_valid_label = bgp_is_valid_label(&label);
11926
11927
0
  if (safi == SAFI_EVPN) {
11928
0
    if (!json) {
11929
0
      vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11930
0
        prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11931
0
                bgp->asnotation)
11932
0
            : "",
11933
0
        prd ? ":" : "", (struct prefix_evpn *)p);
11934
0
    } else {
11935
0
      json_object_string_add(
11936
0
        json, "rd",
11937
0
        prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11938
0
                bgp->asnotation)
11939
0
            : "");
11940
0
      bgp_evpn_route2json((struct prefix_evpn *)p, json);
11941
0
    }
11942
0
  } else {
11943
0
    if (!json) {
11944
0
      vty_out(vty,
11945
0
        "BGP routing table entry for %s%s%pFX, version %" PRIu64
11946
0
        "\n",
11947
0
        (((safi == SAFI_MPLS_VPN ||
11948
0
           safi == SAFI_ENCAP) &&
11949
0
          prd)
11950
0
           ? prefix_rd2str(prd, buf1,
11951
0
               sizeof(buf1),
11952
0
               bgp->asnotation)
11953
0
           : ""),
11954
0
        safi == SAFI_MPLS_VPN && prd ? ":" : "", p,
11955
0
        dest->version);
11956
11957
0
    } else {
11958
0
      if (incremental_print) {
11959
0
        vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11960
0
        vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11961
0
          dest->version);
11962
0
      } else {
11963
0
        json_object_string_addf(json, "prefix", "%pFX",
11964
0
              p);
11965
0
        json_object_int_add(json, "version",
11966
0
                dest->version);
11967
0
      }
11968
0
    }
11969
0
  }
11970
11971
0
  if (has_valid_label) {
11972
0
    if (json) {
11973
0
      if (incremental_print)
11974
0
        vty_out(vty, "\"localLabel\": \"%u\",\n",
11975
0
          label);
11976
0
      else
11977
0
        json_object_int_add(json, "localLabel", label);
11978
0
    } else
11979
0
      vty_out(vty, "Local label: %d\n", label);
11980
0
  }
11981
11982
0
  if (!json)
11983
0
    if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
11984
0
      vty_out(vty, "not allocated\n");
11985
11986
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
11987
0
    struct community *picomm = NULL;
11988
11989
0
    picomm = bgp_attr_get_community(pi->attr);
11990
11991
0
    count++;
11992
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
11993
0
      best = count;
11994
0
      if (bgp_path_suppressed(pi))
11995
0
        suppress = 1;
11996
11997
0
      if (!picomm)
11998
0
        continue;
11999
12000
0
      no_advertise += community_include(
12001
0
        picomm, COMMUNITY_NO_ADVERTISE);
12002
0
      no_export +=
12003
0
        community_include(picomm, COMMUNITY_NO_EXPORT);
12004
0
      local_as +=
12005
0
        community_include(picomm, COMMUNITY_LOCAL_AS);
12006
0
      accept_own +=
12007
0
        community_include(picomm, COMMUNITY_ACCEPT_OWN);
12008
0
      route_filter_translated_v4 += community_include(
12009
0
        picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
12010
0
      route_filter_translated_v6 += community_include(
12011
0
        picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
12012
0
      route_filter_v4 += community_include(
12013
0
        picomm, COMMUNITY_ROUTE_FILTER_v4);
12014
0
      route_filter_v6 += community_include(
12015
0
        picomm, COMMUNITY_ROUTE_FILTER_v6);
12016
0
      llgr_stale +=
12017
0
        community_include(picomm, COMMUNITY_LLGR_STALE);
12018
0
      no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
12019
0
      accept_own_nexthop += community_include(
12020
0
        picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
12021
0
      blackhole +=
12022
0
        community_include(picomm, COMMUNITY_BLACKHOLE);
12023
0
      no_peer += community_include(picomm, COMMUNITY_NO_PEER);
12024
0
    }
12025
0
  }
12026
12027
0
  if (!json) {
12028
0
    vty_out(vty, "Paths: (%d available", count);
12029
0
    if (best) {
12030
0
      vty_out(vty, ", best #%d", best);
12031
0
      if (safi == SAFI_UNICAST) {
12032
0
        if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
12033
0
          vty_out(vty, ", table %s",
12034
0
            VRF_DEFAULT_NAME);
12035
0
        else
12036
0
          vty_out(vty, ", vrf %s",
12037
0
            bgp->name);
12038
0
      }
12039
0
    } else
12040
0
      vty_out(vty, ", no best path");
12041
12042
0
    if (accept_own)
12043
0
      vty_out(vty,
12044
0
      ", accept own local route exported and imported in different VRF");
12045
0
    else if (route_filter_translated_v4)
12046
0
      vty_out(vty,
12047
0
      ", mark translated RTs for VPNv4 route filtering");
12048
0
    else if (route_filter_v4)
12049
0
      vty_out(vty,
12050
0
      ", attach RT as-is for VPNv4 route filtering");
12051
0
    else if (route_filter_translated_v6)
12052
0
      vty_out(vty,
12053
0
      ", mark translated RTs for VPNv6 route filtering");
12054
0
    else if (route_filter_v6)
12055
0
      vty_out(vty,
12056
0
      ", attach RT as-is for VPNv6 route filtering");
12057
0
    else if (llgr_stale)
12058
0
      vty_out(vty,
12059
0
        ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12060
0
    else if (no_llgr)
12061
0
      vty_out(vty,
12062
0
      ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12063
0
    else if (accept_own_nexthop)
12064
0
      vty_out(vty,
12065
0
      ", accept local nexthop");
12066
0
    else if (blackhole)
12067
0
      vty_out(vty, ", inform peer to blackhole prefix");
12068
0
    else if (no_export)
12069
0
      vty_out(vty, ", not advertised to EBGP peer");
12070
0
    else if (no_advertise)
12071
0
      vty_out(vty, ", not advertised to any peer");
12072
0
    else if (local_as)
12073
0
      vty_out(vty, ", not advertised outside local AS");
12074
0
    else if (no_peer)
12075
0
      vty_out(vty,
12076
0
      ", inform EBGP peer not to advertise to their EBGP peers");
12077
12078
0
    if (suppress)
12079
0
      vty_out(vty,
12080
0
        ", Advertisements suppressed by an aggregate.");
12081
0
    vty_out(vty, ")\n");
12082
0
  }
12083
12084
  /* If we are not using addpath then we can display Advertised to and
12085
   * that will
12086
   * show what peers we advertised the bestpath to.  If we are using
12087
   * addpath
12088
   * though then we must display Advertised to on a path-by-path basis. */
12089
0
  if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
12090
0
    for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
12091
0
      if (bgp_adj_out_lookup(peer, dest, 0)) {
12092
0
        if (json && !json_adv_to)
12093
0
          json_adv_to = json_object_new_object();
12094
12095
0
        route_vty_out_advertised_to(
12096
0
          vty, peer, &first,
12097
0
          "  Advertised to non peer-group peers:\n ",
12098
0
          json_adv_to);
12099
0
      }
12100
0
    }
12101
12102
0
    if (json && json_adv_to) {
12103
0
      if (incremental_print) {
12104
0
        vty_out(vty, "\"advertisedTo\": ");
12105
0
        vty_json(vty, json_adv_to);
12106
0
        vty_out(vty, ",");
12107
0
      } else
12108
0
        json_object_object_add(json, "advertisedTo",
12109
0
                   json_adv_to);
12110
0
    } else {
12111
0
      if (!json && first)
12112
0
        vty_out(vty, "  Not advertised to any peer");
12113
0
      vty_out(vty, "\n");
12114
0
    }
12115
0
  }
12116
0
}
12117
12118
static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
12119
             struct bgp_dest *bgp_node, struct vty *vty,
12120
             struct bgp *bgp, afi_t afi, safi_t safi,
12121
             json_object *json, enum bgp_path_type pathtype,
12122
             int *display, enum rpki_states rpki_target_state)
12123
0
{
12124
0
  struct bgp_path_info *pi;
12125
0
  int header = 1;
12126
0
  json_object *json_header = NULL;
12127
0
  json_object *json_paths = NULL;
12128
0
  const struct prefix *p = bgp_dest_get_prefix(bgp_node);
12129
12130
0
  for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
12131
0
    enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
12132
12133
0
    if (p->family == AF_INET || p->family == AF_INET6)
12134
0
      rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12135
0
                pi->peer, pi->attr, p);
12136
12137
0
    if (rpki_target_state != RPKI_NOT_BEING_USED
12138
0
        && rpki_curr_state != rpki_target_state)
12139
0
      continue;
12140
12141
0
    if (json && !json_paths) {
12142
      /* Instantiate json_paths only if path is valid */
12143
0
      json_paths = json_object_new_array();
12144
0
      if (pfx_rd)
12145
0
        json_header = json_object_new_object();
12146
0
      else
12147
0
        json_header = json;
12148
0
    }
12149
12150
0
    if (header) {
12151
0
      route_vty_out_detail_header(
12152
0
        vty, bgp, bgp_node,
12153
0
        bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12154
0
        safi, json_header, false);
12155
0
      header = 0;
12156
0
    }
12157
0
    (*display)++;
12158
12159
0
    if (pathtype == BGP_PATH_SHOW_ALL
12160
0
        || (pathtype == BGP_PATH_SHOW_BESTPATH
12161
0
      && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12162
0
        || (pathtype == BGP_PATH_SHOW_MULTIPATH
12163
0
      && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12164
0
          || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
12165
0
      route_vty_out_detail(vty, bgp, bgp_node,
12166
0
               bgp_dest_get_prefix(bgp_node), pi,
12167
0
               AFI_IP, safi, rpki_curr_state,
12168
0
               json_paths);
12169
0
  }
12170
12171
0
  if (json && json_paths) {
12172
0
    json_object_object_add(json_header, "paths", json_paths);
12173
12174
0
    if (pfx_rd)
12175
0
      json_object_object_addf(
12176
0
        json, json_header,
12177
0
        BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
12178
0
  }
12179
0
}
12180
12181
/*
12182
 * Return rd based on safi
12183
 */
12184
const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12185
           safi_t safi)
12186
0
{
12187
0
  switch (safi) {
12188
0
  case SAFI_MPLS_VPN:
12189
0
  case SAFI_ENCAP:
12190
0
  case SAFI_EVPN:
12191
0
    return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12192
0
  case SAFI_UNSPEC:
12193
0
  case SAFI_UNICAST:
12194
0
  case SAFI_MULTICAST:
12195
0
  case SAFI_LABELED_UNICAST:
12196
0
  case SAFI_FLOWSPEC:
12197
0
  case SAFI_MAX:
12198
0
    return NULL;
12199
0
  }
12200
12201
0
  assert(!"Reached end of function when we were not expecting it");
12202
0
}
12203
12204
/* Display specified route of BGP table. */
12205
static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12206
           struct bgp_table *rib, const char *ip_str,
12207
           afi_t afi, safi_t safi,
12208
           enum rpki_states rpki_target_state,
12209
           struct prefix_rd *prd, int prefix_check,
12210
           enum bgp_path_type pathtype, bool use_json)
12211
0
{
12212
0
  int ret;
12213
0
  int display = 0;
12214
0
  struct prefix match;
12215
0
  struct bgp_dest *dest;
12216
0
  struct bgp_dest *rm;
12217
0
  struct bgp_table *table;
12218
0
  json_object *json = NULL;
12219
0
  json_object *json_paths = NULL;
12220
12221
  /* Check IP address argument. */
12222
0
  ret = str2prefix(ip_str, &match);
12223
0
  if (!ret) {
12224
0
    vty_out(vty, "address is malformed\n");
12225
0
    return CMD_WARNING;
12226
0
  }
12227
12228
0
  match.family = afi2family(afi);
12229
12230
0
  if (use_json)
12231
0
    json = json_object_new_object();
12232
12233
0
  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
12234
0
    for (dest = bgp_table_top(rib); dest;
12235
0
         dest = bgp_route_next(dest)) {
12236
0
      const struct prefix *dest_p = bgp_dest_get_prefix(dest);
12237
12238
0
      if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
12239
0
        continue;
12240
0
      table = bgp_dest_get_bgp_table_info(dest);
12241
0
      if (!table)
12242
0
        continue;
12243
12244
0
      rm = bgp_node_match(table, &match);
12245
0
      if (rm == NULL)
12246
0
        continue;
12247
12248
0
      const struct prefix *rm_p = bgp_dest_get_prefix(rm);
12249
0
      if (prefix_check
12250
0
          && rm_p->prefixlen != match.prefixlen) {
12251
0
        bgp_dest_unlock_node(rm);
12252
0
        continue;
12253
0
      }
12254
12255
0
      bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
12256
0
             bgp, afi, safi, json, pathtype,
12257
0
             &display, rpki_target_state);
12258
12259
0
      bgp_dest_unlock_node(rm);
12260
0
    }
12261
0
  } else if (safi == SAFI_EVPN) {
12262
0
    struct bgp_dest *longest_pfx;
12263
0
    bool is_exact_pfxlen_match = false;
12264
12265
0
    for (dest = bgp_table_top(rib); dest;
12266
0
         dest = bgp_route_next(dest)) {
12267
0
      const struct prefix *dest_p = bgp_dest_get_prefix(dest);
12268
12269
0
      if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
12270
0
        continue;
12271
0
      table = bgp_dest_get_bgp_table_info(dest);
12272
0
      if (!table)
12273
0
        continue;
12274
12275
0
      longest_pfx = NULL;
12276
0
      is_exact_pfxlen_match = false;
12277
      /*
12278
       * Search through all the prefixes for a match.  The
12279
       * pfx's are enumerated in ascending order of pfxlens.
12280
       * So, the last pfx match is the longest match.  Set
12281
       * is_exact_pfxlen_match when we get exact pfxlen match
12282
       */
12283
0
      for (rm = bgp_table_top(table); rm;
12284
0
        rm = bgp_route_next(rm)) {
12285
0
        const struct prefix *rm_p =
12286
0
          bgp_dest_get_prefix(rm);
12287
        /*
12288
         * Get prefixlen of the ip-prefix within type5
12289
         * evpn route
12290
         */
12291
0
        if (evpn_type5_prefix_match(rm_p, &match)
12292
0
            && rm->info) {
12293
0
          longest_pfx = rm;
12294
0
          int type5_pfxlen =
12295
0
            bgp_evpn_get_type5_prefixlen(
12296
0
              rm_p);
12297
0
          if (type5_pfxlen == match.prefixlen) {
12298
0
            is_exact_pfxlen_match = true;
12299
0
            bgp_dest_unlock_node(rm);
12300
0
            break;
12301
0
          }
12302
0
        }
12303
0
      }
12304
12305
0
      if (!longest_pfx)
12306
0
        continue;
12307
12308
0
      if (prefix_check && !is_exact_pfxlen_match)
12309
0
        continue;
12310
12311
0
      rm = longest_pfx;
12312
0
      bgp_dest_lock_node(rm);
12313
12314
0
      bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
12315
0
             bgp, afi, safi, json, pathtype,
12316
0
             &display, rpki_target_state);
12317
12318
0
      bgp_dest_unlock_node(rm);
12319
0
    }
12320
0
  } else if (safi == SAFI_FLOWSPEC) {
12321
0
    if (use_json)
12322
0
      json_paths = json_object_new_array();
12323
12324
0
    display = bgp_flowspec_display_match_per_ip(afi, rib,
12325
0
             &match, prefix_check,
12326
0
             vty,
12327
0
             use_json,
12328
0
             json_paths);
12329
0
    if (use_json) {
12330
0
      if (display)
12331
0
        json_object_object_add(json, "paths",
12332
0
                   json_paths);
12333
0
      else
12334
0
        json_object_free(json_paths);
12335
0
    }
12336
0
  } else {
12337
0
    dest = bgp_node_match(rib, &match);
12338
0
    if (dest != NULL) {
12339
0
      const struct prefix *dest_p = bgp_dest_get_prefix(dest);
12340
0
      if (!prefix_check
12341
0
          || dest_p->prefixlen == match.prefixlen) {
12342
0
        bgp_show_path_info(NULL, dest, vty, bgp, afi,
12343
0
               safi, json, pathtype,
12344
0
               &display, rpki_target_state);
12345
0
      }
12346
12347
0
      bgp_dest_unlock_node(dest);
12348
0
    }
12349
0
  }
12350
12351
0
  if (use_json) {
12352
0
    vty_json(vty, json);
12353
0
  } else {
12354
0
    if (!display) {
12355
0
      vty_out(vty, "%% Network not in table\n");
12356
0
      return CMD_WARNING;
12357
0
    }
12358
0
  }
12359
12360
0
  return CMD_SUCCESS;
12361
0
}
12362
12363
/* Display specified route of Main RIB */
12364
static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12365
        afi_t afi, safi_t safi, struct prefix_rd *prd,
12366
        int prefix_check, enum bgp_path_type pathtype,
12367
        enum rpki_states rpki_target_state, bool use_json)
12368
0
{
12369
0
  if (!bgp) {
12370
0
    bgp = bgp_get_default();
12371
0
    if (!bgp) {
12372
0
      if (!use_json)
12373
0
        vty_out(vty, "No BGP process is configured\n");
12374
0
      else
12375
0
        vty_out(vty, "{}\n");
12376
0
      return CMD_WARNING;
12377
0
    }
12378
0
  }
12379
12380
  /* labeled-unicast routes live in the unicast table */
12381
0
  if (safi == SAFI_LABELED_UNICAST)
12382
0
    safi = SAFI_UNICAST;
12383
12384
0
  return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
12385
0
               afi, safi, rpki_target_state, prd,
12386
0
               prefix_check, pathtype, use_json);
12387
0
}
12388
12389
static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
12390
             struct cmd_token **argv, bool exact, afi_t afi,
12391
             safi_t safi, bool uj)
12392
0
{
12393
0
  struct lcommunity *lcom;
12394
0
  struct buffer *b;
12395
0
  int i;
12396
0
  char *str;
12397
0
  int first = 0;
12398
0
  uint16_t show_flags = 0;
12399
0
  int ret;
12400
12401
0
  if (uj)
12402
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12403
12404
0
  b = buffer_new(1024);
12405
0
  for (i = 0; i < argc; i++) {
12406
0
    if (first)
12407
0
      buffer_putc(b, ' ');
12408
0
    else {
12409
0
      if (strmatch(argv[i]->text, "AA:BB:CC")) {
12410
0
        first = 1;
12411
0
        buffer_putstr(b, argv[i]->arg);
12412
0
      }
12413
0
    }
12414
0
  }
12415
0
  buffer_putc(b, '\0');
12416
12417
0
  str = buffer_getstr(b);
12418
0
  buffer_free(b);
12419
12420
0
  lcom = lcommunity_str2com(str);
12421
0
  XFREE(MTYPE_TMP, str);
12422
0
  if (!lcom) {
12423
0
    vty_out(vty, "%% Large-community malformed\n");
12424
0
    return CMD_WARNING;
12425
0
  }
12426
12427
0
  ret = bgp_show(vty, bgp, afi, safi,
12428
0
           (exact ? bgp_show_type_lcommunity_exact
12429
0
            : bgp_show_type_lcommunity),
12430
0
           lcom, show_flags, RPKI_NOT_BEING_USED);
12431
12432
0
  lcommunity_free(&lcom);
12433
0
  return ret;
12434
0
}
12435
12436
static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
12437
            const char *lcom, bool exact, afi_t afi,
12438
            safi_t safi, bool uj)
12439
0
{
12440
0
  struct community_list *list;
12441
0
  uint16_t show_flags = 0;
12442
12443
0
  if (uj)
12444
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12445
12446
12447
0
  list = community_list_lookup(bgp_clist, lcom, 0,
12448
0
             LARGE_COMMUNITY_LIST_MASTER);
12449
0
  if (list == NULL) {
12450
0
    vty_out(vty, "%% %s is not a valid large-community-list name\n",
12451
0
      lcom);
12452
0
    return CMD_WARNING;
12453
0
  }
12454
12455
0
  return bgp_show(vty, bgp, afi, safi,
12456
0
      (exact ? bgp_show_type_lcommunity_list_exact
12457
0
             : bgp_show_type_lcommunity_list),
12458
0
      list, show_flags, RPKI_NOT_BEING_USED);
12459
0
}
12460
12461
DEFUN (show_ip_bgp_large_community_list,
12462
       show_ip_bgp_large_community_list_cmd,
12463
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
12464
       SHOW_STR
12465
       IP_STR
12466
       BGP_STR
12467
       BGP_INSTANCE_HELP_STR
12468
       BGP_AFI_HELP_STR
12469
       BGP_SAFI_WITH_LABEL_HELP_STR
12470
       "Display routes matching the large-community-list\n"
12471
       "large-community-list number\n"
12472
       "large-community-list name\n"
12473
       "Exact match of the large-communities\n"
12474
       JSON_STR)
12475
0
{
12476
0
  afi_t afi = AFI_IP6;
12477
0
  safi_t safi = SAFI_UNICAST;
12478
0
  int idx = 0;
12479
0
  bool exact_match = 0;
12480
0
  struct bgp *bgp = NULL;
12481
0
  bool uj = use_json(argc, argv);
12482
12483
0
  if (uj)
12484
0
    argc--;
12485
12486
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12487
0
              &bgp, uj);
12488
0
  if (!idx)
12489
0
    return CMD_WARNING;
12490
12491
0
  argv_find(argv, argc, "large-community-list", &idx);
12492
12493
0
  const char *clist_number_or_name = argv[++idx]->arg;
12494
12495
0
  if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12496
0
    exact_match = 1;
12497
12498
0
  return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12499
0
          exact_match, afi, safi, uj);
12500
0
}
12501
DEFUN (show_ip_bgp_large_community,
12502
       show_ip_bgp_large_community_cmd,
12503
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12504
       SHOW_STR
12505
       IP_STR
12506
       BGP_STR
12507
       BGP_INSTANCE_HELP_STR
12508
       BGP_AFI_HELP_STR
12509
       BGP_SAFI_WITH_LABEL_HELP_STR
12510
       "Display routes matching the large-communities\n"
12511
       "List of large-community numbers\n"
12512
       "Exact match of the large-communities\n"
12513
       JSON_STR)
12514
0
{
12515
0
  afi_t afi = AFI_IP6;
12516
0
  safi_t safi = SAFI_UNICAST;
12517
0
  int idx = 0;
12518
0
  bool exact_match = 0;
12519
0
  struct bgp *bgp = NULL;
12520
0
  bool uj = use_json(argc, argv);
12521
0
  uint16_t show_flags = 0;
12522
12523
0
  if (uj) {
12524
0
    argc--;
12525
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12526
0
  }
12527
12528
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12529
0
              &bgp, uj);
12530
0
  if (!idx)
12531
0
    return CMD_WARNING;
12532
12533
0
  if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12534
0
    if (argv_find(argv, argc, "exact-match", &idx)) {
12535
0
      argc--;
12536
0
      exact_match = 1;
12537
0
    }
12538
0
    return bgp_show_lcommunity(vty, bgp, argc, argv,
12539
0
          exact_match, afi, safi, uj);
12540
0
  } else
12541
0
    return bgp_show(vty, bgp, afi, safi,
12542
0
        bgp_show_type_lcommunity_all, NULL, show_flags,
12543
0
        RPKI_NOT_BEING_USED);
12544
0
}
12545
12546
static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12547
          safi_t safi, struct json_object *json_array);
12548
static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12549
         safi_t safi, struct json_object *json);
12550
12551
12552
DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12553
      "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12554
      SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12555
      "Display number of prefixes for all afi/safi\n" JSON_STR)
12556
0
{
12557
0
  bool uj = use_json(argc, argv);
12558
0
  struct bgp *bgp = NULL;
12559
0
  safi_t safi = SAFI_UNICAST;
12560
0
  afi_t afi = AFI_IP6;
12561
0
  int idx = 0;
12562
0
  struct json_object *json_all = NULL;
12563
0
  struct json_object *json_afi_safi = NULL;
12564
12565
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12566
0
              &bgp, false);
12567
0
  if (!idx)
12568
0
    return CMD_WARNING;
12569
12570
0
  if (uj)
12571
0
    json_all = json_object_new_object();
12572
12573
0
  FOREACH_AFI_SAFI (afi, safi) {
12574
    /*
12575
     * So limit output to those afi/safi pairs that
12576
     * actually have something interesting in them
12577
     */
12578
0
    if (strmatch(get_afi_safi_str(afi, safi, true),
12579
0
           "Unknown")) {
12580
0
      continue;
12581
0
    }
12582
0
    if (uj) {
12583
0
      json_afi_safi = json_object_new_array();
12584
0
      json_object_object_add(
12585
0
                 json_all,
12586
0
                 get_afi_safi_str(afi, safi, true),
12587
0
                 json_afi_safi);
12588
0
    } else {
12589
0
      json_afi_safi = NULL;
12590
0
    }
12591
12592
0
    bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12593
0
  }
12594
12595
0
  if (uj)
12596
0
    vty_json(vty, json_all);
12597
12598
0
  return CMD_SUCCESS;
12599
0
}
12600
12601
/* BGP route print out function without JSON */
12602
DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12603
       show_ip_bgp_l2vpn_evpn_statistics_cmd,
12604
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12605
       SHOW_STR
12606
       IP_STR
12607
       BGP_STR
12608
       BGP_INSTANCE_HELP_STR
12609
       L2VPN_HELP_STR
12610
       EVPN_HELP_STR
12611
       "BGP RIB advertisement statistics\n"
12612
       JSON_STR)
12613
0
{
12614
0
  afi_t afi = AFI_IP6;
12615
0
  safi_t safi = SAFI_UNICAST;
12616
0
  struct bgp *bgp = NULL;
12617
0
  int idx = 0, ret;
12618
0
  bool uj = use_json(argc, argv);
12619
0
  struct json_object *json_afi_safi = NULL, *json = NULL;
12620
12621
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12622
0
              &bgp, false);
12623
0
  if (!idx)
12624
0
    return CMD_WARNING;
12625
12626
0
  if (uj)
12627
0
    json_afi_safi = json_object_new_array();
12628
0
  else
12629
0
    json_afi_safi = NULL;
12630
12631
0
  ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12632
12633
0
  if (uj) {
12634
0
    json = json_object_new_object();
12635
0
    json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12636
0
               json_afi_safi);
12637
0
    vty_json(vty, json);
12638
0
  }
12639
0
  return ret;
12640
0
}
12641
12642
/* BGP route print out function without JSON */
12643
DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12644
      "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12645
      " [" BGP_SAFI_WITH_LABEL_CMD_STR
12646
      "]]\
12647
         statistics [json]",
12648
      SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12649
        BGP_SAFI_WITH_LABEL_HELP_STR
12650
      "BGP RIB advertisement statistics\n" JSON_STR)
12651
0
{
12652
0
  afi_t afi = AFI_IP6;
12653
0
  safi_t safi = SAFI_UNICAST;
12654
0
  struct bgp *bgp = NULL;
12655
0
  int idx = 0, ret;
12656
0
  bool uj = use_json(argc, argv);
12657
0
  struct json_object *json_afi_safi = NULL, *json = NULL;
12658
12659
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12660
0
              &bgp, false);
12661
0
  if (!idx)
12662
0
    return CMD_WARNING;
12663
12664
0
  if (uj)
12665
0
    json_afi_safi = json_object_new_array();
12666
0
  else
12667
0
    json_afi_safi = NULL;
12668
12669
0
  ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12670
12671
0
  if (uj) {
12672
0
    json = json_object_new_object();
12673
0
    json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12674
0
               json_afi_safi);
12675
0
    vty_json(vty, json);
12676
0
  }
12677
0
  return ret;
12678
0
}
12679
12680
DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
12681
      "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12682
      " [" BGP_SAFI_WITH_LABEL_CMD_STR
12683
      "]] [all$all] dampening parameters [json]",
12684
      SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12685
        BGP_SAFI_WITH_LABEL_HELP_STR
12686
      "Display the entries for all address families\n"
12687
      "Display detailed information about dampening\n"
12688
      "Display detail of configured dampening parameters\n"
12689
      JSON_STR)
12690
0
{
12691
0
  afi_t afi = AFI_IP6;
12692
0
  safi_t safi = SAFI_UNICAST;
12693
0
  struct bgp *bgp = NULL;
12694
0
  int idx = 0;
12695
0
  uint16_t show_flags = 0;
12696
0
  bool uj = use_json(argc, argv);
12697
12698
0
  if (uj) {
12699
0
    argc--;
12700
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12701
0
  }
12702
12703
  /* [<ipv4|ipv6> [all]] */
12704
0
  if (all) {
12705
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12706
0
    if (argv_find(argv, argc, "ipv4", &idx))
12707
0
      SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12708
12709
0
    if (argv_find(argv, argc, "ipv6", &idx))
12710
0
      SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12711
0
  }
12712
12713
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12714
0
              &bgp, false);
12715
0
  if (!idx)
12716
0
    return CMD_WARNING;
12717
12718
0
  return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
12719
0
}
12720
12721
/* BGP route print out function */
12722
DEFPY(show_ip_bgp, show_ip_bgp_cmd,
12723
      "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12724
      " [" BGP_SAFI_WITH_LABEL_CMD_STR
12725
      "]]\
12726
          [all$all]\
12727
          [cidr-only\
12728
          |dampening <flap-statistics|dampened-paths>\
12729
          |community [AA:NN|local-AS|no-advertise|no-export\
12730
                     |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12731
                     |accept-own|accept-own-nexthop|route-filter-v6\
12732
                     |route-filter-v4|route-filter-translated-v6\
12733
                     |route-filter-translated-v4] [exact-match]\
12734
          |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12735
          |filter-list AS_PATH_FILTER_NAME\
12736
          |prefix-list WORD\
12737
          |access-list ACCESSLIST_NAME\
12738
          |route-map RMAP_NAME\
12739
          |rpki <invalid|valid|notfound>\
12740
          |version (1-4294967295)\
12741
          |alias ALIAS_NAME\
12742
          |A.B.C.D/M longer-prefixes\
12743
          |X:X::X:X/M longer-prefixes\
12744
          |"BGP_SELF_ORIG_CMD_STR"\
12745
          |detail-routes$detail_routes\
12746
          ] [json$uj [detail$detail_json] | wide$wide]",
12747
      SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12748
        BGP_SAFI_WITH_LABEL_HELP_STR
12749
      "Display the entries for all address families\n"
12750
      "Display only routes with non-natural netmasks\n"
12751
      "Display detailed information about dampening\n"
12752
      "Display flap statistics of routes\n"
12753
      "Display paths suppressed due to dampening\n"
12754
      "Display routes matching the communities\n" COMMUNITY_AANN_STR
12755
      "Do not send outside local AS (well-known community)\n"
12756
      "Do not advertise to any peer (well-known community)\n"
12757
      "Do not export to next AS (well-known community)\n"
12758
      "Graceful shutdown (well-known community)\n"
12759
      "Do not export to any peer (well-known community)\n"
12760
      "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12761
      "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12762
      "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12763
      "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12764
      "Should accept VPN route with local nexthop (well-known community)\n"
12765
      "RT VPNv6 route filtering (well-known community)\n"
12766
      "RT VPNv4 route filtering (well-known community)\n"
12767
      "RT translated VPNv6 route filtering (well-known community)\n"
12768
      "RT translated VPNv4 route filtering (well-known community)\n"
12769
      "Exact match of the communities\n"
12770
      "Community-list number\n"
12771
      "Community-list name\n"
12772
      "Display routes matching the community-list\n"
12773
      "Exact match of the communities\n"
12774
      "Display routes conforming to the filter-list\n"
12775
      "Regular expression access list name\n"
12776
      "Display routes conforming to the prefix-list\n"
12777
      "Prefix-list name\n"
12778
      "Display routes conforming to the access-list\n"
12779
      "Access-list name\n"
12780
      "Display routes matching the route-map\n"
12781
      "A route-map to match on\n"
12782
      "RPKI route types\n"
12783
      "A valid path as determined by rpki\n"
12784
      "A invalid path as determined by rpki\n"
12785
      "A path that has no rpki data\n"
12786
      "Display prefixes with matching version numbers\n"
12787
      "Version number and above\n"
12788
      "Display prefixes with matching BGP community alias\n"
12789
      "BGP community alias\n"
12790
      "IPv4 prefix\n"
12791
      "Display route and more specific routes\n"
12792
      "IPv6 prefix\n"
12793
      "Display route and more specific routes\n"
12794
      BGP_SELF_ORIG_HELP_STR
12795
      "Display detailed version of all routes\n"
12796
      JSON_STR
12797
      "Display detailed version of JSON output\n"
12798
      "Increase table width for longer prefixes\n")
12799
0
{
12800
0
  afi_t afi = AFI_IP6;
12801
0
  safi_t safi = SAFI_UNICAST;
12802
0
  enum bgp_show_type sh_type = bgp_show_type_normal;
12803
0
  void *output_arg = NULL;
12804
0
  struct bgp *bgp = NULL;
12805
0
  int idx = 0;
12806
0
  int exact_match = 0;
12807
0
  char *community = NULL;
12808
0
  bool first = true;
12809
0
  uint16_t show_flags = 0;
12810
0
  enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
12811
0
  struct prefix p;
12812
12813
0
  if (uj) {
12814
0
    argc--;
12815
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12816
0
  }
12817
12818
0
  if (detail_json)
12819
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
12820
12821
0
  if (detail_routes)
12822
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
12823
12824
  /* [<ipv4|ipv6> [all]] */
12825
0
  if (all) {
12826
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12827
12828
0
    if (argv_find(argv, argc, "ipv4", &idx))
12829
0
      SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12830
12831
0
    if (argv_find(argv, argc, "ipv6", &idx))
12832
0
      SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12833
0
  }
12834
12835
0
  if (wide)
12836
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12837
12838
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12839
0
              &bgp, uj);
12840
0
  if (!idx)
12841
0
    return CMD_WARNING;
12842
12843
0
  if (argv_find(argv, argc, "cidr-only", &idx))
12844
0
    sh_type = bgp_show_type_cidr_only;
12845
12846
0
  if (argv_find(argv, argc, "dampening", &idx)) {
12847
0
    if (argv_find(argv, argc, "dampened-paths", &idx))
12848
0
      sh_type = bgp_show_type_dampend_paths;
12849
0
    else if (argv_find(argv, argc, "flap-statistics", &idx))
12850
0
      sh_type = bgp_show_type_flap_statistics;
12851
0
  }
12852
12853
0
  if (argv_find(argv, argc, "community", &idx)) {
12854
0
    char *maybecomm = NULL;
12855
12856
0
    if (idx + 1 < argc) {
12857
0
      if (argv[idx + 1]->type == VARIABLE_TKN)
12858
0
        maybecomm = argv[idx + 1]->arg;
12859
0
      else
12860
0
        maybecomm = argv[idx + 1]->text;
12861
0
    }
12862
12863
0
    if (maybecomm && !strmatch(maybecomm, "json")
12864
0
        && !strmatch(maybecomm, "exact-match"))
12865
0
      community = maybecomm;
12866
12867
0
    if (argv_find(argv, argc, "exact-match", &idx))
12868
0
      exact_match = 1;
12869
12870
0
    if (!community)
12871
0
      sh_type = bgp_show_type_community_all;
12872
0
  }
12873
12874
0
  if (argv_find(argv, argc, "community-list", &idx)) {
12875
0
    const char *clist_number_or_name = argv[++idx]->arg;
12876
0
    struct community_list *list;
12877
12878
0
    if (argv_find(argv, argc, "exact-match", &idx))
12879
0
      exact_match = 1;
12880
12881
0
    list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12882
0
               COMMUNITY_LIST_MASTER);
12883
0
    if (list == NULL) {
12884
0
      vty_out(vty, "%% %s community-list not found\n",
12885
0
        clist_number_or_name);
12886
0
      return CMD_WARNING;
12887
0
    }
12888
12889
0
    if (exact_match)
12890
0
      sh_type = bgp_show_type_community_list_exact;
12891
0
    else
12892
0
      sh_type = bgp_show_type_community_list;
12893
0
    output_arg = list;
12894
0
  }
12895
12896
0
  if (argv_find(argv, argc, "filter-list", &idx)) {
12897
0
    const char *filter = argv[++idx]->arg;
12898
0
    struct as_list *as_list;
12899
12900
0
    as_list = as_list_lookup(filter);
12901
0
    if (as_list == NULL) {
12902
0
      vty_out(vty, "%% %s AS-path access-list not found\n",
12903
0
        filter);
12904
0
      return CMD_WARNING;
12905
0
    }
12906
12907
0
    sh_type = bgp_show_type_filter_list;
12908
0
    output_arg = as_list;
12909
0
  }
12910
12911
0
  if (argv_find(argv, argc, "prefix-list", &idx)) {
12912
0
    const char *prefix_list_str = argv[++idx]->arg;
12913
0
    struct prefix_list *plist;
12914
12915
0
    plist = prefix_list_lookup(afi, prefix_list_str);
12916
0
    if (plist == NULL) {
12917
0
      vty_out(vty, "%% %s prefix-list not found\n",
12918
0
        prefix_list_str);
12919
0
      return CMD_WARNING;
12920
0
    }
12921
12922
0
    sh_type = bgp_show_type_prefix_list;
12923
0
    output_arg = plist;
12924
0
  }
12925
12926
0
  if (argv_find(argv, argc, "access-list", &idx)) {
12927
0
    const char *access_list_str = argv[++idx]->arg;
12928
0
    struct access_list *alist;
12929
12930
0
    alist = access_list_lookup(afi, access_list_str);
12931
0
    if (!alist) {
12932
0
      vty_out(vty, "%% %s access-list not found\n",
12933
0
        access_list_str);
12934
0
      return CMD_WARNING;
12935
0
    }
12936
12937
0
    sh_type = bgp_show_type_access_list;
12938
0
    output_arg = alist;
12939
0
  }
12940
12941
0
  if (argv_find(argv, argc, "route-map", &idx)) {
12942
0
    const char *rmap_str = argv[++idx]->arg;
12943
0
    struct route_map *rmap;
12944
12945
0
    rmap = route_map_lookup_by_name(rmap_str);
12946
0
    if (!rmap) {
12947
0
      vty_out(vty, "%% %s route-map not found\n", rmap_str);
12948
0
      return CMD_WARNING;
12949
0
    }
12950
12951
0
    sh_type = bgp_show_type_route_map;
12952
0
    output_arg = rmap;
12953
0
  }
12954
12955
0
  if (argv_find(argv, argc, "rpki", &idx)) {
12956
0
    sh_type = bgp_show_type_rpki;
12957
0
    if (argv_find(argv, argc, "valid", &idx))
12958
0
      rpki_target_state = RPKI_VALID;
12959
0
    else if (argv_find(argv, argc, "invalid", &idx))
12960
0
      rpki_target_state = RPKI_INVALID;
12961
0
    else if (argv_find(argv, argc, "notfound", &idx))
12962
0
      rpki_target_state = RPKI_NOTFOUND;
12963
0
  }
12964
12965
  /* Display prefixes with matching version numbers */
12966
0
  if (argv_find(argv, argc, "version", &idx)) {
12967
0
    sh_type = bgp_show_type_prefix_version;
12968
0
    output_arg = argv[idx + 1]->arg;
12969
0
  }
12970
12971
  /* Display prefixes with matching BGP community alias */
12972
0
  if (argv_find(argv, argc, "alias", &idx)) {
12973
0
    sh_type = bgp_show_type_community_alias;
12974
0
    output_arg = argv[idx + 1]->arg;
12975
0
  }
12976
12977
  /* prefix-longer */
12978
0
  if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12979
0
      || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12980
0
    const char *prefix_str = argv[idx]->arg;
12981
12982
0
    if (!str2prefix(prefix_str, &p)) {
12983
0
      vty_out(vty, "%% Malformed Prefix\n");
12984
0
      return CMD_WARNING;
12985
0
    }
12986
12987
0
    sh_type = bgp_show_type_prefix_longer;
12988
0
    output_arg = &p;
12989
0
  }
12990
12991
  /* self originated only */
12992
0
  if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12993
0
    sh_type = bgp_show_type_self_originated;
12994
12995
0
  if (!all) {
12996
    /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12997
0
    if (community)
12998
0
      return bgp_show_community(vty, bgp, community,
12999
0
              exact_match, afi, safi,
13000
0
              show_flags);
13001
0
    else
13002
0
      return bgp_show(vty, bgp, afi, safi, sh_type,
13003
0
          output_arg, show_flags,
13004
0
          rpki_target_state);
13005
0
  } else {
13006
0
    struct listnode *node;
13007
0
    struct bgp *abgp;
13008
    /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
13009
     * AFI_IP6 */
13010
13011
0
    if (uj)
13012
0
      vty_out(vty, "{\n");
13013
13014
0
    if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13015
0
        || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13016
0
      afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13017
0
              ? AFI_IP
13018
0
              : AFI_IP6;
13019
0
      for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
13020
0
        FOREACH_SAFI (safi) {
13021
0
          if (!bgp_afi_safi_peer_exists(abgp, afi,
13022
0
                      safi))
13023
0
            continue;
13024
13025
0
          if (uj) {
13026
0
            if (first)
13027
0
              first = false;
13028
0
            else
13029
0
              vty_out(vty, ",\n");
13030
0
            vty_out(vty, "\"%s\":{\n",
13031
0
              get_afi_safi_str(afi,
13032
0
                   safi,
13033
0
                   true));
13034
0
          } else
13035
0
            vty_out(vty,
13036
0
              "\nFor address family: %s\n",
13037
0
              get_afi_safi_str(
13038
0
                afi, safi,
13039
0
                false));
13040
13041
0
          if (community)
13042
0
            bgp_show_community(
13043
0
              vty, abgp, community,
13044
0
              exact_match, afi, safi,
13045
0
              show_flags);
13046
0
          else
13047
0
            bgp_show(vty, abgp, afi, safi,
13048
0
               sh_type, output_arg,
13049
0
               show_flags,
13050
0
               rpki_target_state);
13051
0
          if (uj)
13052
0
            vty_out(vty, "}\n");
13053
0
        }
13054
0
      }
13055
0
    } else {
13056
      /* show <ip> bgp all: for each AFI and SAFI*/
13057
0
      for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
13058
0
        FOREACH_AFI_SAFI (afi, safi) {
13059
0
          if (!bgp_afi_safi_peer_exists(abgp, afi,
13060
0
                      safi))
13061
0
            continue;
13062
13063
0
          if (uj) {
13064
0
            if (first)
13065
0
              first = false;
13066
0
            else
13067
0
              vty_out(vty, ",\n");
13068
13069
0
            vty_out(vty, "\"%s\":{\n",
13070
0
              get_afi_safi_str(afi,
13071
0
                   safi,
13072
0
                   true));
13073
13074
            /* Adding 'routes' key to make
13075
             * the json output format valid
13076
             * for evpn
13077
             */
13078
0
            if (safi == SAFI_EVPN)
13079
0
              vty_out(vty,
13080
0
                "\"routes\":");
13081
13082
0
          } else
13083
0
            vty_out(vty,
13084
0
              "\nFor address family: %s\n",
13085
0
              get_afi_safi_str(
13086
0
                afi, safi,
13087
0
                false));
13088
13089
0
          if (community)
13090
0
            bgp_show_community(
13091
0
              vty, abgp, community,
13092
0
              exact_match, afi, safi,
13093
0
              show_flags);
13094
0
          else
13095
0
            bgp_show(vty, abgp, afi, safi,
13096
0
               sh_type, output_arg,
13097
0
               show_flags,
13098
0
               rpki_target_state);
13099
0
          if (uj)
13100
0
            vty_out(vty, "}\n");
13101
0
        }
13102
0
      }
13103
0
    }
13104
0
    if (uj)
13105
0
      vty_out(vty, "}\n");
13106
0
  }
13107
0
  return CMD_SUCCESS;
13108
0
}
13109
13110
DEFUN (show_ip_bgp_route,
13111
       show_ip_bgp_route_cmd,
13112
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
13113
       SHOW_STR
13114
       IP_STR
13115
       BGP_STR
13116
       BGP_INSTANCE_HELP_STR
13117
       BGP_AFI_HELP_STR
13118
       BGP_SAFI_WITH_LABEL_HELP_STR
13119
       "Network in the BGP routing table to display\n"
13120
       "IPv4 prefix\n"
13121
       "Network in the BGP routing table to display\n"
13122
       "IPv6 prefix\n"
13123
       "Display only the bestpath\n"
13124
       "Display only multipaths\n"
13125
       "Display only paths that match the specified rpki state\n"
13126
       "A valid path as determined by rpki\n"
13127
       "A invalid path as determined by rpki\n"
13128
       "A path that has no rpki data\n"
13129
       JSON_STR)
13130
0
{
13131
0
  int prefix_check = 0;
13132
13133
0
  afi_t afi = AFI_IP6;
13134
0
  safi_t safi = SAFI_UNICAST;
13135
0
  char *prefix = NULL;
13136
0
  struct bgp *bgp = NULL;
13137
0
  enum bgp_path_type path_type;
13138
0
  bool uj = use_json(argc, argv);
13139
13140
0
  int idx = 0;
13141
13142
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13143
0
              &bgp, uj);
13144
0
  if (!idx)
13145
0
    return CMD_WARNING;
13146
13147
0
  if (!bgp) {
13148
0
    vty_out(vty,
13149
0
      "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13150
0
    return CMD_WARNING;
13151
0
  }
13152
13153
  /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13154
0
  if (argv_find(argv, argc, "A.B.C.D", &idx)
13155
0
      || argv_find(argv, argc, "X:X::X:X", &idx))
13156
0
    prefix_check = 0;
13157
0
  else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13158
0
     || argv_find(argv, argc, "X:X::X:X/M", &idx))
13159
0
    prefix_check = 1;
13160
13161
0
  if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13162
0
      && afi != AFI_IP6) {
13163
0
    vty_out(vty,
13164
0
      "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13165
0
    return CMD_WARNING;
13166
0
  }
13167
0
  if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13168
0
      && afi != AFI_IP) {
13169
0
    vty_out(vty,
13170
0
      "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13171
0
    return CMD_WARNING;
13172
0
  }
13173
13174
0
  prefix = argv[idx]->arg;
13175
13176
  /* [<bestpath|multipath>] */
13177
0
  if (argv_find(argv, argc, "bestpath", &idx))
13178
0
    path_type = BGP_PATH_SHOW_BESTPATH;
13179
0
  else if (argv_find(argv, argc, "multipath", &idx))
13180
0
    path_type = BGP_PATH_SHOW_MULTIPATH;
13181
0
  else
13182
0
    path_type = BGP_PATH_SHOW_ALL;
13183
13184
0
  return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
13185
0
            path_type, RPKI_NOT_BEING_USED, uj);
13186
0
}
13187
13188
DEFUN (show_ip_bgp_regexp,
13189
       show_ip_bgp_regexp_cmd,
13190
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
13191
       SHOW_STR
13192
       IP_STR
13193
       BGP_STR
13194
       BGP_INSTANCE_HELP_STR
13195
       BGP_AFI_HELP_STR
13196
       BGP_SAFI_WITH_LABEL_HELP_STR
13197
       "Display routes matching the AS path regular expression\n"
13198
       "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13199
       JSON_STR)
13200
0
{
13201
0
  afi_t afi = AFI_IP6;
13202
0
  safi_t safi = SAFI_UNICAST;
13203
0
  struct bgp *bgp = NULL;
13204
0
  bool uj = use_json(argc, argv);
13205
0
  char *regstr = NULL;
13206
13207
0
  int idx = 0;
13208
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13209
0
              &bgp, false);
13210
0
  if (!idx)
13211
0
    return CMD_WARNING;
13212
13213
  // get index of regex
13214
0
  if (argv_find(argv, argc, "REGEX", &idx))
13215
0
    regstr = argv[idx]->arg;
13216
13217
0
  assert(regstr);
13218
0
  return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13219
0
         bgp_show_type_regexp, uj);
13220
0
}
13221
13222
DEFPY (show_ip_bgp_instance_all,
13223
       show_ip_bgp_instance_all_cmd,
13224
       "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
13225
       SHOW_STR
13226
       IP_STR
13227
       BGP_STR
13228
       BGP_INSTANCE_ALL_HELP_STR
13229
       BGP_AFI_HELP_STR
13230
       BGP_SAFI_WITH_LABEL_HELP_STR
13231
       JSON_STR
13232
      "Increase table width for longer prefixes\n")
13233
0
{
13234
0
  afi_t afi = AFI_IP6;
13235
0
  safi_t safi = SAFI_UNICAST;
13236
0
  struct bgp *bgp = NULL;
13237
0
  int idx = 0;
13238
0
  uint16_t show_flags = 0;
13239
13240
0
  if (uj) {
13241
0
    argc--;
13242
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13243
0
  }
13244
13245
0
  if (wide)
13246
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13247
13248
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13249
0
              &bgp, uj);
13250
0
  if (!idx)
13251
0
    return CMD_WARNING;
13252
13253
0
  bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
13254
0
  return CMD_SUCCESS;
13255
0
}
13256
13257
static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
13258
         afi_t afi, safi_t safi, enum bgp_show_type type,
13259
         bool use_json)
13260
0
{
13261
0
  regex_t *regex;
13262
0
  int rc;
13263
0
  uint16_t show_flags = 0;
13264
13265
0
  if (use_json)
13266
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13267
13268
0
  if (!config_bgp_aspath_validate(regstr)) {
13269
0
    vty_out(vty, "Invalid character in REGEX %s\n",
13270
0
      regstr);
13271
0
    return CMD_WARNING_CONFIG_FAILED;
13272
0
  }
13273
13274
0
  regex = bgp_regcomp(regstr);
13275
0
  if (!regex) {
13276
0
    vty_out(vty, "Can't compile regexp %s\n", regstr);
13277
0
    return CMD_WARNING;
13278
0
  }
13279
13280
0
  rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13281
0
          RPKI_NOT_BEING_USED);
13282
0
  bgp_regex_free(regex);
13283
0
  return rc;
13284
0
}
13285
13286
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13287
            const char *comstr, int exact, afi_t afi,
13288
            safi_t safi, uint16_t show_flags)
13289
0
{
13290
0
  struct community *com;
13291
0
  int ret = 0;
13292
13293
0
  com = community_str2com(comstr);
13294
0
  if (!com) {
13295
0
    vty_out(vty, "%% Community malformed: %s\n", comstr);
13296
0
    return CMD_WARNING;
13297
0
  }
13298
13299
0
  ret = bgp_show(vty, bgp, afi, safi,
13300
0
           (exact ? bgp_show_type_community_exact
13301
0
            : bgp_show_type_community),
13302
0
           com, show_flags, RPKI_NOT_BEING_USED);
13303
0
  community_free(&com);
13304
13305
0
  return ret;
13306
0
}
13307
13308
enum bgp_stats {
13309
  BGP_STATS_MAXBITLEN = 0,
13310
  BGP_STATS_RIB,
13311
  BGP_STATS_PREFIXES,
13312
  BGP_STATS_TOTPLEN,
13313
  BGP_STATS_UNAGGREGATEABLE,
13314
  BGP_STATS_MAX_AGGREGATEABLE,
13315
  BGP_STATS_AGGREGATES,
13316
  BGP_STATS_SPACE,
13317
  BGP_STATS_ASPATH_COUNT,
13318
  BGP_STATS_ASPATH_MAXHOPS,
13319
  BGP_STATS_ASPATH_TOTHOPS,
13320
  BGP_STATS_ASPATH_MAXSIZE,
13321
  BGP_STATS_ASPATH_TOTSIZE,
13322
  BGP_STATS_ASN_HIGHEST,
13323
  BGP_STATS_MAX,
13324
};
13325
13326
0
#define TABLE_STATS_IDX_VTY 0
13327
0
#define TABLE_STATS_IDX_JSON 1
13328
13329
static const char *table_stats_strs[][2] = {
13330
  [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13331
  [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13332
  [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
13333
  [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13334
               "unaggregateablePrefixes"},
13335
  [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13336
           "maximumAggregateablePrefixes"},
13337
  [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13338
          "bgpAggregateAdvertisements"},
13339
  [BGP_STATS_SPACE] = {"Address space advertised",
13340
           "addressSpaceAdvertised"},
13341
  [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13342
            "advertisementsWithPaths"},
13343
  [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13344
              "longestAsPath"},
13345
  [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13346
              "largestAsPath"},
13347
  [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13348
              "averageAsPathLengthHops"},
13349
  [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13350
              "averageAsPathSizeBytes"},
13351
  [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
13352
  [BGP_STATS_MAX] = {NULL, NULL}
13353
};
13354
13355
struct bgp_table_stats {
13356
  struct bgp_table *table;
13357
  unsigned long long counts[BGP_STATS_MAX];
13358
13359
  unsigned long long
13360
    prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13361
         1];
13362
13363
  double total_space;
13364
};
13365
13366
static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
13367
             struct bgp_table_stats *ts, unsigned int space)
13368
0
{
13369
0
  struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
13370
0
  struct bgp_path_info *pi;
13371
0
  const struct prefix *rn_p;
13372
0
13373
0
  if (!bgp_dest_has_bgp_path_info_data(dest))
13374
0
    return;
13375
0
13376
0
  rn_p = bgp_dest_get_prefix(dest);
13377
0
  ts->counts[BGP_STATS_PREFIXES]++;
13378
0
  ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
13379
0
13380
0
  ts->prefix_len_count[rn_p->prefixlen]++;
13381
0
  /* check if the prefix is included by any other announcements */
13382
0
  while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13383
0
    pdest = bgp_dest_parent_nolock(pdest);
13384
0
13385
0
  if (pdest == NULL || pdest == top) {
13386
0
    ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13387
0
    /* announced address space */
13388
0
    if (space)
13389
0
      ts->total_space += pow(2.0, space - rn_p->prefixlen);
13390
0
  } else if (bgp_dest_has_bgp_path_info_data(pdest))
13391
0
    ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
13392
0
13393
0
13394
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
13395
0
    ts->counts[BGP_STATS_RIB]++;
13396
0
13397
0
    if (CHECK_FLAG(pi->attr->flag,
13398
0
             ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
13399
0
      ts->counts[BGP_STATS_AGGREGATES]++;
13400
0
13401
0
    /* as-path stats */
13402
0
    if (pi->attr->aspath) {
13403
0
      unsigned int hops = aspath_count_hops(pi->attr->aspath);
13404
0
      unsigned int size = aspath_size(pi->attr->aspath);
13405
0
      as_t highest = aspath_highest(pi->attr->aspath);
13406
0
13407
0
      ts->counts[BGP_STATS_ASPATH_COUNT]++;
13408
0
13409
0
      if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13410
0
        ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13411
0
13412
0
      if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13413
0
        ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13414
0
13415
0
      ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13416
0
      ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
13417
0
      if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13418
0
        ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13419
0
    }
13420
0
  }
13421
0
}
13422
13423
static void bgp_table_stats_walker(struct event *t)
13424
0
{
13425
0
  struct bgp_dest *dest, *ndest;
13426
0
  struct bgp_dest *top;
13427
0
  struct bgp_table_stats *ts = EVENT_ARG(t);
13428
0
  unsigned int space = 0;
13429
0
13430
0
  if (!(top = bgp_table_top(ts->table)))
13431
0
    return;
13432
0
13433
0
  switch (ts->table->afi) {
13434
0
  case AFI_IP:
13435
0
    space = IPV4_MAX_BITLEN;
13436
0
    break;
13437
0
  case AFI_IP6:
13438
0
    space = IPV6_MAX_BITLEN;
13439
0
    break;
13440
0
  case AFI_L2VPN:
13441
0
    space = EVPN_ROUTE_PREFIXLEN;
13442
0
    break;
13443
0
  case AFI_UNSPEC:
13444
0
  case AFI_MAX:
13445
0
    return;
13446
0
  }
13447
0
13448
0
  ts->counts[BGP_STATS_MAXBITLEN] = space;
13449
0
13450
0
  for (dest = top; dest; dest = bgp_route_next(dest)) {
13451
0
    if (ts->table->safi == SAFI_MPLS_VPN
13452
0
        || ts->table->safi == SAFI_ENCAP
13453
0
        || ts->table->safi == SAFI_EVPN) {
13454
0
      struct bgp_table *table;
13455
0
13456
0
      table = bgp_dest_get_bgp_table_info(dest);
13457
0
      if (!table)
13458
0
        continue;
13459
0
13460
0
      top = bgp_table_top(table);
13461
0
      for (ndest = bgp_table_top(table); ndest;
13462
0
           ndest = bgp_route_next(ndest))
13463
0
        bgp_table_stats_rn(ndest, top, ts, space);
13464
0
    } else {
13465
0
      bgp_table_stats_rn(dest, top, ts, space);
13466
0
    }
13467
0
  }
13468
0
}
13469
13470
static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13471
        struct json_object *json_array)
13472
0
{
13473
0
  struct listnode *node, *nnode;
13474
0
  struct bgp *bgp;
13475
13476
0
  for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13477
0
    bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13478
0
}
13479
13480
static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13481
          safi_t safi, struct json_object *json_array)
13482
0
{
13483
0
  struct bgp_table_stats ts;
13484
0
  unsigned int i;
13485
0
  int ret = CMD_SUCCESS;
13486
0
  char temp_buf[20];
13487
0
  struct json_object *json = NULL;
13488
0
  uint32_t bitlen = 0;
13489
0
  struct json_object *json_bitlen;
13490
13491
0
  if (json_array)
13492
0
    json = json_object_new_object();
13493
13494
0
  if (!bgp->rib[afi][safi]) {
13495
0
    char warning_msg[50];
13496
13497
0
    snprintf(warning_msg, sizeof(warning_msg),
13498
0
       "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13499
0
       safi);
13500
13501
0
    if (!json)
13502
0
      vty_out(vty, "%s\n", warning_msg);
13503
0
    else
13504
0
      json_object_string_add(json, "warning", warning_msg);
13505
13506
0
    ret = CMD_WARNING;
13507
0
    goto end_table_stats;
13508
0
  }
13509
13510
0
  if (!json)
13511
0
    vty_out(vty, "BGP %s RIB statistics (%s)\n",
13512
0
      get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13513
0
  else
13514
0
    json_object_string_add(json, "instance", bgp->name_pretty);
13515
13516
  /* labeled-unicast routes live in the unicast table */
13517
0
  if (safi == SAFI_LABELED_UNICAST)
13518
0
    safi = SAFI_UNICAST;
13519
13520
0
  memset(&ts, 0, sizeof(ts));
13521
0
  ts.table = bgp->rib[afi][safi];
13522
0
  event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
13523
13524
0
  for (i = 0; i < BGP_STATS_MAX; i++) {
13525
0
    if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13526
0
        || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
13527
0
      continue;
13528
13529
0
    switch (i) {
13530
0
    case BGP_STATS_ASPATH_TOTHOPS:
13531
0
    case BGP_STATS_ASPATH_TOTSIZE:
13532
0
      if (!json) {
13533
0
        snprintf(
13534
0
          temp_buf, sizeof(temp_buf), "%12.2f",
13535
0
          ts.counts[i]
13536
0
            ? (float)ts.counts[i]
13537
0
                / (float)ts.counts
13538
0
                    [BGP_STATS_ASPATH_COUNT]
13539
0
            : 0);
13540
0
        vty_out(vty, "%-30s: %s",
13541
0
          table_stats_strs[i]
13542
0
              [TABLE_STATS_IDX_VTY],
13543
0
          temp_buf);
13544
0
      } else {
13545
0
        json_object_double_add(
13546
0
          json,
13547
0
          table_stats_strs[i]
13548
0
              [TABLE_STATS_IDX_JSON],
13549
0
          ts.counts[i]
13550
0
            ? (double)ts.counts[i]
13551
0
                / (double)ts.counts
13552
0
                  [BGP_STATS_ASPATH_COUNT]
13553
0
            : 0);
13554
0
      }
13555
0
      break;
13556
0
    case BGP_STATS_TOTPLEN:
13557
0
      if (!json) {
13558
0
        snprintf(
13559
0
          temp_buf, sizeof(temp_buf), "%12.2f",
13560
0
          ts.counts[i]
13561
0
            ? (float)ts.counts[i]
13562
0
                / (float)ts.counts
13563
0
                  [BGP_STATS_PREFIXES]
13564
0
            : 0);
13565
0
        vty_out(vty, "%-30s: %s",
13566
0
          table_stats_strs[i]
13567
0
              [TABLE_STATS_IDX_VTY],
13568
0
          temp_buf);
13569
0
      } else {
13570
0
        json_object_double_add(
13571
0
          json,
13572
0
          table_stats_strs[i]
13573
0
              [TABLE_STATS_IDX_JSON],
13574
0
          ts.counts[i]
13575
0
            ? (double)ts.counts[i]
13576
0
                / (double)ts.counts
13577
0
                  [BGP_STATS_PREFIXES]
13578
0
            : 0);
13579
0
      }
13580
0
      break;
13581
0
    case BGP_STATS_SPACE:
13582
0
      if (!json) {
13583
0
        snprintf(temp_buf, sizeof(temp_buf), "%12g",
13584
0
           ts.total_space);
13585
0
        vty_out(vty, "%-30s: %s\n",
13586
0
          table_stats_strs[i]
13587
0
              [TABLE_STATS_IDX_VTY],
13588
0
          temp_buf);
13589
0
      } else {
13590
0
        json_object_double_add(
13591
0
          json,
13592
0
          table_stats_strs[i]
13593
0
              [TABLE_STATS_IDX_JSON],
13594
0
          (double)ts.total_space);
13595
0
      }
13596
0
      if (afi == AFI_IP6) {
13597
0
        if (!json) {
13598
0
          snprintf(temp_buf, sizeof(temp_buf),
13599
0
             "%12g",
13600
0
             ts.total_space
13601
0
               * pow(2.0, -128 + 32));
13602
0
          vty_out(vty, "%30s: %s\n",
13603
0
            "/32 equivalent %s\n",
13604
0
            temp_buf);
13605
0
        } else {
13606
0
          json_object_double_add(
13607
0
            json, "/32equivalent",
13608
0
            (double)(ts.total_space
13609
0
               * pow(2.0,
13610
0
                     -128 + 32)));
13611
0
        }
13612
0
        if (!json) {
13613
0
          snprintf(temp_buf, sizeof(temp_buf),
13614
0
             "%12g",
13615
0
             ts.total_space
13616
0
               * pow(2.0, -128 + 48));
13617
0
          vty_out(vty, "%30s: %s\n",
13618
0
            "/48 equivalent %s\n",
13619
0
            temp_buf);
13620
0
        } else {
13621
0
          json_object_double_add(
13622
0
            json, "/48equivalent",
13623
0
            (double)(ts.total_space
13624
0
               * pow(2.0,
13625
0
                     -128 + 48)));
13626
0
        }
13627
0
      } else {
13628
0
        if (!json) {
13629
0
          snprintf(temp_buf, sizeof(temp_buf),
13630
0
             "%12.2f",
13631
0
             ts.total_space * 100.
13632
0
               * pow(2.0, -32));
13633
0
          vty_out(vty, "%30s: %s\n",
13634
0
            "% announced ", temp_buf);
13635
0
        } else {
13636
0
          json_object_double_add(
13637
0
            json, "%announced",
13638
0
            (double)(ts.total_space * 100.
13639
0
               * pow(2.0, -32)));
13640
0
        }
13641
0
        if (!json) {
13642
0
          snprintf(temp_buf, sizeof(temp_buf),
13643
0
             "%12.2f",
13644
0
             ts.total_space
13645
0
               * pow(2.0, -32 + 8));
13646
0
          vty_out(vty, "%30s: %s\n",
13647
0
            "/8 equivalent ", temp_buf);
13648
0
        } else {
13649
0
          json_object_double_add(
13650
0
            json, "/8equivalent",
13651
0
            (double)(ts.total_space
13652
0
               * pow(2.0, -32 + 8)));
13653
0
        }
13654
0
        if (!json) {
13655
0
          snprintf(temp_buf, sizeof(temp_buf),
13656
0
             "%12.2f",
13657
0
             ts.total_space
13658
0
               * pow(2.0, -32 + 24));
13659
0
          vty_out(vty, "%30s: %s\n",
13660
0
            "/24 equivalent ", temp_buf);
13661
0
        } else {
13662
0
          json_object_double_add(
13663
0
            json, "/24equivalent",
13664
0
            (double)(ts.total_space
13665
0
               * pow(2.0, -32 + 24)));
13666
0
        }
13667
0
      }
13668
0
      break;
13669
0
    default:
13670
0
      if (!json) {
13671
0
        snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13672
0
           ts.counts[i]);
13673
0
        vty_out(vty, "%-30s: %s",
13674
0
          table_stats_strs[i]
13675
0
              [TABLE_STATS_IDX_VTY],
13676
0
          temp_buf);
13677
0
      } else {
13678
0
        json_object_int_add(
13679
0
          json,
13680
0
          table_stats_strs[i]
13681
0
              [TABLE_STATS_IDX_JSON],
13682
0
          ts.counts[i]);
13683
0
      }
13684
0
    }
13685
0
    if (!json)
13686
0
      vty_out(vty, "\n");
13687
0
  }
13688
13689
0
  switch (afi) {
13690
0
  case AFI_IP:
13691
0
    bitlen = IPV4_MAX_BITLEN;
13692
0
    break;
13693
0
  case AFI_IP6:
13694
0
    bitlen = IPV6_MAX_BITLEN;
13695
0
    break;
13696
0
  case AFI_L2VPN:
13697
0
    bitlen = EVPN_ROUTE_PREFIXLEN;
13698
0
    break;
13699
0
  case AFI_UNSPEC:
13700
0
  case AFI_MAX:
13701
0
    break;
13702
0
  }
13703
13704
0
  if (json) {
13705
0
    json_bitlen = json_object_new_array();
13706
13707
0
    for (i = 0; i <= bitlen; i++) {
13708
0
      struct json_object *ind_bit = json_object_new_object();
13709
13710
0
      if (!ts.prefix_len_count[i])
13711
0
        continue;
13712
13713
0
      snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13714
0
      json_object_int_add(ind_bit, temp_buf,
13715
0
              ts.prefix_len_count[i]);
13716
0
      json_object_array_add(json_bitlen, ind_bit);
13717
0
    }
13718
0
    json_object_object_add(json, "prefixLength", json_bitlen);
13719
0
  }
13720
13721
0
end_table_stats:
13722
0
  if (json)
13723
0
    json_object_array_add(json_array, json);
13724
0
  return ret;
13725
0
}
13726
13727
static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13728
         safi_t safi, struct json_object *json_array)
13729
0
{
13730
0
  if (!bgp) {
13731
0
    bgp_table_stats_all(vty, afi, safi, json_array);
13732
0
    return CMD_SUCCESS;
13733
0
  }
13734
13735
0
  return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13736
0
}
13737
13738
enum bgp_pcounts {
13739
  PCOUNT_ADJ_IN = 0,
13740
  PCOUNT_DAMPED,
13741
  PCOUNT_REMOVED,
13742
  PCOUNT_HISTORY,
13743
  PCOUNT_STALE,
13744
  PCOUNT_VALID,
13745
  PCOUNT_ALL,
13746
  PCOUNT_COUNTED,
13747
  PCOUNT_BPATH_SELECTED,
13748
  PCOUNT_PFCNT, /* the figure we display to users */
13749
  PCOUNT_MAX,
13750
};
13751
13752
static const char *const pcount_strs[] = {
13753
    [PCOUNT_ADJ_IN] = "Adj-in",
13754
    [PCOUNT_DAMPED] = "Damped",
13755
    [PCOUNT_REMOVED] = "Removed",
13756
    [PCOUNT_HISTORY] = "History",
13757
    [PCOUNT_STALE] = "Stale",
13758
    [PCOUNT_VALID] = "Valid",
13759
    [PCOUNT_ALL] = "All RIB",
13760
    [PCOUNT_COUNTED] = "PfxCt counted",
13761
    [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
13762
    [PCOUNT_PFCNT] = "Useable",
13763
    [PCOUNT_MAX] = NULL,
13764
};
13765
13766
struct peer_pcounts {
13767
  unsigned int count[PCOUNT_MAX];
13768
  const struct peer *peer;
13769
  const struct bgp_table *table;
13770
  safi_t safi;
13771
};
13772
13773
static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
13774
0
{
13775
0
  const struct bgp_adj_in *ain;
13776
0
  const struct bgp_path_info *pi;
13777
0
  const struct peer *peer = pc->peer;
13778
0
13779
0
  for (ain = rn->adj_in; ain; ain = ain->next)
13780
0
    if (ain->peer == peer)
13781
0
      pc->count[PCOUNT_ADJ_IN]++;
13782
0
13783
0
  for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
13784
0
13785
0
    if (pi->peer != peer)
13786
0
      continue;
13787
0
13788
0
    pc->count[PCOUNT_ALL]++;
13789
0
13790
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13791
0
      pc->count[PCOUNT_DAMPED]++;
13792
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13793
0
      pc->count[PCOUNT_HISTORY]++;
13794
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13795
0
      pc->count[PCOUNT_REMOVED]++;
13796
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13797
0
      pc->count[PCOUNT_STALE]++;
13798
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13799
0
      pc->count[PCOUNT_VALID]++;
13800
0
    if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13801
0
      pc->count[PCOUNT_PFCNT]++;
13802
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13803
0
      pc->count[PCOUNT_BPATH_SELECTED]++;
13804
0
13805
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13806
0
      pc->count[PCOUNT_COUNTED]++;
13807
0
      if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13808
0
        flog_err(
13809
0
          EC_LIB_DEVELOPMENT,
13810
0
          "Attempting to count but flags say it is unusable");
13811
0
    } else {
13812
0
      if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13813
0
        flog_err(
13814
0
          EC_LIB_DEVELOPMENT,
13815
0
          "Not counted but flags say we should");
13816
0
    }
13817
0
  }
13818
0
}
13819
13820
static void bgp_peer_count_walker(struct event *t)
13821
0
{
13822
0
  struct bgp_dest *rn, *rm;
13823
0
  const struct bgp_table *table;
13824
0
  struct peer_pcounts *pc = EVENT_ARG(t);
13825
0
13826
0
  if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13827
0
      || pc->safi == SAFI_EVPN) {
13828
0
    /* Special handling for 2-level routing tables. */
13829
0
    for (rn = bgp_table_top(pc->table); rn;
13830
0
         rn = bgp_route_next(rn)) {
13831
0
      table = bgp_dest_get_bgp_table_info(rn);
13832
0
      if (table != NULL)
13833
0
        for (rm = bgp_table_top(table); rm;
13834
0
             rm = bgp_route_next(rm))
13835
0
          bgp_peer_count_proc(rm, pc);
13836
0
    }
13837
0
  } else
13838
0
    for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13839
0
      bgp_peer_count_proc(rn, pc);
13840
0
}
13841
13842
static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
13843
         safi_t safi, bool use_json)
13844
0
{
13845
0
  struct peer_pcounts pcounts = {.peer = peer};
13846
0
  unsigned int i;
13847
0
  json_object *json = NULL;
13848
0
  json_object *json_loop = NULL;
13849
13850
0
  if (use_json) {
13851
0
    json = json_object_new_object();
13852
0
    json_loop = json_object_new_object();
13853
0
  }
13854
13855
0
  if (!peer || !peer->bgp || !peer->afc[afi][safi]
13856
0
      || !peer->bgp->rib[afi][safi]) {
13857
0
    if (use_json) {
13858
0
      json_object_string_add(
13859
0
        json, "warning",
13860
0
        "No such neighbor or address family");
13861
0
      vty_out(vty, "%s\n", json_object_to_json_string(json));
13862
0
      json_object_free(json);
13863
0
      json_object_free(json_loop);
13864
0
    } else
13865
0
      vty_out(vty, "%% No such neighbor or address family\n");
13866
13867
0
    return CMD_WARNING;
13868
0
  }
13869
13870
0
  memset(&pcounts, 0, sizeof(pcounts));
13871
0
  pcounts.peer = peer;
13872
0
  pcounts.table = peer->bgp->rib[afi][safi];
13873
0
  pcounts.safi = safi;
13874
13875
  /* in-place call via thread subsystem so as to record execution time
13876
   * stats for the thread-walk (i.e. ensure this can't be blamed on
13877
   * on just vty_read()).
13878
   */
13879
0
  event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13880
13881
0
  if (use_json) {
13882
0
    json_object_string_add(json, "prefixCountsFor", peer->host);
13883
0
    json_object_string_add(json, "multiProtocol",
13884
0
               get_afi_safi_str(afi, safi, true));
13885
0
    json_object_int_add(json, "pfxCounter",
13886
0
            peer->pcount[afi][safi]);
13887
13888
0
    for (i = 0; i < PCOUNT_MAX; i++)
13889
0
      json_object_int_add(json_loop, pcount_strs[i],
13890
0
              pcounts.count[i]);
13891
13892
0
    json_object_object_add(json, "ribTableWalkCounters", json_loop);
13893
13894
0
    if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13895
0
      json_object_string_add(json, "pfxctDriftFor",
13896
0
                 peer->host);
13897
0
      json_object_string_add(
13898
0
        json, "recommended",
13899
0
        "Please report this bug, with the above command output");
13900
0
    }
13901
0
    vty_json(vty, json);
13902
0
  } else {
13903
13904
0
    if (peer->hostname
13905
0
        && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
13906
0
      vty_out(vty, "Prefix counts for %s/%s, %s\n",
13907
0
        peer->hostname, peer->host,
13908
0
        get_afi_safi_str(afi, safi, false));
13909
0
    } else {
13910
0
      vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
13911
0
        get_afi_safi_str(afi, safi, false));
13912
0
    }
13913
13914
0
    vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
13915
0
    vty_out(vty, "\nCounts from RIB table walk:\n\n");
13916
13917
0
    for (i = 0; i < PCOUNT_MAX; i++)
13918
0
      vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13919
0
        pcounts.count[i]);
13920
13921
0
    if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13922
0
      vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13923
0
      vty_out(vty,
13924
0
        "Please report this bug, with the above command output\n");
13925
0
    }
13926
0
  }
13927
13928
0
  return CMD_SUCCESS;
13929
0
}
13930
13931
DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13932
       show_ip_bgp_instance_neighbor_prefix_counts_cmd,
13933
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13934
       SHOW_STR
13935
       IP_STR
13936
       BGP_STR
13937
       BGP_INSTANCE_HELP_STR
13938
       BGP_AFI_HELP_STR
13939
       BGP_SAFI_HELP_STR
13940
       "Detailed information on TCP and BGP neighbor connections\n"
13941
       "Neighbor to display information about\n"
13942
       "Neighbor to display information about\n"
13943
       "Neighbor on BGP configured interface\n"
13944
       "Display detailed prefix count information\n"
13945
       JSON_STR)
13946
0
{
13947
0
  afi_t afi = AFI_IP6;
13948
0
  safi_t safi = SAFI_UNICAST;
13949
0
  struct peer *peer;
13950
0
  int idx = 0;
13951
0
  struct bgp *bgp = NULL;
13952
0
  bool uj = use_json(argc, argv);
13953
13954
0
  if (uj)
13955
0
    argc--;
13956
13957
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13958
0
              &bgp, uj);
13959
0
  if (!idx)
13960
0
    return CMD_WARNING;
13961
13962
0
  argv_find(argv, argc, "neighbors", &idx);
13963
0
  peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13964
0
  if (!peer)
13965
0
    return CMD_WARNING;
13966
13967
0
  return bgp_peer_counts(vty, peer, afi, safi, uj);
13968
0
}
13969
13970
#ifdef KEEP_OLD_VPN_COMMANDS
13971
DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13972
       show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13973
       "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13974
       SHOW_STR
13975
       IP_STR
13976
       BGP_STR
13977
       BGP_VPNVX_HELP_STR
13978
       "Display information about all VPNv4 NLRIs\n"
13979
       "Detailed information on TCP and BGP neighbor connections\n"
13980
       "Neighbor to display information about\n"
13981
       "Neighbor to display information about\n"
13982
       "Neighbor on BGP configured interface\n"
13983
       "Display detailed prefix count information\n"
13984
       JSON_STR)
13985
{
13986
  int idx_peer = 6;
13987
  struct peer *peer;
13988
  bool uj = use_json(argc, argv);
13989
13990
  peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13991
  if (!peer)
13992
    return CMD_WARNING;
13993
13994
  return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
13995
}
13996
13997
DEFUN (show_ip_bgp_vpn_all_route_prefix,
13998
       show_ip_bgp_vpn_all_route_prefix_cmd,
13999
       "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
14000
       SHOW_STR
14001
       IP_STR
14002
       BGP_STR
14003
       BGP_VPNVX_HELP_STR
14004
       "Display information about all VPNv4 NLRIs\n"
14005
       "Network in the BGP routing table to display\n"
14006
       "Network in the BGP routing table to display\n"
14007
       JSON_STR)
14008
{
14009
  int idx = 0;
14010
  char *network = NULL;
14011
  struct bgp *bgp = bgp_get_default();
14012
  if (!bgp) {
14013
    vty_out(vty, "Can't find default instance\n");
14014
    return CMD_WARNING;
14015
  }
14016
14017
  if (argv_find(argv, argc, "A.B.C.D", &idx))
14018
    network = argv[idx]->arg;
14019
  else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
14020
    network = argv[idx]->arg;
14021
  else {
14022
    vty_out(vty, "Unable to figure out Network\n");
14023
    return CMD_WARNING;
14024
  }
14025
14026
  return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
14027
            BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14028
            use_json(argc, argv));
14029
}
14030
#endif /* KEEP_OLD_VPN_COMMANDS */
14031
14032
DEFUN (show_bgp_l2vpn_evpn_route_prefix,
14033
       show_bgp_l2vpn_evpn_route_prefix_cmd,
14034
       "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
14035
       SHOW_STR
14036
       BGP_STR
14037
       L2VPN_HELP_STR
14038
       EVPN_HELP_STR
14039
       "Network in the BGP routing table to display\n"
14040
       "Network in the BGP routing table to display\n"
14041
       "Network in the BGP routing table to display\n"
14042
       "Network in the BGP routing table to display\n"
14043
       JSON_STR)
14044
0
{
14045
0
  int idx = 0;
14046
0
  char *network = NULL;
14047
0
  int prefix_check = 0;
14048
14049
0
  if (argv_find(argv, argc, "A.B.C.D", &idx) ||
14050
0
    argv_find(argv, argc, "X:X::X:X", &idx))
14051
0
    network = argv[idx]->arg;
14052
0
  else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
14053
0
    argv_find(argv, argc, "X:X::X:X/M", &idx)) {
14054
0
    network = argv[idx]->arg;
14055
0
    prefix_check = 1;
14056
0
  } else {
14057
0
    vty_out(vty, "Unable to figure out Network\n");
14058
0
    return CMD_WARNING;
14059
0
  }
14060
0
  return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
14061
0
            prefix_check, BGP_PATH_SHOW_ALL,
14062
0
            RPKI_NOT_BEING_USED, use_json(argc, argv));
14063
0
}
14064
14065
static void show_adj_route_header(struct vty *vty, struct peer *peer,
14066
          struct bgp_table *table, int *header1,
14067
          int *header2, json_object *json,
14068
          json_object *json_scode,
14069
          json_object *json_ocode, bool wide,
14070
          bool detail)
14071
0
{
14072
0
  uint64_t version = table ? table->version : 0;
14073
14074
0
  if (*header1) {
14075
0
    if (json) {
14076
0
      json_object_int_add(json, "bgpTableVersion", version);
14077
0
      json_object_string_addf(json, "bgpLocalRouterId",
14078
0
            "%pI4", &peer->bgp->router_id);
14079
0
      json_object_int_add(json, "defaultLocPrf",
14080
0
              peer->bgp->default_local_pref);
14081
0
      json_object_int_add(json, "localAS",
14082
0
              peer->change_local_as
14083
0
                ? peer->change_local_as
14084
0
                : peer->local_as);
14085
0
      json_object_object_add(json, "bgpStatusCodes",
14086
0
                 json_scode);
14087
0
      json_object_object_add(json, "bgpOriginCodes",
14088
0
                 json_ocode);
14089
0
    } else {
14090
0
      vty_out(vty,
14091
0
        "BGP table version is %" PRIu64
14092
0
        ", local router ID is %pI4, vrf id ",
14093
0
        version, &peer->bgp->router_id);
14094
0
      if (peer->bgp->vrf_id == VRF_UNKNOWN)
14095
0
        vty_out(vty, "%s", VRFID_NONE_STR);
14096
0
      else
14097
0
        vty_out(vty, "%u", peer->bgp->vrf_id);
14098
0
      vty_out(vty, "\n");
14099
0
      vty_out(vty, "Default local pref %u, ",
14100
0
        peer->bgp->default_local_pref);
14101
0
      vty_out(vty, "local AS %u\n",
14102
0
        peer->change_local_as ? peer->change_local_as
14103
0
                  : peer->local_as);
14104
0
      if (!detail) {
14105
0
        vty_out(vty, BGP_SHOW_SCODE_HEADER);
14106
0
        vty_out(vty, BGP_SHOW_NCODE_HEADER);
14107
0
        vty_out(vty, BGP_SHOW_OCODE_HEADER);
14108
0
        vty_out(vty, BGP_SHOW_RPKI_HEADER);
14109
0
      }
14110
0
    }
14111
0
    *header1 = 0;
14112
0
  }
14113
0
  if (*header2) {
14114
0
    if (!json && !detail)
14115
0
      vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14116
0
             : BGP_SHOW_HEADER));
14117
0
    *header2 = 0;
14118
0
  }
14119
0
}
14120
14121
static void
14122
show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14123
         afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14124
         const char *rmap_name, json_object *json, json_object *json_ar,
14125
         json_object *json_scode, json_object *json_ocode,
14126
         uint16_t show_flags, int *header1, int *header2, char *rd_str,
14127
         const struct prefix *match, unsigned long *output_count,
14128
         unsigned long *filtered_count)
14129
0
{
14130
0
  struct bgp_adj_in *ain = NULL;
14131
0
  struct bgp_adj_out *adj = NULL;
14132
0
  struct bgp_dest *dest;
14133
0
  struct bgp *bgp;
14134
0
  struct attr attr;
14135
0
  int ret;
14136
0
  struct update_subgroup *subgrp;
14137
0
  struct peer_af *paf = NULL;
14138
0
  bool route_filtered;
14139
0
  bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14140
0
  bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14141
0
  bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
14142
0
  bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14143
0
      || (safi == SAFI_EVPN))
14144
0
             ? true
14145
0
             : false;
14146
0
  int display = 0;
14147
0
  json_object *json_net = NULL;
14148
14149
0
  bgp = peer->bgp;
14150
14151
  /* If the user supplied a prefix, look for a matching route instead
14152
   * of walking the whole table.
14153
   */
14154
0
  if (match) {
14155
0
    dest = bgp_node_match(table, match);
14156
0
    if (!dest) {
14157
0
      if (!use_json)
14158
0
        vty_out(vty, "Network not in table\n");
14159
0
      return;
14160
0
    }
14161
14162
0
    const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14163
14164
0
    if (rn_p->prefixlen != match->prefixlen) {
14165
0
      if (!use_json)
14166
0
        vty_out(vty, "Network not in table\n");
14167
0
      bgp_dest_unlock_node(dest);
14168
0
      return;
14169
0
    }
14170
14171
0
    if (type == bgp_show_adj_route_received ||
14172
0
        type == bgp_show_adj_route_filtered) {
14173
0
      for (ain = dest->adj_in; ain; ain = ain->next) {
14174
0
        if (ain->peer == peer) {
14175
0
          attr = *ain->attr;
14176
0
          break;
14177
0
        }
14178
0
      }
14179
      /* bail out if if adj_out is empty, or
14180
       * if the prefix isn't in this peer's
14181
       * adj_in
14182
       */
14183
0
      if (!ain || ain->peer != peer) {
14184
0
        if (!use_json)
14185
0
          vty_out(vty, "Network not in table\n");
14186
0
        bgp_dest_unlock_node(dest);
14187
0
        return;
14188
0
      }
14189
0
    } else if (type == bgp_show_adj_route_advertised) {
14190
0
      bool peer_found = false;
14191
14192
0
      RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14193
0
        SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14194
0
          if (paf->peer == peer && adj->attr) {
14195
0
            attr = *adj->attr;
14196
0
            peer_found = true;
14197
0
            break;
14198
0
          }
14199
0
        }
14200
0
        if (peer_found)
14201
0
          break;
14202
0
      }
14203
      /* bail out if if adj_out is empty, or
14204
       * if the prefix isn't in this peer's
14205
       * adj_out
14206
       */
14207
0
      if (!paf || !peer_found) {
14208
0
        if (!use_json)
14209
0
          vty_out(vty, "Network not in table\n");
14210
0
        bgp_dest_unlock_node(dest);
14211
0
        return;
14212
0
      }
14213
0
    }
14214
14215
0
    ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14216
0
            rmap_name);
14217
14218
0
    if (ret != RMAP_DENY) {
14219
0
      show_adj_route_header(vty, peer, table, header1,
14220
0
                header2, json, json_scode,
14221
0
                json_ocode, wide, detail);
14222
14223
0
      if (use_json)
14224
0
        json_net = json_object_new_object();
14225
14226
0
      bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14227
0
             afi, safi, json_net,
14228
0
             BGP_PATH_SHOW_ALL, &display,
14229
0
             RPKI_NOT_BEING_USED);
14230
0
      if (use_json)
14231
0
        json_object_object_addf(json_ar, json_net,
14232
0
              "%pFX", rn_p);
14233
0
      (*output_count)++;
14234
0
    } else
14235
0
      (*filtered_count)++;
14236
14237
0
    bgp_attr_flush(&attr);
14238
0
    bgp_dest_unlock_node(dest);
14239
0
    return;
14240
0
  }
14241
14242
14243
0
  subgrp = peer_subgroup(peer, afi, safi);
14244
14245
0
  if (type == bgp_show_adj_route_advertised && subgrp
14246
0
      && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14247
0
    if (use_json) {
14248
0
      json_object_int_add(json, "bgpTableVersion",
14249
0
              table->version);
14250
0
      json_object_string_addf(json, "bgpLocalRouterId",
14251
0
            "%pI4", &bgp->router_id);
14252
0
      json_object_int_add(json, "defaultLocPrf",
14253
0
            bgp->default_local_pref);
14254
0
      json_object_int_add(json, "localAS",
14255
0
              peer->change_local_as
14256
0
                ? peer->change_local_as
14257
0
                : peer->local_as);
14258
0
      json_object_object_add(json, "bgpStatusCodes",
14259
0
                 json_scode);
14260
0
      json_object_object_add(json, "bgpOriginCodes",
14261
0
                 json_ocode);
14262
0
      json_object_string_add(
14263
0
        json, "bgpOriginatingDefaultNetwork",
14264
0
        (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
14265
0
    } else {
14266
0
      vty_out(vty,
14267
0
        "BGP table version is %" PRIu64
14268
0
        ", local router ID is %pI4, vrf id ",
14269
0
        table->version, &bgp->router_id);
14270
0
      if (bgp->vrf_id == VRF_UNKNOWN)
14271
0
        vty_out(vty, "%s", VRFID_NONE_STR);
14272
0
      else
14273
0
        vty_out(vty, "%u", bgp->vrf_id);
14274
0
      vty_out(vty, "\n");
14275
0
      vty_out(vty, "Default local pref %u, ",
14276
0
        bgp->default_local_pref);
14277
0
      vty_out(vty, "local AS %u\n",
14278
0
        peer->change_local_as ? peer->change_local_as
14279
0
                  : peer->local_as);
14280
0
      if (!detail) {
14281
0
        vty_out(vty, BGP_SHOW_SCODE_HEADER);
14282
0
        vty_out(vty, BGP_SHOW_NCODE_HEADER);
14283
0
        vty_out(vty, BGP_SHOW_OCODE_HEADER);
14284
0
        vty_out(vty, BGP_SHOW_RPKI_HEADER);
14285
0
      }
14286
14287
0
      vty_out(vty, "Originating default network %s\n\n",
14288
0
        (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
14289
0
    }
14290
0
    (*output_count)++;
14291
0
    *header1 = 0;
14292
0
  }
14293
14294
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
14295
0
    if (type == bgp_show_adj_route_received
14296
0
        || type == bgp_show_adj_route_filtered) {
14297
0
      for (ain = dest->adj_in; ain; ain = ain->next) {
14298
0
        if (ain->peer != peer)
14299
0
          continue;
14300
0
        show_adj_route_header(vty, peer, table, header1,
14301
0
                  header2, json, json_scode,
14302
0
                  json_ocode, wide, detail);
14303
14304
0
        if ((safi == SAFI_MPLS_VPN)
14305
0
            || (safi == SAFI_ENCAP)
14306
0
            || (safi == SAFI_EVPN)) {
14307
0
          if (use_json)
14308
0
            json_object_string_add(
14309
0
              json_ar, "rd", rd_str);
14310
0
          else if (show_rd && rd_str) {
14311
0
            vty_out(vty,
14312
0
              "Route Distinguisher: %s\n",
14313
0
              rd_str);
14314
0
            show_rd = false;
14315
0
          }
14316
0
        }
14317
14318
0
        attr = *ain->attr;
14319
0
        route_filtered = false;
14320
14321
        /* Filter prefix using distribute list,
14322
         * filter list or prefix list
14323
         */
14324
0
        const struct prefix *rn_p =
14325
0
          bgp_dest_get_prefix(dest);
14326
0
        if ((bgp_input_filter(peer, rn_p, &attr, afi,
14327
0
                  safi))
14328
0
            == FILTER_DENY)
14329
0
          route_filtered = true;
14330
14331
        /* Filter prefix using route-map */
14332
0
        ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14333
0
               safi, rmap_name, NULL,
14334
0
               0, NULL);
14335
14336
0
        if (type == bgp_show_adj_route_filtered &&
14337
0
          !route_filtered && ret != RMAP_DENY) {
14338
0
          bgp_attr_flush(&attr);
14339
0
          continue;
14340
0
        }
14341
14342
0
        if (type == bgp_show_adj_route_received
14343
0
            && (route_filtered || ret == RMAP_DENY))
14344
0
          (*filtered_count)++;
14345
14346
0
        if (detail) {
14347
0
          if (use_json)
14348
0
            json_net =
14349
0
              json_object_new_object();
14350
14351
0
          struct bgp_path_info bpi;
14352
0
          struct bgp_dest buildit = *dest;
14353
0
          struct bgp_dest *pass_in;
14354
14355
0
          if (route_filtered ||
14356
0
              ret == RMAP_DENY) {
14357
0
            bpi.attr = &attr;
14358
0
            bpi.peer = peer;
14359
0
            buildit.info = &bpi;
14360
14361
0
            pass_in = &buildit;
14362
0
          } else
14363
0
            pass_in = dest;
14364
0
          bgp_show_path_info(
14365
0
            NULL, pass_in, vty, bgp, afi,
14366
0
            safi, json_net,
14367
0
            BGP_PATH_SHOW_ALL, &display,
14368
0
            RPKI_NOT_BEING_USED);
14369
0
          if (use_json)
14370
0
            json_object_object_addf(
14371
0
              json_ar, json_net,
14372
0
              "%pFX", rn_p);
14373
0
        } else
14374
0
          route_vty_out_tmp(vty, dest, rn_p,
14375
0
                &attr, safi, use_json,
14376
0
                json_ar, wide);
14377
0
        bgp_attr_flush(&attr);
14378
0
        (*output_count)++;
14379
0
      }
14380
0
    } else if (type == bgp_show_adj_route_advertised) {
14381
0
      RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
14382
0
        SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14383
0
          if (paf->peer != peer || !adj->attr)
14384
0
            continue;
14385
14386
0
          show_adj_route_header(
14387
0
            vty, peer, table, header1,
14388
0
            header2, json, json_scode,
14389
0
            json_ocode, wide, detail);
14390
14391
0
          const struct prefix *rn_p =
14392
0
            bgp_dest_get_prefix(dest);
14393
14394
0
          attr = *adj->attr;
14395
0
          ret = bgp_output_modifier(
14396
0
            peer, rn_p, &attr, afi, safi,
14397
0
            rmap_name);
14398
14399
0
          if (ret != RMAP_DENY) {
14400
0
            if ((safi == SAFI_MPLS_VPN)
14401
0
                || (safi == SAFI_ENCAP)
14402
0
                || (safi == SAFI_EVPN)) {
14403
0
              if (use_json)
14404
0
                json_object_string_add(
14405
0
                  json_ar,
14406
0
                  "rd",
14407
0
                  rd_str);
14408
0
              else if (show_rd
14409
0
                 && rd_str) {
14410
0
                vty_out(vty,
14411
0
                  "Route Distinguisher: %s\n",
14412
0
                  rd_str);
14413
0
                show_rd = false;
14414
0
              }
14415
0
            }
14416
0
            if (detail) {
14417
0
              if (use_json)
14418
0
                json_net =
14419
0
                  json_object_new_object();
14420
0
              bgp_show_path_info(
14421
                NULL /* prefix_rd
14422
                      */
14423
0
                ,
14424
0
                dest, vty, bgp,
14425
0
                afi, safi,
14426
0
                json_net,
14427
0
                BGP_PATH_SHOW_ALL,
14428
0
                &display,
14429
0
                RPKI_NOT_BEING_USED);
14430
0
              if (use_json)
14431
0
                json_object_object_addf(
14432
0
                  json_ar,
14433
0
                  json_net,
14434
0
                  "%pFX",
14435
0
                  rn_p);
14436
0
            } else
14437
0
              route_vty_out_tmp(
14438
0
                vty, dest, rn_p,
14439
0
                &attr, safi,
14440
0
                use_json,
14441
0
                json_ar, wide);
14442
0
            (*output_count)++;
14443
0
          } else {
14444
0
            (*filtered_count)++;
14445
0
          }
14446
14447
0
          bgp_attr_flush(&attr);
14448
0
        }
14449
0
    } else if (type == bgp_show_adj_route_bestpath) {
14450
0
      struct bgp_path_info *pi;
14451
14452
0
      show_adj_route_header(vty, peer, table, header1,
14453
0
                header2, json, json_scode,
14454
0
                json_ocode, wide, detail);
14455
14456
0
      const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14457
14458
0
      for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14459
0
           pi = pi->next) {
14460
0
        if (pi->peer != peer)
14461
0
          continue;
14462
14463
0
        if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14464
0
          continue;
14465
14466
0
        if (detail) {
14467
0
          if (use_json)
14468
0
            json_net =
14469
0
              json_object_new_object();
14470
0
          bgp_show_path_info(
14471
0
            NULL /* prefix_rd */, dest, vty,
14472
0
            bgp, afi, safi, json_net,
14473
0
            BGP_PATH_SHOW_BESTPATH,
14474
0
            &display, RPKI_NOT_BEING_USED);
14475
0
          if (use_json)
14476
0
            json_object_object_addf(
14477
0
              json_ar, json_net,
14478
0
              "%pFX", rn_p);
14479
0
        } else
14480
0
          route_vty_out_tmp(
14481
0
            vty, dest, rn_p, pi->attr, safi,
14482
0
            use_json, json_ar, wide);
14483
0
        (*output_count)++;
14484
0
      }
14485
0
    }
14486
0
  }
14487
0
}
14488
14489
static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
14490
         safi_t safi, enum bgp_show_adj_route_type type,
14491
         const char *rmap_name, const struct prefix *match,
14492
         uint16_t show_flags)
14493
0
{
14494
0
  struct bgp *bgp;
14495
0
  struct bgp_table *table;
14496
0
  json_object *json = NULL;
14497
0
  json_object *json_scode = NULL;
14498
0
  json_object *json_ocode = NULL;
14499
0
  json_object *json_ar = NULL;
14500
0
  bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14501
14502
  /* Init BGP headers here so they're only displayed once
14503
   * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14504
   */
14505
0
  int header1 = 1;
14506
0
  int header2 = 1;
14507
14508
  /*
14509
   * Initialize variables for each RD
14510
   * All prefixes under an RD is aggregated within "json_routes"
14511
   */
14512
0
  char rd_str[BUFSIZ] = {0};
14513
0
  json_object *json_routes = NULL;
14514
14515
14516
  /* For 2-tier tables, prefix counts need to be
14517
   * maintained across multiple runs of show_adj_route()
14518
   */
14519
0
  unsigned long output_count_per_rd;
14520
0
  unsigned long filtered_count_per_rd;
14521
0
  unsigned long output_count = 0;
14522
0
  unsigned long filtered_count = 0;
14523
14524
0
  if (use_json) {
14525
0
    json = json_object_new_object();
14526
0
    json_ar = json_object_new_object();
14527
0
    json_scode = json_object_new_object();
14528
0
    json_ocode = json_object_new_object();
14529
#if CONFDATE > 20231208
14530
CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14531
#endif
14532
0
    json_object_string_add(json_scode, "suppressed", "s");
14533
0
    json_object_string_add(json_scode, "damped", "d");
14534
0
    json_object_string_add(json_scode, "history", "h");
14535
0
    json_object_string_add(json_scode, "valid", "*");
14536
0
    json_object_string_add(json_scode, "best", ">");
14537
0
    json_object_string_add(json_scode, "multipath", "=");
14538
0
    json_object_string_add(json_scode, "internal", "i");
14539
0
    json_object_string_add(json_scode, "ribFailure", "r");
14540
0
    json_object_string_add(json_scode, "stale", "S");
14541
0
    json_object_string_add(json_scode, "removed", "R");
14542
14543
#if CONFDATE > 20231208
14544
CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14545
#endif
14546
0
    json_object_string_add(json_ocode, "igp", "i");
14547
0
    json_object_string_add(json_ocode, "egp", "e");
14548
0
    json_object_string_add(json_ocode, "incomplete", "?");
14549
0
  }
14550
14551
0
  if (!peer || !peer->afc[afi][safi]) {
14552
0
    if (use_json) {
14553
0
      json_object_string_add(
14554
0
        json, "warning",
14555
0
        "No such neighbor or address family");
14556
0
      vty_out(vty, "%s\n", json_object_to_json_string(json));
14557
0
      json_object_free(json);
14558
0
      json_object_free(json_ar);
14559
0
      json_object_free(json_scode);
14560
0
      json_object_free(json_ocode);
14561
0
    } else
14562
0
      vty_out(vty, "%% No such neighbor or address family\n");
14563
14564
0
    return CMD_WARNING;
14565
0
  }
14566
14567
0
  if ((type == bgp_show_adj_route_received
14568
0
       || type == bgp_show_adj_route_filtered)
14569
0
      && !CHECK_FLAG(peer->af_flags[afi][safi],
14570
0
         PEER_FLAG_SOFT_RECONFIG)) {
14571
0
    if (use_json) {
14572
0
      json_object_string_add(
14573
0
        json, "warning",
14574
0
        "Inbound soft reconfiguration not enabled");
14575
0
      vty_out(vty, "%s\n", json_object_to_json_string(json));
14576
0
      json_object_free(json);
14577
0
      json_object_free(json_ar);
14578
0
      json_object_free(json_scode);
14579
0
      json_object_free(json_ocode);
14580
0
    } else
14581
0
      vty_out(vty,
14582
0
        "%% Inbound soft reconfiguration not enabled\n");
14583
14584
0
    return CMD_WARNING;
14585
0
  }
14586
14587
0
  bgp = peer->bgp;
14588
14589
  /* labeled-unicast routes live in the unicast table */
14590
0
  if (safi == SAFI_LABELED_UNICAST)
14591
0
    table = bgp->rib[afi][SAFI_UNICAST];
14592
0
  else
14593
0
    table = bgp->rib[afi][safi];
14594
14595
0
  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14596
0
      || (safi == SAFI_EVPN)) {
14597
14598
0
    struct bgp_dest *dest;
14599
14600
0
    for (dest = bgp_table_top(table); dest;
14601
0
         dest = bgp_route_next(dest)) {
14602
0
      table = bgp_dest_get_bgp_table_info(dest);
14603
0
      if (!table)
14604
0
        continue;
14605
14606
0
      output_count_per_rd = 0;
14607
0
      filtered_count_per_rd = 0;
14608
14609
0
      if (use_json)
14610
0
        json_routes = json_object_new_object();
14611
14612
0
      const struct prefix_rd *prd;
14613
0
      prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14614
0
        dest);
14615
14616
0
      prefix_rd2str(prd, rd_str, sizeof(rd_str),
14617
0
              bgp->asnotation);
14618
14619
0
      show_adj_route(
14620
0
        vty, peer, table, afi, safi, type, rmap_name,
14621
0
        json, json_routes, json_scode, json_ocode,
14622
0
        show_flags, &header1, &header2, rd_str, match,
14623
0
        &output_count_per_rd, &filtered_count_per_rd);
14624
14625
      /* Don't include an empty RD in the output! */
14626
0
      if (json_routes && (output_count_per_rd > 0))
14627
0
        json_object_object_add(json_ar, rd_str,
14628
0
                   json_routes);
14629
14630
0
      output_count += output_count_per_rd;
14631
0
      filtered_count += filtered_count_per_rd;
14632
0
    }
14633
0
  } else
14634
0
    show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14635
0
             json, json_ar, json_scode, json_ocode,
14636
0
             show_flags, &header1, &header2, rd_str, match,
14637
0
             &output_count, &filtered_count);
14638
14639
0
  if (use_json) {
14640
0
    if (type == bgp_show_adj_route_advertised)
14641
0
      json_object_object_add(json, "advertisedRoutes",
14642
0
                 json_ar);
14643
0
    else
14644
0
      json_object_object_add(json, "receivedRoutes", json_ar);
14645
0
    json_object_int_add(json, "totalPrefixCounter", output_count);
14646
0
    json_object_int_add(json, "filteredPrefixCounter",
14647
0
            filtered_count);
14648
14649
    /*
14650
     * These fields only give up ownership to `json` when `header1`
14651
     * is used (set to zero). See code in `show_adj_route` and
14652
     * `show_adj_route_header`.
14653
     */
14654
0
    if (header1 == 1) {
14655
0
      json_object_free(json_scode);
14656
0
      json_object_free(json_ocode);
14657
0
    }
14658
14659
0
    vty_json(vty, json);
14660
0
  } else if (output_count > 0) {
14661
0
    if (!match && filtered_count > 0)
14662
0
      vty_out(vty,
14663
0
        "\nTotal number of prefixes %ld (%ld filtered)\n",
14664
0
        output_count, filtered_count);
14665
0
    else
14666
0
      vty_out(vty, "\nTotal number of prefixes %ld\n",
14667
0
        output_count);
14668
0
  }
14669
14670
0
  return CMD_SUCCESS;
14671
0
}
14672
14673
DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14674
       show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14675
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
14676
       SHOW_STR
14677
       IP_STR
14678
       BGP_STR
14679
       BGP_INSTANCE_HELP_STR
14680
       BGP_AFI_HELP_STR
14681
       BGP_SAFI_WITH_LABEL_HELP_STR
14682
       "Detailed information on TCP and BGP neighbor connections\n"
14683
       "Neighbor to display information about\n"
14684
       "Neighbor to display information about\n"
14685
       "Neighbor on BGP configured interface\n"
14686
       "Display the routes selected by best path\n"
14687
       "Display detailed version of routes\n"
14688
       JSON_STR
14689
       "Increase table width for longer prefixes\n")
14690
0
{
14691
0
  afi_t afi = AFI_IP6;
14692
0
  safi_t safi = SAFI_UNICAST;
14693
0
  char *rmap_name = NULL;
14694
0
  char *peerstr = NULL;
14695
0
  struct bgp *bgp = NULL;
14696
0
  struct peer *peer;
14697
0
  enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14698
0
  int idx = 0;
14699
0
  uint16_t show_flags = 0;
14700
14701
0
  if (detail)
14702
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14703
14704
0
  if (uj)
14705
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14706
14707
0
  if (wide)
14708
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
14709
14710
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14711
0
              &bgp, uj);
14712
14713
0
  if (!idx)
14714
0
    return CMD_WARNING;
14715
14716
0
  argv_find(argv, argc, "neighbors", &idx);
14717
0
  peerstr = argv[++idx]->arg;
14718
14719
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14720
0
  if (!peer)
14721
0
    return CMD_WARNING;
14722
14723
0
  return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
14724
0
             show_flags);
14725
0
}
14726
14727
DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14728
      show_ip_bgp_instance_neighbor_advertised_route_cmd,
14729
      "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
14730
      SHOW_STR
14731
      IP_STR
14732
      BGP_STR
14733
      BGP_INSTANCE_HELP_STR
14734
      BGP_AFI_HELP_STR
14735
      BGP_SAFI_WITH_LABEL_HELP_STR
14736
      "Display the entries for all address families\n"
14737
      "Detailed information on TCP and BGP neighbor connections\n"
14738
      "Neighbor to display information about\n"
14739
      "Neighbor to display information about\n"
14740
      "Neighbor on BGP configured interface\n"
14741
      "Display the routes advertised to a BGP neighbor\n"
14742
      "Display the received routes from neighbor\n"
14743
      "Display the filtered routes received from neighbor\n"
14744
      "Route-map to modify the attributes\n"
14745
      "Name of the route map\n"
14746
      "IPv4 prefix\n"
14747
      "IPv6 prefix\n"
14748
      "Display detailed version of routes\n"
14749
      JSON_STR
14750
      "Increase table width for longer prefixes\n")
14751
0
{
14752
0
  afi_t afi = AFI_IP6;
14753
0
  safi_t safi = SAFI_UNICAST;
14754
0
  char *peerstr = NULL;
14755
0
  struct bgp *bgp = NULL;
14756
0
  struct peer *peer;
14757
0
  enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
14758
0
  int idx = 0;
14759
0
  bool first = true;
14760
0
  uint16_t show_flags = 0;
14761
0
  struct listnode *node;
14762
0
  struct bgp *abgp;
14763
14764
0
  if (detail || prefix_str)
14765
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14766
14767
0
  if (uj) {
14768
0
    argc--;
14769
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14770
0
  }
14771
14772
0
  if (all) {
14773
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14774
0
    if (argv_find(argv, argc, "ipv4", &idx))
14775
0
      SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14776
14777
0
    if (argv_find(argv, argc, "ipv6", &idx))
14778
0
      SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14779
0
  }
14780
14781
0
  if (wide)
14782
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
14783
14784
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14785
0
              &bgp, uj);
14786
0
  if (!idx)
14787
0
    return CMD_WARNING;
14788
14789
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14790
0
  argv_find(argv, argc, "neighbors", &idx);
14791
0
  peerstr = argv[++idx]->arg;
14792
14793
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14794
0
  if (!peer)
14795
0
    return CMD_WARNING;
14796
14797
0
  if (argv_find(argv, argc, "advertised-routes", &idx))
14798
0
    type = bgp_show_adj_route_advertised;
14799
0
  else if (argv_find(argv, argc, "received-routes", &idx))
14800
0
    type = bgp_show_adj_route_received;
14801
0
  else if (argv_find(argv, argc, "filtered-routes", &idx))
14802
0
    type = bgp_show_adj_route_filtered;
14803
14804
0
  if (!all)
14805
0
    return peer_adj_routes(vty, peer, afi, safi, type, route_map,
14806
0
               prefix_str ? prefix : NULL, show_flags);
14807
0
  if (uj)
14808
0
    vty_out(vty, "{\n");
14809
14810
0
  if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14811
0
      || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14812
0
    afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14813
0
                  : AFI_IP6;
14814
0
    for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14815
0
      FOREACH_SAFI (safi) {
14816
0
        if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14817
0
          continue;
14818
14819
0
        if (uj) {
14820
0
          if (first)
14821
0
            first = false;
14822
0
          else
14823
0
            vty_out(vty, ",\n");
14824
0
          vty_out(vty, "\"%s\":",
14825
0
            get_afi_safi_str(afi, safi,
14826
0
                 true));
14827
0
        } else
14828
0
          vty_out(vty,
14829
0
            "\nFor address family: %s\n",
14830
0
            get_afi_safi_str(afi, safi,
14831
0
                 false));
14832
14833
0
        peer_adj_routes(vty, peer, afi, safi, type,
14834
0
            route_map, prefix, show_flags);
14835
0
      }
14836
0
    }
14837
0
  } else {
14838
0
    for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14839
0
      FOREACH_AFI_SAFI (afi, safi) {
14840
0
        if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14841
0
          continue;
14842
14843
0
        if (uj) {
14844
0
          if (first)
14845
0
            first = false;
14846
0
          else
14847
0
            vty_out(vty, ",\n");
14848
0
          vty_out(vty, "\"%s\":",
14849
0
            get_afi_safi_str(afi, safi,
14850
0
                 true));
14851
0
        } else
14852
0
          vty_out(vty,
14853
0
            "\nFor address family: %s\n",
14854
0
            get_afi_safi_str(afi, safi,
14855
0
                 false));
14856
14857
0
        peer_adj_routes(vty, peer, afi, safi, type,
14858
0
            route_map, prefix, show_flags);
14859
0
      }
14860
0
    }
14861
0
  }
14862
0
  if (uj)
14863
0
    vty_out(vty, "}\n");
14864
14865
0
  return CMD_SUCCESS;
14866
0
}
14867
14868
DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14869
       show_ip_bgp_neighbor_received_prefix_filter_cmd,
14870
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14871
       SHOW_STR
14872
       IP_STR
14873
       BGP_STR
14874
       BGP_INSTANCE_HELP_STR
14875
       BGP_AF_STR
14876
       BGP_AF_STR
14877
       BGP_AF_MODIFIER_STR
14878
       "Detailed information on TCP and BGP neighbor connections\n"
14879
       "Neighbor to display information about\n"
14880
       "Neighbor to display information about\n"
14881
       "Neighbor on BGP configured interface\n"
14882
       "Display information received from a BGP neighbor\n"
14883
       "Display the prefixlist filter\n"
14884
       JSON_STR)
14885
0
{
14886
0
  afi_t afi = AFI_IP6;
14887
0
  safi_t safi = SAFI_UNICAST;
14888
0
  char *peerstr = NULL;
14889
0
  char name[BUFSIZ];
14890
0
  struct peer *peer;
14891
0
  int count;
14892
0
  int idx = 0;
14893
0
  struct bgp *bgp = NULL;
14894
0
  bool uj = use_json(argc, argv);
14895
14896
0
  if (uj)
14897
0
    argc--;
14898
14899
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14900
0
              &bgp, uj);
14901
0
  if (!idx)
14902
0
    return CMD_WARNING;
14903
14904
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14905
0
  argv_find(argv, argc, "neighbors", &idx);
14906
0
  peerstr = argv[++idx]->arg;
14907
14908
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14909
0
  if (!peer)
14910
0
    return CMD_WARNING;
14911
14912
0
  snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
14913
0
  count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14914
0
  if (count) {
14915
0
    if (!uj)
14916
0
      vty_out(vty, "Address Family: %s\n",
14917
0
        get_afi_safi_str(afi, safi, false));
14918
0
    prefix_bgp_show_prefix_list(vty, afi, name, uj);
14919
0
  } else {
14920
0
    if (uj)
14921
0
      vty_out(vty, "{}\n");
14922
0
    else
14923
0
      vty_out(vty, "No functional output\n");
14924
0
  }
14925
14926
0
  return CMD_SUCCESS;
14927
0
}
14928
14929
static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14930
           afi_t afi, safi_t safi,
14931
           enum bgp_show_type type, bool use_json)
14932
0
{
14933
0
  uint16_t show_flags = 0;
14934
14935
0
  if (use_json)
14936
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14937
14938
0
  if (!peer || !peer->afc[afi][safi]) {
14939
0
    if (use_json) {
14940
0
      json_object *json_no = NULL;
14941
0
      json_no = json_object_new_object();
14942
0
      json_object_string_add(
14943
0
        json_no, "warning",
14944
0
        "No such neighbor or address family");
14945
0
      vty_out(vty, "%s\n",
14946
0
        json_object_to_json_string(json_no));
14947
0
      json_object_free(json_no);
14948
0
    } else
14949
0
      vty_out(vty, "%% No such neighbor or address family\n");
14950
0
    return CMD_WARNING;
14951
0
  }
14952
14953
  /* labeled-unicast routes live in the unicast table */
14954
0
  if (safi == SAFI_LABELED_UNICAST)
14955
0
    safi = SAFI_UNICAST;
14956
14957
0
  return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14958
0
      RPKI_NOT_BEING_USED);
14959
0
}
14960
14961
/*
14962
 * Used for "detailed" output for cmds like show bgp <afi> <safi> (or)
14963
 * show bgp <vrf> (or) show bgp <vrf> <afi> <safi>
14964
 */
14965
DEFPY(show_ip_bgp_vrf_afi_safi_routes_detailed,
14966
      show_ip_bgp_vrf_afi_safi_routes_detailed_cmd,
14967
      "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf_name] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] detail [json$uj]",
14968
      SHOW_STR
14969
      IP_STR
14970
      BGP_STR
14971
      BGP_INSTANCE_HELP_STR
14972
      BGP_AFI_HELP_STR
14973
      BGP_SAFI_WITH_LABEL_HELP_STR
14974
      "Detailed information\n"
14975
      JSON_STR)
14976
0
{
14977
0
  afi_t afi = AFI_IP6;
14978
0
  safi_t safi = SAFI_UNICAST;
14979
0
  struct bgp *bgp = NULL;
14980
0
  int idx = 0;
14981
0
  uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
14982
14983
0
  if (uj)
14984
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14985
14986
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14987
0
              &bgp, uj);
14988
0
  if (!idx)
14989
0
    return CMD_WARNING;
14990
  /* 'vrf all' case to iterate all vrfs & show output per vrf instance */
14991
0
  if (vrf_name && strmatch(vrf_name, "all")) {
14992
0
    bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
14993
0
    return CMD_SUCCESS;
14994
0
  }
14995
14996
  /* All other cases except vrf all */
14997
0
  return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
14998
0
      show_flags, RPKI_NOT_BEING_USED);
14999
0
}
15000
15001
DEFUN (show_ip_bgp_neighbor_routes,
15002
       show_ip_bgp_neighbor_routes_cmd,
15003
       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
15004
       SHOW_STR
15005
       IP_STR
15006
       BGP_STR
15007
       BGP_INSTANCE_HELP_STR
15008
       BGP_AFI_HELP_STR
15009
       BGP_SAFI_WITH_LABEL_HELP_STR
15010
       "Detailed information on TCP and BGP neighbor connections\n"
15011
       "Neighbor to display information about\n"
15012
       "Neighbor to display information about\n"
15013
       "Neighbor on BGP configured interface\n"
15014
       "Display flap statistics of the routes learned from neighbor\n"
15015
       "Display the dampened routes received from neighbor\n"
15016
       "Display routes learned from neighbor\n"
15017
       JSON_STR)
15018
0
{
15019
0
  char *peerstr = NULL;
15020
0
  struct bgp *bgp = NULL;
15021
0
  afi_t afi = AFI_IP6;
15022
0
  safi_t safi = SAFI_UNICAST;
15023
0
  struct peer *peer;
15024
0
  enum bgp_show_type sh_type = bgp_show_type_neighbor;
15025
0
  int idx = 0;
15026
0
  bool uj = use_json(argc, argv);
15027
15028
0
  if (uj)
15029
0
    argc--;
15030
15031
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
15032
0
              &bgp, uj);
15033
0
  if (!idx)
15034
0
    return CMD_WARNING;
15035
15036
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
15037
0
  argv_find(argv, argc, "neighbors", &idx);
15038
0
  peerstr = argv[++idx]->arg;
15039
15040
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
15041
0
  if (!peer)
15042
0
    return CMD_WARNING;
15043
15044
0
  if (argv_find(argv, argc, "flap-statistics", &idx))
15045
0
    sh_type = bgp_show_type_flap_neighbor;
15046
0
  else if (argv_find(argv, argc, "dampened-routes", &idx))
15047
0
    sh_type = bgp_show_type_damp_neighbor;
15048
0
  else if (argv_find(argv, argc, "routes", &idx))
15049
0
    sh_type = bgp_show_type_neighbor;
15050
15051
0
  return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
15052
0
}
15053
15054
struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
15055
15056
struct bgp_distance {
15057
  /* Distance value for the IP source prefix. */
15058
  uint8_t distance;
15059
15060
  /* Name of the access-list to be matched. */
15061
  char *access_list;
15062
};
15063
15064
DEFUN (show_bgp_afi_vpn_rd_route,
15065
       show_bgp_afi_vpn_rd_route_cmd,
15066
       "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
15067
       SHOW_STR
15068
       BGP_STR
15069
       BGP_AFI_HELP_STR
15070
       BGP_AF_MODIFIER_STR
15071
       "Display information for a route distinguisher\n"
15072
       "Route Distinguisher\n"
15073
       "All Route Distinguishers\n"
15074
       "Network in the BGP routing table to display\n"
15075
       "Network in the BGP routing table to display\n"
15076
       JSON_STR)
15077
0
{
15078
0
  int ret;
15079
0
  struct prefix_rd prd;
15080
0
  afi_t afi = AFI_MAX;
15081
0
  int idx = 0;
15082
15083
0
  if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
15084
0
    vty_out(vty, "%% Malformed Address Family\n");
15085
0
    return CMD_WARNING;
15086
0
  }
15087
15088
0
  if (!strcmp(argv[5]->arg, "all"))
15089
0
    return bgp_show_route(vty, NULL, argv[6]->arg, afi,
15090
0
              SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
15091
0
              RPKI_NOT_BEING_USED,
15092
0
              use_json(argc, argv));
15093
15094
0
  ret = str2prefix_rd(argv[5]->arg, &prd);
15095
0
  if (!ret) {
15096
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
15097
0
    return CMD_WARNING;
15098
0
  }
15099
15100
0
  return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
15101
0
            0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
15102
0
            use_json(argc, argv));
15103
0
}
15104
15105
static struct bgp_distance *bgp_distance_new(void)
15106
0
{
15107
0
  return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
15108
0
}
15109
15110
static void bgp_distance_free(struct bgp_distance *bdistance)
15111
0
{
15112
0
  XFREE(MTYPE_BGP_DISTANCE, bdistance);
15113
0
}
15114
15115
static int bgp_distance_set(struct vty *vty, const char *distance_str,
15116
          const char *ip_str, const char *access_list_str)
15117
0
{
15118
0
  int ret;
15119
0
  afi_t afi;
15120
0
  safi_t safi;
15121
0
  struct prefix p;
15122
0
  uint8_t distance;
15123
0
  struct bgp_dest *dest;
15124
0
  struct bgp_distance *bdistance;
15125
15126
0
  afi = bgp_node_afi(vty);
15127
0
  safi = bgp_node_safi(vty);
15128
15129
0
  ret = str2prefix(ip_str, &p);
15130
0
  if (ret == 0) {
15131
0
    vty_out(vty, "Malformed prefix\n");
15132
0
    return CMD_WARNING_CONFIG_FAILED;
15133
0
  }
15134
15135
0
  distance = atoi(distance_str);
15136
15137
  /* Get BGP distance node. */
15138
0
  dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15139
0
  bdistance = bgp_dest_get_bgp_distance_info(dest);
15140
0
  if (bdistance)
15141
0
    bgp_dest_unlock_node(dest);
15142
0
  else {
15143
0
    bdistance = bgp_distance_new();
15144
0
    bgp_dest_set_bgp_distance_info(dest, bdistance);
15145
0
  }
15146
15147
  /* Set distance value. */
15148
0
  bdistance->distance = distance;
15149
15150
  /* Reset access-list configuration. */
15151
0
  XFREE(MTYPE_AS_LIST, bdistance->access_list);
15152
0
  if (access_list_str)
15153
0
    bdistance->access_list =
15154
0
      XSTRDUP(MTYPE_AS_LIST, access_list_str);
15155
15156
0
  return CMD_SUCCESS;
15157
0
}
15158
15159
static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15160
            const char *ip_str, const char *access_list_str)
15161
0
{
15162
0
  int ret;
15163
0
  afi_t afi;
15164
0
  safi_t safi;
15165
0
  struct prefix p;
15166
0
  int distance;
15167
0
  struct bgp_dest *dest;
15168
0
  struct bgp_distance *bdistance;
15169
15170
0
  afi = bgp_node_afi(vty);
15171
0
  safi = bgp_node_safi(vty);
15172
15173
0
  ret = str2prefix(ip_str, &p);
15174
0
  if (ret == 0) {
15175
0
    vty_out(vty, "Malformed prefix\n");
15176
0
    return CMD_WARNING_CONFIG_FAILED;
15177
0
  }
15178
15179
0
  dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15180
0
  if (!dest) {
15181
0
    vty_out(vty, "Can't find specified prefix\n");
15182
0
    return CMD_WARNING_CONFIG_FAILED;
15183
0
  }
15184
15185
0
  bdistance = bgp_dest_get_bgp_distance_info(dest);
15186
0
  distance = atoi(distance_str);
15187
15188
0
  if (bdistance->distance != distance) {
15189
0
    vty_out(vty, "Distance does not match configured\n");
15190
0
    bgp_dest_unlock_node(dest);
15191
0
    return CMD_WARNING_CONFIG_FAILED;
15192
0
  }
15193
15194
0
  XFREE(MTYPE_AS_LIST, bdistance->access_list);
15195
0
  bgp_distance_free(bdistance);
15196
15197
0
  bgp_dest_set_bgp_path_info(dest, NULL);
15198
0
  bgp_dest_unlock_node(dest);
15199
0
  bgp_dest_unlock_node(dest);
15200
15201
0
  return CMD_SUCCESS;
15202
0
}
15203
15204
/* Apply BGP information to distance method. */
15205
uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
15206
         afi_t afi, safi_t safi, struct bgp *bgp)
15207
0
{
15208
0
  struct bgp_dest *dest;
15209
0
  struct prefix q = {0};
15210
0
  struct peer *peer;
15211
0
  struct bgp_distance *bdistance;
15212
0
  struct access_list *alist;
15213
0
  struct bgp_static *bgp_static;
15214
0
  struct bgp_path_info *bpi_ultimate;
15215
15216
0
  if (!bgp)
15217
0
    return 0;
15218
15219
0
  peer = pinfo->peer;
15220
15221
0
  if (pinfo->attr->distance)
15222
0
    return pinfo->attr->distance;
15223
15224
  /* get peer origin to calculate appropriate distance */
15225
0
  if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15226
0
    bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15227
0
    peer = bpi_ultimate->peer;
15228
0
  }
15229
15230
  /* Check source address.
15231
   * Note: for aggregate route, peer can have unspec af type.
15232
   */
15233
0
  if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15234
0
      && !sockunion2hostprefix(&peer->su, &q))
15235
0
    return 0;
15236
15237
0
  dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15238
0
  if (dest) {
15239
0
    bdistance = bgp_dest_get_bgp_distance_info(dest);
15240
0
    bgp_dest_unlock_node(dest);
15241
15242
0
    if (bdistance->access_list) {
15243
0
      alist = access_list_lookup(afi, bdistance->access_list);
15244
0
      if (alist
15245
0
          && access_list_apply(alist, p) == FILTER_PERMIT)
15246
0
        return bdistance->distance;
15247
0
    } else
15248
0
      return bdistance->distance;
15249
0
  }
15250
15251
  /* Backdoor check. */
15252
0
  dest = bgp_node_lookup(bgp->route[afi][safi], p);
15253
0
  if (dest) {
15254
0
    bgp_static = bgp_dest_get_bgp_static_info(dest);
15255
0
    bgp_dest_unlock_node(dest);
15256
15257
0
    if (bgp_static->backdoor) {
15258
0
      if (bgp->distance_local[afi][safi])
15259
0
        return bgp->distance_local[afi][safi];
15260
0
      else
15261
0
        return ZEBRA_IBGP_DISTANCE_DEFAULT;
15262
0
    }
15263
0
  }
15264
15265
0
  if (peer->sort == BGP_PEER_EBGP) {
15266
0
    if (bgp->distance_ebgp[afi][safi])
15267
0
      return bgp->distance_ebgp[afi][safi];
15268
0
    return ZEBRA_EBGP_DISTANCE_DEFAULT;
15269
0
  } else if (peer->sort == BGP_PEER_IBGP) {
15270
0
    if (bgp->distance_ibgp[afi][safi])
15271
0
      return bgp->distance_ibgp[afi][safi];
15272
0
    return ZEBRA_IBGP_DISTANCE_DEFAULT;
15273
0
  } else {
15274
0
    if (bgp->distance_local[afi][safi])
15275
0
      return bgp->distance_local[afi][safi];
15276
0
    return ZEBRA_IBGP_DISTANCE_DEFAULT;
15277
0
  }
15278
0
}
15279
15280
/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15281
 * we should tell ZEBRA update the routes for a specific
15282
 * AFI/SAFI to reflect changes in RIB.
15283
 */
15284
static void bgp_announce_routes_distance_update(struct bgp *bgp,
15285
            afi_t update_afi,
15286
            safi_t update_safi)
15287
0
{
15288
0
  afi_t afi;
15289
0
  safi_t safi;
15290
15291
0
  FOREACH_AFI_SAFI (afi, safi) {
15292
0
    if (!bgp_fibupd_safi(safi))
15293
0
      continue;
15294
15295
0
    if (afi != update_afi && safi != update_safi)
15296
0
      continue;
15297
15298
0
    if (BGP_DEBUG(zebra, ZEBRA))
15299
0
      zlog_debug(
15300
0
        "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15301
0
        __func__, afi, safi);
15302
0
    bgp_zebra_announce_table(bgp, afi, safi);
15303
0
  }
15304
0
}
15305
15306
DEFUN (bgp_distance,
15307
       bgp_distance_cmd,
15308
       "distance bgp (1-255) (1-255) (1-255)",
15309
       "Define an administrative distance\n"
15310
       "BGP distance\n"
15311
       "Distance for routes external to the AS\n"
15312
       "Distance for routes internal to the AS\n"
15313
       "Distance for local routes\n")
15314
0
{
15315
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
15316
0
  int idx_number = 2;
15317
0
  int idx_number_2 = 3;
15318
0
  int idx_number_3 = 4;
15319
0
  int distance_ebgp = atoi(argv[idx_number]->arg);
15320
0
  int distance_ibgp = atoi(argv[idx_number_2]->arg);
15321
0
  int distance_local = atoi(argv[idx_number_3]->arg);
15322
0
  afi_t afi;
15323
0
  safi_t safi;
15324
15325
0
  afi = bgp_node_afi(vty);
15326
0
  safi = bgp_node_safi(vty);
15327
15328
0
  if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15329
0
      || bgp->distance_ibgp[afi][safi] != distance_ibgp
15330
0
      || bgp->distance_local[afi][safi] != distance_local) {
15331
0
    bgp->distance_ebgp[afi][safi] = distance_ebgp;
15332
0
    bgp->distance_ibgp[afi][safi] = distance_ibgp;
15333
0
    bgp->distance_local[afi][safi] = distance_local;
15334
0
    bgp_announce_routes_distance_update(bgp, afi, safi);
15335
0
  }
15336
0
  return CMD_SUCCESS;
15337
0
}
15338
15339
DEFUN (no_bgp_distance,
15340
       no_bgp_distance_cmd,
15341
       "no distance bgp [(1-255) (1-255) (1-255)]",
15342
       NO_STR
15343
       "Define an administrative distance\n"
15344
       "BGP distance\n"
15345
       "Distance for routes external to the AS\n"
15346
       "Distance for routes internal to the AS\n"
15347
       "Distance for local routes\n")
15348
0
{
15349
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
15350
0
  afi_t afi;
15351
0
  safi_t safi;
15352
15353
0
  afi = bgp_node_afi(vty);
15354
0
  safi = bgp_node_safi(vty);
15355
15356
0
  if (bgp->distance_ebgp[afi][safi] != 0
15357
0
      || bgp->distance_ibgp[afi][safi] != 0
15358
0
      || bgp->distance_local[afi][safi] != 0) {
15359
0
    bgp->distance_ebgp[afi][safi] = 0;
15360
0
    bgp->distance_ibgp[afi][safi] = 0;
15361
0
    bgp->distance_local[afi][safi] = 0;
15362
0
    bgp_announce_routes_distance_update(bgp, afi, safi);
15363
0
  }
15364
0
  return CMD_SUCCESS;
15365
0
}
15366
15367
15368
DEFUN (bgp_distance_source,
15369
       bgp_distance_source_cmd,
15370
       "distance (1-255) A.B.C.D/M",
15371
       "Define an administrative distance\n"
15372
       "Administrative distance\n"
15373
       "IP source prefix\n")
15374
0
{
15375
0
  int idx_number = 1;
15376
0
  int idx_ipv4_prefixlen = 2;
15377
0
  bgp_distance_set(vty, argv[idx_number]->arg,
15378
0
       argv[idx_ipv4_prefixlen]->arg, NULL);
15379
0
  return CMD_SUCCESS;
15380
0
}
15381
15382
DEFUN (no_bgp_distance_source,
15383
       no_bgp_distance_source_cmd,
15384
       "no distance (1-255) A.B.C.D/M",
15385
       NO_STR
15386
       "Define an administrative distance\n"
15387
       "Administrative distance\n"
15388
       "IP source prefix\n")
15389
0
{
15390
0
  int idx_number = 2;
15391
0
  int idx_ipv4_prefixlen = 3;
15392
0
  bgp_distance_unset(vty, argv[idx_number]->arg,
15393
0
         argv[idx_ipv4_prefixlen]->arg, NULL);
15394
0
  return CMD_SUCCESS;
15395
0
}
15396
15397
DEFUN (bgp_distance_source_access_list,
15398
       bgp_distance_source_access_list_cmd,
15399
       "distance (1-255) A.B.C.D/M WORD",
15400
       "Define an administrative distance\n"
15401
       "Administrative distance\n"
15402
       "IP source prefix\n"
15403
       "Access list name\n")
15404
0
{
15405
0
  int idx_number = 1;
15406
0
  int idx_ipv4_prefixlen = 2;
15407
0
  int idx_word = 3;
15408
0
  bgp_distance_set(vty, argv[idx_number]->arg,
15409
0
       argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15410
0
  return CMD_SUCCESS;
15411
0
}
15412
15413
DEFUN (no_bgp_distance_source_access_list,
15414
       no_bgp_distance_source_access_list_cmd,
15415
       "no distance (1-255) A.B.C.D/M WORD",
15416
       NO_STR
15417
       "Define an administrative distance\n"
15418
       "Administrative distance\n"
15419
       "IP source prefix\n"
15420
       "Access list name\n")
15421
0
{
15422
0
  int idx_number = 2;
15423
0
  int idx_ipv4_prefixlen = 3;
15424
0
  int idx_word = 4;
15425
0
  bgp_distance_unset(vty, argv[idx_number]->arg,
15426
0
         argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15427
0
  return CMD_SUCCESS;
15428
0
}
15429
15430
DEFUN (ipv6_bgp_distance_source,
15431
       ipv6_bgp_distance_source_cmd,
15432
       "distance (1-255) X:X::X:X/M",
15433
       "Define an administrative distance\n"
15434
       "Administrative distance\n"
15435
       "IP source prefix\n")
15436
0
{
15437
0
  bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15438
0
  return CMD_SUCCESS;
15439
0
}
15440
15441
DEFUN (no_ipv6_bgp_distance_source,
15442
       no_ipv6_bgp_distance_source_cmd,
15443
       "no distance (1-255) X:X::X:X/M",
15444
       NO_STR
15445
       "Define an administrative distance\n"
15446
       "Administrative distance\n"
15447
       "IP source prefix\n")
15448
0
{
15449
0
  bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15450
0
  return CMD_SUCCESS;
15451
0
}
15452
15453
DEFUN (ipv6_bgp_distance_source_access_list,
15454
       ipv6_bgp_distance_source_access_list_cmd,
15455
       "distance (1-255) X:X::X:X/M WORD",
15456
       "Define an administrative distance\n"
15457
       "Administrative distance\n"
15458
       "IP source prefix\n"
15459
       "Access list name\n")
15460
0
{
15461
0
  bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15462
0
  return CMD_SUCCESS;
15463
0
}
15464
15465
DEFUN (no_ipv6_bgp_distance_source_access_list,
15466
       no_ipv6_bgp_distance_source_access_list_cmd,
15467
       "no distance (1-255) X:X::X:X/M WORD",
15468
       NO_STR
15469
       "Define an administrative distance\n"
15470
       "Administrative distance\n"
15471
       "IP source prefix\n"
15472
       "Access list name\n")
15473
0
{
15474
0
  bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15475
0
  return CMD_SUCCESS;
15476
0
}
15477
15478
DEFUN (bgp_damp_set,
15479
       bgp_damp_set_cmd,
15480
       "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15481
       "BGP Specific commands\n"
15482
       "Enable route-flap dampening\n"
15483
       "Half-life time for the penalty\n"
15484
       "Value to start reusing a route\n"
15485
       "Value to start suppressing a route\n"
15486
       "Maximum duration to suppress a stable route\n")
15487
0
{
15488
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
15489
0
  int idx_half_life = 2;
15490
0
  int idx_reuse = 3;
15491
0
  int idx_suppress = 4;
15492
0
  int idx_max_suppress = 5;
15493
0
  int half = DEFAULT_HALF_LIFE * 60;
15494
0
  int reuse = DEFAULT_REUSE;
15495
0
  int suppress = DEFAULT_SUPPRESS;
15496
0
  int max = 4 * half;
15497
15498
0
  if (argc == 6) {
15499
0
    half = atoi(argv[idx_half_life]->arg) * 60;
15500
0
    reuse = atoi(argv[idx_reuse]->arg);
15501
0
    suppress = atoi(argv[idx_suppress]->arg);
15502
0
    max = atoi(argv[idx_max_suppress]->arg) * 60;
15503
0
  } else if (argc == 3) {
15504
0
    half = atoi(argv[idx_half_life]->arg) * 60;
15505
0
    max = 4 * half;
15506
0
  }
15507
15508
  /*
15509
   * These can't be 0 but our SA doesn't understand the
15510
   * way our cli is constructed
15511
   */
15512
0
  assert(reuse);
15513
0
  assert(half);
15514
0
  if (suppress < reuse) {
15515
0
    vty_out(vty,
15516
0
      "Suppress value cannot be less than reuse value \n");
15517
0
    return 0;
15518
0
  }
15519
15520
0
  return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15521
0
             reuse, suppress, max);
15522
0
}
15523
15524
DEFUN (bgp_damp_unset,
15525
       bgp_damp_unset_cmd,
15526
       "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15527
       NO_STR
15528
       "BGP Specific commands\n"
15529
       "Enable route-flap dampening\n"
15530
       "Half-life time for the penalty\n"
15531
       "Value to start reusing a route\n"
15532
       "Value to start suppressing a route\n"
15533
       "Maximum duration to suppress a stable route\n")
15534
0
{
15535
0
  VTY_DECLVAR_CONTEXT(bgp, bgp);
15536
0
  return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
15537
0
}
15538
15539
/* Display specified route of BGP table. */
15540
static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15541
        const char *ip_str, afi_t afi, safi_t safi,
15542
        struct prefix_rd *prd, int prefix_check)
15543
0
{
15544
0
  int ret;
15545
0
  struct prefix match;
15546
0
  struct bgp_dest *dest;
15547
0
  struct bgp_dest *rm;
15548
0
  struct bgp_path_info *pi;
15549
0
  struct bgp_path_info *pi_temp;
15550
0
  struct bgp *bgp;
15551
0
  struct bgp_table *table;
15552
15553
  /* BGP structure lookup. */
15554
0
  if (view_name) {
15555
0
    bgp = bgp_lookup_by_name(view_name);
15556
0
    if (bgp == NULL) {
15557
0
      vty_out(vty, "%% Can't find BGP instance %s\n",
15558
0
        view_name);
15559
0
      return CMD_WARNING;
15560
0
    }
15561
0
  } else {
15562
0
    bgp = bgp_get_default();
15563
0
    if (bgp == NULL) {
15564
0
      vty_out(vty, "%% No BGP process is configured\n");
15565
0
      return CMD_WARNING;
15566
0
    }
15567
0
  }
15568
15569
  /* Check IP address argument. */
15570
0
  ret = str2prefix(ip_str, &match);
15571
0
  if (!ret) {
15572
0
    vty_out(vty, "%% address is malformed\n");
15573
0
    return CMD_WARNING;
15574
0
  }
15575
15576
0
  match.family = afi2family(afi);
15577
15578
0
  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15579
0
      || (safi == SAFI_EVPN)) {
15580
0
    for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15581
0
         dest = bgp_route_next(dest)) {
15582
0
      const struct prefix *dest_p = bgp_dest_get_prefix(dest);
15583
15584
0
      if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
15585
0
        continue;
15586
0
      table = bgp_dest_get_bgp_table_info(dest);
15587
0
      if (!table)
15588
0
        continue;
15589
0
      rm = bgp_node_match(table, &match);
15590
0
      if (rm == NULL)
15591
0
        continue;
15592
15593
0
      const struct prefix *rm_p = bgp_dest_get_prefix(dest);
15594
15595
0
      if (!prefix_check
15596
0
          || rm_p->prefixlen == match.prefixlen) {
15597
0
        pi = bgp_dest_get_bgp_path_info(rm);
15598
0
        while (pi) {
15599
0
          if (pi->extra && pi->extra->damp_info) {
15600
0
            pi_temp = pi->next;
15601
0
            bgp_damp_info_free(
15602
0
              pi->extra->damp_info,
15603
0
              1, afi, safi);
15604
0
            pi = pi_temp;
15605
0
          } else
15606
0
            pi = pi->next;
15607
0
        }
15608
0
      }
15609
15610
0
      bgp_dest_unlock_node(rm);
15611
0
    }
15612
0
  } else {
15613
0
    dest = bgp_node_match(bgp->rib[afi][safi], &match);
15614
0
    if (dest != NULL) {
15615
0
      const struct prefix *dest_p = bgp_dest_get_prefix(dest);
15616
15617
0
      if (!prefix_check
15618
0
          || dest_p->prefixlen == match.prefixlen) {
15619
0
        pi = bgp_dest_get_bgp_path_info(dest);
15620
0
        while (pi) {
15621
0
          if (pi->extra && pi->extra->damp_info) {
15622
0
            pi_temp = pi->next;
15623
0
            bgp_damp_info_free(
15624
0
              pi->extra->damp_info,
15625
0
              1, afi, safi);
15626
0
            pi = pi_temp;
15627
0
          } else
15628
0
            pi = pi->next;
15629
0
        }
15630
0
      }
15631
15632
0
      bgp_dest_unlock_node(dest);
15633
0
    }
15634
0
  }
15635
15636
0
  return CMD_SUCCESS;
15637
0
}
15638
15639
DEFUN (clear_ip_bgp_dampening,
15640
       clear_ip_bgp_dampening_cmd,
15641
       "clear ip bgp dampening",
15642
       CLEAR_STR
15643
       IP_STR
15644
       BGP_STR
15645
       "Clear route flap dampening information\n")
15646
0
{
15647
0
  bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
15648
0
  return CMD_SUCCESS;
15649
0
}
15650
15651
DEFUN (clear_ip_bgp_dampening_prefix,
15652
       clear_ip_bgp_dampening_prefix_cmd,
15653
       "clear ip bgp dampening A.B.C.D/M",
15654
       CLEAR_STR
15655
       IP_STR
15656
       BGP_STR
15657
       "Clear route flap dampening information\n"
15658
       "IPv4 prefix\n")
15659
0
{
15660
0
  int idx_ipv4_prefixlen = 4;
15661
0
  return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15662
0
            AFI_IP, SAFI_UNICAST, NULL, 1);
15663
0
}
15664
15665
DEFUN (clear_ip_bgp_dampening_address,
15666
       clear_ip_bgp_dampening_address_cmd,
15667
       "clear ip bgp dampening A.B.C.D",
15668
       CLEAR_STR
15669
       IP_STR
15670
       BGP_STR
15671
       "Clear route flap dampening information\n"
15672
       "Network to clear damping information\n")
15673
0
{
15674
0
  int idx_ipv4 = 4;
15675
0
  return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15676
0
            SAFI_UNICAST, NULL, 0);
15677
0
}
15678
15679
DEFUN (clear_ip_bgp_dampening_address_mask,
15680
       clear_ip_bgp_dampening_address_mask_cmd,
15681
       "clear ip bgp dampening A.B.C.D A.B.C.D",
15682
       CLEAR_STR
15683
       IP_STR
15684
       BGP_STR
15685
       "Clear route flap dampening information\n"
15686
       "Network to clear damping information\n"
15687
       "Network mask\n")
15688
0
{
15689
0
  int idx_ipv4 = 4;
15690
0
  int idx_ipv4_2 = 5;
15691
0
  int ret;
15692
0
  char prefix_str[BUFSIZ];
15693
15694
0
  ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
15695
0
             prefix_str, sizeof(prefix_str));
15696
0
  if (!ret) {
15697
0
    vty_out(vty, "%% Inconsistent address and mask\n");
15698
0
    return CMD_WARNING;
15699
0
  }
15700
15701
0
  return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15702
0
            NULL, 0);
15703
0
}
15704
15705
static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
15706
0
{
15707
0
       struct vty *vty = arg;
15708
0
       struct peer *peer = bucket->data;
15709
15710
0
       vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
15711
0
}
15712
15713
DEFUN (show_bgp_listeners,
15714
       show_bgp_listeners_cmd,
15715
       "show bgp listeners",
15716
       SHOW_STR
15717
       BGP_STR
15718
       "Display Listen Sockets and who created them\n")
15719
0
{
15720
0
  bgp_dump_listener_info(vty);
15721
15722
0
  return CMD_SUCCESS;
15723
0
}
15724
15725
DEFUN (show_bgp_peerhash,
15726
       show_bgp_peerhash_cmd,
15727
       "show bgp peerhash",
15728
       SHOW_STR
15729
       BGP_STR
15730
       "Display information about the BGP peerhash\n")
15731
0
{
15732
0
       struct list *instances = bm->bgp;
15733
0
       struct listnode *node;
15734
0
       struct bgp *bgp;
15735
15736
0
       for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15737
0
               vty_out(vty, "BGP: %s\n", bgp->name);
15738
0
               hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15739
0
                            vty);
15740
0
       }
15741
15742
0
       return CMD_SUCCESS;
15743
0
}
15744
15745
/* also used for encap safi */
15746
static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15747
           afi_t afi, safi_t safi)
15748
0
{
15749
0
  struct bgp_dest *pdest;
15750
0
  struct bgp_dest *dest;
15751
0
  struct bgp_table *table;
15752
0
  const struct prefix *p;
15753
0
  struct bgp_static *bgp_static;
15754
0
  mpls_label_t label;
15755
15756
  /* Network configuration. */
15757
0
  for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15758
0
       pdest = bgp_route_next(pdest)) {
15759
0
    table = bgp_dest_get_bgp_table_info(pdest);
15760
0
    if (!table)
15761
0
      continue;
15762
15763
0
    for (dest = bgp_table_top(table); dest;
15764
0
         dest = bgp_route_next(dest)) {
15765
0
      bgp_static = bgp_dest_get_bgp_static_info(dest);
15766
0
      if (bgp_static == NULL)
15767
0
        continue;
15768
15769
0
      p = bgp_dest_get_prefix(dest);
15770
15771
      /* "network" configuration display.  */
15772
0
      label = decode_label(&bgp_static->label);
15773
15774
0
      vty_out(vty, "  network %pFX rd %s", p,
15775
0
        bgp_static->prd_pretty);
15776
0
      if (safi == SAFI_MPLS_VPN)
15777
0
        vty_out(vty, " label %u", label);
15778
15779
0
      if (bgp_static->rmap.name)
15780
0
        vty_out(vty, " route-map %s",
15781
0
          bgp_static->rmap.name);
15782
15783
0
      if (bgp_static->backdoor)
15784
0
        vty_out(vty, " backdoor");
15785
15786
0
      vty_out(vty, "\n");
15787
0
    }
15788
0
  }
15789
0
}
15790
15791
static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15792
            afi_t afi, safi_t safi)
15793
0
{
15794
0
  struct bgp_dest *pdest;
15795
0
  struct bgp_dest *dest;
15796
0
  struct bgp_table *table;
15797
0
  const struct prefix *p;
15798
0
  struct bgp_static *bgp_static;
15799
0
  char buf[PREFIX_STRLEN * 2];
15800
0
  char buf2[SU_ADDRSTRLEN];
15801
0
  char esi_buf[ESI_STR_LEN];
15802
15803
  /* Network configuration. */
15804
0
  for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15805
0
       pdest = bgp_route_next(pdest)) {
15806
0
    table = bgp_dest_get_bgp_table_info(pdest);
15807
0
    if (!table)
15808
0
      continue;
15809
15810
0
    for (dest = bgp_table_top(table); dest;
15811
0
         dest = bgp_route_next(dest)) {
15812
0
      bgp_static = bgp_dest_get_bgp_static_info(dest);
15813
0
      if (bgp_static == NULL)
15814
0
        continue;
15815
15816
0
      char *macrouter = NULL;
15817
15818
0
      if (bgp_static->router_mac)
15819
0
        macrouter = prefix_mac2str(
15820
0
          bgp_static->router_mac, NULL, 0);
15821
0
      if (bgp_static->eth_s_id)
15822
0
        esi_to_str(bgp_static->eth_s_id,
15823
0
            esi_buf, sizeof(esi_buf));
15824
0
      p = bgp_dest_get_prefix(dest);
15825
15826
      /* "network" configuration display.  */
15827
0
      if (p->u.prefix_evpn.route_type == 5) {
15828
0
        char local_buf[PREFIX_STRLEN];
15829
15830
0
        uint8_t family = is_evpn_prefix_ipaddr_v4((
15831
0
               struct prefix_evpn *)p)
15832
0
               ? AF_INET
15833
0
               : AF_INET6;
15834
0
        inet_ntop(family,
15835
0
            &p->u.prefix_evpn.prefix_addr.ip.ip
15836
0
               .addr,
15837
0
            local_buf, sizeof(local_buf));
15838
0
        snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15839
0
           p->u.prefix_evpn.prefix_addr
15840
0
             .ip_prefix_length);
15841
0
      } else {
15842
0
        prefix2str(p, buf, sizeof(buf));
15843
0
      }
15844
15845
0
      if (bgp_static->gatewayIp.family == AF_INET
15846
0
          || bgp_static->gatewayIp.family == AF_INET6)
15847
0
        inet_ntop(bgp_static->gatewayIp.family,
15848
0
            &bgp_static->gatewayIp.u.prefix, buf2,
15849
0
            sizeof(buf2));
15850
0
      vty_out(vty,
15851
0
        "  network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15852
0
        buf, bgp_static->prd_pretty,
15853
0
        p->u.prefix_evpn.prefix_addr.eth_tag,
15854
0
        decode_label(&bgp_static->label), esi_buf, buf2,
15855
0
        macrouter);
15856
15857
0
      XFREE(MTYPE_TMP, macrouter);
15858
0
    }
15859
0
  }
15860
0
}
15861
15862
/* Configuration of static route announcement and aggregate
15863
   information. */
15864
void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15865
            safi_t safi)
15866
0
{
15867
0
  struct bgp_dest *dest;
15868
0
  const struct prefix *p;
15869
0
  struct bgp_static *bgp_static;
15870
0
  struct bgp_aggregate *bgp_aggregate;
15871
15872
0
  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15873
0
    bgp_config_write_network_vpn(vty, bgp, afi, safi);
15874
0
    return;
15875
0
  }
15876
15877
0
  if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15878
0
    bgp_config_write_network_evpn(vty, bgp, afi, safi);
15879
0
    return;
15880
0
  }
15881
15882
  /* Network configuration. */
15883
0
  for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15884
0
       dest = bgp_route_next(dest)) {
15885
0
    bgp_static = bgp_dest_get_bgp_static_info(dest);
15886
0
    if (bgp_static == NULL)
15887
0
      continue;
15888
15889
0
    p = bgp_dest_get_prefix(dest);
15890
15891
0
    vty_out(vty, "  network %pFX", p);
15892
15893
0
    if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15894
0
      vty_out(vty, " label-index %u",
15895
0
        bgp_static->label_index);
15896
15897
0
    if (bgp_static->rmap.name)
15898
0
      vty_out(vty, " route-map %s", bgp_static->rmap.name);
15899
15900
0
    if (bgp_static->backdoor)
15901
0
      vty_out(vty, " backdoor");
15902
15903
0
    vty_out(vty, "\n");
15904
0
  }
15905
15906
  /* Aggregate-address configuration. */
15907
0
  for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15908
0
       dest = bgp_route_next(dest)) {
15909
0
    bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
15910
0
    if (bgp_aggregate == NULL)
15911
0
      continue;
15912
15913
0
    p = bgp_dest_get_prefix(dest);
15914
15915
0
    vty_out(vty, "  aggregate-address %pFX", p);
15916
15917
0
    if (bgp_aggregate->as_set)
15918
0
      vty_out(vty, " as-set");
15919
15920
0
    if (bgp_aggregate->summary_only)
15921
0
      vty_out(vty, " summary-only");
15922
15923
0
    if (bgp_aggregate->rmap.name)
15924
0
      vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15925
15926
0
    if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15927
0
      vty_out(vty, " origin %s",
15928
0
        bgp_origin2str(bgp_aggregate->origin));
15929
15930
0
    if (bgp_aggregate->match_med)
15931
0
      vty_out(vty, " matching-MED-only");
15932
15933
0
    if (bgp_aggregate->suppress_map_name)
15934
0
      vty_out(vty, " suppress-map %s",
15935
0
        bgp_aggregate->suppress_map_name);
15936
15937
0
    vty_out(vty, "\n");
15938
0
  }
15939
0
}
15940
15941
void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
15942
             safi_t safi)
15943
0
{
15944
0
  struct bgp_dest *dest;
15945
0
  struct bgp_distance *bdistance;
15946
15947
  /* Distance configuration. */
15948
0
  if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15949
0
      && bgp->distance_local[afi][safi]
15950
0
      && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15951
0
    || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15952
0
    || bgp->distance_local[afi][safi]
15953
0
         != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
15954
0
    vty_out(vty, "  distance bgp %d %d %d\n",
15955
0
      bgp->distance_ebgp[afi][safi],
15956
0
      bgp->distance_ibgp[afi][safi],
15957
0
      bgp->distance_local[afi][safi]);
15958
0
  }
15959
15960
0
  for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15961
0
       dest = bgp_route_next(dest)) {
15962
0
    bdistance = bgp_dest_get_bgp_distance_info(dest);
15963
0
    if (bdistance != NULL)
15964
0
      vty_out(vty, "  distance %d %pBD %s\n",
15965
0
        bdistance->distance, dest,
15966
0
        bdistance->access_list ? bdistance->access_list
15967
0
                   : "");
15968
0
  }
15969
0
}
15970
15971
/* Allocate routing table structure and install commands. */
15972
void bgp_route_init(void)
15973
1
{
15974
1
  afi_t afi;
15975
1
  safi_t safi;
15976
15977
  /* Init BGP distance table. */
15978
3
  FOREACH_AFI_SAFI (afi, safi)
15979
21
    bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
15980
15981
  /* IPv4 BGP commands. */
15982
1
  install_element(BGP_NODE, &bgp_table_map_cmd);
15983
1
  install_element(BGP_NODE, &bgp_network_cmd);
15984
1
  install_element(BGP_NODE, &no_bgp_table_map_cmd);
15985
15986
1
  install_element(BGP_NODE, &aggregate_addressv4_cmd);
15987
15988
  /* IPv4 unicast configuration.  */
15989
1
  install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15990
1
  install_element(BGP_IPV4_NODE, &bgp_network_cmd);
15991
1
  install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
15992
15993
1
  install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
15994
15995
  /* IPv4 multicast configuration.  */
15996
1
  install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15997
1
  install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
15998
1
  install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
15999
1
  install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
16000
16001
  /* IPv4 labeled-unicast configuration.  */
16002
1
  install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
16003
1
  install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
16004
16005
1
  install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
16006
1
  install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
16007
1
  install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
16008
1
  install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
16009
1
  install_element(VIEW_NODE, &show_ip_bgp_cmd);
16010
1
  install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
16011
1
  install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
16012
1
  install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
16013
16014
1
  install_element(VIEW_NODE,
16015
1
      &show_ip_bgp_instance_neighbor_advertised_route_cmd);
16016
1
  install_element(VIEW_NODE,
16017
1
      &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
16018
1
  install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
16019
1
  install_element(VIEW_NODE,
16020
1
      &show_ip_bgp_neighbor_received_prefix_filter_cmd);
16021
#ifdef KEEP_OLD_VPN_COMMANDS
16022
  install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
16023
#endif /* KEEP_OLD_VPN_COMMANDS */
16024
1
  install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
16025
1
  install_element(VIEW_NODE,
16026
1
      &show_bgp_l2vpn_evpn_route_prefix_cmd);
16027
16028
  /* BGP dampening clear commands */
16029
1
  install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
16030
1
  install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
16031
16032
1
  install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
16033
1
  install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
16034
16035
  /* prefix count */
16036
1
  install_element(ENABLE_NODE,
16037
1
      &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
16038
#ifdef KEEP_OLD_VPN_COMMANDS
16039
  install_element(ENABLE_NODE,
16040
      &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
16041
#endif /* KEEP_OLD_VPN_COMMANDS */
16042
16043
  /* New config IPv6 BGP commands.  */
16044
1
  install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
16045
1
  install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
16046
1
  install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
16047
16048
1
  install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
16049
16050
1
  install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
16051
16052
  /* IPv6 labeled unicast address family. */
16053
1
  install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
16054
1
  install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
16055
16056
1
  install_element(BGP_NODE, &bgp_distance_cmd);
16057
1
  install_element(BGP_NODE, &no_bgp_distance_cmd);
16058
1
  install_element(BGP_NODE, &bgp_distance_source_cmd);
16059
1
  install_element(BGP_NODE, &no_bgp_distance_source_cmd);
16060
1
  install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
16061
1
  install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
16062
1
  install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
16063
1
  install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
16064
1
  install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
16065
1
  install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
16066
1
  install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
16067
1
  install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
16068
1
  install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
16069
1
  install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
16070
1
  install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
16071
1
  install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
16072
1
  install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
16073
1
  install_element(BGP_IPV4M_NODE,
16074
1
      &no_bgp_distance_source_access_list_cmd);
16075
1
  install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
16076
1
  install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
16077
1
  install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
16078
1
  install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
16079
1
  install_element(BGP_IPV6_NODE,
16080
1
      &ipv6_bgp_distance_source_access_list_cmd);
16081
1
  install_element(BGP_IPV6_NODE,
16082
1
      &no_ipv6_bgp_distance_source_access_list_cmd);
16083
1
  install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
16084
1
  install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
16085
1
  install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
16086
1
  install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
16087
1
  install_element(BGP_IPV6M_NODE,
16088
1
      &ipv6_bgp_distance_source_access_list_cmd);
16089
1
  install_element(BGP_IPV6M_NODE,
16090
1
      &no_ipv6_bgp_distance_source_access_list_cmd);
16091
16092
  /* BGP dampening */
16093
1
  install_element(BGP_NODE, &bgp_damp_set_cmd);
16094
1
  install_element(BGP_NODE, &bgp_damp_unset_cmd);
16095
1
  install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
16096
1
  install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
16097
1
  install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
16098
1
  install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
16099
1
  install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
16100
1
  install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
16101
1
  install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
16102
1
  install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
16103
1
  install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
16104
1
  install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
16105
1
  install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
16106
1
  install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
16107
16108
  /* Large Communities */
16109
1
  install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
16110
1
  install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
16111
16112
  /* show bgp vrf <afi> <safi> detailed */
16113
1
  install_element(VIEW_NODE,
16114
1
      &show_ip_bgp_vrf_afi_safi_routes_detailed_cmd);
16115
16116
1
  install_element(VIEW_NODE, &show_bgp_listeners_cmd);
16117
1
  install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
16118
1
}
16119
16120
void bgp_route_finish(void)
16121
0
{
16122
0
  afi_t afi;
16123
0
  safi_t safi;
16124
16125
0
  FOREACH_AFI_SAFI (afi, safi) {
16126
0
    bgp_table_unlock(bgp_distance_table[afi][safi]);
16127
    bgp_distance_table[afi][safi] = NULL;
16128
0
  }
16129
0
}