]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Allow shortened 'no set large-community' and 'no set large-comm-list'
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
25#include "prefix.h"
26#include "linklist.h"
27#include "memory.h"
28#include "command.h"
29#include "stream.h"
30#include "filter.h"
718e3744 31#include "log.h"
32#include "routemap.h"
33#include "buffer.h"
34#include "sockunion.h"
35#include "plist.h"
36#include "thread.h"
200df115 37#include "workqueue.h"
3f9c7369 38#include "queue.h"
6e919709 39#include "memory.h"
4dcadbef 40#include "lib/json.h"
d8d084d9 41#include "lib_errors.h"
718e3744 42
43#include "bgpd/bgpd.h"
44#include "bgpd/bgp_table.h"
45#include "bgpd/bgp_route.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_debug.h"
14454c9f 48#include "bgpd/bgp_errors.h"
718e3744 49#include "bgpd/bgp_aspath.h"
50#include "bgpd/bgp_regex.h"
51#include "bgpd/bgp_community.h"
52#include "bgpd/bgp_ecommunity.h"
57d187bc 53#include "bgpd/bgp_lcommunity.h"
718e3744 54#include "bgpd/bgp_clist.h"
55#include "bgpd/bgp_packet.h"
56#include "bgpd/bgp_filter.h"
57#include "bgpd/bgp_fsm.h"
58#include "bgpd/bgp_mplsvpn.h"
59#include "bgpd/bgp_nexthop.h"
60#include "bgpd/bgp_damp.h"
61#include "bgpd/bgp_advertise.h"
62#include "bgpd/bgp_zebra.h"
0a486e5f 63#include "bgpd/bgp_vty.h"
96450faf 64#include "bgpd/bgp_mpath.h"
fc9a856f 65#include "bgpd/bgp_nht.h"
3f9c7369 66#include "bgpd/bgp_updgrp.h"
cd1964ff 67#include "bgpd/bgp_label.h"
dcc68b5e 68#include "bgpd/bgp_addpath.h"
718e3744 69
65efcfce 70#if ENABLE_BGP_VNC
f8b6f499
LB
71#include "bgpd/rfapi/rfapi_backend.h"
72#include "bgpd/rfapi/vnc_import_bgp.h"
73#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 74#endif
aee875b5
PG
75#include "bgpd/bgp_encap_types.h"
76#include "bgpd/bgp_encap_tlv.h"
684a7227 77#include "bgpd/bgp_evpn.h"
3da6fcd5 78#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 79#include "bgpd/bgp_flowspec.h"
98a9dbc7 80#include "bgpd/bgp_flowspec_util.h"
45918cfb 81#include "bgpd/bgp_pbr.h"
65efcfce 82
e2a86ad9
DS
83#ifndef VTYSH_EXTRACT_PL
84#include "bgpd/bgp_route_clippy.c"
85#endif
aee875b5 86
718e3744 87/* Extern from bgp_dump.c */
dde72586
SH
88extern const char *bgp_origin_str[];
89extern const char *bgp_origin_long_str[];
6b0655a2 90
b7d08f5a 91/* PMSI strings. */
92#define PMSI_TNLTYPE_STR_NO_INFO "No info"
93#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
94static const struct message bgp_pmsi_tnltype_str[] = {
95 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
96 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
97 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
98 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
99 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
100 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
101 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
102 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 103 {0}
104};
b7d08f5a 105
9df8b37c
PZ
106#define VRFID_NONE_STR "-"
107
d62a17ae 108struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
109 safi_t safi, struct prefix *p,
110 struct prefix_rd *prd)
111{
112 struct bgp_node *rn;
113 struct bgp_node *prn = NULL;
114
115 assert(table);
116 if (!table)
117 return NULL;
118
119 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
120 || (safi == SAFI_EVPN)) {
121 prn = bgp_node_get(table, (struct prefix *)prd);
122
67009e22
DS
123 if (!bgp_node_has_bgp_path_info_data(prn))
124 bgp_node_set_bgp_table_info(
125 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 126 else
127 bgp_unlock_node(prn);
67009e22 128 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 129 }
718e3744 130
d62a17ae 131 rn = bgp_node_get(table, p);
718e3744 132
d62a17ae 133 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
134 || (safi == SAFI_EVPN))
135 rn->prn = prn;
718e3744 136
d62a17ae 137 return rn;
718e3744 138}
6b0655a2 139
d62a17ae 140struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
141 safi_t safi, struct prefix *p,
142 struct prefix_rd *prd)
128ea8ab 143{
d62a17ae 144 struct bgp_node *rn;
145 struct bgp_node *prn = NULL;
128ea8ab 146
d62a17ae 147 if (!table)
148 return NULL;
128ea8ab 149
d62a17ae 150 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
151 || (safi == SAFI_EVPN)) {
152 prn = bgp_node_lookup(table, (struct prefix *)prd);
153 if (!prn)
154 return NULL;
128ea8ab 155
6f94b685 156 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 157 bgp_unlock_node(prn);
158 return NULL;
159 }
128ea8ab 160
67009e22 161 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 162 }
128ea8ab 163
d62a17ae 164 rn = bgp_node_lookup(table, p);
128ea8ab 165
d62a17ae 166 return rn;
128ea8ab 167}
168
18ee8310
DS
169/* Allocate bgp_path_info_extra */
170static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 171{
4b7e6066
DS
172 struct bgp_path_info_extra *new;
173 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
174 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
175 new->label[0] = MPLS_INVALID_LABEL;
176 new->num_labels = 0;
d62a17ae 177 return new;
fb982c25
PJ
178}
179
a2e219fe 180void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 181{
4b7e6066 182 struct bgp_path_info_extra *e;
d62a17ae 183
c93a3b77
DS
184 if (!extra || !*extra)
185 return;
d62a17ae 186
c93a3b77
DS
187 e = *extra;
188 if (e->damp_info)
189 bgp_damp_info_free(e->damp_info, 0);
d62a17ae 190
c93a3b77
DS
191 e->damp_info = NULL;
192 if (e->parent) {
40381db7 193 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 194
40381db7 195 if (bpi->net) {
0e70e6c8
DL
196 /* FIXME: since multiple e may have the same e->parent
197 * and e->parent->net is holding a refcount for each
198 * of them, we need to do some fudging here.
199 *
40381db7
DS
200 * WARNING: if bpi->net->lock drops to 0, bpi may be
201 * freed as well (because bpi->net was holding the
202 * last reference to bpi) => write after free!
0e70e6c8
DL
203 */
204 unsigned refcount;
205
40381db7
DS
206 bpi = bgp_path_info_lock(bpi);
207 refcount = bpi->net->lock - 1;
208 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 209 if (!refcount)
40381db7
DS
210 bpi->net = NULL;
211 bgp_path_info_unlock(bpi);
0e70e6c8 212 }
18ee8310 213 bgp_path_info_unlock(e->parent);
c93a3b77 214 e->parent = NULL;
d62a17ae 215 }
c93a3b77
DS
216
217 if (e->bgp_orig)
218 bgp_unlock(e->bgp_orig);
c26edcda
PG
219
220 if ((*extra)->bgp_fs_pbr)
6a154c88 221 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
222 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
223
224 *extra = NULL;
fb982c25
PJ
225}
226
18ee8310
DS
227/* Get bgp_path_info extra information for the given bgp_path_info, lazy
228 * allocated if required.
fb982c25 229 */
40381db7 230struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 231{
40381db7
DS
232 if (!pi->extra)
233 pi->extra = bgp_path_info_extra_new();
234 return pi->extra;
fb982c25
PJ
235}
236
65efcfce 237/* Allocate new bgp info structure. */
18ee8310 238struct bgp_path_info *bgp_path_info_new(void)
65efcfce 239{
4b7e6066 240 return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
65efcfce
LB
241}
242
718e3744 243/* Free bgp route information. */
9b6d8fcf 244static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 245{
9b6d8fcf
DS
246 if (path->attr)
247 bgp_attr_unintern(&path->attr);
fb018d25 248
9b6d8fcf
DS
249 bgp_unlink_nexthop(path);
250 bgp_path_info_extra_free(&path->extra);
251 bgp_path_info_mpath_free(&path->mpath);
dcc68b5e
MS
252 bgp_addpath_free_info_data(&path->tx_addpath,
253 path->net ? &path->net->tx_addpath : NULL);
718e3744 254
9b6d8fcf 255 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 256
9b6d8fcf 257 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 258}
259
9b6d8fcf 260struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 261{
9b6d8fcf
DS
262 path->lock++;
263 return path;
200df115 264}
265
9b6d8fcf 266struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 267{
9b6d8fcf
DS
268 assert(path && path->lock > 0);
269 path->lock--;
d62a17ae 270
9b6d8fcf 271 if (path->lock == 0) {
200df115 272#if 0
273 zlog_debug ("%s: unlocked and freeing", __func__);
274 zlog_backtrace (LOG_DEBUG);
275#endif
9b6d8fcf 276 bgp_path_info_free(path);
d62a17ae 277 return NULL;
278 }
200df115 279
280#if 0
9b6d8fcf 281 if (path->lock == 1)
200df115 282 {
283 zlog_debug ("%s: unlocked to 1", __func__);
284 zlog_backtrace (LOG_DEBUG);
285 }
286#endif
d62a17ae 287
9b6d8fcf 288 return path;
200df115 289}
290
40381db7 291void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 292{
4b7e6066 293 struct bgp_path_info *top;
718e3744 294
6f94b685 295 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 296
6f94b685 297 pi->next = top;
40381db7 298 pi->prev = NULL;
d62a17ae 299 if (top)
40381db7 300 top->prev = pi;
6f94b685 301 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 302
40381db7 303 bgp_path_info_lock(pi);
d62a17ae 304 bgp_lock_node(rn);
40381db7 305 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 306}
307
d62a17ae 308/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 309 completion callback *only* */
40381db7 310void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 311{
40381db7
DS
312 if (pi->next)
313 pi->next->prev = pi->prev;
314 if (pi->prev)
315 pi->prev->next = pi->next;
d62a17ae 316 else
6f94b685 317 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 318
40381db7
DS
319 bgp_path_info_mpath_dequeue(pi);
320 bgp_path_info_unlock(pi);
d62a17ae 321 bgp_unlock_node(rn);
718e3744 322}
323
40381db7 324void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 325{
40381db7 326 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 327 /* set of previous already took care of pcount */
40381db7 328 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 329}
330
18ee8310 331/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
332 called when a route is deleted and then quickly re-added before the
333 deletion has been processed */
40381db7 334void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 335{
40381db7 336 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 337 /* unset of previous already took care of pcount */
40381db7 338 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
339}
340
d62a17ae 341/* Adjust pcount as required */
40381db7 342static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 343{
d62a17ae 344 struct bgp_table *table;
67174041 345
d62a17ae 346 assert(rn && bgp_node_table(rn));
40381db7 347 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 348
d62a17ae 349 table = bgp_node_table(rn);
67174041 350
40381db7 351 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 352 return;
353
40381db7
DS
354 if (!BGP_PATH_COUNTABLE(pi)
355 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 356
40381db7 357 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 358
359 /* slight hack, but more robust against errors. */
40381db7
DS
360 if (pi->peer->pcount[table->afi][table->safi])
361 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 362 else
450971aa 363 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 364 "Asked to decrement 0 prefix count for peer");
40381db7
DS
365 } else if (BGP_PATH_COUNTABLE(pi)
366 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
367 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
368 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 369 }
1a392d46
PJ
370}
371
40381db7
DS
372static int bgp_label_index_differs(struct bgp_path_info *pi1,
373 struct bgp_path_info *pi2)
28d58fd7 374{
40381db7 375 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 376}
1a392d46 377
18ee8310 378/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
379 * This is here primarily to keep prefix-count in check.
380 */
40381db7 381void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 382 uint32_t flag)
1a392d46 383{
40381db7 384 SET_FLAG(pi->flags, flag);
d62a17ae 385
386 /* early bath if we know it's not a flag that changes countability state
387 */
388 if (!CHECK_FLAG(flag,
1defdda8 389 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 390 return;
391
40381db7 392 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
393}
394
40381db7 395void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 396 uint32_t flag)
1a392d46 397{
40381db7 398 UNSET_FLAG(pi->flags, flag);
d62a17ae 399
400 /* early bath if we know it's not a flag that changes countability state
401 */
402 if (!CHECK_FLAG(flag,
1defdda8 403 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 404 return;
405
40381db7 406 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
407}
408
718e3744 409/* Get MED value. If MED value is missing and "bgp bestpath
410 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 411static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 412{
413 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
414 return attr->med;
415 else {
416 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
417 return BGP_MED_MAX;
418 else
419 return 0;
420 }
718e3744 421}
422
40381db7 423void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 424{
40381db7
DS
425 if (pi->addpath_rx_id)
426 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
427 pi->addpath_rx_id);
d62a17ae 428 else
40381db7 429 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 430}
9fbdd100 431
d62a17ae 432/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
433 */
18ee8310
DS
434static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
435 struct bgp_path_info *exist, int *paths_eq,
436 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
437 char *pfx_buf, afi_t afi, safi_t safi)
d62a17ae 438{
439 struct attr *newattr, *existattr;
440 bgp_peer_sort_t new_sort;
441 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
442 uint32_t new_pref;
443 uint32_t exist_pref;
444 uint32_t new_med;
445 uint32_t exist_med;
446 uint32_t new_weight;
447 uint32_t exist_weight;
d62a17ae 448 uint32_t newm, existm;
449 struct in_addr new_id;
450 struct in_addr exist_id;
451 int new_cluster;
452 int exist_cluster;
453 int internal_as_route;
454 int confed_as_route;
04d14c8b 455 int ret = 0;
d62a17ae 456 char new_buf[PATH_ADDPATH_STR_BUFFER];
457 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
458 uint32_t new_mm_seq;
459 uint32_t exist_mm_seq;
6d8c603a 460 int nh_cmp;
d62a17ae 461
462 *paths_eq = 0;
463
464 /* 0. Null check. */
465 if (new == NULL) {
466 if (debug)
467 zlog_debug("%s: new is NULL", pfx_buf);
468 return 0;
469 }
2ec1e66f 470
d62a17ae 471 if (debug)
18ee8310 472 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 473
d62a17ae 474 if (exist == NULL) {
475 if (debug)
476 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
477 new_buf);
478 return 1;
479 }
2ec1e66f 480
d62a17ae 481 if (debug) {
18ee8310 482 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 483 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
484 pfx_buf, new_buf, new->flags, exist_buf,
485 exist->flags);
486 }
8ff56318 487
d62a17ae 488 newattr = new->attr;
489 existattr = exist->attr;
490
491 /* For EVPN routes, we cannot just go by local vs remote, we have to
492 * look at the MAC mobility sequence number, if present.
493 */
494 if (safi == SAFI_EVPN) {
495 /* This is an error condition described in RFC 7432 Section
496 * 15.2. The RFC
497 * states that in this scenario "the PE MUST alert the operator"
498 * but it
499 * does not state what other action to take. In order to provide
500 * some
501 * consistency in this scenario we are going to prefer the path
502 * with the
503 * sticky flag.
504 */
505 if (newattr->sticky != existattr->sticky) {
506 if (!debug) {
507 prefix2str(&new->net->p, pfx_buf,
508 sizeof(*pfx_buf)
509 * PREFIX2STR_BUFFER);
18ee8310
DS
510 bgp_path_info_path_with_addpath_rx_str(new,
511 new_buf);
512 bgp_path_info_path_with_addpath_rx_str(
513 exist, exist_buf);
d62a17ae 514 }
515
516 if (newattr->sticky && !existattr->sticky) {
deff24ca
DS
517 if (debug)
518 zlog_debug(
519 "%s: %s wins over %s due to sticky MAC flag",
520 pfx_buf, new_buf, exist_buf);
d62a17ae 521 return 1;
522 }
523
524 if (!newattr->sticky && existattr->sticky) {
deff24ca
DS
525 if (debug)
526 zlog_debug(
527 "%s: %s loses to %s due to sticky MAC flag",
528 pfx_buf, new_buf, exist_buf);
d62a17ae 529 return 0;
530 }
531 }
128ea8ab 532
d62a17ae 533 new_mm_seq = mac_mobility_seqnum(newattr);
534 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 535
d62a17ae 536 if (new_mm_seq > exist_mm_seq) {
537 if (debug)
538 zlog_debug(
539 "%s: %s wins over %s due to MM seq %u > %u",
540 pfx_buf, new_buf, exist_buf, new_mm_seq,
541 exist_mm_seq);
542 return 1;
543 }
8ff56318 544
d62a17ae 545 if (new_mm_seq < exist_mm_seq) {
546 if (debug)
547 zlog_debug(
548 "%s: %s loses to %s due to MM seq %u < %u",
549 pfx_buf, new_buf, exist_buf, new_mm_seq,
550 exist_mm_seq);
551 return 0;
552 }
6d8c603a
AK
553
554 /*
555 * if sequence numbers are the same path with the lowest IP
556 * wins
557 */
558 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
559 if (nh_cmp < 0) {
560 if (debug)
561 zlog_debug(
562 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
563 pfx_buf, new_buf, exist_buf, new_mm_seq,
564 inet_ntoa(new->attr->nexthop));
565 return 1;
566 }
567 if (nh_cmp > 0) {
568 if (debug)
569 zlog_debug(
570 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
571 pfx_buf, new_buf, exist_buf, new_mm_seq,
572 inet_ntoa(new->attr->nexthop));
573 return 0;
574 }
d62a17ae 575 }
9fbdd100 576
d62a17ae 577 /* 1. Weight check. */
d62a17ae 578 new_weight = newattr->weight;
579 exist_weight = existattr->weight;
8ff56318 580
d62a17ae 581 if (new_weight > exist_weight) {
582 if (debug)
583 zlog_debug("%s: %s wins over %s due to weight %d > %d",
584 pfx_buf, new_buf, exist_buf, new_weight,
585 exist_weight);
586 return 1;
587 }
718e3744 588
d62a17ae 589 if (new_weight < exist_weight) {
590 if (debug)
591 zlog_debug("%s: %s loses to %s due to weight %d < %d",
592 pfx_buf, new_buf, exist_buf, new_weight,
593 exist_weight);
594 return 0;
595 }
9fbdd100 596
d62a17ae 597 /* 2. Local preference check. */
598 new_pref = exist_pref = bgp->default_local_pref;
599
600 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
601 new_pref = newattr->local_pref;
602 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
603 exist_pref = existattr->local_pref;
604
605 if (new_pref > exist_pref) {
606 if (debug)
607 zlog_debug(
608 "%s: %s wins over %s due to localpref %d > %d",
609 pfx_buf, new_buf, exist_buf, new_pref,
610 exist_pref);
611 return 1;
612 }
718e3744 613
d62a17ae 614 if (new_pref < exist_pref) {
615 if (debug)
616 zlog_debug(
617 "%s: %s loses to %s due to localpref %d < %d",
618 pfx_buf, new_buf, exist_buf, new_pref,
619 exist_pref);
620 return 0;
621 }
9fbdd100 622
d62a17ae 623 /* 3. Local route check. We prefer:
624 * - BGP_ROUTE_STATIC
625 * - BGP_ROUTE_AGGREGATE
626 * - BGP_ROUTE_REDISTRIBUTE
627 */
90f4f482 628 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
629 new->sub_type == BGP_ROUTE_IMPORTED)) {
d62a17ae 630 if (debug)
631 zlog_debug(
632 "%s: %s wins over %s due to preferred BGP_ROUTE type",
633 pfx_buf, new_buf, exist_buf);
634 return 1;
635 }
718e3744 636
90f4f482 637 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 638 exist->sub_type == BGP_ROUTE_IMPORTED)) {
d62a17ae 639 if (debug)
640 zlog_debug(
641 "%s: %s loses to %s due to preferred BGP_ROUTE type",
642 pfx_buf, new_buf, exist_buf);
643 return 0;
6811845b 644 }
718e3744 645
d62a17ae 646 /* 4. AS path length check. */
647 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
648 int exist_hops = aspath_count_hops(existattr->aspath);
649 int exist_confeds = aspath_count_confeds(existattr->aspath);
650
651 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
652 int aspath_hops;
653
654 aspath_hops = aspath_count_hops(newattr->aspath);
655 aspath_hops += aspath_count_confeds(newattr->aspath);
656
657 if (aspath_hops < (exist_hops + exist_confeds)) {
658 if (debug)
659 zlog_debug(
660 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
661 pfx_buf, new_buf, exist_buf,
662 aspath_hops,
663 (exist_hops + exist_confeds));
664 return 1;
665 }
666
667 if (aspath_hops > (exist_hops + exist_confeds)) {
668 if (debug)
669 zlog_debug(
670 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
671 pfx_buf, new_buf, exist_buf,
672 aspath_hops,
673 (exist_hops + exist_confeds));
674 return 0;
675 }
676 } else {
677 int newhops = aspath_count_hops(newattr->aspath);
678
679 if (newhops < exist_hops) {
680 if (debug)
681 zlog_debug(
682 "%s: %s wins over %s due to aspath hopcount %d < %d",
683 pfx_buf, new_buf, exist_buf,
684 newhops, exist_hops);
685 return 1;
686 }
687
688 if (newhops > exist_hops) {
689 if (debug)
690 zlog_debug(
691 "%s: %s loses to %s due to aspath hopcount %d > %d",
692 pfx_buf, new_buf, exist_buf,
693 newhops, exist_hops);
694 return 0;
695 }
696 }
697 }
9fbdd100 698
d62a17ae 699 /* 5. Origin check. */
700 if (newattr->origin < existattr->origin) {
701 if (debug)
702 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
703 pfx_buf, new_buf, exist_buf,
704 bgp_origin_long_str[newattr->origin],
705 bgp_origin_long_str[existattr->origin]);
706 return 1;
707 }
718e3744 708
d62a17ae 709 if (newattr->origin > existattr->origin) {
710 if (debug)
711 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
712 pfx_buf, new_buf, exist_buf,
713 bgp_origin_long_str[newattr->origin],
714 bgp_origin_long_str[existattr->origin]);
715 return 0;
716 }
718e3744 717
d62a17ae 718 /* 6. MED check. */
719 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
720 && aspath_count_hops(existattr->aspath) == 0);
721 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
722 && aspath_count_confeds(existattr->aspath) > 0
723 && aspath_count_hops(newattr->aspath) == 0
724 && aspath_count_hops(existattr->aspath) == 0);
725
726 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
727 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
728 || aspath_cmp_left(newattr->aspath, existattr->aspath)
729 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
730 || internal_as_route) {
731 new_med = bgp_med_value(new->attr, bgp);
732 exist_med = bgp_med_value(exist->attr, bgp);
733
734 if (new_med < exist_med) {
735 if (debug)
736 zlog_debug(
737 "%s: %s wins over %s due to MED %d < %d",
738 pfx_buf, new_buf, exist_buf, new_med,
739 exist_med);
740 return 1;
741 }
8ff56318 742
d62a17ae 743 if (new_med > exist_med) {
744 if (debug)
745 zlog_debug(
746 "%s: %s loses to %s due to MED %d > %d",
747 pfx_buf, new_buf, exist_buf, new_med,
748 exist_med);
749 return 0;
750 }
751 }
9fbdd100 752
d62a17ae 753 /* 7. Peer type check. */
754 new_sort = new->peer->sort;
755 exist_sort = exist->peer->sort;
756
757 if (new_sort == BGP_PEER_EBGP
758 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
759 if (debug)
760 zlog_debug(
761 "%s: %s wins over %s due to eBGP peer > iBGP peer",
762 pfx_buf, new_buf, exist_buf);
763 return 1;
764 }
718e3744 765
d62a17ae 766 if (exist_sort == BGP_PEER_EBGP
767 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
768 if (debug)
769 zlog_debug(
770 "%s: %s loses to %s due to iBGP peer < eBGP peer",
771 pfx_buf, new_buf, exist_buf);
772 return 0;
773 }
8ff56318 774
d62a17ae 775 /* 8. IGP metric check. */
776 newm = existm = 0;
8ff56318 777
d62a17ae 778 if (new->extra)
779 newm = new->extra->igpmetric;
780 if (exist->extra)
781 existm = exist->extra->igpmetric;
9fbdd100 782
d62a17ae 783 if (newm < existm) {
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s due to IGP metric %d < %d",
787 pfx_buf, new_buf, exist_buf, newm, existm);
788 ret = 1;
789 }
718e3744 790
d62a17ae 791 if (newm > existm) {
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s due to IGP metric %d > %d",
795 pfx_buf, new_buf, exist_buf, newm, existm);
796 ret = 0;
5e242b0d 797 }
5e242b0d 798
d62a17ae 799 /* 9. Same IGP metric. Compare the cluster list length as
800 representative of IGP hops metric. Rewrite the metric value
801 pair (newm, existm) with the cluster list length. Prefer the
802 path with smaller cluster list length. */
803 if (newm == existm) {
804 if (peer_sort(new->peer) == BGP_PEER_IBGP
805 && peer_sort(exist->peer) == BGP_PEER_IBGP
806 && (mpath_cfg == NULL
807 || CHECK_FLAG(
808 mpath_cfg->ibgp_flags,
809 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
810 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
811 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
812
813 if (newm < existm) {
814 if (debug)
815 zlog_debug(
816 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
817 pfx_buf, new_buf, exist_buf,
818 newm, existm);
819 ret = 1;
820 }
821
822 if (newm > existm) {
823 if (debug)
824 zlog_debug(
825 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
826 pfx_buf, new_buf, exist_buf,
827 newm, existm);
828 ret = 0;
829 }
830 }
831 }
31a4638f 832
d62a17ae 833 /* 10. confed-external vs. confed-internal */
834 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
835 if (new_sort == BGP_PEER_CONFED
836 && exist_sort == BGP_PEER_IBGP) {
837 if (debug)
838 zlog_debug(
839 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
840 pfx_buf, new_buf, exist_buf);
841 return 1;
842 }
718e3744 843
d62a17ae 844 if (exist_sort == BGP_PEER_CONFED
845 && new_sort == BGP_PEER_IBGP) {
846 if (debug)
847 zlog_debug(
848 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
849 pfx_buf, new_buf, exist_buf);
850 return 0;
851 }
852 }
718e3744 853
d62a17ae 854 /* 11. Maximum path check. */
855 if (newm == existm) {
856 /* If one path has a label but the other does not, do not treat
857 * them as equals for multipath
858 */
a4d82a8a 859 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 860 != (exist->extra
b57ba6d2 861 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 862 if (debug)
863 zlog_debug(
864 "%s: %s and %s cannot be multipath, one has a label while the other does not",
865 pfx_buf, new_buf, exist_buf);
866 } else if (bgp_flag_check(bgp,
867 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
868
869 /*
870 * For the two paths, all comparison steps till IGP
871 * metric
872 * have succeeded - including AS_PATH hop count. Since
873 * 'bgp
874 * bestpath as-path multipath-relax' knob is on, we
875 * don't need
876 * an exact match of AS_PATH. Thus, mark the paths are
877 * equal.
878 * That will trigger both these paths to get into the
879 * multipath
880 * array.
881 */
882 *paths_eq = 1;
883
884 if (debug)
885 zlog_debug(
886 "%s: %s and %s are equal via multipath-relax",
887 pfx_buf, new_buf, exist_buf);
888 } else if (new->peer->sort == BGP_PEER_IBGP) {
889 if (aspath_cmp(new->attr->aspath,
890 exist->attr->aspath)) {
891 *paths_eq = 1;
892
893 if (debug)
894 zlog_debug(
895 "%s: %s and %s are equal via matching aspaths",
896 pfx_buf, new_buf, exist_buf);
897 }
898 } else if (new->peer->as == exist->peer->as) {
899 *paths_eq = 1;
900
901 if (debug)
902 zlog_debug(
903 "%s: %s and %s are equal via same remote-as",
904 pfx_buf, new_buf, exist_buf);
905 }
906 } else {
907 /*
908 * TODO: If unequal cost ibgp multipath is enabled we can
909 * mark the paths as equal here instead of returning
910 */
911 if (debug) {
912 if (ret == 1)
913 zlog_debug(
914 "%s: %s wins over %s after IGP metric comparison",
915 pfx_buf, new_buf, exist_buf);
916 else
917 zlog_debug(
918 "%s: %s loses to %s after IGP metric comparison",
919 pfx_buf, new_buf, exist_buf);
920 }
921 return ret;
922 }
718e3744 923
d62a17ae 924 /* 12. If both paths are external, prefer the path that was received
925 first (the oldest one). This step minimizes route-flap, since a
926 newer path won't displace an older one, even if it was the
927 preferred route based on the additional decision criteria below. */
928 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
929 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 930 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
d62a17ae 931 if (debug)
932 zlog_debug(
933 "%s: %s wins over %s due to oldest external",
934 pfx_buf, new_buf, exist_buf);
935 return 1;
936 }
9fbdd100 937
1defdda8 938 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
d62a17ae 939 if (debug)
940 zlog_debug(
941 "%s: %s loses to %s due to oldest external",
942 pfx_buf, new_buf, exist_buf);
943 return 0;
944 }
945 }
718e3744 946
d62a17ae 947 /* 13. Router-ID comparision. */
948 /* If one of the paths is "stale", the corresponding peer router-id will
949 * be 0 and would always win over the other path. If originator id is
950 * used for the comparision, it will decide which path is better.
951 */
952 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
953 new_id.s_addr = newattr->originator_id.s_addr;
954 else
955 new_id.s_addr = new->peer->remote_id.s_addr;
956 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
957 exist_id.s_addr = existattr->originator_id.s_addr;
958 else
959 exist_id.s_addr = exist->peer->remote_id.s_addr;
960
961 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
962 if (debug)
963 zlog_debug(
964 "%s: %s wins over %s due to Router-ID comparison",
965 pfx_buf, new_buf, exist_buf);
966 return 1;
967 }
718e3744 968
d62a17ae 969 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
970 if (debug)
971 zlog_debug(
972 "%s: %s loses to %s due to Router-ID comparison",
973 pfx_buf, new_buf, exist_buf);
974 return 0;
975 }
9fbdd100 976
d62a17ae 977 /* 14. Cluster length comparision. */
978 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
979 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
980
981 if (new_cluster < exist_cluster) {
982 if (debug)
983 zlog_debug(
984 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
985 pfx_buf, new_buf, exist_buf, new_cluster,
986 exist_cluster);
987 return 1;
988 }
718e3744 989
d62a17ae 990 if (new_cluster > exist_cluster) {
991 if (debug)
992 zlog_debug(
993 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
994 pfx_buf, new_buf, exist_buf, new_cluster,
995 exist_cluster);
996 return 0;
997 }
9fbdd100 998
d62a17ae 999 /* 15. Neighbor address comparision. */
1000 /* Do this only if neither path is "stale" as stale paths do not have
1001 * valid peer information (as the connection may or may not be up).
1002 */
1defdda8 1003 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
d62a17ae 1004 if (debug)
1005 zlog_debug(
1006 "%s: %s wins over %s due to latter path being STALE",
1007 pfx_buf, new_buf, exist_buf);
1008 return 1;
1009 }
0de5153c 1010
1defdda8 1011 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
d62a17ae 1012 if (debug)
1013 zlog_debug(
1014 "%s: %s loses to %s due to former path being STALE",
1015 pfx_buf, new_buf, exist_buf);
1016 return 0;
1017 }
718e3744 1018
d62a17ae 1019 /* locally configured routes to advertise do not have su_remote */
1020 if (new->peer->su_remote == NULL)
1021 return 0;
1022 if (exist->peer->su_remote == NULL)
1023 return 1;
9fbdd100 1024
d62a17ae 1025 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1026
1027 if (ret == 1) {
1028 if (debug)
1029 zlog_debug(
1030 "%s: %s loses to %s due to Neighor IP comparison",
1031 pfx_buf, new_buf, exist_buf);
1032 return 0;
1033 }
1034
1035 if (ret == -1) {
1036 if (debug)
1037 zlog_debug(
1038 "%s: %s wins over %s due to Neighor IP comparison",
1039 pfx_buf, new_buf, exist_buf);
1040 return 1;
1041 }
9fbdd100 1042
d62a17ae 1043 if (debug)
1044 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1045 pfx_buf, new_buf, exist_buf);
718e3744 1046
d62a17ae 1047 return 1;
718e3744 1048}
1049
65efcfce
LB
1050/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1051 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1052 * multipath is enabled
65efcfce 1053 * This version is compatible with */
18ee8310
DS
1054int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1055 struct bgp_path_info *exist, char *pfx_buf,
1056 afi_t afi, safi_t safi)
d62a17ae 1057{
1058 int paths_eq;
1059 int ret;
18ee8310
DS
1060 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1061 afi, safi);
d62a17ae 1062
1063 if (paths_eq)
1064 ret = 0;
1065 else {
1066 if (ret == 1)
1067 ret = -1;
1068 else
1069 ret = 1;
1070 }
1071 return ret;
65efcfce
LB
1072}
1073
d62a17ae 1074static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1075 struct attr *attr, afi_t afi,
1076 safi_t safi)
718e3744 1077{
d62a17ae 1078 struct bgp_filter *filter;
718e3744 1079
d62a17ae 1080 filter = &peer->filter[afi][safi];
718e3744 1081
d62a17ae 1082#define FILTER_EXIST_WARN(F, f, filter) \
1083 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1084 zlog_debug("%s: Could not find configured input %s-list %s!", \
1085 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1086
1087 if (DISTRIBUTE_IN_NAME(filter)) {
1088 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1089
1090 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1091 return FILTER_DENY;
1092 }
1093
1094 if (PREFIX_LIST_IN_NAME(filter)) {
1095 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1096
1097 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1098 return FILTER_DENY;
1099 }
1100
1101 if (FILTER_LIST_IN_NAME(filter)) {
1102 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1103
1104 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1105 == AS_FILTER_DENY)
1106 return FILTER_DENY;
1107 }
1108
1109 return FILTER_PERMIT;
650f76c2 1110#undef FILTER_EXIST_WARN
718e3744 1111}
1112
d62a17ae 1113static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1114 struct attr *attr, afi_t afi,
1115 safi_t safi)
718e3744 1116{
d62a17ae 1117 struct bgp_filter *filter;
1118
1119 filter = &peer->filter[afi][safi];
1120
1121#define FILTER_EXIST_WARN(F, f, filter) \
1122 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1123 zlog_debug("%s: Could not find configured output %s-list %s!", \
1124 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1125
d62a17ae 1126 if (DISTRIBUTE_OUT_NAME(filter)) {
1127 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1128
d62a17ae 1129 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1130 return FILTER_DENY;
1131 }
1132
1133 if (PREFIX_LIST_OUT_NAME(filter)) {
1134 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1135
d62a17ae 1136 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1137 == PREFIX_DENY)
1138 return FILTER_DENY;
1139 }
718e3744 1140
d62a17ae 1141 if (FILTER_LIST_OUT_NAME(filter)) {
1142 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1143
d62a17ae 1144 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1145 == AS_FILTER_DENY)
1146 return FILTER_DENY;
1147 }
718e3744 1148
d62a17ae 1149 return FILTER_PERMIT;
650f76c2 1150#undef FILTER_EXIST_WARN
718e3744 1151}
1152
1153/* If community attribute includes no_export then return 1. */
d62a17ae 1154static int bgp_community_filter(struct peer *peer, struct attr *attr)
1155{
1156 if (attr->community) {
1157 /* NO_ADVERTISE check. */
1158 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1159 return 1;
1160
1161 /* NO_EXPORT check. */
1162 if (peer->sort == BGP_PEER_EBGP
1163 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1164 return 1;
1165
1166 /* NO_EXPORT_SUBCONFED check. */
1167 if (peer->sort == BGP_PEER_EBGP
1168 || peer->sort == BGP_PEER_CONFED)
1169 if (community_include(attr->community,
1170 COMMUNITY_NO_EXPORT_SUBCONFED))
1171 return 1;
1172 }
1173 return 0;
718e3744 1174}
1175
1176/* Route reflection loop check. */
d62a17ae 1177static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1178{
d62a17ae 1179 struct in_addr cluster_id;
718e3744 1180
d62a17ae 1181 if (attr->cluster) {
1182 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1183 cluster_id = peer->bgp->cluster_id;
1184 else
1185 cluster_id = peer->bgp->router_id;
1186
1187 if (cluster_loop_check(attr->cluster, cluster_id))
1188 return 1;
1189 }
1190 return 0;
718e3744 1191}
6b0655a2 1192
d62a17ae 1193static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1194 struct attr *attr, afi_t afi, safi_t safi,
1195 const char *rmap_name)
718e3744 1196{
d62a17ae 1197 struct bgp_filter *filter;
40381db7 1198 struct bgp_path_info rmap_path;
d62a17ae 1199 route_map_result_t ret;
1200 struct route_map *rmap = NULL;
718e3744 1201
d62a17ae 1202 filter = &peer->filter[afi][safi];
718e3744 1203
d62a17ae 1204 /* Apply default weight value. */
1205 if (peer->weight[afi][safi])
1206 attr->weight = peer->weight[afi][safi];
718e3744 1207
d62a17ae 1208 if (rmap_name) {
1209 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1210
d62a17ae 1211 if (rmap == NULL)
1212 return RMAP_DENY;
1213 } else {
1214 if (ROUTE_MAP_IN_NAME(filter)) {
1215 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1216
d62a17ae 1217 if (rmap == NULL)
1218 return RMAP_DENY;
1219 }
1220 }
0b16f239 1221
d62a17ae 1222 /* Route map apply. */
1223 if (rmap) {
40381db7 1224 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1225 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1226 rmap_path.peer = peer;
1227 rmap_path.attr = attr;
718e3744 1228
d62a17ae 1229 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1230
d62a17ae 1231 /* Apply BGP route map to the attribute. */
40381db7 1232 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1233
d62a17ae 1234 peer->rmap_type = 0;
0b16f239 1235
1f2263be 1236 if (ret == RMAP_DENYMATCH)
d62a17ae 1237 return RMAP_DENY;
0b16f239 1238 }
d62a17ae 1239 return RMAP_PERMIT;
0b16f239
DS
1240}
1241
d62a17ae 1242static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1243 struct attr *attr, afi_t afi, safi_t safi,
1244 const char *rmap_name)
0b16f239 1245{
40381db7 1246 struct bgp_path_info rmap_path;
d62a17ae 1247 route_map_result_t ret;
1248 struct route_map *rmap = NULL;
d7c0a89a 1249 uint8_t rmap_type;
0b16f239 1250
b787157a
DS
1251 /*
1252 * So if we get to this point and have no rmap_name
1253 * we want to just show the output as it currently
1254 * exists.
1255 */
1256 if (!rmap_name)
1257 return RMAP_PERMIT;
0b16f239 1258
d62a17ae 1259 /* Apply default weight value. */
1260 if (peer->weight[afi][safi])
1261 attr->weight = peer->weight[afi][safi];
0b16f239 1262
b787157a 1263 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1264
b787157a
DS
1265 /*
1266 * If we have a route map name and we do not find
1267 * the routemap that means we have an implicit
1268 * deny.
1269 */
1270 if (rmap == NULL)
1271 return RMAP_DENY;
0b16f239 1272
40381db7 1273 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1274 /* Route map apply. */
b787157a 1275 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1276 rmap_path.peer = peer;
1277 rmap_path.attr = attr;
0b16f239 1278
0f672529 1279 rmap_type = peer->rmap_type;
b787157a 1280 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1281
b787157a 1282 /* Apply BGP route map to the attribute. */
40381db7 1283 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1284
0f672529 1285 peer->rmap_type = rmap_type;
b787157a
DS
1286
1287 if (ret == RMAP_DENYMATCH)
1288 /*
1289 * caller has multiple error paths with bgp_attr_flush()
1290 */
1291 return RMAP_DENY;
ac41b2a2 1292
d62a17ae 1293 return RMAP_PERMIT;
718e3744 1294}
6b0655a2 1295
5000f21c 1296/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1297static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1298 struct peer *peer, struct attr *attr)
1299{
1300 if (peer->sort == BGP_PEER_EBGP
1301 && (peer_af_flag_check(peer, afi, safi,
1302 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1303 || peer_af_flag_check(peer, afi, safi,
1304 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1305 || peer_af_flag_check(peer, afi, safi,
1306 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1307 || peer_af_flag_check(peer, afi, safi,
1308 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1309 // Take action on the entire aspath
1310 if (peer_af_flag_check(peer, afi, safi,
1311 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1312 || peer_af_flag_check(peer, afi, safi,
1313 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1314 if (peer_af_flag_check(
1315 peer, afi, safi,
1316 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1317 attr->aspath = aspath_replace_private_asns(
1318 attr->aspath, bgp->as);
1319
1320 // The entire aspath consists of private ASNs so create
1321 // an empty aspath
1322 else if (aspath_private_as_check(attr->aspath))
1323 attr->aspath = aspath_empty_get();
1324
1325 // There are some public and some private ASNs, remove
1326 // the private ASNs
1327 else
1328 attr->aspath = aspath_remove_private_asns(
1329 attr->aspath);
1330 }
1331
1332 // 'all' was not specified so the entire aspath must be private
1333 // ASNs
1334 // for us to do anything
1335 else if (aspath_private_as_check(attr->aspath)) {
1336 if (peer_af_flag_check(
1337 peer, afi, safi,
1338 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1339 attr->aspath = aspath_replace_private_asns(
1340 attr->aspath, bgp->as);
1341 else
1342 attr->aspath = aspath_empty_get();
1343 }
1344 }
5000f21c
DS
1345}
1346
c7122e14 1347/* If this is an EBGP peer with as-override */
d62a17ae 1348static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1349 struct peer *peer, struct attr *attr)
1350{
1351 if (peer->sort == BGP_PEER_EBGP
1352 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1353 if (aspath_single_asn_check(attr->aspath, peer->as))
1354 attr->aspath = aspath_replace_specific_asn(
1355 attr->aspath, peer->as, bgp->as);
1356 }
1357}
1358
7f323236
DW
1359void bgp_attr_add_gshut_community(struct attr *attr)
1360{
1361 struct community *old;
1362 struct community *new;
1363 struct community *merge;
1364 struct community *gshut;
1365
1366 old = attr->community;
1367 gshut = community_str2com("graceful-shutdown");
1368
990f4f91 1369 assert(gshut);
1370
7f323236
DW
1371 if (old) {
1372 merge = community_merge(community_dup(old), gshut);
1373
a4d82a8a 1374 if (old->refcnt == 0)
3c1f53de 1375 community_free(&old);
7f323236
DW
1376
1377 new = community_uniq_sort(merge);
3c1f53de 1378 community_free(&merge);
7f323236
DW
1379 } else {
1380 new = community_dup(gshut);
1381 }
1382
3c1f53de 1383 community_free(&gshut);
7f323236
DW
1384 attr->community = new;
1385 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1386
1387 /* When we add the graceful-shutdown community we must also
1388 * lower the local-preference */
1389 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1390 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1391}
1392
1393
d7c0a89a 1394static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1395{
960035b2 1396 if (family == AF_INET) {
d62a17ae 1397 attr->nexthop.s_addr = 0;
960035b2
PZ
1398 attr->mp_nexthop_global_in.s_addr = 0;
1399 }
d62a17ae 1400 if (family == AF_INET6)
1401 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1402 if (family == AF_EVPN)
1403 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1404}
1405
40381db7 1406int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1407 struct update_subgroup *subgrp, struct prefix *p,
1408 struct attr *attr)
1409{
1410 struct bgp_filter *filter;
1411 struct peer *from;
1412 struct peer *peer;
1413 struct peer *onlypeer;
1414 struct bgp *bgp;
40381db7 1415 struct attr *piattr;
d62a17ae 1416 char buf[PREFIX_STRLEN];
1417 int ret;
1418 int transparent;
1419 int reflect;
1420 afi_t afi;
1421 safi_t safi;
1422 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1423
1424 if (DISABLE_BGP_ANNOUNCE)
1425 return 0;
1426
1427 afi = SUBGRP_AFI(subgrp);
1428 safi = SUBGRP_SAFI(subgrp);
1429 peer = SUBGRP_PEER(subgrp);
1430 onlypeer = NULL;
1431 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1432 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1433
40381db7 1434 from = pi->peer;
d62a17ae 1435 filter = &peer->filter[afi][safi];
1436 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1437 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1438 : pi->attr;
3f9c7369 1439
65efcfce 1440#if ENABLE_BGP_VNC
d62a17ae 1441 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1442 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1443 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1444
1445 /*
1446 * direct and direct_ext type routes originate internally even
1447 * though they can have peer pointers that reference other
1448 * systems
1449 */
1450 prefix2str(p, buf, PREFIX_STRLEN);
1451 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1452 __func__, buf);
1453 samepeer_safe = 1;
1454 }
65efcfce
LB
1455#endif
1456
ddb5b488
PZ
1457 if (((afi == AFI_IP) || (afi == AFI_IP6))
1458 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1459 && (pi->type == ZEBRA_ROUTE_BGP)
1460 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1461
1462 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1463
1464 samepeer_safe = 1;
1465 }
1466
d62a17ae 1467 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1468 * pi is valid */
1469 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1470 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1471 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1472 return 0;
1473 }
adbac85e 1474
d62a17ae 1475 /* If this is not the bestpath then check to see if there is an enabled
1476 * addpath
1477 * feature that requires us to advertise it */
40381db7 1478 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1479 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1480 return 0;
1481 }
1482 }
06370dac 1483
d62a17ae 1484 /* Aggregate-address suppress check. */
40381db7 1485 if (pi->extra && pi->extra->suppress)
d62a17ae 1486 if (!UNSUPPRESS_MAP_NAME(filter)) {
1487 return 0;
1488 }
3f9c7369 1489
13b7e7f0
DS
1490 /*
1491 * If we are doing VRF 2 VRF leaking via the import
1492 * statement, we want to prevent the route going
1493 * off box as that the RT and RD created are localy
1494 * significant and globaly useless.
1495 */
40381db7
DS
1496 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1497 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1498 return 0;
1499
d62a17ae 1500 /* If it's labeled safi, make sure the route has a valid label. */
1501 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1502 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1503 if (!bgp_is_valid_label(&label)) {
1504 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1505 zlog_debug("u%" PRIu64 ":s%" PRIu64
1506 " %s/%d is filtered - no label (%p)",
1507 subgrp->update_group->id, subgrp->id,
1508 inet_ntop(p->family, &p->u.prefix,
1509 buf, SU_ADDRSTRLEN),
1510 p->prefixlen, &label);
1511 return 0;
1512 }
1513 }
cd1964ff 1514
d62a17ae 1515 /* Do not send back route to sender. */
1516 if (onlypeer && from == onlypeer) {
1517 return 0;
1518 }
3f9c7369 1519
d62a17ae 1520 /* Do not send the default route in the BGP table if the neighbor is
1521 * configured for default-originate */
1522 if (CHECK_FLAG(peer->af_flags[afi][safi],
1523 PEER_FLAG_DEFAULT_ORIGINATE)) {
1524 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1525 return 0;
1526 else if (p->family == AF_INET6 && p->prefixlen == 0)
1527 return 0;
1528 }
4125bb67 1529
d62a17ae 1530 /* Transparency check. */
1531 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1532 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1533 transparent = 1;
1534 else
1535 transparent = 0;
1536
1537 /* If community is not disabled check the no-export and local. */
40381db7 1538 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1539 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1540 zlog_debug(
1541 "subgrpannouncecheck: community filter check fail");
1542 return 0;
1543 }
3f9c7369 1544
d62a17ae 1545 /* If the attribute has originator-id and it is same as remote
1546 peer's id. */
40381db7
DS
1547 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1548 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1549 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1550 zlog_debug(
1551 "%s [Update:SEND] %s originator-id is same as "
1552 "remote router-id",
1553 onlypeer->host,
1554 prefix2str(p, buf, sizeof(buf)));
1555 return 0;
1556 }
3f9c7369 1557
d62a17ae 1558 /* ORF prefix-list filter check */
1559 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1560 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1561 || CHECK_FLAG(peer->af_cap[afi][safi],
1562 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1563 if (peer->orf_plist[afi][safi]) {
1564 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1565 == PREFIX_DENY) {
1566 if (bgp_debug_update(NULL, p,
1567 subgrp->update_group, 0))
1568 zlog_debug(
1569 "%s [Update:SEND] %s is filtered via ORF",
1570 peer->host,
1571 prefix2str(p, buf,
1572 sizeof(buf)));
1573 return 0;
1574 }
1575 }
1576
1577 /* Output filter check. */
40381db7 1578 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1579 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1580 zlog_debug("%s [Update:SEND] %s is filtered",
1581 peer->host, prefix2str(p, buf, sizeof(buf)));
1582 return 0;
1583 }
3f9c7369
DS
1584
1585#ifdef BGP_SEND_ASPATH_CHECK
d62a17ae 1586 /* AS path loop check. */
40381db7 1587 if (onlypeer && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1588 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1589 zlog_debug(
1590 "%s [Update:SEND] suppress announcement to peer AS %u "
1591 "that is part of AS path.",
1592 onlypeer->host, onlypeer->as);
1593 return 0;
1594 }
3f9c7369
DS
1595#endif /* BGP_SEND_ASPATH_CHECK */
1596
d62a17ae 1597 /* If we're a CONFED we need to loop check the CONFED ID too */
1598 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1599 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1600 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1601 zlog_debug(
1602 "%s [Update:SEND] suppress announcement to peer AS %u"
1603 " is AS path.",
1604 peer->host, bgp->confed_id);
1605 return 0;
1606 }
3f9c7369 1607 }
3f9c7369 1608
d62a17ae 1609 /* Route-Reflect check. */
1610 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1611 reflect = 1;
1612 else
1613 reflect = 0;
1614
1615 /* IBGP reflection check. */
1616 if (reflect && !samepeer_safe) {
1617 /* A route from a Client peer. */
1618 if (CHECK_FLAG(from->af_flags[afi][safi],
1619 PEER_FLAG_REFLECTOR_CLIENT)) {
1620 /* Reflect to all the Non-Client peers and also to the
1621 Client peers other than the originator. Originator
1622 check
1623 is already done. So there is noting to do. */
1624 /* no bgp client-to-client reflection check. */
1625 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1626 if (CHECK_FLAG(peer->af_flags[afi][safi],
1627 PEER_FLAG_REFLECTOR_CLIENT))
1628 return 0;
1629 } else {
1630 /* A route from a Non-client peer. Reflect to all other
1631 clients. */
1632 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1633 PEER_FLAG_REFLECTOR_CLIENT))
1634 return 0;
1635 }
1636 }
3f9c7369 1637
d62a17ae 1638 /* For modify attribute, copy it to temporary structure. */
40381db7 1639 bgp_attr_dup(attr, piattr);
d62a17ae 1640
1641 /* If local-preference is not set. */
1642 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1643 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1644 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1645 attr->local_pref = bgp->default_local_pref;
3f9c7369 1646 }
3f9c7369 1647
d62a17ae 1648 /* If originator-id is not set and the route is to be reflected,
1649 set the originator id */
1650 if (reflect
1651 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1652 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1653 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1654 }
3f9c7369 1655
d62a17ae 1656 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1657 */
1658 if (peer->sort == BGP_PEER_EBGP
1659 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1660 if (from != bgp->peer_self && !transparent
1661 && !CHECK_FLAG(peer->af_flags[afi][safi],
1662 PEER_FLAG_MED_UNCHANGED))
1663 attr->flag &=
1664 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1665 }
3f9c7369 1666
d62a17ae 1667 /* Since the nexthop attribute can vary per peer, it is not explicitly
1668 * set
1669 * in announce check, only certain flags and length (or number of
1670 * nexthops
1671 * -- for IPv6/MP_REACH) are set here in order to guide the update
1672 * formation
1673 * code in setting the nexthop(s) on a per peer basis in
1674 * reformat_peer().
1675 * Typically, the source nexthop in the attribute is preserved but in
1676 * the
1677 * scenarios where we know it will always be overwritten, we reset the
1678 * nexthop to "0" in an attempt to achieve better Update packing. An
1679 * example of this is when a prefix from each of 2 IBGP peers needs to
1680 * be
1681 * announced to an EBGP peer (and they have the same attributes barring
1682 * their nexthop).
1683 */
1684 if (reflect)
1685 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1686
1687#define NEXTHOP_IS_V6 \
1688 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1689 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1690 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1691 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1692
1693 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1694 * if
1695 * the peer (group) is configured to receive link-local nexthop
1696 * unchanged
1697 * and it is available in the prefix OR we're not reflecting the route
1698 * and
1699 * the peer (group) to whom we're going to announce is on a shared
1700 * network
1701 * and this is either a self-originated route or the peer is EBGP.
1702 */
1703 if (NEXTHOP_IS_V6) {
1704 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1705 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1706 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1707 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
1708 || (!reflect && peer->shared_network
1709 && (from == bgp->peer_self
1710 || peer->sort == BGP_PEER_EBGP))) {
1711 attr->mp_nexthop_len =
1712 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1713 }
3f9c7369 1714
d62a17ae 1715 /* Clear off link-local nexthop in source, whenever it is not
1716 * needed to
1717 * ensure more prefixes share the same attribute for
1718 * announcement.
1719 */
1720 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1721 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1722 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1723 }
3f9c7369 1724
d62a17ae 1725 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1726 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1727
1728 /* Route map & unsuppress-map apply. */
40381db7
DS
1729 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
1730 struct bgp_path_info rmap_path;
1731 struct bgp_path_info_extra dummy_rmap_path_extra;
d62a17ae 1732 struct attr dummy_attr;
1733
40381db7
DS
1734 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1735 rmap_path.peer = peer;
1736 rmap_path.attr = attr;
d37ba549 1737
40381db7
DS
1738 if (pi->extra) {
1739 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1740 sizeof(struct bgp_path_info_extra));
40381db7 1741 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1742 }
1743
d62a17ae 1744 /* don't confuse inbound and outbound setting */
1745 RESET_FLAG(attr->rmap_change_flags);
1746
1747 /*
1748 * The route reflector is not allowed to modify the attributes
1749 * of the reflected IBGP routes unless explicitly allowed.
1750 */
1751 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1752 && !bgp_flag_check(bgp,
1753 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1754 bgp_attr_dup(&dummy_attr, attr);
40381db7 1755 rmap_path.attr = &dummy_attr;
d62a17ae 1756 }
3f9c7369 1757
d62a17ae 1758 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1759
40381db7 1760 if (pi->extra && pi->extra->suppress)
d62a17ae 1761 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1762 RMAP_BGP, &rmap_path);
d62a17ae 1763 else
1764 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1765 RMAP_BGP, &rmap_path);
d62a17ae 1766
1767 peer->rmap_type = 0;
1768
1769 if (ret == RMAP_DENYMATCH) {
1770 bgp_attr_flush(attr);
1771 return 0;
1772 }
3f9c7369 1773 }
3f9c7369 1774
7f323236 1775 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1776 if (peer->sort == BGP_PEER_IBGP
1777 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1778 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1779 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1780 } else {
1781 bgp_attr_add_gshut_community(attr);
1782 }
1783 }
1784
d62a17ae 1785 /* After route-map has been applied, we check to see if the nexthop to
1786 * be carried in the attribute (that is used for the announcement) can
1787 * be cleared off or not. We do this in all cases where we would be
1788 * setting the nexthop to "ourselves". For IPv6, we only need to
1789 * consider
1790 * the global nexthop here; the link-local nexthop would have been
1791 * cleared
1792 * already, and if not, it is required by the update formation code.
1793 * Also see earlier comments in this function.
1794 */
1795 /*
1796 * If route-map has performed some operation on the nexthop or the peer
1797 * configuration says to pass it unchanged, we cannot reset the nexthop
1798 * here, so only attempt to do it if these aren't true. Note that the
1799 * route-map handler itself might have cleared the nexthop, if for
1800 * example,
1801 * it is configured as 'peer-address'.
1802 */
1803 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1804 piattr->rmap_change_flags)
d62a17ae 1805 && !transparent
1806 && !CHECK_FLAG(peer->af_flags[afi][safi],
1807 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1808 /* We can reset the nexthop, if setting (or forcing) it to
1809 * 'self' */
1810 if (CHECK_FLAG(peer->af_flags[afi][safi],
1811 PEER_FLAG_NEXTHOP_SELF)
1812 || CHECK_FLAG(peer->af_flags[afi][safi],
1813 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1814 if (!reflect
1815 || CHECK_FLAG(peer->af_flags[afi][safi],
1816 PEER_FLAG_FORCE_NEXTHOP_SELF))
1817 subgroup_announce_reset_nhop(
1818 (peer_cap_enhe(peer, afi, safi)
1819 ? AF_INET6
1820 : p->family),
1821 attr);
1822 } else if (peer->sort == BGP_PEER_EBGP) {
1823 /* Can also reset the nexthop if announcing to EBGP, but
1824 * only if
1825 * no peer in the subgroup is on a shared subnet.
1826 * Note: 3rd party nexthop currently implemented for
1827 * IPv4 only.
1828 */
40381db7 1829 if (!bgp_subgrp_multiaccess_check_v4(piattr->nexthop,
65d4e0c6 1830 subgrp))
d62a17ae 1831 subgroup_announce_reset_nhop(
1832 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1833 ? AF_INET6
1834 : p->family),
d62a17ae 1835 attr);
40381db7 1836 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1837 /*
1838 * This flag is used for leaked vpn-vrf routes
1839 */
1840 int family = p->family;
1841
1842 if (peer_cap_enhe(peer, afi, safi))
1843 family = AF_INET6;
1844
1845 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1846 zlog_debug(
1defdda8 1847 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1848 __func__, family2str(family));
1849 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1850 }
960035b2 1851
d62a17ae 1852 /* If IPv6/MP and nexthop does not have any override and happens
1853 * to
1854 * be a link-local address, reset it so that we don't pass along
1855 * the
1856 * source's link-local IPv6 address to recipients who may not be
1857 * on
1858 * the same interface.
1859 */
1860 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1861 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1862 subgroup_announce_reset_nhop(AF_INET6, attr);
1863 }
1864 }
3f9c7369 1865
d62a17ae 1866 return 1;
3f9c7369
DS
1867}
1868
d62a17ae 1869void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1870 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1871 struct bgp_path_info_pair *result, afi_t afi,
1872 safi_t safi)
1873{
1874 struct bgp_path_info *new_select;
1875 struct bgp_path_info *old_select;
40381db7
DS
1876 struct bgp_path_info *pi;
1877 struct bgp_path_info *pi1;
1878 struct bgp_path_info *pi2;
1879 struct bgp_path_info *nextpi = NULL;
d62a17ae 1880 int paths_eq, do_mpath, debug;
1881 struct list mp_list;
1882 char pfx_buf[PREFIX2STR_BUFFER];
1883 char path_buf[PATH_ADDPATH_STR_BUFFER];
1884
1885 bgp_mp_list_init(&mp_list);
1886 do_mpath =
1887 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1888
1889 debug = bgp_debug_bestpath(&rn->p);
1890
1891 if (debug)
1892 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1893
1894 /* bgp deterministic-med */
1895 new_select = NULL;
1896 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1897
1defdda8 1898 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
1899 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1900 pi1 = pi1->next)
40381db7 1901 bgp_path_info_unset_flag(rn, pi1,
18ee8310 1902 BGP_PATH_DMED_SELECTED);
d62a17ae 1903
6f94b685
DS
1904 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1905 pi1 = pi1->next) {
40381db7 1906 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 1907 continue;
40381db7 1908 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 1909 continue;
40381db7
DS
1910 if (pi1->peer && pi1->peer != bgp->peer_self)
1911 if (pi1->peer->status != Established)
d62a17ae 1912 continue;
1913
40381db7
DS
1914 new_select = pi1;
1915 if (pi1->next) {
1916 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
1917 if (CHECK_FLAG(pi2->flags,
1defdda8 1918 BGP_PATH_DMED_CHECK))
d62a17ae 1919 continue;
40381db7 1920 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 1921 continue;
40381db7
DS
1922 if (pi2->peer
1923 && pi2->peer != bgp->peer_self
d62a17ae 1924 && !CHECK_FLAG(
40381db7 1925 pi2->peer->sflags,
d62a17ae 1926 PEER_STATUS_NSF_WAIT))
40381db7 1927 if (pi2->peer->status
d62a17ae 1928 != Established)
1929 continue;
1930
121e245d
DS
1931 if (!aspath_cmp_left(pi1->attr->aspath,
1932 pi2->attr->aspath)
1933 && !aspath_cmp_left_confed(
40381db7 1934 pi1->attr->aspath,
121e245d
DS
1935 pi2->attr->aspath))
1936 continue;
d62a17ae 1937
121e245d
DS
1938 if (bgp_path_info_cmp(
1939 bgp, pi2, new_select,
1940 &paths_eq, mpath_cfg, debug,
1941 pfx_buf, afi, safi)) {
1942 bgp_path_info_unset_flag(
1943 rn, new_select,
1944 BGP_PATH_DMED_SELECTED);
1945 new_select = pi2;
d62a17ae 1946 }
121e245d
DS
1947
1948 bgp_path_info_set_flag(
1949 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 1950 }
1951 }
18ee8310
DS
1952 bgp_path_info_set_flag(rn, new_select,
1953 BGP_PATH_DMED_CHECK);
1954 bgp_path_info_set_flag(rn, new_select,
1955 BGP_PATH_DMED_SELECTED);
d62a17ae 1956
1957 if (debug) {
18ee8310
DS
1958 bgp_path_info_path_with_addpath_rx_str(
1959 new_select, path_buf);
c66faab1 1960 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 1961 pfx_buf, path_buf,
1962 aspath_get_first_as(
1963 new_select->attr->aspath));
1964 }
1965 }
1966 }
96450faf 1967
d62a17ae 1968 /* Check old selected route and new selected route. */
1969 old_select = NULL;
1970 new_select = NULL;
6f94b685
DS
1971 for (pi = bgp_node_get_bgp_path_info(rn);
1972 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
1973 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
1974 old_select = pi;
d62a17ae 1975
40381db7 1976 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 1977 /* reap REMOVED routes, if needs be
1978 * selected route must stay for a while longer though
1979 */
40381db7
DS
1980 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
1981 && (pi != old_select))
1982 bgp_path_info_reap(rn, pi);
d62a17ae 1983
ddb5b488 1984 if (debug)
40381db7
DS
1985 zlog_debug("%s: pi %p in holddown", __func__,
1986 pi);
ddb5b488 1987
d62a17ae 1988 continue;
1989 }
96450faf 1990
40381db7
DS
1991 if (pi->peer && pi->peer != bgp->peer_self
1992 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
1993 if (pi->peer->status != Established) {
ddb5b488
PZ
1994
1995 if (debug)
1996 zlog_debug(
40381db7
DS
1997 "%s: pi %p non self peer %s not estab state",
1998 __func__, pi, pi->peer->host);
ddb5b488 1999
d62a17ae 2000 continue;
ddb5b488 2001 }
9fbdd100 2002
d62a17ae 2003 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2004 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2005 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2006 if (debug)
40381db7 2007 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2008 continue;
2009 }
9fbdd100 2010
40381db7 2011 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2012
40381db7 2013 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
18ee8310 2014 debug, pfx_buf, afi, safi)) {
40381db7 2015 new_select = pi;
d62a17ae 2016 }
2017 }
718e3744 2018
d62a17ae 2019 /* Now that we know which path is the bestpath see if any of the other
2020 * paths
2021 * qualify as multipaths
2022 */
2023 if (debug) {
2024 if (new_select)
18ee8310
DS
2025 bgp_path_info_path_with_addpath_rx_str(new_select,
2026 path_buf);
d62a17ae 2027 else
2028 sprintf(path_buf, "NONE");
2029 zlog_debug(
2030 "%s: After path selection, newbest is %s oldbest was %s",
2031 pfx_buf, path_buf,
2032 old_select ? old_select->peer->host : "NONE");
96450faf 2033 }
9fbdd100 2034
d62a17ae 2035 if (do_mpath && new_select) {
6f94b685
DS
2036 for (pi = bgp_node_get_bgp_path_info(rn);
2037 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2038
2039 if (debug)
18ee8310 2040 bgp_path_info_path_with_addpath_rx_str(
40381db7 2041 pi, path_buf);
d62a17ae 2042
40381db7 2043 if (pi == new_select) {
d62a17ae 2044 if (debug)
2045 zlog_debug(
2046 "%s: %s is the bestpath, add to the multipath list",
2047 pfx_buf, path_buf);
40381db7 2048 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2049 continue;
2050 }
2051
40381db7 2052 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2053 continue;
2054
40381db7
DS
2055 if (pi->peer && pi->peer != bgp->peer_self
2056 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2057 PEER_STATUS_NSF_WAIT))
40381db7 2058 if (pi->peer->status != Established)
d62a17ae 2059 continue;
2060
40381db7 2061 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2062 if (debug)
2063 zlog_debug(
2064 "%s: %s has the same nexthop as the bestpath, skip it",
2065 pfx_buf, path_buf);
2066 continue;
2067 }
2068
40381db7 2069 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
18ee8310 2070 mpath_cfg, debug, pfx_buf, afi, safi);
d62a17ae 2071
2072 if (paths_eq) {
2073 if (debug)
2074 zlog_debug(
2075 "%s: %s is equivalent to the bestpath, add to the multipath list",
2076 pfx_buf, path_buf);
40381db7 2077 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2078 }
2079 }
2080 }
fee0f4c6 2081
18ee8310
DS
2082 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2083 mpath_cfg);
2084 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2085 bgp_mp_list_clear(&mp_list);
96450faf 2086
dcc68b5e
MS
2087 bgp_addpath_update_ids(bgp, rn, afi, safi);
2088
d62a17ae 2089 result->old = old_select;
2090 result->new = new_select;
96450faf 2091
d62a17ae 2092 return;
fee0f4c6 2093}
2094
3f9c7369
DS
2095/*
2096 * A new route/change in bestpath of an existing route. Evaluate the path
2097 * for advertisement to the subgroup.
2098 */
d62a17ae 2099int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2100 struct bgp_path_info *selected,
d62a17ae 2101 struct bgp_node *rn,
d7c0a89a 2102 uint32_t addpath_tx_id)
d62a17ae 2103{
2104 struct prefix *p;
2105 struct peer *onlypeer;
2106 struct attr attr;
2107 afi_t afi;
2108 safi_t safi;
adbac85e 2109
d62a17ae 2110 p = &rn->p;
2111 afi = SUBGRP_AFI(subgrp);
2112 safi = SUBGRP_SAFI(subgrp);
2113 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2114 : NULL);
2115
e0207895
PZ
2116 if (BGP_DEBUG(update, UPDATE_OUT)) {
2117 char buf_prefix[PREFIX_STRLEN];
2118 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2119 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2120 selected);
e0207895
PZ
2121 }
2122
d62a17ae 2123 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2124 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2125 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2126 return 0;
2127
2128 memset(&attr, 0, sizeof(struct attr));
2129 /* It's initialized in bgp_announce_check() */
2130
2131 /* Announcement to the subgroup. If the route is filtered withdraw it.
2132 */
2133 if (selected) {
2134 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2135 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2136 else
2137 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2138 addpath_tx_id);
d62a17ae 2139 }
2140
2141 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2142 else {
2143 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2144 }
558d1fec 2145
d62a17ae 2146 return 0;
200df115 2147}
fee0f4c6 2148
3064bf43 2149/*
e1072051 2150 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2151 * This is called at the end of route processing.
3064bf43 2152 */
d62a17ae 2153void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2154{
40381db7 2155 struct bgp_path_info *pi;
3064bf43 2156
6f94b685 2157 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2158 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2159 continue;
40381db7
DS
2160 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2161 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2162 }
3064bf43 2163}
2164
2165/*
2166 * Has the route changed from the RIB's perspective? This is invoked only
2167 * if the route selection returns the same best route as earlier - to
2168 * determine if we need to update zebra or not.
2169 */
4b7e6066
DS
2170int bgp_zebra_has_route_changed(struct bgp_node *rn,
2171 struct bgp_path_info *selected)
d62a17ae 2172{
4b7e6066 2173 struct bgp_path_info *mpinfo;
d62a17ae 2174
2bb9eff4
DS
2175 /* If this is multipath, check all selected paths for any nexthop
2176 * change or attribute change. Some attribute changes (e.g., community)
2177 * aren't of relevance to the RIB, but we'll update zebra to ensure
2178 * we handle the case of BGP nexthop change. This is the behavior
2179 * when the best path has an attribute change anyway.
d62a17ae 2180 */
1defdda8
DS
2181 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2182 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2183 return 1;
2184
2bb9eff4
DS
2185 /*
2186 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2187 */
18ee8310
DS
2188 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2189 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2190 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2191 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2192 return 1;
2193 }
3064bf43 2194
d62a17ae 2195 /* Nothing has changed from the RIB's perspective. */
2196 return 0;
3064bf43 2197}
2198
d62a17ae 2199struct bgp_process_queue {
2200 struct bgp *bgp;
a4d82a8a 2201 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2202#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2203 unsigned int flags;
2204 unsigned int queued;
200df115 2205};
2206
3103e8d2
DS
2207/*
2208 * old_select = The old best path
2209 * new_select = the new best path
2210 *
2211 * if (!old_select && new_select)
2212 * We are sending new information on.
2213 *
2214 * if (old_select && new_select) {
2215 * if (new_select != old_select)
2216 * We have a new best path send a change
2217 * else
2218 * We've received a update with new attributes that needs
2219 * to be passed on.
2220 * }
2221 *
2222 * if (old_select && !new_select)
2223 * We have no eligible route that we can announce or the rn
2224 * is being removed.
2225 */
aac24838
JB
2226static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2227 afi_t afi, safi_t safi)
d62a17ae 2228{
4b7e6066
DS
2229 struct bgp_path_info *new_select;
2230 struct bgp_path_info *old_select;
2231 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2232 char pfx_buf[PREFIX2STR_BUFFER];
2233 int debug = 0;
d62a17ae 2234
2235 /* Is it end of initial update? (after startup) */
2236 if (!rn) {
2237 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2238 sizeof(bgp->update_delay_zebra_resume_time));
2239
2240 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2241 FOREACH_AFI_SAFI (afi, safi) {
2242 if (bgp_fibupd_safi(safi))
2243 bgp_zebra_announce_table(bgp, afi, safi);
2244 }
d62a17ae 2245 bgp->main_peers_update_hold = 0;
2246
2247 bgp_start_routeadv(bgp);
aac24838 2248 return;
d62a17ae 2249 }
cb1faec9 2250
b575a12c
A
2251 struct prefix *p = &rn->p;
2252
ddb5b488
PZ
2253 debug = bgp_debug_bestpath(&rn->p);
2254 if (debug) {
2255 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2256 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2257 afi2str(afi), safi2str(safi));
2258 }
2259
d62a17ae 2260 /* Best path selection. */
2261 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2262 afi, safi);
2263 old_select = old_and_new.old;
2264 new_select = old_and_new.new;
2265
2266 /* Do we need to allocate or free labels?
2267 * Right now, since we only deal with per-prefix labels, it is not
cb499ebb 2268 * necessary to do this upon changes to best path except if the label
09fdc88c 2269 * index changes
d62a17ae 2270 */
318cac96 2271 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2272 if (new_select) {
2273 if (!old_select
2274 || bgp_label_index_differs(new_select, old_select)
2275 || new_select->sub_type != old_select->sub_type) {
2276 if (new_select->sub_type == BGP_ROUTE_STATIC
2277 && new_select->attr->flag
2278 & ATTR_FLAG_BIT(
2279 BGP_ATTR_PREFIX_SID)
2280 && new_select->attr->label_index
2281 != BGP_INVALID_LABEL_INDEX) {
2282 if (CHECK_FLAG(
2283 rn->flags,
2284 BGP_NODE_REGISTERED_FOR_LABEL))
2285 bgp_unregister_for_label(rn);
70e98a7f 2286 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2287 &rn->local_label);
2288 bgp_set_valid_label(&rn->local_label);
2289 } else
2290 bgp_register_for_label(rn, new_select);
2291 }
a4d82a8a
PZ
2292 } else if (CHECK_FLAG(rn->flags,
2293 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2294 bgp_unregister_for_label(rn);
318cac96
DW
2295 }
2296 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2297 bgp_unregister_for_label(rn);
d62a17ae 2298 }
cd1964ff 2299
ddb5b488
PZ
2300 if (debug) {
2301 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2302 zlog_debug(
2303 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2304 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2305 old_select, new_select);
2306 }
2307
d62a17ae 2308 /* If best route remains the same and this is not due to user-initiated
2309 * clear, see exactly what needs to be done.
2310 */
d62a17ae 2311 if (old_select && old_select == new_select
2312 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2313 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2314 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2315 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2316#if ENABLE_BGP_VNC
d62a17ae 2317 vnc_import_bgp_add_route(bgp, p, old_select);
2318 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2319#endif
bb744275 2320 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2321 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2322
2323 if (new_select->type == ZEBRA_ROUTE_BGP
2324 && (new_select->sub_type == BGP_ROUTE_NORMAL
2325 || new_select->sub_type
2326 == BGP_ROUTE_IMPORTED))
2327
2328 bgp_zebra_announce(rn, p, old_select,
2329 bgp, afi, safi);
2330 }
d62a17ae 2331 }
1defdda8 2332 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2333 bgp_zebra_clear_route_change_flags(rn);
2334
2335 /* If there is a change of interest to peers, reannounce the
2336 * route. */
1defdda8 2337 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2338 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2339 group_announce_route(bgp, afi, safi, rn, new_select);
2340
2341 /* unicast routes must also be annouced to
2342 * labeled-unicast update-groups */
2343 if (safi == SAFI_UNICAST)
2344 group_announce_route(bgp, afi,
2345 SAFI_LABELED_UNICAST, rn,
2346 new_select);
2347
1defdda8 2348 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2349 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2350 }
fee0f4c6 2351
d62a17ae 2352 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2353 return;
d62a17ae 2354 }
8ad7271d 2355
d62a17ae 2356 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2357 */
2358 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2359
2360 /* bestpath has changed; bump version */
2361 if (old_select || new_select) {
2362 bgp_bump_version(rn);
2363
2364 if (!bgp->t_rmap_def_originate_eval) {
2365 bgp_lock(bgp);
2366 thread_add_timer(
2367 bm->master,
2368 update_group_refresh_default_originate_route_map,
2369 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2370 &bgp->t_rmap_def_originate_eval);
2371 }
2372 }
3f9c7369 2373
d62a17ae 2374 if (old_select)
18ee8310 2375 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2376 if (new_select) {
ddb5b488
PZ
2377 if (debug)
2378 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2379 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2380 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2381 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2382 }
338b3424 2383
65efcfce 2384#if ENABLE_BGP_VNC
d62a17ae 2385 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2386 if (old_select != new_select) {
2387 if (old_select) {
2388 vnc_import_bgp_exterior_del_route(bgp, p,
2389 old_select);
2390 vnc_import_bgp_del_route(bgp, p, old_select);
2391 }
2392 if (new_select) {
2393 vnc_import_bgp_exterior_add_route(bgp, p,
2394 new_select);
2395 vnc_import_bgp_add_route(bgp, p, new_select);
2396 }
2397 }
2398 }
65efcfce
LB
2399#endif
2400
d62a17ae 2401 group_announce_route(bgp, afi, safi, rn, new_select);
2402
2403 /* unicast routes must also be annouced to labeled-unicast update-groups
2404 */
2405 if (safi == SAFI_UNICAST)
2406 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2407 new_select);
2408
2409 /* FIB update. */
2410 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2411 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2412 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2413 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2414 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2415 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2416
2417 /* if this is an evpn imported type-5 prefix,
2418 * we need to withdraw the route first to clear
2419 * the nh neigh and the RMAC entry.
2420 */
2421 if (old_select &&
2422 is_route_parent_evpn(old_select))
2423 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2424
d62a17ae 2425 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2426 } else {
d62a17ae 2427 /* Withdraw the route from the kernel. */
2428 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2429 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2430 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2431 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2432
568e10ca 2433 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2434 }
718e3744 2435 }
3064bf43 2436
5424b7ba
MK
2437 /* advertise/withdraw type-5 routes */
2438 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
7b1bf203 2439 if (advertise_type5_routes(bgp, afi) && new_select &&
7e4ed18e
MK
2440 (!new_select->extra || !new_select->extra->parent)) {
2441
2442 /* apply the route-map */
2443 if (bgp->adv_cmd_rmap[afi][safi].map) {
2444 int ret = 0;
2445
3518f352
DS
2446 ret = route_map_apply(
2447 bgp->adv_cmd_rmap[afi][safi].map,
2448 &rn->p, RMAP_BGP, new_select);
7e4ed18e 2449 if (ret == RMAP_MATCH)
3518f352
DS
2450 bgp_evpn_advertise_type5_route(
2451 bgp, &rn->p, new_select->attr,
2452 afi, safi);
7e4ed18e
MK
2453 } else {
2454 bgp_evpn_advertise_type5_route(bgp,
2455 &rn->p,
2456 new_select->attr,
2457 afi, safi);
2458
2459 }
2460 } else if (advertise_type5_routes(bgp, afi) && old_select &&
2461 (!old_select->extra || !old_select->extra->parent))
31310b25 2462 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2463 }
2464
d62a17ae 2465 /* Clear any route change flags. */
2466 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2467
18ee8310 2468 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2469 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2470 bgp_path_info_reap(rn, old_select);
d62a17ae 2471
2472 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2473 return;
718e3744 2474}
2475
aac24838 2476static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2477{
aac24838
JB
2478 struct bgp_process_queue *pqnode = data;
2479 struct bgp *bgp = pqnode->bgp;
d62a17ae 2480 struct bgp_table *table;
ac021f40 2481 struct bgp_node *rn;
aac24838
JB
2482
2483 /* eoiu marker */
2484 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2485 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2486 /* should always have dedicated wq call */
2487 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2488 return WQ_SUCCESS;
2489 }
2490
ac021f40
LB
2491 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2492 rn = STAILQ_FIRST(&pqnode->pqueue);
2493 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2494 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2495 table = bgp_node_table(rn);
ac021f40 2496 /* note, new RNs may be added as part of processing */
aac24838 2497 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2498
aac24838 2499 bgp_unlock_node(rn);
d62a17ae 2500 bgp_table_unlock(table);
2501 }
aac24838
JB
2502
2503 return WQ_SUCCESS;
2504}
2505
2506static void bgp_processq_del(struct work_queue *wq, void *data)
2507{
2508 struct bgp_process_queue *pqnode = data;
2509
2510 bgp_unlock(pqnode->bgp);
2511
2512 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2513}
2514
d62a17ae 2515void bgp_process_queue_init(void)
200df115 2516{
0ce1ca80 2517 if (!bm->process_main_queue)
d62a17ae 2518 bm->process_main_queue =
2519 work_queue_new(bm->master, "process_main_queue");
2520
aac24838 2521 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2522 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2523 bm->process_main_queue->spec.max_retries = 0;
2524 bm->process_main_queue->spec.hold = 50;
2525 /* Use a higher yield value of 50ms for main queue processing */
2526 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2527}
2528
cfe8d15a 2529static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2530{
2531 struct bgp_process_queue *pqnode;
2532
a4d82a8a
PZ
2533 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2534 sizeof(struct bgp_process_queue));
aac24838
JB
2535
2536 /* unlocked in bgp_processq_del */
2537 pqnode->bgp = bgp_lock(bgp);
2538 STAILQ_INIT(&pqnode->pqueue);
2539
aac24838
JB
2540 return pqnode;
2541}
2542
d62a17ae 2543void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2544{
aac24838
JB
2545#define ARBITRARY_PROCESS_QLEN 10000
2546 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2547 struct bgp_process_queue *pqnode;
cfe8d15a 2548 int pqnode_reuse = 0;
495f0b13 2549
d62a17ae 2550 /* already scheduled for processing? */
2551 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2552 return;
2e02b9b2 2553
aac24838 2554 if (wq == NULL)
d62a17ae 2555 return;
2556
aac24838 2557 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2558 limit only if is from the same BGP view and it's not an EOIU marker
2559 */
aac24838
JB
2560 if (work_queue_item_count(wq)) {
2561 struct work_queue_item *item = work_queue_last_item(wq);
2562 pqnode = item->data;
228da428 2563
a4d82a8a
PZ
2564 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2565 || pqnode->bgp != bgp
2566 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2567 pqnode = bgp_processq_alloc(bgp);
2568 else
2569 pqnode_reuse = 1;
aac24838 2570 } else
cfe8d15a 2571 pqnode = bgp_processq_alloc(bgp);
aac24838 2572 /* all unlocked in bgp_process_wq */
d62a17ae 2573 bgp_table_lock(bgp_node_table(rn));
aac24838 2574
d62a17ae 2575 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2576 bgp_lock_node(rn);
2577
60466a63
QY
2578 /* can't be enqueued twice */
2579 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2580 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2581 pqnode->queued++;
2582
cfe8d15a
LB
2583 if (!pqnode_reuse)
2584 work_queue_add(wq, pqnode);
2585
d62a17ae 2586 return;
fee0f4c6 2587}
0a486e5f 2588
d62a17ae 2589void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2590{
d62a17ae 2591 struct bgp_process_queue *pqnode;
cb1faec9 2592
d62a17ae 2593 if (bm->process_main_queue == NULL)
2594 return;
2e02b9b2 2595
cfe8d15a 2596 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2597
aac24838 2598 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2599 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2600}
2601
d62a17ae 2602static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2603{
d62a17ae 2604 struct peer *peer;
0a486e5f 2605
d62a17ae 2606 peer = THREAD_ARG(thread);
2607 peer->t_pmax_restart = NULL;
0a486e5f 2608
d62a17ae 2609 if (bgp_debug_neighbor_events(peer))
2610 zlog_debug(
2611 "%s Maximum-prefix restart timer expired, restore peering",
2612 peer->host);
0a486e5f 2613
a9bafa95
DS
2614 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2615 zlog_debug("%s: %s peer_clear failed",
2616 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2617
d62a17ae 2618 return 0;
0a486e5f 2619}
2620
d62a17ae 2621int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2622 int always)
718e3744 2623{
d62a17ae 2624 iana_afi_t pkt_afi;
5c525538 2625 iana_safi_t pkt_safi;
9cabb64b 2626
d62a17ae 2627 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2628 return 0;
e0701b79 2629
d62a17ae 2630 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2631 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2632 PEER_STATUS_PREFIX_LIMIT)
2633 && !always)
2634 return 0;
e0701b79 2635
d62a17ae 2636 zlog_info(
2637 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2638 "limit %ld",
2639 afi_safi_print(afi, safi), peer->host,
2640 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2641 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2642
2643 if (CHECK_FLAG(peer->af_flags[afi][safi],
2644 PEER_FLAG_MAX_PREFIX_WARNING))
2645 return 0;
2646
2647 /* Convert AFI, SAFI to values for packet. */
2648 pkt_afi = afi_int2iana(afi);
2649 pkt_safi = safi_int2iana(safi);
2650 {
d7c0a89a 2651 uint8_t ndata[7];
d62a17ae 2652
2653 ndata[0] = (pkt_afi >> 8);
2654 ndata[1] = pkt_afi;
2655 ndata[2] = pkt_safi;
2656 ndata[3] = (peer->pmax[afi][safi] >> 24);
2657 ndata[4] = (peer->pmax[afi][safi] >> 16);
2658 ndata[5] = (peer->pmax[afi][safi] >> 8);
2659 ndata[6] = (peer->pmax[afi][safi]);
2660
2661 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2662 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2663 BGP_NOTIFY_CEASE_MAX_PREFIX,
2664 ndata, 7);
2665 }
2666
2667 /* Dynamic peers will just close their connection. */
2668 if (peer_dynamic_neighbor(peer))
2669 return 1;
2670
2671 /* restart timer start */
2672 if (peer->pmax_restart[afi][safi]) {
2673 peer->v_pmax_restart =
2674 peer->pmax_restart[afi][safi] * 60;
2675
2676 if (bgp_debug_neighbor_events(peer))
2677 zlog_debug(
2678 "%s Maximum-prefix restart timer started for %d secs",
2679 peer->host, peer->v_pmax_restart);
2680
2681 BGP_TIMER_ON(peer->t_pmax_restart,
2682 bgp_maximum_prefix_restart_timer,
2683 peer->v_pmax_restart);
2684 }
2685
2686 return 1;
2687 } else
2688 UNSET_FLAG(peer->af_sflags[afi][safi],
2689 PEER_STATUS_PREFIX_LIMIT);
2690
2691 if (peer->pcount[afi][safi]
2692 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2693 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2694 PEER_STATUS_PREFIX_THRESHOLD)
2695 && !always)
2696 return 0;
2697
2698 zlog_info(
2699 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2700 afi_safi_print(afi, safi), peer->host,
2701 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2702 SET_FLAG(peer->af_sflags[afi][safi],
2703 PEER_STATUS_PREFIX_THRESHOLD);
2704 } else
2705 UNSET_FLAG(peer->af_sflags[afi][safi],
2706 PEER_STATUS_PREFIX_THRESHOLD);
2707 return 0;
718e3744 2708}
2709
b40d939b 2710/* Unconditionally remove the route from the RIB, without taking
2711 * damping into consideration (eg, because the session went down)
2712 */
40381db7 2713void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 2714 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2715{
40381db7 2716 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 2717
40381db7
DS
2718 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
2719 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 2720
2721 bgp_process(peer->bgp, rn, afi, safi);
2722}
2723
40381db7 2724static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 2725 struct peer *peer, afi_t afi, safi_t safi,
2726 struct prefix_rd *prd)
2727{
d62a17ae 2728 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 2729 * the bgp_path_info in the RIB for historical reference.
d62a17ae 2730 */
2731 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2732 && peer->sort == BGP_PEER_EBGP)
40381db7 2733 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 2734 == BGP_DAMP_SUPPRESSED) {
40381db7 2735 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 2736 safi);
2737 return;
2738 }
2739
65efcfce 2740#if ENABLE_BGP_VNC
d62a17ae 2741 if (safi == SAFI_MPLS_VPN) {
2742 struct bgp_node *prn = NULL;
2743 struct bgp_table *table = NULL;
2744
2745 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2746 (struct prefix *)prd);
67009e22
DS
2747 if (bgp_node_has_bgp_path_info_data(prn)) {
2748 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 2749
2750 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 2751 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 2752 }
2753 bgp_unlock_node(prn);
2754 }
2755 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 2756 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 2757
40381db7 2758 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 2759 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 2760 pi);
d62a17ae 2761 }
65efcfce 2762 }
d62a17ae 2763#endif
128ea8ab 2764
d62a17ae 2765 /* If this is an EVPN route, process for un-import. */
2766 if (safi == SAFI_EVPN)
40381db7 2767 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 2768
40381db7 2769 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 2770}
2771
4b7e6066
DS
2772struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
2773 struct peer *peer, struct attr *attr,
2774 struct bgp_node *rn)
fb018d25 2775{
4b7e6066 2776 struct bgp_path_info *new;
fb018d25 2777
d62a17ae 2778 /* Make new BGP info. */
4b7e6066 2779 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 2780 new->type = type;
2781 new->instance = instance;
2782 new->sub_type = sub_type;
2783 new->peer = peer;
2784 new->attr = attr;
2785 new->uptime = bgp_clock();
2786 new->net = rn;
d62a17ae 2787 return new;
fb018d25
DS
2788}
2789
d62a17ae 2790static void overlay_index_update(struct attr *attr,
2791 struct eth_segment_id *eth_s_id,
2792 union gw_addr *gw_ip)
684a7227 2793{
d62a17ae 2794 if (!attr)
2795 return;
684a7227 2796
d62a17ae 2797 if (eth_s_id == NULL) {
2798 memset(&(attr->evpn_overlay.eth_s_id), 0,
2799 sizeof(struct eth_segment_id));
2800 } else {
2801 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2802 sizeof(struct eth_segment_id));
2803 }
2804 if (gw_ip == NULL) {
2805 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2806 } else {
2807 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2808 sizeof(union gw_addr));
2809 }
684a7227
PG
2810}
2811
40381db7 2812static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 2813 struct eth_segment_id *eth_s_id,
2814 union gw_addr *gw_ip)
2815{
40381db7
DS
2816 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
2817 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
2818 union {
2819 struct eth_segment_id esi;
2820 union gw_addr ip;
2821 } temp;
d62a17ae 2822
2823 if (afi != AFI_L2VPN)
2824 return true;
40381db7 2825 if (!path->attr) {
11ebf4ed 2826 memset(&temp, 0, sizeof(temp));
40381db7
DS
2827 path_eth_s_id = &temp.esi;
2828 path_gw_ip = &temp.ip;
11ebf4ed 2829
d62a17ae 2830 if (eth_s_id == NULL && gw_ip == NULL)
2831 return true;
2832 } else {
40381db7
DS
2833 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2834 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
d62a17ae 2835 }
11ebf4ed
DS
2836
2837 if (gw_ip == NULL) {
2838 memset(&temp, 0, sizeof(temp));
40381db7 2839 path_gw_ip_remote = &temp.ip;
11ebf4ed 2840 } else
40381db7 2841 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2842
2843 if (eth_s_id == NULL) {
2844 memset(&temp, 0, sizeof(temp));
40381db7 2845 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2846 } else
40381db7 2847 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2848
40381db7 2849 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2850 return false;
11ebf4ed 2851
40381db7 2852 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2853 sizeof(struct eth_segment_id));
684a7227
PG
2854}
2855
c265ee22 2856/* Check if received nexthop is valid or not. */
d62a17ae 2857static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2858 struct attr *attr)
2859{
2860 int ret = 0;
2861
2862 /* Only validated for unicast and multicast currently. */
2863 /* Also valid for EVPN where the nexthop is an IP address. */
2864 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2865 return 0;
2866
2867 /* If NEXT_HOP is present, validate it. */
2868 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2869 if (attr->nexthop.s_addr == 0
2870 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2871 || bgp_nexthop_self(bgp, attr->nexthop))
2872 return 1;
2873 }
c265ee22 2874
d62a17ae 2875 /* If MP_NEXTHOP is present, validate it. */
2876 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2877 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2878 * it is not an IPv6 link-local address.
2879 */
2880 if (attr->mp_nexthop_len) {
2881 switch (attr->mp_nexthop_len) {
2882 case BGP_ATTR_NHLEN_IPV4:
2883 case BGP_ATTR_NHLEN_VPNV4:
2884 ret = (attr->mp_nexthop_global_in.s_addr == 0
2885 || IPV4_CLASS_DE(ntohl(
2886 attr->mp_nexthop_global_in.s_addr))
2887 || bgp_nexthop_self(bgp,
2888 attr->mp_nexthop_global_in));
2889 break;
2890
2891 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2892 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2893 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2894 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
2895 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
2896 || IN6_IS_ADDR_MULTICAST(
2897 &attr->mp_nexthop_global));
2898 break;
2899
2900 default:
2901 ret = 1;
2902 break;
2903 }
2904 }
c265ee22 2905
d62a17ae 2906 return ret;
2907}
2908
d7c0a89a 2909int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 2910 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 2911 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 2912 uint32_t num_labels, int soft_reconfig,
a4d82a8a 2913 struct bgp_route_evpn *evpn)
d62a17ae 2914{
2915 int ret;
2916 int aspath_loop_count = 0;
2917 struct bgp_node *rn;
2918 struct bgp *bgp;
2919 struct attr new_attr;
2920 struct attr *attr_new;
40381db7 2921 struct bgp_path_info *pi;
4b7e6066
DS
2922 struct bgp_path_info *new;
2923 struct bgp_path_info_extra *extra;
d62a17ae 2924 const char *reason;
2925 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 2926 int connected = 0;
2927 int do_loop_check = 1;
2928 int has_valid_label = 0;
65efcfce 2929#if ENABLE_BGP_VNC
d62a17ae 2930 int vnc_implicit_withdraw = 0;
65efcfce 2931#endif
d62a17ae 2932 int same_attr = 0;
718e3744 2933
d62a17ae 2934 memset(&new_attr, 0, sizeof(struct attr));
2935 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
2936 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 2937
d62a17ae 2938 bgp = peer->bgp;
2939 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
2940 /* TODO: Check to see if we can get rid of "is_valid_label" */
2941 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
2942 has_valid_label = (num_labels > 0) ? 1 : 0;
2943 else
2944 has_valid_label = bgp_is_valid_label(label);
718e3744 2945
d62a17ae 2946 /* When peer's soft reconfiguration enabled. Record input packet in
2947 Adj-RIBs-In. */
2948 if (!soft_reconfig
2949 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
2950 && peer != bgp->peer_self)
2951 bgp_adj_in_set(rn, peer, attr, addpath_id);
2952
2953 /* Check previously received route. */
6f94b685 2954 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
2955 if (pi->peer == peer && pi->type == type
2956 && pi->sub_type == sub_type
2957 && pi->addpath_rx_id == addpath_id)
d62a17ae 2958 break;
2959
2960 /* AS path local-as loop check. */
2961 if (peer->change_local_as) {
c4368918
DW
2962 if (peer->allowas_in[afi][safi])
2963 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
2964 else if (!CHECK_FLAG(peer->flags,
2965 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 2966 aspath_loop_count = 1;
2967
2968 if (aspath_loop_check(attr->aspath, peer->change_local_as)
2969 > aspath_loop_count) {
2970 reason = "as-path contains our own AS;";
2971 goto filtered;
2972 }
718e3744 2973 }
718e3744 2974
d62a17ae 2975 /* If the peer is configured for "allowas-in origin" and the last ASN in
2976 * the
2977 * as-path is our ASN then we do not need to call aspath_loop_check
2978 */
2979 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
2980 if (aspath_get_last_as(attr->aspath) == bgp->as)
2981 do_loop_check = 0;
2982
2983 /* AS path loop check. */
2984 if (do_loop_check) {
2985 if (aspath_loop_check(attr->aspath, bgp->as)
2986 > peer->allowas_in[afi][safi]
2987 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
2988 && aspath_loop_check(attr->aspath, bgp->confed_id)
2989 > peer->allowas_in[afi][safi])) {
2990 reason = "as-path contains our own AS;";
2991 goto filtered;
2992 }
2993 }
aac9ef6c 2994
d62a17ae 2995 /* Route reflector originator ID check. */
2996 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2997 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
2998 reason = "originator is us;";
2999 goto filtered;
3000 }
718e3744 3001
d62a17ae 3002 /* Route reflector cluster ID check. */
3003 if (bgp_cluster_filter(peer, attr)) {
3004 reason = "reflected from the same cluster;";
3005 goto filtered;
3006 }
718e3744 3007
d62a17ae 3008 /* Apply incoming filter. */
3009 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
3010 reason = "filter;";
3011 goto filtered;
3012 }
718e3744 3013
d62a17ae 3014 bgp_attr_dup(&new_attr, attr);
3015
3016 /* Apply incoming route-map.
3017 * NB: new_attr may now contain newly allocated values from route-map
3018 * "set"
3019 * commands, so we need bgp_attr_flush in the error paths, until we
3020 * intern
3021 * the attr (which takes over the memory references) */
3022 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
3023 == RMAP_DENY) {
3024 reason = "route-map;";
3025 bgp_attr_flush(&new_attr);
3026 goto filtered;
3027 }
718e3744 3028
7f323236
DW
3029 if (peer->sort == BGP_PEER_EBGP) {
3030
a4d82a8a
PZ
3031 /* If we receive the graceful-shutdown community from an eBGP
3032 * peer we must lower local-preference */
3033 if (new_attr.community
3034 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3035 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3036 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3037
a4d82a8a
PZ
3038 /* If graceful-shutdown is configured then add the GSHUT
3039 * community to all paths received from eBGP peers */
3040 } else if (bgp_flag_check(peer->bgp,
3041 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3042 bgp_attr_add_gshut_community(&new_attr);
3043 }
3044 }
3045
d62a17ae 3046 /* next hop check. */
a4d82a8a
PZ
3047 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3048 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
d62a17ae 3049 reason = "martian or self next-hop;";
3050 bgp_attr_flush(&new_attr);
3051 goto filtered;
3052 }
718e3744 3053
d62a17ae 3054 attr_new = bgp_attr_intern(&new_attr);
3055
3056 /* If the update is implicit withdraw. */
40381db7
DS
3057 if (pi) {
3058 pi->uptime = bgp_clock();
3059 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3060
3061 /* Same attribute comes in. */
40381db7
DS
3062 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3063 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3064 && (!has_valid_label
40381db7 3065 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3066 num_labels * sizeof(mpls_label_t))
d62a17ae 3067 == 0)
3068 && (overlay_index_equal(
40381db7 3069 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3070 evpn == NULL ? NULL : &evpn->gw_ip))) {
3071 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3072 BGP_CONFIG_DAMPENING)
3073 && peer->sort == BGP_PEER_EBGP
40381db7 3074 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3075 if (bgp_debug_update(peer, p, NULL, 1)) {
3076 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3077 afi, safi, prd, p, label,
3078 num_labels, addpath_id ? 1 : 0,
3079 addpath_id, pfx_buf,
3080 sizeof(pfx_buf));
d62a17ae 3081 zlog_debug("%s rcvd %s", peer->host,
3082 pfx_buf);
3083 }
3084
40381db7 3085 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3086 != BGP_DAMP_SUPPRESSED) {
40381db7 3087 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3088 safi);
3089 bgp_process(bgp, rn, afi, safi);
3090 }
3091 } else /* Duplicate - odd */
3092 {
3093 if (bgp_debug_update(peer, p, NULL, 1)) {
3094 if (!peer->rcvd_attr_printed) {
3095 zlog_debug(
3096 "%s rcvd UPDATE w/ attr: %s",
3097 peer->host,
3098 peer->rcvd_attr_str);
3099 peer->rcvd_attr_printed = 1;
3100 }
3101
3102 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3103 afi, safi, prd, p, label,
3104 num_labels, addpath_id ? 1 : 0,
3105 addpath_id, pfx_buf,
3106 sizeof(pfx_buf));
d62a17ae 3107 zlog_debug(
3108 "%s rcvd %s...duplicate ignored",
3109 peer->host, pfx_buf);
3110 }
3111
3112 /* graceful restart STALE flag unset. */
40381db7 3113 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3114 bgp_path_info_unset_flag(
40381db7 3115 rn, pi, BGP_PATH_STALE);
d62a17ae 3116 bgp_process(bgp, rn, afi, safi);
3117 }
3118 }
3119
3120 bgp_unlock_node(rn);
3121 bgp_attr_unintern(&attr_new);
3122
3123 return 0;
3124 }
718e3744 3125
d62a17ae 3126 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3127 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3128 if (bgp_debug_update(peer, p, NULL, 1)) {
3129 bgp_debug_rdpfxpath2str(
a4d82a8a 3130 afi, safi, prd, p, label, num_labels,
d62a17ae 3131 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3132 sizeof(pfx_buf));
3133 zlog_debug(
3134 "%s rcvd %s, flapped quicker than processing",
3135 peer->host, pfx_buf);
3136 }
3137
40381db7 3138 bgp_path_info_restore(rn, pi);
d62a17ae 3139 }
718e3744 3140
d62a17ae 3141 /* Received Logging. */
3142 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3143 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3144 num_labels, addpath_id ? 1 : 0,
3145 addpath_id, pfx_buf,
3146 sizeof(pfx_buf));
d62a17ae 3147 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3148 }
718e3744 3149
d62a17ae 3150 /* graceful restart STALE flag unset. */
40381db7
DS
3151 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3152 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3153
3154 /* The attribute is changed. */
40381db7 3155 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3156
3157 /* implicit withdraw, decrement aggregate and pcount here.
3158 * only if update is accepted, they'll increment below.
3159 */
40381db7 3160 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3161
3162 /* Update bgp route dampening information. */
3163 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3164 && peer->sort == BGP_PEER_EBGP) {
3165 /* This is implicit withdraw so we should update
3166 dampening
3167 information. */
40381db7
DS
3168 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3169 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3170 }
65efcfce 3171#if ENABLE_BGP_VNC
d62a17ae 3172 if (safi == SAFI_MPLS_VPN) {
3173 struct bgp_node *prn = NULL;
3174 struct bgp_table *table = NULL;
3175
3176 prn = bgp_node_get(bgp->rib[afi][safi],
3177 (struct prefix *)prd);
67009e22
DS
3178 if (bgp_node_has_bgp_path_info_data(prn)) {
3179 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3180
3181 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3182 bgp, prd, table, p, pi);
d62a17ae 3183 }
3184 bgp_unlock_node(prn);
3185 }
3186 if ((afi == AFI_IP || afi == AFI_IP6)
3187 && (safi == SAFI_UNICAST)) {
40381db7 3188 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3189 /*
3190 * Implicit withdraw case.
3191 */
3192 ++vnc_implicit_withdraw;
40381db7
DS
3193 vnc_import_bgp_del_route(bgp, p, pi);
3194 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3195 }
3196 }
65efcfce 3197#endif
128ea8ab 3198
d62a17ae 3199 /* Special handling for EVPN update of an existing route. If the
3200 * extended community attribute has changed, we need to
3201 * un-import
3202 * the route using its existing extended community. It will be
3203 * subsequently processed for import with the new extended
3204 * community.
3205 */
3206 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3207 if ((pi->attr->flag
d62a17ae 3208 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3209 && (attr_new->flag
3210 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3211 int cmp;
3212
40381db7 3213 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3214 attr_new->ecommunity);
3215 if (!cmp) {
3216 if (bgp_debug_update(peer, p, NULL, 1))
3217 zlog_debug(
3218 "Change in EXT-COMM, existing %s new %s",
3219 ecommunity_str(
40381db7 3220 pi->attr->ecommunity),
d62a17ae 3221 ecommunity_str(
3222 attr_new->ecommunity));
3223 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3224 p, pi);
d62a17ae 3225 }
3226 }
3227 }
718e3744 3228
d62a17ae 3229 /* Update to new attribute. */
40381db7
DS
3230 bgp_attr_unintern(&pi->attr);
3231 pi->attr = attr_new;
d62a17ae 3232
3233 /* Update MPLS label */
3234 if (has_valid_label) {
40381db7 3235 extra = bgp_path_info_extra_get(pi);
b57ba6d2
MK
3236 memcpy(&extra->label, label,
3237 num_labels * sizeof(mpls_label_t));
3238 extra->num_labels = num_labels;
3239 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3240 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3241 }
718e3744 3242
65efcfce 3243#if ENABLE_BGP_VNC
d62a17ae 3244 if ((afi == AFI_IP || afi == AFI_IP6)
3245 && (safi == SAFI_UNICAST)) {
3246 if (vnc_implicit_withdraw) {
3247 /*
3248 * Add back the route with its new attributes
3249 * (e.g., nexthop).
3250 * The route is still selected, until the route
3251 * selection
3252 * queued by bgp_process actually runs. We have
3253 * to make this
3254 * update to the VNC side immediately to avoid
3255 * racing against
3256 * configuration changes (e.g., route-map
3257 * changes) which
3258 * trigger re-importation of the entire RIB.
3259 */
40381db7
DS
3260 vnc_import_bgp_add_route(bgp, p, pi);
3261 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3262 }
3263 }
65efcfce 3264#endif
d62a17ae 3265 /* Update Overlay Index */
3266 if (afi == AFI_L2VPN) {
3267 overlay_index_update(
40381db7 3268 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3269 evpn == NULL ? NULL : &evpn->gw_ip);
3270 }
65efcfce 3271
d62a17ae 3272 /* Update bgp route dampening information. */
3273 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3274 && peer->sort == BGP_PEER_EBGP) {
3275 /* Now we do normal update dampening. */
40381db7 3276 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3277 if (ret == BGP_DAMP_SUPPRESSED) {
3278 bgp_unlock_node(rn);
3279 return 0;
3280 }
3281 }
128ea8ab 3282
d62a17ae 3283 /* Nexthop reachability check - for unicast and
3284 * labeled-unicast.. */
3285 if ((afi == AFI_IP || afi == AFI_IP6)
3286 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3287 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3288 && !CHECK_FLAG(peer->flags,
3289 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3290 && !bgp_flag_check(
3291 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3292 connected = 1;
3293 else
3294 connected = 0;
3295
960035b2
PZ
3296 struct bgp *bgp_nexthop = bgp;
3297
40381db7
DS
3298 if (pi->extra && pi->extra->bgp_orig)
3299 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3300
40381db7
DS
3301 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi,
3302 NULL, connected)
a4d82a8a 3303 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3304 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3305 else {
3306 if (BGP_DEBUG(nht, NHT)) {
3307 char buf1[INET6_ADDRSTRLEN];
3308 inet_ntop(AF_INET,
3309 (const void *)&attr_new
3310 ->nexthop,
3311 buf1, INET6_ADDRSTRLEN);
3312 zlog_debug("%s(%s): NH unresolved",
3313 __FUNCTION__, buf1);
3314 }
40381db7 3315 bgp_path_info_unset_flag(rn, pi,
18ee8310 3316 BGP_PATH_VALID);
d62a17ae 3317 }
3318 } else
40381db7 3319 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3320
3321#if ENABLE_BGP_VNC
3322 if (safi == SAFI_MPLS_VPN) {
3323 struct bgp_node *prn = NULL;
3324 struct bgp_table *table = NULL;
3325
3326 prn = bgp_node_get(bgp->rib[afi][safi],
3327 (struct prefix *)prd);
67009e22
DS
3328 if (bgp_node_has_bgp_path_info_data(prn)) {
3329 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3330
3331 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3332 bgp, prd, table, p, pi);
d62a17ae 3333 }
3334 bgp_unlock_node(prn);
3335 }
3336#endif
718e3744 3337
d62a17ae 3338 /* If this is an EVPN route and some attribute has changed,
3339 * process
3340 * route for import. If the extended community has changed, we
3341 * would
3342 * have done the un-import earlier and the import would result
3343 * in the
3344 * route getting injected into appropriate L2 VNIs. If it is
3345 * just
3346 * some other attribute change, the import will result in
3347 * updating
3348 * the attributes for the route in the VNI(s).
3349 */
3350 if (safi == SAFI_EVPN && !same_attr)
40381db7 3351 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3352
3353 /* Process change. */
40381db7 3354 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3355
3356 bgp_process(bgp, rn, afi, safi);
3357 bgp_unlock_node(rn);
558d1fec 3358
ddb5b488
PZ
3359 if (SAFI_UNICAST == safi
3360 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3361 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3362
40381db7 3363 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3364 }
3365 if ((SAFI_MPLS_VPN == safi)
3366 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3367
40381db7 3368 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3369 }
3370
28070ee3 3371#if ENABLE_BGP_VNC
d62a17ae 3372 if (SAFI_MPLS_VPN == safi) {
3373 mpls_label_t label_decoded = decode_label(label);
28070ee3 3374
d62a17ae 3375 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3376 type, sub_type, &label_decoded);
3377 }
3378 if (SAFI_ENCAP == safi) {
3379 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3380 type, sub_type, NULL);
3381 }
28070ee3
PZ
3382#endif
3383
d62a17ae 3384 return 0;
3385 } // End of implicit withdraw
718e3744 3386
d62a17ae 3387 /* Received Logging. */
3388 if (bgp_debug_update(peer, p, NULL, 1)) {
3389 if (!peer->rcvd_attr_printed) {
3390 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3391 peer->rcvd_attr_str);
3392 peer->rcvd_attr_printed = 1;
3393 }
718e3744 3394
a4d82a8a 3395 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3396 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3397 sizeof(pfx_buf));
3398 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3399 }
718e3744 3400
d62a17ae 3401 /* Make new BGP info. */
3402 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3403
d62a17ae 3404 /* Update MPLS label */
3405 if (has_valid_label) {
18ee8310 3406 extra = bgp_path_info_extra_get(new);
a4d82a8a 3407 memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t));
b57ba6d2
MK
3408 extra->num_labels = num_labels;
3409 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3410 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3411 }
718e3744 3412
d62a17ae 3413 /* Update Overlay Index */
3414 if (afi == AFI_L2VPN) {
3415 overlay_index_update(new->attr,
3416 evpn == NULL ? NULL : &evpn->eth_s_id,
3417 evpn == NULL ? NULL : &evpn->gw_ip);
3418 }
3419 /* Nexthop reachability check. */
3420 if ((afi == AFI_IP || afi == AFI_IP6)
3421 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3422 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3423 && !CHECK_FLAG(peer->flags,
3424 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3425 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3426 connected = 1;
3427 else
3428 connected = 0;
3429
960035b2 3430 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected)
a4d82a8a 3431 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3432 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3433 else {
3434 if (BGP_DEBUG(nht, NHT)) {
3435 char buf1[INET6_ADDRSTRLEN];
3436 inet_ntop(AF_INET,
3437 (const void *)&attr_new->nexthop,
3438 buf1, INET6_ADDRSTRLEN);
3439 zlog_debug("%s(%s): NH unresolved",
3440 __FUNCTION__, buf1);
3441 }
18ee8310 3442 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3443 }
3444 } else
18ee8310 3445 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3446
d62a17ae 3447 /* Addpath ID */
3448 new->addpath_rx_id = addpath_id;
3449
3450 /* Increment prefix */
3451 bgp_aggregate_increment(bgp, p, new, afi, safi);
3452
3453 /* Register new BGP information. */
18ee8310 3454 bgp_path_info_add(rn, new);
d62a17ae 3455
3456 /* route_node_get lock */
3457 bgp_unlock_node(rn);
558d1fec 3458
65efcfce 3459#if ENABLE_BGP_VNC
d62a17ae 3460 if (safi == SAFI_MPLS_VPN) {
3461 struct bgp_node *prn = NULL;
3462 struct bgp_table *table = NULL;
3463
3464 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3465 if (bgp_node_has_bgp_path_info_data(prn)) {
3466 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3467
3468 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3469 bgp, prd, table, p, new);
3470 }
3471 bgp_unlock_node(prn);
3472 }
65efcfce
LB
3473#endif
3474
d62a17ae 3475 /* If maximum prefix count is configured and current prefix
3476 count exeed it. */
3477 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3478 return -1;
718e3744 3479
d62a17ae 3480 /* If this is an EVPN route, process for import. */
3481 if (safi == SAFI_EVPN)
3482 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3483
d62a17ae 3484 /* Process change. */
3485 bgp_process(bgp, rn, afi, safi);
718e3744 3486
ddb5b488
PZ
3487 if (SAFI_UNICAST == safi
3488 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3489 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3490 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3491 }
3492 if ((SAFI_MPLS_VPN == safi)
3493 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3494
3495 vpn_leak_to_vrf_update(bgp, new);
3496 }
28070ee3 3497#if ENABLE_BGP_VNC
d62a17ae 3498 if (SAFI_MPLS_VPN == safi) {
3499 mpls_label_t label_decoded = decode_label(label);
28070ee3 3500
d62a17ae 3501 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3502 sub_type, &label_decoded);
3503 }
3504 if (SAFI_ENCAP == safi) {
3505 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3506 sub_type, NULL);
3507 }
28070ee3
PZ
3508#endif
3509
d62a17ae 3510 return 0;
718e3744 3511
d62a17ae 3512/* This BGP update is filtered. Log the reason then update BGP
3513 entry. */
3514filtered:
3515 if (bgp_debug_update(peer, p, NULL, 1)) {
3516 if (!peer->rcvd_attr_printed) {
3517 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3518 peer->rcvd_attr_str);
3519 peer->rcvd_attr_printed = 1;
3520 }
718e3744 3521
a4d82a8a 3522 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3523 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3524 sizeof(pfx_buf));
3525 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3526 peer->host, pfx_buf, reason);
3527 }
128ea8ab 3528
40381db7 3529 if (pi) {
d62a17ae 3530 /* If this is an EVPN route, un-import it as it is now filtered.
3531 */
3532 if (safi == SAFI_EVPN)
40381db7 3533 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3534
ddb5b488
PZ
3535 if (SAFI_UNICAST == safi
3536 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3537 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3538
40381db7 3539 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3540 }
3541 if ((SAFI_MPLS_VPN == safi)
3542 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3543
40381db7 3544 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3545 }
3546
40381db7 3547 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3548 }
3549
3550 bgp_unlock_node(rn);
558d1fec 3551
97736e32 3552#if ENABLE_BGP_VNC
d62a17ae 3553 /*
3554 * Filtered update is treated as an implicit withdrawal (see
3555 * bgp_rib_remove()
3556 * a few lines above)
3557 */
3558 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3559 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3560 0);
3561 }
97736e32
PZ
3562#endif
3563
d62a17ae 3564 return 0;
718e3744 3565}
3566
d7c0a89a 3567int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3568 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3569 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3570 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3571{
d62a17ae 3572 struct bgp *bgp;
3573 char pfx_buf[BGP_PRD_PATH_STRLEN];
3574 struct bgp_node *rn;
40381db7 3575 struct bgp_path_info *pi;
718e3744 3576
28070ee3 3577#if ENABLE_BGP_VNC
d62a17ae 3578 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3579 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3580 0);
3581 }
28070ee3
PZ
3582#endif
3583
d62a17ae 3584 bgp = peer->bgp;
3585
3586 /* Lookup node. */
3587 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3588
3589 /* If peer is soft reconfiguration enabled. Record input packet for
3590 * further calculation.
3591 *
3592 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3593 * routes that are filtered. This tanks out Quagga RS pretty badly due
3594 * to
3595 * the iteration over all RS clients.
3596 * Since we need to remove the entry from adj_in anyway, do that first
3597 * and
3598 * if there was no entry, we don't need to do anything more.
3599 */
3600 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3601 && peer != bgp->peer_self)
3602 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
3603 if (bgp_debug_update(peer, p, NULL, 1)) {
3604 bgp_debug_rdpfxpath2str(
a4d82a8a 3605 afi, safi, prd, p, label, num_labels,
d62a17ae 3606 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3607 sizeof(pfx_buf));
3608 zlog_debug(
3609 "%s withdrawing route %s not in adj-in",
3610 peer->host, pfx_buf);
3611 }
3612 bgp_unlock_node(rn);
3613 return 0;
3614 }
cd808e74 3615
d62a17ae 3616 /* Lookup withdrawn route. */
6f94b685 3617 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3618 if (pi->peer == peer && pi->type == type
3619 && pi->sub_type == sub_type
3620 && pi->addpath_rx_id == addpath_id)
d62a17ae 3621 break;
3622
3623 /* Logging. */
3624 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3625 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3626 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3627 sizeof(pfx_buf));
3628 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3629 pfx_buf);
3630 }
718e3744 3631
d62a17ae 3632 /* Withdraw specified route from routing table. */
40381db7
DS
3633 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3634 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3635 if (SAFI_UNICAST == safi
3636 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3637 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3638 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3639 }
3640 if ((SAFI_MPLS_VPN == safi)
3641 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3642
40381db7 3643 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3644 }
3645 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3646 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3647 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3648 sizeof(pfx_buf));
3649 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3650 }
718e3744 3651
d62a17ae 3652 /* Unlock bgp_node_get() lock. */
3653 bgp_unlock_node(rn);
3654
3655 return 0;
718e3744 3656}
6b0655a2 3657
d62a17ae 3658void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3659 int withdraw)
718e3744 3660{
d62a17ae 3661 struct update_subgroup *subgrp;
3662 subgrp = peer_subgroup(peer, afi, safi);
3663 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3664}
6182d65b 3665
718e3744 3666
3f9c7369
DS
3667/*
3668 * bgp_stop_announce_route_timer
3669 */
d62a17ae 3670void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3671{
d62a17ae 3672 if (!paf->t_announce_route)
3673 return;
3674
3675 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3676}
6b0655a2 3677
3f9c7369
DS
3678/*
3679 * bgp_announce_route_timer_expired
3680 *
3681 * Callback that is invoked when the route announcement timer for a
3682 * peer_af expires.
3683 */
d62a17ae 3684static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3685{
d62a17ae 3686 struct peer_af *paf;
3687 struct peer *peer;
558d1fec 3688
d62a17ae 3689 paf = THREAD_ARG(t);
3690 peer = paf->peer;
718e3744 3691
d62a17ae 3692 if (peer->status != Established)
3693 return 0;
3f9c7369 3694
d62a17ae 3695 if (!peer->afc_nego[paf->afi][paf->safi])
3696 return 0;
3f9c7369 3697
d62a17ae 3698 peer_af_announce_route(paf, 1);
3699 return 0;
718e3744 3700}
3701
3f9c7369
DS
3702/*
3703 * bgp_announce_route
3704 *
3705 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3706 */
d62a17ae 3707void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3708{
3709 struct peer_af *paf;
3710 struct update_subgroup *subgrp;
3711
3712 paf = peer_af_find(peer, afi, safi);
3713 if (!paf)
3714 return;
3715 subgrp = PAF_SUBGRP(paf);
3716
3717 /*
3718 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3719 * or a refresh has already been triggered.
3720 */
3721 if (!subgrp || paf->t_announce_route)
3722 return;
3723
3724 /*
3725 * Start a timer to stagger/delay the announce. This serves
3726 * two purposes - announcement can potentially be combined for
3727 * multiple peers and the announcement doesn't happen in the
3728 * vty context.
3729 */
3730 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3731 (subgrp->peer_count == 1)
3732 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3733 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3734 &paf->t_announce_route);
3f9c7369
DS
3735}
3736
3737/*
3738 * Announce routes from all AF tables to a peer.
3739 *
3740 * This should ONLY be called when there is a need to refresh the
3741 * routes to the peer based on a policy change for this peer alone
3742 * or a route refresh request received from the peer.
3743 * The operation will result in splitting the peer from its existing
3744 * subgroups and putting it in new subgroups.
3745 */
d62a17ae 3746void bgp_announce_route_all(struct peer *peer)
718e3744 3747{
d62a17ae 3748 afi_t afi;
3749 safi_t safi;
3750
05c7a1cc
QY
3751 FOREACH_AFI_SAFI (afi, safi)
3752 bgp_announce_route(peer, afi, safi);
718e3744 3753}
6b0655a2 3754
d62a17ae 3755static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3756 struct bgp_table *table,
3757 struct prefix_rd *prd)
718e3744 3758{
d62a17ae 3759 int ret;
3760 struct bgp_node *rn;
3761 struct bgp_adj_in *ain;
718e3744 3762
d62a17ae 3763 if (!table)
3764 table = peer->bgp->rib[afi][safi];
718e3744 3765
d62a17ae 3766 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3767 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3768 if (ain->peer != peer)
3769 continue;
8692c506 3770
6f94b685
DS
3771 struct bgp_path_info *pi =
3772 bgp_node_get_bgp_path_info(rn);
d7c0a89a 3773 uint32_t num_labels = 0;
b57ba6d2
MK
3774 mpls_label_t *label_pnt = NULL;
3775
40381db7
DS
3776 if (pi && pi->extra)
3777 num_labels = pi->extra->num_labels;
b57ba6d2 3778 if (num_labels)
40381db7 3779 label_pnt = &pi->extra->label[0];
8692c506 3780
ea47320b
DL
3781 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3782 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
3783 BGP_ROUTE_NORMAL, prd, label_pnt,
3784 num_labels, 1, NULL);
ea47320b
DL
3785
3786 if (ret < 0) {
3787 bgp_unlock_node(rn);
3788 return;
d62a17ae 3789 }
3790 }
718e3744 3791}
3792
d62a17ae 3793void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3794{
d62a17ae 3795 struct bgp_node *rn;
3796 struct bgp_table *table;
718e3744 3797
d62a17ae 3798 if (peer->status != Established)
3799 return;
718e3744 3800
d62a17ae 3801 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3802 && (safi != SAFI_EVPN))
3803 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3804 else
3805 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
3806 rn = bgp_route_next(rn)) {
3807 table = bgp_node_get_bgp_table_info(rn);
3808 if (table != NULL) {
d62a17ae 3809 struct prefix_rd prd;
67009e22 3810
d62a17ae 3811 prd.family = AF_UNSPEC;
3812 prd.prefixlen = 64;
3813 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3814
d62a17ae 3815 bgp_soft_reconfig_table(peer, afi, safi, table,
3816 &prd);
3817 }
67009e22 3818 }
718e3744 3819}
6b0655a2 3820
228da428 3821
d62a17ae 3822struct bgp_clear_node_queue {
3823 struct bgp_node *rn;
228da428
CC
3824};
3825
d62a17ae 3826static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3827{
d62a17ae 3828 struct bgp_clear_node_queue *cnq = data;
3829 struct bgp_node *rn = cnq->rn;
3830 struct peer *peer = wq->spec.data;
40381db7 3831 struct bgp_path_info *pi;
3103e8d2 3832 struct bgp *bgp;
d62a17ae 3833 afi_t afi = bgp_node_table(rn)->afi;
3834 safi_t safi = bgp_node_table(rn)->safi;
3835
3836 assert(rn && peer);
3103e8d2 3837 bgp = peer->bgp;
d62a17ae 3838
3839 /* It is possible that we have multiple paths for a prefix from a peer
3840 * if that peer is using AddPath.
3841 */
6f94b685 3842 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 3843 if (pi->peer != peer)
ea47320b
DL
3844 continue;
3845
3846 /* graceful restart STALE flag set. */
3847 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
3848 && peer->nsf[afi][safi]
40381db7
DS
3849 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
3850 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
3851 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
3852 else {
3853 /* If this is an EVPN route, process for
3854 * un-import. */
3855 if (safi == SAFI_EVPN)
40381db7
DS
3856 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
3857 pi);
3103e8d2
DS
3858 /* Handle withdraw for VRF route-leaking and L3VPN */
3859 if (SAFI_UNICAST == safi
3860 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 3861 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 3862 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 3863 bgp, pi);
960035b2 3864 }
3103e8d2 3865 if (SAFI_MPLS_VPN == safi &&
960035b2 3866 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 3867 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 3868 }
3103e8d2 3869
40381db7 3870 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3871 }
ea47320b 3872 }
d62a17ae 3873 return WQ_SUCCESS;
200df115 3874}
3875
d62a17ae 3876static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 3877{
d62a17ae 3878 struct bgp_clear_node_queue *cnq = data;
3879 struct bgp_node *rn = cnq->rn;
3880 struct bgp_table *table = bgp_node_table(rn);
228da428 3881
d62a17ae 3882 bgp_unlock_node(rn);
3883 bgp_table_unlock(table);
3884 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 3885}
3886
d62a17ae 3887static void bgp_clear_node_complete(struct work_queue *wq)
200df115 3888{
d62a17ae 3889 struct peer *peer = wq->spec.data;
64e580a7 3890
d62a17ae 3891 /* Tickle FSM to start moving again */
3892 BGP_EVENT_ADD(peer, Clearing_Completed);
3893
3894 peer_unlock(peer); /* bgp_clear_route */
200df115 3895}
718e3744 3896
d62a17ae 3897static void bgp_clear_node_queue_init(struct peer *peer)
200df115 3898{
d62a17ae 3899 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3900
3901 snprintf(wname, sizeof(wname), "clear %s", peer->host);
3902#undef CLEAR_QUEUE_NAME_LEN
3903
0ce1ca80 3904 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 3905 peer->clear_node_queue->spec.hold = 10;
3906 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
3907 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
3908 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
3909 peer->clear_node_queue->spec.max_retries = 0;
3910
3911 /* we only 'lock' this peer reference when the queue is actually active
3912 */
3913 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
3914}
3915
d62a17ae 3916static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
3917 struct bgp_table *table)
65ca75e0 3918{
d62a17ae 3919 struct bgp_node *rn;
3920 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 3921
d62a17ae 3922 if (!table)
3923 table = peer->bgp->rib[afi][safi];
dc83d712 3924
d62a17ae 3925 /* If still no table => afi/safi isn't configured at all or smth. */
3926 if (!table)
3927 return;
dc83d712 3928
d62a17ae 3929 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 3930 struct bgp_path_info *pi, *next;
d62a17ae 3931 struct bgp_adj_in *ain;
3932 struct bgp_adj_in *ain_next;
3933
3934 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3935 * queued for every clearing peer, regardless of whether it is
3936 * relevant to the peer at hand.
3937 *
3938 * Overview: There are 3 different indices which need to be
3939 * scrubbed, potentially, when a peer is removed:
3940 *
3941 * 1 peer's routes visible via the RIB (ie accepted routes)
3942 * 2 peer's routes visible by the (optional) peer's adj-in index
3943 * 3 other routes visible by the peer's adj-out index
3944 *
3945 * 3 there is no hurry in scrubbing, once the struct peer is
3946 * removed from bgp->peer, we could just GC such deleted peer's
3947 * adj-outs at our leisure.
3948 *
3949 * 1 and 2 must be 'scrubbed' in some way, at least made
3950 * invisible via RIB index before peer session is allowed to be
3951 * brought back up. So one needs to know when such a 'search' is
3952 * complete.
3953 *
3954 * Ideally:
3955 *
3956 * - there'd be a single global queue or a single RIB walker
3957 * - rather than tracking which route_nodes still need to be
3958 * examined on a peer basis, we'd track which peers still
3959 * aren't cleared
3960 *
3961 * Given that our per-peer prefix-counts now should be reliable,
3962 * this may actually be achievable. It doesn't seem to be a huge
3963 * problem at this time,
3964 *
3965 * It is possible that we have multiple paths for a prefix from
3966 * a peer
3967 * if that peer is using AddPath.
3968 */
3969 ain = rn->adj_in;
3970 while (ain) {
3971 ain_next = ain->next;
3972
3973 if (ain->peer == peer) {
3974 bgp_adj_in_remove(rn, ain);
3975 bgp_unlock_node(rn);
3976 }
3977
3978 ain = ain_next;
3979 }
3980
6f94b685 3981 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
3982 next = pi->next;
3983 if (pi->peer != peer)
d62a17ae 3984 continue;
3985
3986 if (force)
40381db7 3987 bgp_path_info_reap(rn, pi);
d62a17ae 3988 else {
3989 struct bgp_clear_node_queue *cnq;
3990
3991 /* both unlocked in bgp_clear_node_queue_del */
3992 bgp_table_lock(bgp_node_table(rn));
3993 bgp_lock_node(rn);
3994 cnq = XCALLOC(
3995 MTYPE_BGP_CLEAR_NODE_QUEUE,
3996 sizeof(struct bgp_clear_node_queue));
3997 cnq->rn = rn;
3998 work_queue_add(peer->clear_node_queue, cnq);
3999 break;
4000 }
4001 }
4002 }
4003 return;
4004}
4005
4006void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4007{
4008 struct bgp_node *rn;
4009 struct bgp_table *table;
4010
4011 if (peer->clear_node_queue == NULL)
4012 bgp_clear_node_queue_init(peer);
4013
4014 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4015 * Idle until it receives a Clearing_Completed event. This protects
4016 * against peers which flap faster than we can we clear, which could
4017 * lead to:
4018 *
4019 * a) race with routes from the new session being installed before
4020 * clear_route_node visits the node (to delete the route of that
4021 * peer)
4022 * b) resource exhaustion, clear_route_node likely leads to an entry
4023 * on the process_main queue. Fast-flapping could cause that queue
4024 * to grow and grow.
4025 */
4026
4027 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4028 * the unlock will happen upon work-queue completion; other wise, the
4029 * unlock happens at the end of this function.
4030 */
4031 if (!peer->clear_node_queue->thread)
4032 peer_lock(peer);
4033
4034 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4035 bgp_clear_route_table(peer, afi, safi, NULL);
4036 else
4037 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4038 rn = bgp_route_next(rn)) {
4039 table = bgp_node_get_bgp_table_info(rn);
4040 if (!table)
4041 continue;
4042
4043 bgp_clear_route_table(peer, afi, safi, table);
4044 }
d62a17ae 4045
4046 /* unlock if no nodes got added to the clear-node-queue. */
4047 if (!peer->clear_node_queue->thread)
4048 peer_unlock(peer);
718e3744 4049}
d62a17ae 4050
4051void bgp_clear_route_all(struct peer *peer)
718e3744 4052{
d62a17ae 4053 afi_t afi;
4054 safi_t safi;
718e3744 4055
05c7a1cc
QY
4056 FOREACH_AFI_SAFI (afi, safi)
4057 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4058
4059#if ENABLE_BGP_VNC
d62a17ae 4060 rfapiProcessPeerDown(peer);
65efcfce 4061#endif
718e3744 4062}
4063
d62a17ae 4064void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4065{
d62a17ae 4066 struct bgp_table *table;
4067 struct bgp_node *rn;
4068 struct bgp_adj_in *ain;
4069 struct bgp_adj_in *ain_next;
718e3744 4070
d62a17ae 4071 table = peer->bgp->rib[afi][safi];
718e3744 4072
d62a17ae 4073 /* It is possible that we have multiple paths for a prefix from a peer
4074 * if that peer is using AddPath.
4075 */
4076 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4077 ain = rn->adj_in;
43143c8f 4078
d62a17ae 4079 while (ain) {
4080 ain_next = ain->next;
43143c8f 4081
d62a17ae 4082 if (ain->peer == peer) {
4083 bgp_adj_in_remove(rn, ain);
4084 bgp_unlock_node(rn);
4085 }
43143c8f 4086
d62a17ae 4087 ain = ain_next;
4088 }
4089 }
718e3744 4090}
93406d87 4091
d62a17ae 4092void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4093{
4094 struct bgp_node *rn;
40381db7 4095 struct bgp_path_info *pi;
d62a17ae 4096 struct bgp_table *table;
4097
4098 if (safi == SAFI_MPLS_VPN) {
4099 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4100 rn = bgp_route_next(rn)) {
4101 struct bgp_node *rm;
d62a17ae 4102
4103 /* look for neighbor in tables */
67009e22
DS
4104 table = bgp_node_get_bgp_table_info(rn);
4105 if (!table)
ea47320b
DL
4106 continue;
4107
4108 for (rm = bgp_table_top(table); rm;
4109 rm = bgp_route_next(rm))
6f94b685
DS
4110 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4111 pi = pi->next) {
40381db7 4112 if (pi->peer != peer)
ea47320b 4113 continue;
40381db7 4114 if (!CHECK_FLAG(pi->flags,
1defdda8 4115 BGP_PATH_STALE))
ea47320b
DL
4116 break;
4117
40381db7 4118 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4119 break;
4120 }
d62a17ae 4121 }
4122 } else {
4123 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4124 rn = bgp_route_next(rn))
6f94b685
DS
4125 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4126 pi = pi->next) {
40381db7 4127 if (pi->peer != peer)
ea47320b 4128 continue;
40381db7 4129 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4130 break;
40381db7 4131 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4132 break;
4133 }
d62a17ae 4134 }
93406d87 4135}
6b0655a2 4136
568e10ca 4137static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4138 safi_t safi)
bb86c601 4139{
d62a17ae 4140 struct bgp_node *rn;
40381db7 4141 struct bgp_path_info *pi;
4b7e6066 4142 struct bgp_path_info *next;
bb86c601 4143
d62a17ae 4144 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4145 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4146 next = pi->next;
4147 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4148 && pi->type == ZEBRA_ROUTE_BGP
4149 && (pi->sub_type == BGP_ROUTE_NORMAL
4150 || pi->sub_type == BGP_ROUTE_AGGREGATE
4151 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4152
d62a17ae 4153 if (bgp_fibupd_safi(safi))
40381db7
DS
4154 bgp_zebra_withdraw(&rn->p, pi, bgp,
4155 safi);
4156 bgp_path_info_reap(rn, pi);
d62a17ae 4157 }
4158 }
bb86c601
LB
4159}
4160
718e3744 4161/* Delete all kernel routes. */
d62a17ae 4162void bgp_cleanup_routes(struct bgp *bgp)
4163{
4164 afi_t afi;
4165 struct bgp_node *rn;
67009e22 4166 struct bgp_table *table;
d62a17ae 4167
4168 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4169 if (afi == AFI_L2VPN)
4170 continue;
568e10ca 4171 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4172 SAFI_UNICAST);
d62a17ae 4173 /*
4174 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4175 */
4176 if (afi != AFI_L2VPN) {
4177 safi_t safi;
4178 safi = SAFI_MPLS_VPN;
4179 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4180 rn = bgp_route_next(rn)) {
67009e22
DS
4181 table = bgp_node_get_bgp_table_info(rn);
4182 if (table != NULL) {
4183 bgp_cleanup_table(bgp, table, safi);
4184 bgp_table_finish(&table);
4185 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4186 bgp_unlock_node(rn);
4187 }
4188 }
4189 safi = SAFI_ENCAP;
4190 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4191 rn = bgp_route_next(rn)) {
67009e22
DS
4192 table = bgp_node_get_bgp_table_info(rn);
4193 if (table != NULL) {
4194 bgp_cleanup_table(bgp, table, safi);
4195 bgp_table_finish(&table);
4196 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4197 bgp_unlock_node(rn);
4198 }
4199 }
4200 }
4201 }
4202 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4203 rn = bgp_route_next(rn)) {
67009e22
DS
4204 table = bgp_node_get_bgp_table_info(rn);
4205 if (table != NULL) {
4206 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4207 bgp_table_finish(&table);
4208 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4209 bgp_unlock_node(rn);
4210 }
bb86c601 4211 }
718e3744 4212}
4213
d62a17ae 4214void bgp_reset(void)
718e3744 4215{
d62a17ae 4216 vty_reset();
4217 bgp_zclient_reset();
4218 access_list_reset();
4219 prefix_list_reset();
718e3744 4220}
6b0655a2 4221
d62a17ae 4222static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4223{
d62a17ae 4224 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4225 && CHECK_FLAG(peer->af_cap[afi][safi],
4226 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4227}
4228
718e3744 4229/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4230 value. */
d62a17ae 4231int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4232 struct bgp_nlri *packet)
4233{
d7c0a89a
QY
4234 uint8_t *pnt;
4235 uint8_t *lim;
d62a17ae 4236 struct prefix p;
4237 int psize;
4238 int ret;
4239 afi_t afi;
4240 safi_t safi;
4241 int addpath_encoded;
d7c0a89a 4242 uint32_t addpath_id;
d62a17ae 4243
d62a17ae 4244 pnt = packet->nlri;
4245 lim = pnt + packet->length;
4246 afi = packet->afi;
4247 safi = packet->safi;
4248 addpath_id = 0;
4249 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4250
4251 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4252 syntactic validity. If the field is syntactically incorrect,
4253 then the Error Subcode is set to Invalid Network Field. */
4254 for (; pnt < lim; pnt += psize) {
4255 /* Clear prefix structure. */
4256 memset(&p, 0, sizeof(struct prefix));
4257
4258 if (addpath_encoded) {
4259
4260 /* When packet overflow occurs return immediately. */
4261 if (pnt + BGP_ADDPATH_ID_LEN > lim)
4262 return -1;
4263
4264 addpath_id = ntohl(*((uint32_t *)pnt));
4265 pnt += BGP_ADDPATH_ID_LEN;
4266 }
718e3744 4267
d62a17ae 4268 /* Fetch prefix length. */
4269 p.prefixlen = *pnt++;
4270 /* afi/safi validity already verified by caller,
4271 * bgp_update_receive */
4272 p.family = afi2family(afi);
4273
4274 /* Prefix length check. */
4275 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4276 flog_err(
e50f7cfd 4277 EC_BGP_UPDATE_RCV,
14454c9f 4278 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4279 peer->host, p.prefixlen, packet->afi);
4280 return -1;
4281 }
6b0655a2 4282
d62a17ae 4283 /* Packet size overflow check. */
4284 psize = PSIZE(p.prefixlen);
4285
4286 /* When packet overflow occur return immediately. */
4287 if (pnt + psize > lim) {
af4c2728 4288 flog_err(
e50f7cfd 4289 EC_BGP_UPDATE_RCV,
d62a17ae 4290 "%s [Error] Update packet error (prefix length %d overflows packet)",
4291 peer->host, p.prefixlen);
4292 return -1;
4293 }
4294
4295 /* Defensive coding, double-check the psize fits in a struct
4296 * prefix */
4297 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4298 flog_err(
e50f7cfd 4299 EC_BGP_UPDATE_RCV,
d62a17ae 4300 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4301 peer->host, p.prefixlen, sizeof(p.u));
4302 return -1;
4303 }
4304
4305 /* Fetch prefix from NLRI packet. */
a85297a7 4306 memcpy(p.u.val, pnt, psize);
d62a17ae 4307
4308 /* Check address. */
4309 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4310 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4311 /* From RFC4271 Section 6.3:
4312 *
4313 * If a prefix in the NLRI field is semantically
4314 * incorrect
4315 * (e.g., an unexpected multicast IP address),
4316 * an error SHOULD
4317 * be logged locally, and the prefix SHOULD be
4318 * ignored.
a4d82a8a 4319 */
af4c2728 4320 flog_err(
e50f7cfd 4321 EC_BGP_UPDATE_RCV,
d62a17ae 4322 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4323 peer->host, inet_ntoa(p.u.prefix4));
4324 continue;
4325 }
4326 }
4327
4328 /* Check address. */
4329 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4330 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4331 char buf[BUFSIZ];
4332
af4c2728 4333 flog_err(
e50f7cfd 4334 EC_BGP_UPDATE_RCV,
d62a17ae 4335 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4336 peer->host,
4337 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4338 BUFSIZ));
4339
4340 continue;
4341 }
4342 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4343 char buf[BUFSIZ];
4344
af4c2728 4345 flog_err(
e50f7cfd 4346 EC_BGP_UPDATE_RCV,
d62a17ae 4347 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4348 peer->host,
4349 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4350 BUFSIZ));
4351
4352 continue;
4353 }
4354 }
4355
4356 /* Normal process. */
4357 if (attr)
4358 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4359 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4360 NULL, NULL, 0, 0, NULL);
d62a17ae 4361 else
4362 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4363 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4364 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4365 NULL);
d62a17ae 4366
4367 /* Address family configuration mismatch or maximum-prefix count
4368 overflow. */
4369 if (ret < 0)
4370 return -1;
4371 }
4372
4373 /* Packet length consistency check. */
4374 if (pnt != lim) {
af4c2728 4375 flog_err(
e50f7cfd 4376 EC_BGP_UPDATE_RCV,
d62a17ae 4377 "%s [Error] Update packet error (prefix length mismatch with total length)",
4378 peer->host);
4379 return -1;
4380 }
6b0655a2 4381
d62a17ae 4382 return 0;
718e3744 4383}
4384
d62a17ae 4385static struct bgp_static *bgp_static_new(void)
718e3744 4386{
d62a17ae 4387 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4388}
4389
d62a17ae 4390static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4391{
d62a17ae 4392 if (bgp_static->rmap.name)
4393 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4394 if (bgp_static->eth_s_id)
4395 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
4396 XFREE(MTYPE_BGP_STATIC, bgp_static);
4397}
4398
4399void bgp_static_update(struct bgp *bgp, struct prefix *p,
4400 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4401{
4402 struct bgp_node *rn;
40381db7 4403 struct bgp_path_info *pi;
4b7e6066 4404 struct bgp_path_info *new;
40381db7 4405 struct bgp_path_info rmap_path;
d62a17ae 4406 struct attr attr;
4407 struct attr *attr_new;
4408 int ret;
65efcfce 4409#if ENABLE_BGP_VNC
d62a17ae 4410 int vnc_implicit_withdraw = 0;
65efcfce 4411#endif
fee0f4c6 4412
d62a17ae 4413 assert(bgp_static);
4414 if (!bgp_static)
4415 return;
dd8103a9 4416
d62a17ae 4417 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4418
d62a17ae 4419 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4420
d62a17ae 4421 attr.nexthop = bgp_static->igpnexthop;
4422 attr.med = bgp_static->igpmetric;
4423 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4424
d62a17ae 4425 if (bgp_static->atomic)
4426 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4427
d62a17ae 4428 /* Store label index, if required. */
4429 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4430 attr.label_index = bgp_static->label_index;
4431 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4432 }
718e3744 4433
d62a17ae 4434 /* Apply route-map. */
4435 if (bgp_static->rmap.name) {
4436 struct attr attr_tmp = attr;
80ced710 4437
40381db7
DS
4438 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4439 rmap_path.peer = bgp->peer_self;
4440 rmap_path.attr = &attr_tmp;
fee0f4c6 4441
d62a17ae 4442 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4443
40381db7
DS
4444 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4445 &rmap_path);
fee0f4c6 4446
d62a17ae 4447 bgp->peer_self->rmap_type = 0;
718e3744 4448
d62a17ae 4449 if (ret == RMAP_DENYMATCH) {
4450 /* Free uninterned attribute. */
4451 bgp_attr_flush(&attr_tmp);
718e3744 4452
d62a17ae 4453 /* Unintern original. */
4454 aspath_unintern(&attr.aspath);
4455 bgp_static_withdraw(bgp, p, afi, safi);
4456 return;
4457 }
7f323236
DW
4458
4459 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4460 bgp_attr_add_gshut_community(&attr_tmp);
4461
d62a17ae 4462 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4463 } else {
4464
4465 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4466 bgp_attr_add_gshut_community(&attr);
4467
d62a17ae 4468 attr_new = bgp_attr_intern(&attr);
7f323236 4469 }
718e3744 4470
6f94b685 4471 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4472 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4473 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4474 break;
4475
40381db7
DS
4476 if (pi) {
4477 if (attrhash_cmp(pi->attr, attr_new)
4478 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4479 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4480 bgp_unlock_node(rn);
4481 bgp_attr_unintern(&attr_new);
4482 aspath_unintern(&attr.aspath);
4483 return;
4484 } else {
4485 /* The attribute is changed. */
40381db7 4486 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4487
4488 /* Rewrite BGP route information. */
40381db7
DS
4489 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4490 bgp_path_info_restore(rn, pi);
d62a17ae 4491 else
40381db7 4492 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4493#if ENABLE_BGP_VNC
d62a17ae 4494 if ((afi == AFI_IP || afi == AFI_IP6)
4495 && (safi == SAFI_UNICAST)) {
40381db7 4496 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4497 /*
4498 * Implicit withdraw case.
40381db7 4499 * We have to do this before pi is
d62a17ae 4500 * changed
4501 */
4502 ++vnc_implicit_withdraw;
40381db7 4503 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4504 vnc_import_bgp_exterior_del_route(
40381db7 4505 bgp, p, pi);
d62a17ae 4506 }
4507 }
65efcfce 4508#endif
40381db7
DS
4509 bgp_attr_unintern(&pi->attr);
4510 pi->attr = attr_new;
4511 pi->uptime = bgp_clock();
65efcfce 4512#if ENABLE_BGP_VNC
d62a17ae 4513 if ((afi == AFI_IP || afi == AFI_IP6)
4514 && (safi == SAFI_UNICAST)) {
4515 if (vnc_implicit_withdraw) {
40381db7 4516 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4517 vnc_import_bgp_exterior_add_route(
40381db7 4518 bgp, p, pi);
d62a17ae 4519 }
4520 }
65efcfce 4521#endif
718e3744 4522
d62a17ae 4523 /* Nexthop reachability check. */
4524 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4525 && (safi == SAFI_UNICAST
4526 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4527
4528 struct bgp *bgp_nexthop = bgp;
4529
40381db7
DS
4530 if (pi->extra && pi->extra->bgp_orig)
4531 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4532
4533 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4534 afi, pi, NULL, 0))
4535 bgp_path_info_set_flag(rn, pi,
18ee8310 4536 BGP_PATH_VALID);
d62a17ae 4537 else {
4538 if (BGP_DEBUG(nht, NHT)) {
4539 char buf1[INET6_ADDRSTRLEN];
4540 inet_ntop(p->family,
4541 &p->u.prefix, buf1,
4542 INET6_ADDRSTRLEN);
4543 zlog_debug(
4544 "%s(%s): Route not in table, not advertising",
4545 __FUNCTION__, buf1);
4546 }
18ee8310 4547 bgp_path_info_unset_flag(
40381db7 4548 rn, pi, BGP_PATH_VALID);
d62a17ae 4549 }
4550 } else {
4551 /* Delete the NHT structure if any, if we're
4552 * toggling between
4553 * enabling/disabling import check. We
4554 * deregister the route
4555 * from NHT to avoid overloading NHT and the
4556 * process interaction
4557 */
40381db7
DS
4558 bgp_unlink_nexthop(pi);
4559 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4560 }
4561 /* Process change. */
40381db7 4562 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4563 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4564
4565 if (SAFI_UNICAST == safi
4566 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4567 || bgp->inst_type
4568 == BGP_INSTANCE_TYPE_DEFAULT)) {
4569 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4570 pi);
ddb5b488
PZ
4571 }
4572
d62a17ae 4573 bgp_unlock_node(rn);
4574 aspath_unintern(&attr.aspath);
4575 return;
4576 }
718e3744 4577 }
718e3744 4578
d62a17ae 4579 /* Make new BGP info. */
4580 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4581 attr_new, rn);
4582 /* Nexthop reachability check. */
4583 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4584 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4585 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4586 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4587 else {
4588 if (BGP_DEBUG(nht, NHT)) {
4589 char buf1[INET6_ADDRSTRLEN];
4590 inet_ntop(p->family, &p->u.prefix, buf1,
4591 INET6_ADDRSTRLEN);
4592 zlog_debug(
4593 "%s(%s): Route not in table, not advertising",
4594 __FUNCTION__, buf1);
4595 }
18ee8310 4596 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4597 }
4598 } else {
4599 /* Delete the NHT structure if any, if we're toggling between
4600 * enabling/disabling import check. We deregister the route
4601 * from NHT to avoid overloading NHT and the process interaction
4602 */
4603 bgp_unlink_nexthop(new);
4604
18ee8310 4605 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4606 }
078430f6 4607
d62a17ae 4608 /* Aggregate address increment. */
4609 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4610
d62a17ae 4611 /* Register new BGP information. */
18ee8310 4612 bgp_path_info_add(rn, new);
718e3744 4613
d62a17ae 4614 /* route_node_get lock */
4615 bgp_unlock_node(rn);
4616
4617 /* Process change. */
4618 bgp_process(bgp, rn, afi, safi);
4619
ddb5b488
PZ
4620 if (SAFI_UNICAST == safi
4621 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4622 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4623 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4624 }
4625
d62a17ae 4626 /* Unintern original. */
4627 aspath_unintern(&attr.aspath);
718e3744 4628}
4629
d62a17ae 4630void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4631 safi_t safi)
718e3744 4632{
d62a17ae 4633 struct bgp_node *rn;
40381db7 4634 struct bgp_path_info *pi;
718e3744 4635
d62a17ae 4636 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4637
d62a17ae 4638 /* Check selected route and self inserted route. */
6f94b685 4639 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4640 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4641 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4642 break;
4643
4644 /* Withdraw static BGP route from routing table. */
40381db7 4645 if (pi) {
ddb5b488
PZ
4646 if (SAFI_UNICAST == safi
4647 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4648 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4649 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4650 }
40381db7
DS
4651 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4652 bgp_unlink_nexthop(pi);
4653 bgp_path_info_delete(rn, pi);
d62a17ae 4654 bgp_process(bgp, rn, afi, safi);
4655 }
718e3744 4656
d62a17ae 4657 /* Unlock bgp_node_lookup. */
4658 bgp_unlock_node(rn);
718e3744 4659}
4660
137446f9
LB
4661/*
4662 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4663 */
d62a17ae 4664static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4665 afi_t afi, safi_t safi,
4666 struct prefix_rd *prd)
718e3744 4667{
d62a17ae 4668 struct bgp_node *rn;
40381db7 4669 struct bgp_path_info *pi;
718e3744 4670
d62a17ae 4671 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4672
d62a17ae 4673 /* Check selected route and self inserted route. */
6f94b685 4674 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4675 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4676 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4677 break;
718e3744 4678
d62a17ae 4679 /* Withdraw static BGP route from routing table. */
40381db7 4680 if (pi) {
65efcfce 4681#if ENABLE_BGP_VNC
d62a17ae 4682 rfapiProcessWithdraw(
40381db7 4683 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4684 1); /* Kill, since it is an administrative change */
65efcfce 4685#endif
ddb5b488
PZ
4686 if (SAFI_MPLS_VPN == safi
4687 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4688 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4689 }
40381db7
DS
4690 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4691 bgp_path_info_delete(rn, pi);
d62a17ae 4692 bgp_process(bgp, rn, afi, safi);
4693 }
718e3744 4694
d62a17ae 4695 /* Unlock bgp_node_lookup. */
4696 bgp_unlock_node(rn);
718e3744 4697}
4698
d62a17ae 4699static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4700 struct bgp_static *bgp_static, afi_t afi,
4701 safi_t safi)
137446f9 4702{
d62a17ae 4703 struct bgp_node *rn;
4b7e6066 4704 struct bgp_path_info *new;
d62a17ae 4705 struct attr *attr_new;
4706 struct attr attr = {0};
40381db7 4707 struct bgp_path_info *pi;
65efcfce 4708#if ENABLE_BGP_VNC
d62a17ae 4709 mpls_label_t label = 0;
65efcfce 4710#endif
d7c0a89a 4711 uint32_t num_labels = 0;
d62a17ae 4712 union gw_addr add;
137446f9 4713
d62a17ae 4714 assert(bgp_static);
137446f9 4715
b57ba6d2
MK
4716 if (bgp_static->label != MPLS_INVALID_LABEL)
4717 num_labels = 1;
d62a17ae 4718 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4719 &bgp_static->prd);
137446f9 4720
d62a17ae 4721 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4722
d62a17ae 4723 attr.nexthop = bgp_static->igpnexthop;
4724 attr.med = bgp_static->igpmetric;
4725 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4726
d62a17ae 4727 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4728 || (safi == SAFI_ENCAP)) {
4729 if (afi == AFI_IP) {
4730 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4731 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4732 }
4733 }
4734 if (afi == AFI_L2VPN) {
4735 if (bgp_static->gatewayIp.family == AF_INET)
4736 add.ipv4.s_addr =
4737 bgp_static->gatewayIp.u.prefix4.s_addr;
4738 else if (bgp_static->gatewayIp.family == AF_INET6)
4739 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4740 sizeof(struct in6_addr));
4741 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4742 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4743 struct bgp_encap_type_vxlan bet;
4744 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4745 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4746 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4747 }
4748 if (bgp_static->router_mac) {
4749 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4750 }
4751 }
4752 /* Apply route-map. */
4753 if (bgp_static->rmap.name) {
4754 struct attr attr_tmp = attr;
40381db7 4755 struct bgp_path_info rmap_path;
d62a17ae 4756 int ret;
137446f9 4757
40381db7
DS
4758 rmap_path.peer = bgp->peer_self;
4759 rmap_path.attr = &attr_tmp;
137446f9 4760
d62a17ae 4761 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4762
40381db7
DS
4763 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4764 &rmap_path);
137446f9 4765
d62a17ae 4766 bgp->peer_self->rmap_type = 0;
137446f9 4767
d62a17ae 4768 if (ret == RMAP_DENYMATCH) {
4769 /* Free uninterned attribute. */
4770 bgp_attr_flush(&attr_tmp);
137446f9 4771
d62a17ae 4772 /* Unintern original. */
4773 aspath_unintern(&attr.aspath);
4774 bgp_static_withdraw_safi(bgp, p, afi, safi,
4775 &bgp_static->prd);
4776 return;
4777 }
137446f9 4778
d62a17ae 4779 attr_new = bgp_attr_intern(&attr_tmp);
4780 } else {
4781 attr_new = bgp_attr_intern(&attr);
4782 }
137446f9 4783
6f94b685 4784 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4785 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4786 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4787 break;
4788
40381db7 4789 if (pi) {
d62a17ae 4790 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
4791 if (attrhash_cmp(pi->attr, attr_new)
4792 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
4793 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4794 bgp_unlock_node(rn);
4795 bgp_attr_unintern(&attr_new);
4796 aspath_unintern(&attr.aspath);
4797 return;
4798 } else {
4799 /* The attribute is changed. */
40381db7 4800 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4801
4802 /* Rewrite BGP route information. */
40381db7
DS
4803 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4804 bgp_path_info_restore(rn, pi);
d62a17ae 4805 else
40381db7
DS
4806 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4807 bgp_attr_unintern(&pi->attr);
4808 pi->attr = attr_new;
4809 pi->uptime = bgp_clock();
65efcfce 4810#if ENABLE_BGP_VNC
40381db7
DS
4811 if (pi->extra)
4812 label = decode_label(&pi->extra->label[0]);
65efcfce 4813#endif
137446f9 4814
d62a17ae 4815 /* Process change. */
40381db7 4816 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4817 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4818
4819 if (SAFI_MPLS_VPN == safi
4820 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4821 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 4822 }
65efcfce 4823#if ENABLE_BGP_VNC
40381db7
DS
4824 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
4825 pi->attr, afi, safi, pi->type,
4826 pi->sub_type, &label);
65efcfce 4827#endif
d62a17ae 4828 bgp_unlock_node(rn);
4829 aspath_unintern(&attr.aspath);
4830 return;
4831 }
4832 }
137446f9
LB
4833
4834
d62a17ae 4835 /* Make new BGP info. */
4836 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4837 attr_new, rn);
1defdda8 4838 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 4839 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
4840 if (num_labels) {
4841 new->extra->label[0] = bgp_static->label;
4842 new->extra->num_labels = num_labels;
4843 }
65efcfce 4844#if ENABLE_BGP_VNC
d62a17ae 4845 label = decode_label(&bgp_static->label);
65efcfce 4846#endif
137446f9 4847
d62a17ae 4848 /* Aggregate address increment. */
4849 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 4850
d62a17ae 4851 /* Register new BGP information. */
18ee8310 4852 bgp_path_info_add(rn, new);
d62a17ae 4853 /* route_node_get lock */
4854 bgp_unlock_node(rn);
137446f9 4855
d62a17ae 4856 /* Process change. */
4857 bgp_process(bgp, rn, afi, safi);
137446f9 4858
ddb5b488
PZ
4859 if (SAFI_MPLS_VPN == safi
4860 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4861 vpn_leak_to_vrf_update(bgp, new);
4862 }
65efcfce 4863#if ENABLE_BGP_VNC
d62a17ae 4864 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
4865 safi, new->type, new->sub_type, &label);
65efcfce
LB
4866#endif
4867
d62a17ae 4868 /* Unintern original. */
4869 aspath_unintern(&attr.aspath);
137446f9
LB
4870}
4871
718e3744 4872/* Configure static BGP network. When user don't run zebra, static
4873 route should be installed as valid. */
e2a86ad9
DS
4874static int bgp_static_set(struct vty *vty, const char *negate,
4875 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 4876 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 4877{
4878 VTY_DECLVAR_CONTEXT(bgp, bgp);
4879 int ret;
4880 struct prefix p;
4881 struct bgp_static *bgp_static;
4882 struct bgp_node *rn;
d7c0a89a 4883 uint8_t need_update = 0;
d62a17ae 4884
4885 /* Convert IP prefix string to struct prefix. */
4886 ret = str2prefix(ip_str, &p);
4887 if (!ret) {
4888 vty_out(vty, "%% Malformed prefix\n");
4889 return CMD_WARNING_CONFIG_FAILED;
4890 }
4891 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4892 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4893 return CMD_WARNING_CONFIG_FAILED;
4894 }
718e3744 4895
d62a17ae 4896 apply_mask(&p);
718e3744 4897
e2a86ad9 4898 if (negate) {
718e3744 4899
e2a86ad9
DS
4900 /* Set BGP static route configuration. */
4901 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 4902
e2a86ad9 4903 if (!rn) {
a4d82a8a 4904 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 4905 return CMD_WARNING_CONFIG_FAILED;
4906 }
4907
5a8ba9fc 4908 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 4909
e2a86ad9
DS
4910 if ((label_index != BGP_INVALID_LABEL_INDEX)
4911 && (label_index != bgp_static->label_index)) {
4912 vty_out(vty,
4913 "%% label-index doesn't match static route\n");
4914 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4915 }
d62a17ae 4916
e2a86ad9
DS
4917 if ((rmap && bgp_static->rmap.name)
4918 && strcmp(rmap, bgp_static->rmap.name)) {
4919 vty_out(vty,
4920 "%% route-map name doesn't match static route\n");
4921 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4922 }
718e3744 4923
e2a86ad9
DS
4924 /* Update BGP RIB. */
4925 if (!bgp_static->backdoor)
4926 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 4927
e2a86ad9
DS
4928 /* Clear configuration. */
4929 bgp_static_free(bgp_static);
5a8ba9fc 4930 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
4931 bgp_unlock_node(rn);
4932 bgp_unlock_node(rn);
4933 } else {
718e3744 4934
e2a86ad9
DS
4935 /* Set BGP static route configuration. */
4936 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 4937
5a8ba9fc 4938 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 4939 if (bgp_static) {
e2a86ad9 4940 /* Configuration change. */
e2a86ad9
DS
4941 /* Label index cannot be changed. */
4942 if (bgp_static->label_index != label_index) {
4943 vty_out(vty, "%% cannot change label-index\n");
4944 return CMD_WARNING_CONFIG_FAILED;
4945 }
d62a17ae 4946
e2a86ad9 4947 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
4948 if (bgp_static->valid
4949 && bgp_static->backdoor != backdoor)
e2a86ad9 4950 need_update = 1;
718e3744 4951
e2a86ad9 4952 bgp_static->backdoor = backdoor;
718e3744 4953
e2a86ad9
DS
4954 if (rmap) {
4955 if (bgp_static->rmap.name)
4956 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4957 bgp_static->rmap.name);
e2a86ad9
DS
4958 bgp_static->rmap.name =
4959 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4960 bgp_static->rmap.map =
4961 route_map_lookup_by_name(rmap);
4962 } else {
4963 if (bgp_static->rmap.name)
4964 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4965 bgp_static->rmap.name);
e2a86ad9
DS
4966 bgp_static->rmap.name = NULL;
4967 bgp_static->rmap.map = NULL;
4968 bgp_static->valid = 0;
4969 }
4970 bgp_unlock_node(rn);
4971 } else {
4972 /* New configuration. */
4973 bgp_static = bgp_static_new();
4974 bgp_static->backdoor = backdoor;
4975 bgp_static->valid = 0;
4976 bgp_static->igpmetric = 0;
4977 bgp_static->igpnexthop.s_addr = 0;
4978 bgp_static->label_index = label_index;
718e3744 4979
e2a86ad9
DS
4980 if (rmap) {
4981 if (bgp_static->rmap.name)
4982 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4983 bgp_static->rmap.name);
e2a86ad9
DS
4984 bgp_static->rmap.name =
4985 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4986 bgp_static->rmap.map =
4987 route_map_lookup_by_name(rmap);
4988 }
5a8ba9fc 4989 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 4990 }
d62a17ae 4991
e2a86ad9
DS
4992 bgp_static->valid = 1;
4993 if (need_update)
4994 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 4995
e2a86ad9
DS
4996 if (!bgp_static->backdoor)
4997 bgp_static_update(bgp, &p, bgp_static, afi, safi);
4998 }
d62a17ae 4999
5000 return CMD_SUCCESS;
5001}
5002
5003void bgp_static_add(struct bgp *bgp)
5004{
5005 afi_t afi;
5006 safi_t safi;
5007 struct bgp_node *rn;
5008 struct bgp_node *rm;
5009 struct bgp_table *table;
5010 struct bgp_static *bgp_static;
5011
05c7a1cc
QY
5012 FOREACH_AFI_SAFI (afi, safi)
5013 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5014 rn = bgp_route_next(rn)) {
67009e22 5015 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5016 continue;
ea47320b 5017
05c7a1cc
QY
5018 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5019 || (safi == SAFI_EVPN)) {
67009e22 5020 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5021
5022 for (rm = bgp_table_top(table); rm;
5023 rm = bgp_route_next(rm)) {
a78beeb5 5024 bgp_static =
5a8ba9fc
DS
5025 bgp_node_get_bgp_static_info(
5026 rm);
05c7a1cc
QY
5027 bgp_static_update_safi(bgp, &rm->p,
5028 bgp_static, afi,
5029 safi);
d62a17ae 5030 }
05c7a1cc 5031 } else {
5a8ba9fc
DS
5032 bgp_static_update(
5033 bgp, &rn->p,
5034 bgp_node_get_bgp_static_info(rn), afi,
5035 safi);
ea47320b 5036 }
05c7a1cc 5037 }
6aeb9e78
DS
5038}
5039
718e3744 5040/* Called from bgp_delete(). Delete all static routes from the BGP
5041 instance. */
d62a17ae 5042void bgp_static_delete(struct bgp *bgp)
5043{
5044 afi_t afi;
5045 safi_t safi;
5046 struct bgp_node *rn;
5047 struct bgp_node *rm;
5048 struct bgp_table *table;
5049 struct bgp_static *bgp_static;
5050
05c7a1cc
QY
5051 FOREACH_AFI_SAFI (afi, safi)
5052 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5053 rn = bgp_route_next(rn)) {
67009e22 5054 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5055 continue;
ea47320b 5056
05c7a1cc
QY
5057 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5058 || (safi == SAFI_EVPN)) {
67009e22 5059 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5060
5061 for (rm = bgp_table_top(table); rm;
5062 rm = bgp_route_next(rm)) {
a78beeb5 5063 bgp_static =
5a8ba9fc
DS
5064 bgp_node_get_bgp_static_info(
5065 rm);
05c7a1cc
QY
5066 bgp_static_withdraw_safi(
5067 bgp, &rm->p, AFI_IP, safi,
5068 (struct prefix_rd *)&rn->p);
ea47320b 5069 bgp_static_free(bgp_static);
5a8ba9fc 5070 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5071 bgp_unlock_node(rn);
d62a17ae 5072 }
05c7a1cc 5073 } else {
5a8ba9fc 5074 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5075 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5076 bgp_static_free(bgp_static);
5a8ba9fc 5077 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5078 bgp_unlock_node(rn);
ea47320b 5079 }
05c7a1cc 5080 }
d62a17ae 5081}
5082
5083void bgp_static_redo_import_check(struct bgp *bgp)
5084{
5085 afi_t afi;
5086 safi_t safi;
5087 struct bgp_node *rn;
5088 struct bgp_node *rm;
5089 struct bgp_table *table;
5090 struct bgp_static *bgp_static;
5091
5092 /* Use this flag to force reprocessing of the route */
5093 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5094 FOREACH_AFI_SAFI (afi, safi) {
5095 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5096 rn = bgp_route_next(rn)) {
67009e22 5097 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5098 continue;
ea47320b 5099
05c7a1cc
QY
5100 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5101 || (safi == SAFI_EVPN)) {
67009e22 5102 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5103
5104 for (rm = bgp_table_top(table); rm;
5105 rm = bgp_route_next(rm)) {
a78beeb5 5106 bgp_static =
5a8ba9fc
DS
5107 bgp_node_get_bgp_static_info(
5108 rm);
05c7a1cc
QY
5109 bgp_static_update_safi(bgp, &rm->p,
5110 bgp_static, afi,
5111 safi);
d62a17ae 5112 }
05c7a1cc 5113 } else {
5a8ba9fc 5114 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5115 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5116 safi);
ea47320b 5117 }
05c7a1cc
QY
5118 }
5119 }
d62a17ae 5120 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5121}
5122
5123static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5124 safi_t safi)
5125{
5126 struct bgp_table *table;
5127 struct bgp_node *rn;
40381db7 5128 struct bgp_path_info *pi;
d62a17ae 5129
5130 table = bgp->rib[afi][safi];
5131 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5132 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5133 if (pi->peer == bgp->peer_self
5134 && ((pi->type == ZEBRA_ROUTE_BGP
5135 && pi->sub_type == BGP_ROUTE_STATIC)
5136 || (pi->type != ZEBRA_ROUTE_BGP
5137 && pi->sub_type
d62a17ae 5138 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5139 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5140 safi);
40381db7
DS
5141 bgp_unlink_nexthop(pi);
5142 bgp_path_info_delete(rn, pi);
d62a17ae 5143 bgp_process(bgp, rn, afi, safi);
5144 }
5145 }
5146 }
ad4cbda1 5147}
5148
5149/*
5150 * Purge all networks and redistributed routes from routing table.
5151 * Invoked upon the instance going down.
5152 */
d62a17ae 5153void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5154{
d62a17ae 5155 afi_t afi;
5156 safi_t safi;
ad4cbda1 5157
05c7a1cc
QY
5158 FOREACH_AFI_SAFI (afi, safi)
5159 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5160}
5161
137446f9
LB
5162/*
5163 * gpz 110624
5164 * Currently this is used to set static routes for VPN and ENCAP.
5165 * I think it can probably be factored with bgp_static_set.
5166 */
d62a17ae 5167int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5168 const char *ip_str, const char *rd_str,
5169 const char *label_str, const char *rmap_str,
5170 int evpn_type, const char *esi, const char *gwip,
5171 const char *ethtag, const char *routermac)
5172{
5173 VTY_DECLVAR_CONTEXT(bgp, bgp);
5174 int ret;
5175 struct prefix p;
5176 struct prefix_rd prd;
5177 struct bgp_node *prn;
5178 struct bgp_node *rn;
5179 struct bgp_table *table;
5180 struct bgp_static *bgp_static;
5181 mpls_label_t label = MPLS_INVALID_LABEL;
5182 struct prefix gw_ip;
5183
5184 /* validate ip prefix */
5185 ret = str2prefix(ip_str, &p);
5186 if (!ret) {
5187 vty_out(vty, "%% Malformed prefix\n");
5188 return CMD_WARNING_CONFIG_FAILED;
5189 }
5190 apply_mask(&p);
5191 if ((afi == AFI_L2VPN)
5192 && (bgp_build_evpn_prefix(evpn_type,
5193 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5194 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5195 return CMD_WARNING_CONFIG_FAILED;
5196 }
718e3744 5197
d62a17ae 5198 ret = str2prefix_rd(rd_str, &prd);
5199 if (!ret) {
5200 vty_out(vty, "%% Malformed rd\n");
5201 return CMD_WARNING_CONFIG_FAILED;
5202 }
718e3744 5203
d62a17ae 5204 if (label_str) {
5205 unsigned long label_val;
5206 label_val = strtoul(label_str, NULL, 10);
5207 encode_label(label_val, &label);
5208 }
9bedbb1e 5209
d62a17ae 5210 if (safi == SAFI_EVPN) {
5211 if (esi && str2esi(esi, NULL) == 0) {
5212 vty_out(vty, "%% Malformed ESI\n");
5213 return CMD_WARNING_CONFIG_FAILED;
5214 }
5215 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5216 vty_out(vty, "%% Malformed Router MAC\n");
5217 return CMD_WARNING_CONFIG_FAILED;
5218 }
5219 if (gwip) {
5220 memset(&gw_ip, 0, sizeof(struct prefix));
5221 ret = str2prefix(gwip, &gw_ip);
5222 if (!ret) {
5223 vty_out(vty, "%% Malformed GatewayIp\n");
5224 return CMD_WARNING_CONFIG_FAILED;
5225 }
5226 if ((gw_ip.family == AF_INET
3714a385 5227 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5228 (struct prefix_evpn *)&p))
5229 || (gw_ip.family == AF_INET6
3714a385 5230 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5231 (struct prefix_evpn *)&p))) {
5232 vty_out(vty,
5233 "%% GatewayIp family differs with IP prefix\n");
5234 return CMD_WARNING_CONFIG_FAILED;
5235 }
5236 }
5237 }
5238 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5239 if (!bgp_node_has_bgp_path_info_data(prn))
5240 bgp_node_set_bgp_table_info(prn,
5241 bgp_table_init(bgp, afi, safi));
d62a17ae 5242 else
5243 bgp_unlock_node(prn);
67009e22 5244 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5245
5246 rn = bgp_node_get(table, &p);
5247
67009e22 5248 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5249 vty_out(vty, "%% Same network configuration exists\n");
5250 bgp_unlock_node(rn);
5251 } else {
5252 /* New configuration. */
5253 bgp_static = bgp_static_new();
5254 bgp_static->backdoor = 0;
5255 bgp_static->valid = 0;
5256 bgp_static->igpmetric = 0;
5257 bgp_static->igpnexthop.s_addr = 0;
5258 bgp_static->label = label;
5259 bgp_static->prd = prd;
5260
5261 if (rmap_str) {
5262 if (bgp_static->rmap.name)
5263 XFREE(MTYPE_ROUTE_MAP_NAME,
5264 bgp_static->rmap.name);
5265 bgp_static->rmap.name =
5266 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5267 bgp_static->rmap.map =
5268 route_map_lookup_by_name(rmap_str);
5269 }
718e3744 5270
d62a17ae 5271 if (safi == SAFI_EVPN) {
5272 if (esi) {
5273 bgp_static->eth_s_id =
5274 XCALLOC(MTYPE_ATTR,
5275 sizeof(struct eth_segment_id));
5276 str2esi(esi, bgp_static->eth_s_id);
5277 }
5278 if (routermac) {
5279 bgp_static->router_mac =
28328ea9 5280 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5281 (void)prefix_str2mac(routermac,
5282 bgp_static->router_mac);
d62a17ae 5283 }
5284 if (gwip)
5285 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5286 }
5a8ba9fc 5287 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5288
d62a17ae 5289 bgp_static->valid = 1;
5290 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5291 }
718e3744 5292
d62a17ae 5293 return CMD_SUCCESS;
718e3744 5294}
5295
5296/* Configure static BGP network. */
d62a17ae 5297int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5298 const char *ip_str, const char *rd_str,
5299 const char *label_str, int evpn_type, const char *esi,
5300 const char *gwip, const char *ethtag)
5301{
5302 VTY_DECLVAR_CONTEXT(bgp, bgp);
5303 int ret;
5304 struct prefix p;
5305 struct prefix_rd prd;
5306 struct bgp_node *prn;
5307 struct bgp_node *rn;
5308 struct bgp_table *table;
5309 struct bgp_static *bgp_static;
5310 mpls_label_t label = MPLS_INVALID_LABEL;
5311
5312 /* Convert IP prefix string to struct prefix. */
5313 ret = str2prefix(ip_str, &p);
5314 if (!ret) {
5315 vty_out(vty, "%% Malformed prefix\n");
5316 return CMD_WARNING_CONFIG_FAILED;
5317 }
5318 apply_mask(&p);
5319 if ((afi == AFI_L2VPN)
5320 && (bgp_build_evpn_prefix(evpn_type,
5321 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5322 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5323 return CMD_WARNING_CONFIG_FAILED;
5324 }
5325 ret = str2prefix_rd(rd_str, &prd);
5326 if (!ret) {
5327 vty_out(vty, "%% Malformed rd\n");
5328 return CMD_WARNING_CONFIG_FAILED;
5329 }
718e3744 5330
d62a17ae 5331 if (label_str) {
5332 unsigned long label_val;
5333 label_val = strtoul(label_str, NULL, 10);
5334 encode_label(label_val, &label);
5335 }
718e3744 5336
d62a17ae 5337 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5338 if (!bgp_node_has_bgp_path_info_data(prn))
5339 bgp_node_set_bgp_table_info(prn,
5340 bgp_table_init(bgp, afi, safi));
d62a17ae 5341 else
5342 bgp_unlock_node(prn);
67009e22 5343 table = bgp_node_get_bgp_table_info(prn);
718e3744 5344
d62a17ae 5345 rn = bgp_node_lookup(table, &p);
6b0655a2 5346
d62a17ae 5347 if (rn) {
5348 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5349
5a8ba9fc 5350 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5351 bgp_static_free(bgp_static);
5a8ba9fc 5352 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5353 bgp_unlock_node(rn);
5354 bgp_unlock_node(rn);
5355 } else
5356 vty_out(vty, "%% Can't find the route\n");
5357
5358 return CMD_SUCCESS;
5359}
5360
5361static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5362 const char *rmap_name)
5363{
5364 VTY_DECLVAR_CONTEXT(bgp, bgp);
5365 struct bgp_rmap *rmap;
5366
5367 rmap = &bgp->table_map[afi][safi];
5368 if (rmap_name) {
5369 if (rmap->name)
5370 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5371 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5372 rmap->map = route_map_lookup_by_name(rmap_name);
5373 } else {
5374 if (rmap->name)
5375 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5376 rmap->name = NULL;
5377 rmap->map = NULL;
5378 }
73ac8160 5379
d62a17ae 5380 if (bgp_fibupd_safi(safi))
5381 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5382
d62a17ae 5383 return CMD_SUCCESS;
73ac8160
DS
5384}
5385
d62a17ae 5386static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5387 const char *rmap_name)
73ac8160 5388{
d62a17ae 5389 VTY_DECLVAR_CONTEXT(bgp, bgp);
5390 struct bgp_rmap *rmap;
73ac8160 5391
d62a17ae 5392 rmap = &bgp->table_map[afi][safi];
5393 if (rmap->name)
5394 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5395 rmap->name = NULL;
5396 rmap->map = NULL;
73ac8160 5397
d62a17ae 5398 if (bgp_fibupd_safi(safi))
5399 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5400
d62a17ae 5401 return CMD_SUCCESS;
73ac8160
DS
5402}
5403
2b791107 5404void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5405 safi_t safi)
73ac8160 5406{
d62a17ae 5407 if (bgp->table_map[afi][safi].name) {
d62a17ae 5408 vty_out(vty, " table-map %s\n",
5409 bgp->table_map[afi][safi].name);
5410 }
73ac8160
DS
5411}
5412
73ac8160
DS
5413DEFUN (bgp_table_map,
5414 bgp_table_map_cmd,
5415 "table-map WORD",
5416 "BGP table to RIB route download filter\n"
5417 "Name of the route map\n")
5418{
d62a17ae 5419 int idx_word = 1;
5420 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5421 argv[idx_word]->arg);
73ac8160
DS
5422}
5423DEFUN (no_bgp_table_map,
5424 no_bgp_table_map_cmd,
5425 "no table-map WORD",
3a2d747c 5426 NO_STR
73ac8160
DS
5427 "BGP table to RIB route download filter\n"
5428 "Name of the route map\n")
5429{
d62a17ae 5430 int idx_word = 2;
5431 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5432 argv[idx_word]->arg);
73ac8160
DS
5433}
5434
e2a86ad9
DS
5435DEFPY(bgp_network,
5436 bgp_network_cmd,
5437 "[no] network \
5438 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5439 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5440 backdoor$backdoor}]",
5441 NO_STR
5442 "Specify a network to announce via BGP\n"
5443 "IPv4 prefix\n"
5444 "Network number\n"
5445 "Network mask\n"
5446 "Network mask\n"
5447 "Route-map to modify the attributes\n"
5448 "Name of the route map\n"
5449 "Label index to associate with the prefix\n"
5450 "Label index value\n"
5451 "Specify a BGP backdoor route\n")
5452{
5453 char addr_prefix_str[BUFSIZ];
5454
5455 if (address_str) {
5456 int ret;
718e3744 5457
e2a86ad9
DS
5458 ret = netmask_str2prefix_str(address_str, netmask_str,
5459 addr_prefix_str);
5460 if (!ret) {
5461 vty_out(vty, "%% Inconsistent address and mask\n");
5462 return CMD_WARNING_CONFIG_FAILED;
5463 }
d62a17ae 5464 }
718e3744 5465
a4d82a8a
PZ
5466 return bgp_static_set(
5467 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5468 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5469 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5470}
5471
e2a86ad9
DS
5472DEFPY(ipv6_bgp_network,
5473 ipv6_bgp_network_cmd,
5474 "[no] network X:X::X:X/M$prefix \
5475 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5476 NO_STR
5477 "Specify a network to announce via BGP\n"
5478 "IPv6 prefix\n"
5479 "Route-map to modify the attributes\n"
5480 "Name of the route map\n"
5481 "Label index to associate with the prefix\n"
5482 "Label index value\n")
718e3744 5483{
a4d82a8a
PZ
5484 return bgp_static_set(
5485 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5486 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5487}
5488
718e3744 5489/* Aggreagete address:
5490
5491 advertise-map Set condition to advertise attribute
5492 as-set Generate AS set path information
5493 attribute-map Set attributes of aggregate
5494 route-map Set parameters of aggregate
5495 summary-only Filter more specific routes from updates
5496 suppress-map Conditionally filter more specific routes from updates
5497 <cr>
5498 */
d62a17ae 5499struct bgp_aggregate {
5500 /* Summary-only flag. */
d7c0a89a 5501 uint8_t summary_only;
718e3744 5502
d62a17ae 5503 /* AS set generation. */
d7c0a89a 5504 uint8_t as_set;
718e3744 5505
d62a17ae 5506 /* Route-map for aggregated route. */
5507 struct route_map *map;
718e3744 5508
d62a17ae 5509 /* Suppress-count. */
5510 unsigned long count;
718e3744 5511
d62a17ae 5512 /* SAFI configuration. */
5513 safi_t safi;
718e3744 5514};
5515
d62a17ae 5516static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5517{
d62a17ae 5518 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5519}
5520
d62a17ae 5521static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5522{
d62a17ae 5523 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5524}
718e3744 5525
40381db7 5526static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5527 struct aspath *aspath,
3da2cc32 5528 struct community *comm,
dd18c5a9
DS
5529 struct ecommunity *ecomm,
5530 struct lcommunity *lcomm)
eaaf8adb
DS
5531{
5532 static struct aspath *ae = NULL;
5533
5534 if (!ae)
5535 ae = aspath_empty();
5536
40381db7 5537 if (!pi)
eaaf8adb
DS
5538 return 0;
5539
40381db7 5540 if (origin != pi->attr->origin)
eaaf8adb
DS
5541 return 0;
5542
40381db7 5543 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5544 return 0;
5545
40381db7 5546 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5547 return 0;
5548
3da2cc32 5549 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5550 return 0;
5551
dd18c5a9
DS
5552 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5553 return 0;
5554
40381db7 5555 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5556 return 0;
5557
eaaf8adb
DS
5558 return 1;
5559}
5560
c701010e
DS
5561static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5562 struct prefix *p, uint8_t origin,
5563 struct aspath *aspath,
5564 struct community *community,
3da2cc32 5565 struct ecommunity *ecommunity,
dd18c5a9 5566 struct lcommunity *lcommunity,
c701010e
DS
5567 uint8_t atomic_aggregate,
5568 struct bgp_aggregate *aggregate)
5569{
5570 struct bgp_node *rn;
5571 struct bgp_table *table;
6f94b685 5572 struct bgp_path_info *pi, *orig, *new;
c701010e
DS
5573
5574 table = bgp->rib[afi][safi];
5575
5576 rn = bgp_node_get(table, p);
eaaf8adb 5577
6f94b685 5578 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5579 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5580 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5581 break;
5582
c701010e 5583 if (aggregate->count > 0) {
eaaf8adb
DS
5584 /*
5585 * If the aggregate information has not changed
5586 * no need to re-install it again.
5587 */
6f94b685 5588 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5589 ecommunity, lcommunity)) {
eaaf8adb
DS
5590 bgp_unlock_node(rn);
5591
5592 if (aspath)
5593 aspath_free(aspath);
5594 if (community)
3c1f53de 5595 community_free(&community);
3da2cc32
DS
5596 if (ecommunity)
5597 ecommunity_free(&ecommunity);
dd18c5a9
DS
5598 if (lcommunity)
5599 lcommunity_free(&lcommunity);
eaaf8adb
DS
5600
5601 return;
5602 }
5603
5604 /*
5605 * Mark the old as unusable
5606 */
40381db7
DS
5607 if (pi)
5608 bgp_path_info_delete(rn, pi);
eaaf8adb 5609
3da2cc32
DS
5610 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
5611 bgp->peer_self,
5612 bgp_attr_aggregate_intern(bgp, origin, aspath,
5613 community, ecommunity,
dd18c5a9 5614 lcommunity,
3da2cc32
DS
5615 aggregate->as_set,
5616 atomic_aggregate),
5617 rn);
1defdda8 5618 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5619
18ee8310 5620 bgp_path_info_add(rn, new);
c701010e
DS
5621 bgp_process(bgp, rn, afi, safi);
5622 } else {
6f94b685 5623 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5624 if (pi->peer == bgp->peer_self
5625 && pi->type == ZEBRA_ROUTE_BGP
5626 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5627 break;
5628
5629 /* Withdraw static BGP route from routing table. */
40381db7
DS
5630 if (pi) {
5631 bgp_path_info_delete(rn, pi);
c701010e
DS
5632 bgp_process(bgp, rn, afi, safi);
5633 }
5634 }
5635
5636 bgp_unlock_node(rn);
5637}
5638
b5d58c32 5639/* Update an aggregate as routes are added/removed from the BGP table */
d62a17ae 5640static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
40381db7 5641 struct bgp_path_info *pinew, afi_t afi,
4b7e6066 5642 safi_t safi, struct bgp_path_info *del,
d62a17ae 5643 struct bgp_aggregate *aggregate)
5644{
5645 struct bgp_table *table;
5646 struct bgp_node *top;
5647 struct bgp_node *rn;
d7c0a89a 5648 uint8_t origin;
d62a17ae 5649 struct aspath *aspath = NULL;
5650 struct aspath *asmerge = NULL;
5651 struct community *community = NULL;
5652 struct community *commerge = NULL;
3da2cc32
DS
5653 struct ecommunity *ecommunity = NULL;
5654 struct ecommunity *ecommerge = NULL;
dd18c5a9
DS
5655 struct lcommunity *lcommunity = NULL;
5656 struct lcommunity *lcommerge = NULL;
40381db7 5657 struct bgp_path_info *pi;
d62a17ae 5658 unsigned long match = 0;
d7c0a89a 5659 uint8_t atomic_aggregate = 0;
d62a17ae 5660
d62a17ae 5661 /* ORIGIN attribute: If at least one route among routes that are
5662 aggregated has ORIGIN with the value INCOMPLETE, then the
5663 aggregated route must have the ORIGIN attribute with the value
5664 INCOMPLETE. Otherwise, if at least one route among routes that
5665 are aggregated has ORIGIN with the value EGP, then the aggregated
5666 route must have the origin attribute with the value EGP. In all
5667 other case the value of the ORIGIN attribute of the aggregated
5668 route is INTERNAL. */
5669 origin = BGP_ORIGIN_IGP;
718e3744 5670
d62a17ae 5671 table = bgp->rib[afi][safi];
718e3744 5672
d62a17ae 5673 top = bgp_node_get(table, p);
5674 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5675 rn = bgp_route_next_until(rn, top)) {
5676 if (rn->p.prefixlen <= p->prefixlen)
5677 continue;
d62a17ae 5678
c2ff8b3e 5679 match = 0;
d62a17ae 5680
6f94b685 5681 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5682 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5683 continue;
718e3744 5684
40381db7 5685 if (del && pi == del)
c2ff8b3e 5686 continue;
718e3744 5687
40381db7 5688 if (pi->attr->flag
c2ff8b3e
DS
5689 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5690 atomic_aggregate = 1;
d62a17ae 5691
40381db7 5692 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5693 continue;
d62a17ae 5694
f273fef1
DS
5695 /*
5696 * summary-only aggregate route suppress
5697 * aggregated route announcements.
5698 */
c2ff8b3e 5699 if (aggregate->summary_only) {
40381db7
DS
5700 (bgp_path_info_extra_get(pi))->suppress++;
5701 bgp_path_info_set_flag(rn, pi,
18ee8310 5702 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5703 match++;
d62a17ae 5704 }
c2ff8b3e
DS
5705
5706 aggregate->count++;
5707
f273fef1
DS
5708 /*
5709 * If at least one route among routes that are
5710 * aggregated has ORIGIN with the value INCOMPLETE,
5711 * then the aggregated route MUST have the ORIGIN
5712 * attribute with the value INCOMPLETE. Otherwise, if
5713 * at least one route among routes that are aggregated
5714 * has ORIGIN with the value EGP, then the aggregated
5715 * route MUST have the ORIGIN attribute with the value
5716 * EGP.
5717 */
40381db7
DS
5718 if (origin < pi->attr->origin)
5719 origin = pi->attr->origin;
c2ff8b3e
DS
5720
5721 if (!aggregate->as_set)
5722 continue;
5723
f273fef1
DS
5724 /*
5725 * as-set aggregate route generate origin, as path,
5726 * and community aggregation.
5727 */
c2ff8b3e
DS
5728 if (aspath) {
5729 asmerge = aspath_aggregate(aspath,
40381db7 5730 pi->attr->aspath);
c2ff8b3e
DS
5731 aspath_free(aspath);
5732 aspath = asmerge;
5733 } else
40381db7 5734 aspath = aspath_dup(pi->attr->aspath);
c2ff8b3e 5735
3da2cc32
DS
5736 if (pi->attr->community) {
5737 if (community) {
5738 commerge = community_merge(
5739 community, pi->attr->community);
5740 community =
5741 community_uniq_sort(commerge);
3c1f53de 5742 community_free(&commerge);
3da2cc32
DS
5743 } else
5744 community = community_dup(
5745 pi->attr->community);
5746 }
c2ff8b3e 5747
3da2cc32
DS
5748 if (pi->attr->ecommunity) {
5749 if (ecommunity) {
5750 ecommerge = ecommunity_merge(
5751 ecommunity,
5752 pi->attr->ecommunity);
5753 ecommunity =
5754 ecommunity_uniq_sort(ecommerge);
5755 ecommunity_free(&ecommerge);
5756 } else
5757 ecommunity = ecommunity_dup(
5758 pi->attr->ecommunity);
5759 }
dd18c5a9
DS
5760
5761 if (pi->attr->lcommunity) {
5762 if (lcommunity) {
5763 lcommerge = lcommunity_merge(
5764 lcommunity,
5765 pi->attr->lcommunity);
5766 lcommunity =
5767 lcommunity_uniq_sort(lcommerge);
5768 lcommunity_free(&lcommerge);
5769 } else
5770 lcommunity = lcommunity_dup(
5771 pi->attr->lcommunity);
5772 }
d62a17ae 5773 }
c2ff8b3e
DS
5774 if (match)
5775 bgp_process(bgp, rn, afi, safi);
5776 }
d62a17ae 5777 bgp_unlock_node(top);
718e3744 5778
40381db7 5779 if (pinew) {
718e3744 5780 aggregate->count++;
5781
d62a17ae 5782 if (aggregate->summary_only)
40381db7 5783 (bgp_path_info_extra_get(pinew))->suppress++;
d62a17ae 5784
40381db7
DS
5785 if (origin < pinew->attr->origin)
5786 origin = pinew->attr->origin;
d62a17ae 5787
5788 if (aggregate->as_set) {
5789 if (aspath) {
5790 asmerge = aspath_aggregate(aspath,
40381db7 5791 pinew->attr->aspath);
d62a17ae 5792 aspath_free(aspath);
5793 aspath = asmerge;
5794 } else
40381db7 5795 aspath = aspath_dup(pinew->attr->aspath);
d62a17ae 5796
40381db7 5797 if (pinew->attr->community) {
d62a17ae 5798 if (community) {
5799 commerge = community_merge(
5800 community,
40381db7 5801 pinew->attr->community);
d62a17ae 5802 community =
5803 community_uniq_sort(commerge);
3c1f53de 5804 community_free(&commerge);
d62a17ae 5805 } else
5806 community = community_dup(
40381db7 5807 pinew->attr->community);
d62a17ae 5808 }
3da2cc32
DS
5809
5810 if (pinew->attr->ecommunity) {
5811 if (ecommunity) {
5812 ecommerge = ecommunity_merge(
5813 ecommunity,
5814 pinew->attr->ecommunity);
5815 ecommunity =
5816 ecommunity_uniq_sort(ecommerge);
5817 ecommunity_free(&ecommerge);
5818 } else
5819 ecommunity = ecommunity_dup(
5820 pinew->attr->ecommunity);
5821 }
dd18c5a9
DS
5822
5823 if (pinew->attr->lcommunity) {
5824 if (lcommunity) {
5825 lcommerge = lcommunity_merge(
5826 lcommunity,
5827 pinew->attr->lcommunity);
5828 lcommunity =
5829 lcommunity_uniq_sort(lcommerge);
5830 lcommunity_free(&lcommerge);
5831 } else
5832 lcommunity = lcommunity_dup(
5833 pinew->attr->lcommunity);
d62a17ae 5834 }
718e3744 5835 }
718e3744 5836 }
718e3744 5837
c701010e 5838 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
5839 ecommunity, lcommunity, atomic_aggregate,
5840 aggregate);
d62a17ae 5841
c701010e 5842 if (aggregate->count == 0) {
d62a17ae 5843 if (aspath)
5844 aspath_free(aspath);
5845 if (community)
3c1f53de 5846 community_free(&community);
3da2cc32
DS
5847 if (ecommunity)
5848 ecommunity_free(&ecommunity);
dd18c5a9
DS
5849 if (lcommunity)
5850 lcommunity_free(&lcommunity);
d62a17ae 5851 }
718e3744 5852}
5853
3b7db173
DS
5854static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5855 safi_t safi, struct bgp_aggregate *aggregate)
5856{
5857 struct bgp_table *table;
5858 struct bgp_node *top;
5859 struct bgp_node *rn;
40381db7 5860 struct bgp_path_info *pi;
3b7db173
DS
5861 unsigned long match;
5862
5863 table = bgp->rib[afi][safi];
5864
5865 /* If routes exists below this node, generate aggregate routes. */
5866 top = bgp_node_get(table, p);
5867 for (rn = bgp_node_get(table, p); rn;
5868 rn = bgp_route_next_until(rn, top)) {
5869 if (rn->p.prefixlen <= p->prefixlen)
5870 continue;
5871 match = 0;
5872
6f94b685 5873 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5874 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
5875 continue;
5876
40381db7 5877 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
5878 continue;
5879
40381db7
DS
5880 if (aggregate->summary_only && pi->extra) {
5881 pi->extra->suppress--;
3b7db173 5882
40381db7 5883 if (pi->extra->suppress == 0) {
18ee8310 5884 bgp_path_info_set_flag(
40381db7 5885 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
5886 match++;
5887 }
5888 }
5889 aggregate->count--;
5890 }
5891
5892 /* If this node was suppressed, process the change. */
5893 if (match)
5894 bgp_process(bgp, rn, afi, safi);
5895 }
5896 bgp_unlock_node(top);
5897}
718e3744 5898
d62a17ae 5899void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 5900 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 5901{
d62a17ae 5902 struct bgp_node *child;
5903 struct bgp_node *rn;
5904 struct bgp_aggregate *aggregate;
5905 struct bgp_table *table;
718e3744 5906
d62a17ae 5907 table = bgp->aggregate[afi][safi];
f018db83 5908
d62a17ae 5909 /* No aggregates configured. */
5910 if (bgp_table_top_nolock(table) == NULL)
5911 return;
f018db83 5912
d62a17ae 5913 if (p->prefixlen == 0)
5914 return;
718e3744 5915
40381db7 5916 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 5917 return;
718e3744 5918
d62a17ae 5919 child = bgp_node_get(table, p);
718e3744 5920
d62a17ae 5921 /* Aggregate address configuration check. */
b1e62edd 5922 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 5923 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 5924 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
d62a17ae 5925 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
40381db7 5926 bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL,
d62a17ae 5927 aggregate);
5928 }
b1e62edd 5929 }
d62a17ae 5930 bgp_unlock_node(child);
718e3744 5931}
5932
d62a17ae 5933void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 5934 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 5935{
d62a17ae 5936 struct bgp_node *child;
5937 struct bgp_node *rn;
5938 struct bgp_aggregate *aggregate;
5939 struct bgp_table *table;
718e3744 5940
d62a17ae 5941 table = bgp->aggregate[afi][safi];
718e3744 5942
d62a17ae 5943 /* No aggregates configured. */
5944 if (bgp_table_top_nolock(table) == NULL)
5945 return;
718e3744 5946
d62a17ae 5947 if (p->prefixlen == 0)
5948 return;
718e3744 5949
d62a17ae 5950 child = bgp_node_get(table, p);
718e3744 5951
d62a17ae 5952 /* Aggregate address configuration check. */
b1e62edd 5953 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 5954 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 5955 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
d62a17ae 5956 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5957 bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
5958 aggregate);
5959 }
b1e62edd 5960 }
d62a17ae 5961 bgp_unlock_node(child);
5962}
718e3744 5963
718e3744 5964/* Aggregate route attribute. */
5965#define AGGREGATE_SUMMARY_ONLY 1
5966#define AGGREGATE_AS_SET 1
5967
d62a17ae 5968static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5969 afi_t afi, safi_t safi)
718e3744 5970{
d62a17ae 5971 VTY_DECLVAR_CONTEXT(bgp, bgp);
5972 int ret;
5973 struct prefix p;
5974 struct bgp_node *rn;
5975 struct bgp_aggregate *aggregate;
718e3744 5976
d62a17ae 5977 /* Convert string to prefix structure. */
5978 ret = str2prefix(prefix_str, &p);
5979 if (!ret) {
5980 vty_out(vty, "Malformed prefix\n");
5981 return CMD_WARNING_CONFIG_FAILED;
5982 }
5983 apply_mask(&p);
5984
5985 /* Old configuration check. */
5986 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5987 if (!rn) {
5988 vty_out(vty,
5989 "%% There is no aggregate-address configuration.\n");
5990 return CMD_WARNING_CONFIG_FAILED;
5991 }
f6269b4f 5992
b613a918 5993 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 5994 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
5995 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
5996 NULL, NULL, 0, aggregate);
d62a17ae 5997
5998 /* Unlock aggregate address configuration. */
b613a918 5999 bgp_node_set_bgp_aggregate_info(rn, NULL);
d62a17ae 6000 bgp_aggregate_free(aggregate);
6001 bgp_unlock_node(rn);
6002 bgp_unlock_node(rn);
6003
6004 return CMD_SUCCESS;
6005}
6006
6007static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
d7c0a89a 6008 safi_t safi, uint8_t summary_only, uint8_t as_set)
d62a17ae 6009{
6010 VTY_DECLVAR_CONTEXT(bgp, bgp);
6011 int ret;
6012 struct prefix p;
6013 struct bgp_node *rn;
6014 struct bgp_aggregate *aggregate;
6015
6016 /* Convert string to prefix structure. */
6017 ret = str2prefix(prefix_str, &p);
6018 if (!ret) {
6019 vty_out(vty, "Malformed prefix\n");
6020 return CMD_WARNING_CONFIG_FAILED;
6021 }
6022 apply_mask(&p);
6023
3624ac81
DS
6024 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6025 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6026 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6027 prefix_str);
6028 return CMD_WARNING_CONFIG_FAILED;
6029 }
6030
d62a17ae 6031 /* Old configuration check. */
6032 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
6033
67009e22 6034 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 6035 vty_out(vty, "There is already same aggregate network.\n");
6036 /* try to remove the old entry */
6037 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6038 if (ret) {
6039 vty_out(vty, "Error deleting aggregate.\n");
6040 bgp_unlock_node(rn);
6041 return CMD_WARNING_CONFIG_FAILED;
6042 }
6043 }
718e3744 6044
d62a17ae 6045 /* Make aggregate address structure. */
6046 aggregate = bgp_aggregate_new();
6047 aggregate->summary_only = summary_only;
6048 aggregate->as_set = as_set;
6049 aggregate->safi = safi;
b613a918 6050 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6051
d62a17ae 6052 /* Aggregate address insert into BGP routing table. */
f273fef1 6053 bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate);
718e3744 6054
d62a17ae 6055 return CMD_SUCCESS;
718e3744 6056}
6057
6058DEFUN (aggregate_address,
6059 aggregate_address_cmd,
e3e6107d 6060 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6061 "Configure BGP aggregate entries\n"
6062 "Aggregate prefix\n"
6063 "Generate AS set path information\n"
a636c635
DW
6064 "Filter more specific routes from updates\n"
6065 "Filter more specific routes from updates\n"
6066 "Generate AS set path information\n")
718e3744 6067{
d62a17ae 6068 int idx = 0;
6069 argv_find(argv, argc, "A.B.C.D/M", &idx);
6070 char *prefix = argv[idx]->arg;
6071 int as_set =
6072 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6073 idx = 0;
6074 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6075 ? AGGREGATE_SUMMARY_ONLY
6076 : 0;
e3e6107d 6077
d62a17ae 6078 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
6079 summary_only, as_set);
718e3744 6080}
6081
e3e6107d
QY
6082DEFUN (aggregate_address_mask,
6083 aggregate_address_mask_cmd,
6084 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6085 "Configure BGP aggregate entries\n"
6086 "Aggregate address\n"
6087 "Aggregate mask\n"
6088 "Generate AS set path information\n"
a636c635
DW
6089 "Filter more specific routes from updates\n"
6090 "Filter more specific routes from updates\n"
6091 "Generate AS set path information\n")
718e3744 6092{
d62a17ae 6093 int idx = 0;
6094 argv_find(argv, argc, "A.B.C.D", &idx);
6095 char *prefix = argv[idx]->arg;
6096 char *mask = argv[idx + 1]->arg;
6097 int as_set =
6098 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6099 idx = 0;
6100 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6101 ? AGGREGATE_SUMMARY_ONLY
6102 : 0;
6103
6104 char prefix_str[BUFSIZ];
6105 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6106
6107 if (!ret) {
6108 vty_out(vty, "%% Inconsistent address and mask\n");
6109 return CMD_WARNING_CONFIG_FAILED;
6110 }
718e3744 6111
d62a17ae 6112 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
6113 summary_only, as_set);
718e3744 6114}
6115
718e3744 6116DEFUN (no_aggregate_address,
6117 no_aggregate_address_cmd,
e3e6107d 6118 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6119 NO_STR
6120 "Configure BGP aggregate entries\n"
a636c635
DW
6121 "Aggregate prefix\n"
6122 "Generate AS set path information\n"
e3e6107d
QY
6123 "Filter more specific routes from updates\n"
6124 "Filter more specific routes from updates\n"
6125 "Generate AS set path information\n")
718e3744 6126{
d62a17ae 6127 int idx = 0;
6128 argv_find(argv, argc, "A.B.C.D/M", &idx);
6129 char *prefix = argv[idx]->arg;
6130 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6131}
6132
718e3744 6133DEFUN (no_aggregate_address_mask,
6134 no_aggregate_address_mask_cmd,
e3e6107d 6135 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6136 NO_STR
6137 "Configure BGP aggregate entries\n"
6138 "Aggregate address\n"
a636c635
DW
6139 "Aggregate mask\n"
6140 "Generate AS set path information\n"
e3e6107d
QY
6141 "Filter more specific routes from updates\n"
6142 "Filter more specific routes from updates\n"
6143 "Generate AS set path information\n")
718e3744 6144{
d62a17ae 6145 int idx = 0;
6146 argv_find(argv, argc, "A.B.C.D", &idx);
6147 char *prefix = argv[idx]->arg;
6148 char *mask = argv[idx + 1]->arg;
718e3744 6149
d62a17ae 6150 char prefix_str[BUFSIZ];
6151 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6152
d62a17ae 6153 if (!ret) {
6154 vty_out(vty, "%% Inconsistent address and mask\n");
6155 return CMD_WARNING_CONFIG_FAILED;
6156 }
718e3744 6157
d62a17ae 6158 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6159}
6160
718e3744 6161DEFUN (ipv6_aggregate_address,
6162 ipv6_aggregate_address_cmd,
e3e6107d 6163 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6164 "Configure BGP aggregate entries\n"
6165 "Aggregate prefix\n"
6166 "Filter more specific routes from updates\n")
6167{
d62a17ae 6168 int idx = 0;
6169 argv_find(argv, argc, "X:X::X:X/M", &idx);
6170 char *prefix = argv[idx]->arg;
6171 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6172 ? AGGREGATE_SUMMARY_ONLY
6173 : 0;
6174 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6175 0);
718e3744 6176}
6177
6178DEFUN (no_ipv6_aggregate_address,
6179 no_ipv6_aggregate_address_cmd,
e3e6107d 6180 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6181 NO_STR
6182 "Configure BGP aggregate entries\n"
16cedbb0
QY
6183 "Aggregate prefix\n"
6184 "Filter more specific routes from updates\n")
718e3744 6185{
d62a17ae 6186 int idx = 0;
6187 argv_find(argv, argc, "X:X::X:X/M", &idx);
6188 char *prefix = argv[idx]->arg;
6189 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6190}
6191
718e3744 6192/* Redistribute route treatment. */
d62a17ae 6193void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6194 const union g_addr *nexthop, ifindex_t ifindex,
6195 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6196 uint8_t type, unsigned short instance,
6197 route_tag_t tag)
d62a17ae 6198{
4b7e6066 6199 struct bgp_path_info *new;
40381db7
DS
6200 struct bgp_path_info *bpi;
6201 struct bgp_path_info rmap_path;
d62a17ae 6202 struct bgp_node *bn;
6203 struct attr attr;
6204 struct attr *new_attr;
6205 afi_t afi;
6206 int ret;
6207 struct bgp_redist *red;
6208
6209 /* Make default attribute. */
6210 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff 6211
a4d82a8a 6212 switch (nhtype) {
9de1f7ff
DS
6213 case NEXTHOP_TYPE_IFINDEX:
6214 break;
6215 case NEXTHOP_TYPE_IPV4:
6216 case NEXTHOP_TYPE_IPV4_IFINDEX:
6217 attr.nexthop = nexthop->ipv4;
6218 break;
6219 case NEXTHOP_TYPE_IPV6:
6220 case NEXTHOP_TYPE_IPV6_IFINDEX:
6221 attr.mp_nexthop_global = nexthop->ipv6;
6222 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6223 break;
6224 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6225 switch (p->family) {
6226 case AF_INET:
9de1f7ff 6227 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6228 break;
6229 case AF_INET6:
9de1f7ff
DS
6230 memset(&attr.mp_nexthop_global, 0,
6231 sizeof(attr.mp_nexthop_global));
74489921 6232 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6233 break;
74489921 6234 }
9de1f7ff 6235 break;
d62a17ae 6236 }
74489921 6237 attr.nh_ifindex = ifindex;
f04a80a5 6238
d62a17ae 6239 attr.med = metric;
6240 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6241 attr.tag = tag;
718e3744 6242
d62a17ae 6243 afi = family2afi(p->family);
6aeb9e78 6244
d62a17ae 6245 red = bgp_redist_lookup(bgp, afi, type, instance);
6246 if (red) {
6247 struct attr attr_new;
718e3744 6248
d62a17ae 6249 /* Copy attribute for modification. */
6250 bgp_attr_dup(&attr_new, &attr);
718e3744 6251
d62a17ae 6252 if (red->redist_metric_flag)
6253 attr_new.med = red->redist_metric;
718e3744 6254
d62a17ae 6255 /* Apply route-map. */
6256 if (red->rmap.name) {
40381db7
DS
6257 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6258 rmap_path.peer = bgp->peer_self;
6259 rmap_path.attr = &attr_new;
718e3744 6260
d62a17ae 6261 SET_FLAG(bgp->peer_self->rmap_type,
6262 PEER_RMAP_TYPE_REDISTRIBUTE);
6263
6264 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6265 &rmap_path);
d62a17ae 6266
6267 bgp->peer_self->rmap_type = 0;
6268
6269 if (ret == RMAP_DENYMATCH) {
6270 /* Free uninterned attribute. */
6271 bgp_attr_flush(&attr_new);
6272
6273 /* Unintern original. */
6274 aspath_unintern(&attr.aspath);
6275 bgp_redistribute_delete(bgp, p, type, instance);
6276 return;
6277 }
6278 }
6279
7f323236
DW
6280 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6281 bgp_attr_add_gshut_community(&attr_new);
6282
d62a17ae 6283 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6284 SAFI_UNICAST, p, NULL);
6285
6286 new_attr = bgp_attr_intern(&attr_new);
6287
6f94b685
DS
6288 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6289 bpi = bpi->next)
40381db7
DS
6290 if (bpi->peer == bgp->peer_self
6291 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6292 break;
6293
40381db7 6294 if (bpi) {
d62a17ae 6295 /* Ensure the (source route) type is updated. */
40381db7
DS
6296 bpi->type = type;
6297 if (attrhash_cmp(bpi->attr, new_attr)
6298 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6299 bgp_attr_unintern(&new_attr);
6300 aspath_unintern(&attr.aspath);
6301 bgp_unlock_node(bn);
6302 return;
6303 } else {
6304 /* The attribute is changed. */
40381db7 6305 bgp_path_info_set_flag(bn, bpi,
18ee8310 6306 BGP_PATH_ATTR_CHANGED);
d62a17ae 6307
6308 /* Rewrite BGP route information. */
40381db7
DS
6309 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6310 bgp_path_info_restore(bn, bpi);
d62a17ae 6311 else
40381db7
DS
6312 bgp_aggregate_decrement(
6313 bgp, p, bpi, afi, SAFI_UNICAST);
6314 bgp_attr_unintern(&bpi->attr);
6315 bpi->attr = new_attr;
6316 bpi->uptime = bgp_clock();
d62a17ae 6317
6318 /* Process change. */
40381db7 6319 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6320 SAFI_UNICAST);
6321 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6322 bgp_unlock_node(bn);
6323 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6324
6325 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6326 || (bgp->inst_type
6327 == BGP_INSTANCE_TYPE_DEFAULT)) {
6328
6329 vpn_leak_from_vrf_update(
40381db7 6330 bgp_get_default(), bgp, bpi);
ddb5b488 6331 }
d62a17ae 6332 return;
6333 }
6334 }
6335
6336 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6337 bgp->peer_self, new_attr, bn);
1defdda8 6338 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6339
6340 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6341 bgp_path_info_add(bn, new);
d62a17ae 6342 bgp_unlock_node(bn);
6343 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6344
6345 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6346 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6347
6348 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6349 }
d62a17ae 6350 }
6351
6352 /* Unintern original. */
6353 aspath_unintern(&attr.aspath);
718e3744 6354}
6355
d7c0a89a
QY
6356void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6357 unsigned short instance)
718e3744 6358{
d62a17ae 6359 afi_t afi;
6360 struct bgp_node *rn;
40381db7 6361 struct bgp_path_info *pi;
d62a17ae 6362 struct bgp_redist *red;
718e3744 6363
d62a17ae 6364 afi = family2afi(p->family);
718e3744 6365
d62a17ae 6366 red = bgp_redist_lookup(bgp, afi, type, instance);
6367 if (red) {
6368 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6369 SAFI_UNICAST, p, NULL);
6370
6f94b685 6371 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6372 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6373 break;
6374
40381db7 6375 if (pi) {
ddb5b488
PZ
6376 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6377 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6378
6379 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6380 bgp, pi);
ddb5b488 6381 }
40381db7
DS
6382 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
6383 bgp_path_info_delete(rn, pi);
d62a17ae 6384 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6385 }
6386 bgp_unlock_node(rn);
6387 }
6388}
6389
6390/* Withdraw specified route type's route. */
6391void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6392 unsigned short instance)
d62a17ae 6393{
6394 struct bgp_node *rn;
40381db7 6395 struct bgp_path_info *pi;
d62a17ae 6396 struct bgp_table *table;
6397
6398 table = bgp->rib[afi][SAFI_UNICAST];
6399
6400 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 6401 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6402 if (pi->peer == bgp->peer_self && pi->type == type
6403 && pi->instance == instance)
d62a17ae 6404 break;
6405
40381db7 6406 if (pi) {
ddb5b488
PZ
6407 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6408 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6409
6410 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6411 bgp, pi);
ddb5b488 6412 }
40381db7 6413 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 6414 SAFI_UNICAST);
40381db7 6415 bgp_path_info_delete(rn, pi);
d62a17ae 6416 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6417 }
718e3744 6418 }
718e3744 6419}
6b0655a2 6420
718e3744 6421/* Static function to display route. */
9c92b5f7
MK
6422static void route_vty_out_route(struct prefix *p, struct vty *vty,
6423 json_object *json)
718e3744 6424{
be054588 6425 int len = 0;
d62a17ae 6426 char buf[BUFSIZ];
50e05855 6427 char buf2[BUFSIZ];
718e3744 6428
d62a17ae 6429 if (p->family == AF_INET) {
c6462ff4 6430 if (!json) {
89e5e9f0
PM
6431 len = vty_out(
6432 vty, "%s/%d",
6433 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6434 p->prefixlen);
c6462ff4
MK
6435 } else {
6436 json_object_string_add(json, "prefix",
6437 inet_ntop(p->family,
6438 &p->u.prefix, buf,
6439 BUFSIZ));
6440 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 6441 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 6442 json_object_string_add(json, "network", buf2);
c6462ff4 6443 }
d62a17ae 6444 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6445 prefix2str(p, buf, PREFIX_STRLEN);
6446 len = vty_out(vty, "%s", buf);
6447 } else if (p->family == AF_EVPN) {
57f7feb6 6448 if (!json)
60466a63
QY
6449 len = vty_out(
6450 vty, "%s",
6451 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6452 BUFSIZ));
57f7feb6 6453 else
60466a63 6454 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6455 } else if (p->family == AF_FLOWSPEC) {
6456 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6457 json ?
6458 NLRI_STRING_FORMAT_JSON_SIMPLE :
6459 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6460 } else {
c6462ff4 6461 if (!json)
60466a63
QY
6462 len = vty_out(
6463 vty, "%s/%d",
6464 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6465 p->prefixlen);
50e05855
AD
6466 else {
6467 json_object_string_add(json, "prefix",
6468 inet_ntop(p->family,
6469 &p->u.prefix, buf,
6470 BUFSIZ));
6471 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
6472 prefix2str(p, buf2, PREFIX_STRLEN);
6473 json_object_string_add(json, "network", buf2);
6474 }
9c92b5f7 6475 }
d62a17ae 6476
9c92b5f7
MK
6477 if (!json) {
6478 len = 17 - len;
6479 if (len < 1)
6480 vty_out(vty, "\n%*s", 20, " ");
6481 else
6482 vty_out(vty, "%*s", len, " ");
6483 }
718e3744 6484}
6485
d62a17ae 6486enum bgp_display_type {
6487 normal_list,
718e3744 6488};
6489
18ee8310 6490/* Print the short form route status for a bgp_path_info */
4b7e6066 6491static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 6492 struct bgp_path_info *path,
d62a17ae 6493 json_object *json_path)
718e3744 6494{
d62a17ae 6495 if (json_path) {
b05a1c8b 6496
d62a17ae 6497 /* Route status display. */
9b6d8fcf 6498 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 6499 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6500
9b6d8fcf 6501 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 6502 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6503
9b6d8fcf 6504 if (path->extra && path->extra->suppress)
d62a17ae 6505 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6506
9b6d8fcf
DS
6507 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
6508 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6509 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6510
d62a17ae 6511 /* Selected */
9b6d8fcf 6512 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6513 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6514
9b6d8fcf 6515 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 6516 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6517
9b6d8fcf 6518 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 6519 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6520
9b6d8fcf 6521 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 6522 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6523
d62a17ae 6524 /* Internal route. */
9b6d8fcf
DS
6525 if ((path->peer->as)
6526 && (path->peer->as == path->peer->local_as))
d62a17ae 6527 json_object_string_add(json_path, "pathFrom",
6528 "internal");
6529 else
6530 json_object_string_add(json_path, "pathFrom",
6531 "external");
b05a1c8b 6532
d62a17ae 6533 return;
6534 }
b05a1c8b 6535
d62a17ae 6536 /* Route status display. */
9b6d8fcf 6537 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 6538 vty_out(vty, "R");
9b6d8fcf 6539 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 6540 vty_out(vty, "S");
9b6d8fcf 6541 else if (path->extra && path->extra->suppress)
d62a17ae 6542 vty_out(vty, "s");
9b6d8fcf
DS
6543 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
6544 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6545 vty_out(vty, "*");
6546 else
6547 vty_out(vty, " ");
6548
6549 /* Selected */
9b6d8fcf 6550 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6551 vty_out(vty, "h");
9b6d8fcf 6552 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 6553 vty_out(vty, "d");
9b6d8fcf 6554 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 6555 vty_out(vty, ">");
9b6d8fcf 6556 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 6557 vty_out(vty, "=");
6558 else
6559 vty_out(vty, " ");
718e3744 6560
d62a17ae 6561 /* Internal route. */
9b6d8fcf
DS
6562 if (path->peer && (path->peer->as)
6563 && (path->peer->as == path->peer->local_as))
d62a17ae 6564 vty_out(vty, "i");
6565 else
6566 vty_out(vty, " ");
b40d939b 6567}
6568
6569/* called from terminal list command */
4b7e6066 6570void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 6571 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 6572 json_object *json_paths)
d62a17ae 6573{
6574 struct attr *attr;
6575 json_object *json_path = NULL;
6576 json_object *json_nexthops = NULL;
6577 json_object *json_nexthop_global = NULL;
6578 json_object *json_nexthop_ll = NULL;
9df8b37c 6579 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 6580 bool nexthop_self =
9b6d8fcf 6581 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 6582 bool nexthop_othervrf = false;
43089216 6583 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 6584 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
d62a17ae 6585
6586 if (json_paths)
6587 json_path = json_object_new_object();
6588
6589 /* short status lead text */
9b6d8fcf 6590 route_vty_short_status_out(vty, path, json_path);
d62a17ae 6591
6592 if (!json_paths) {
6593 /* print prefix and mask */
6594 if (!display)
9c92b5f7 6595 route_vty_out_route(p, vty, json_path);
d62a17ae 6596 else
6597 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6598 } else {
b682f6de 6599 route_vty_out_route(p, vty, json_path);
d62a17ae 6600 }
47fc97cc 6601
d62a17ae 6602 /* Print attribute */
9b6d8fcf 6603 attr = path->attr;
445c2480
DS
6604 if (!attr) {
6605 if (json_paths)
6606 json_object_array_add(json_paths, json_path);
6607 else
6608 vty_out(vty, "\n");
d62a17ae 6609
445c2480
DS
6610 return;
6611 }
6612
9df8b37c
PZ
6613 /*
6614 * If vrf id of nexthop is different from that of prefix,
6615 * set up printable string to append
6616 */
9b6d8fcf 6617 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
6618 const char *self = "";
6619
6620 if (nexthop_self)
6621 self = "<";
6622
6623 nexthop_othervrf = true;
9b6d8fcf 6624 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 6625
9b6d8fcf 6626 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
6627 snprintf(vrf_id_str, sizeof(vrf_id_str),
6628 "@%s%s", VRFID_NONE_STR, self);
6629 else
6630 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 6631 path->extra->bgp_orig->vrf_id, self);
9df8b37c 6632
9b6d8fcf
DS
6633 if (path->extra->bgp_orig->inst_type
6634 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 6635
9b6d8fcf 6636 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
6637 } else {
6638 const char *self = "";
6639
6640 if (nexthop_self)
6641 self = "<";
6642
6643 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
6644 }
6645
445c2480
DS
6646 /*
6647 * For ENCAP and EVPN routes, nexthop address family is not
6648 * neccessarily the same as the prefix address family.
6649 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6650 * EVPN routes are also exchanged with a MP nexthop. Currently,
6651 * this
6652 * is only IPv4, the value will be present in either
6653 * attr->nexthop or
6654 * attr->mp_nexthop_global_in
6655 */
6656 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6657 char buf[BUFSIZ];
6658 char nexthop[128];
6659 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6660
6661 switch (af) {
6662 case AF_INET:
6663 sprintf(nexthop, "%s",
a4d82a8a
PZ
6664 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
6665 BUFSIZ));
445c2480
DS
6666 break;
6667 case AF_INET6:
6668 sprintf(nexthop, "%s",
a4d82a8a
PZ
6669 inet_ntop(af, &attr->mp_nexthop_global, buf,
6670 BUFSIZ));
445c2480
DS
6671 break;
6672 default:
6673 sprintf(nexthop, "?");
6674 break;
d62a17ae 6675 }
d62a17ae 6676
445c2480
DS
6677 if (json_paths) {
6678 json_nexthop_global = json_object_new_object();
6679
a4d82a8a
PZ
6680 json_object_string_add(json_nexthop_global, "afi",
6681 (af == AF_INET) ? "ip" : "ipv6");
445c2480 6682 json_object_string_add(json_nexthop_global,
a4d82a8a 6683 (af == AF_INET) ? "ip" : "ipv6",
445c2480
DS
6684 nexthop);
6685 json_object_boolean_true_add(json_nexthop_global,
6686 "used");
6687 } else
9df8b37c 6688 vty_out(vty, "%s%s", nexthop, vrf_id_str);
445c2480
DS
6689 } else if (safi == SAFI_EVPN) {
6690 if (json_paths) {
6691 json_nexthop_global = json_object_new_object();
6692
6693 json_object_string_add(json_nexthop_global, "ip",
6694 inet_ntoa(attr->nexthop));
a4d82a8a
PZ
6695 json_object_string_add(json_nexthop_global, "afi",
6696 "ipv4");
445c2480
DS
6697 json_object_boolean_true_add(json_nexthop_global,
6698 "used");
6699 } else
9df8b37c
PZ
6700 vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
6701 vrf_id_str);
d33fc23b 6702 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
6703 if (attr->nexthop.s_addr != 0) {
6704 if (json_paths) {
6705 json_nexthop_global = json_object_new_object();
6706 json_object_string_add(
6707 json_nexthop_global, "ip",
6708 inet_ntoa(attr->nexthop));
6709 json_object_string_add(json_nexthop_global,
6710 "afi", "ipv4");
50e05855
AD
6711 json_object_boolean_true_add(
6712 json_nexthop_global,
026b914a
PG
6713 "used");
6714 } else {
6715 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6716 }
6717 }
d33fc23b 6718 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6719 if (json_paths) {
6720 json_nexthop_global = json_object_new_object();
d62a17ae 6721
a4d82a8a
PZ
6722 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
6723 json_object_string_add(
6724 json_nexthop_global, "ip",
6725 inet_ntoa(attr->mp_nexthop_global_in));
445c2480 6726 else
a4d82a8a
PZ
6727 json_object_string_add(
6728 json_nexthop_global, "ip",
6729 inet_ntoa(attr->nexthop));
445c2480 6730
a4d82a8a
PZ
6731 json_object_string_add(json_nexthop_global, "afi",
6732 "ipv4");
445c2480
DS
6733 json_object_boolean_true_add(json_nexthop_global,
6734 "used");
6735 } else {
9df8b37c
PZ
6736 char buf[BUFSIZ];
6737
d87ff2dd 6738 snprintf(buf, sizeof(buf), "%s%s",
6739 inet_ntoa(attr->nexthop), vrf_id_str);
9df8b37c 6740 vty_out(vty, "%-16s", buf);
d62a17ae 6741 }
445c2480 6742 }
b05a1c8b 6743
445c2480 6744 /* IPv6 Next Hop */
a4d82a8a 6745 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6746 int len;
6747 char buf[BUFSIZ];
d62a17ae 6748
445c2480
DS
6749 if (json_paths) {
6750 json_nexthop_global = json_object_new_object();
a4d82a8a
PZ
6751 json_object_string_add(
6752 json_nexthop_global, "ip",
6753 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
6754 buf, BUFSIZ));
6755 json_object_string_add(json_nexthop_global, "afi",
6756 "ipv6");
6757 json_object_string_add(json_nexthop_global, "scope",
6758 "global");
445c2480
DS
6759
6760 /* We display both LL & GL if both have been
6761 * received */
6762 if ((attr->mp_nexthop_len == 32)
9b6d8fcf 6763 || (path->peer->conf_if)) {
a4d82a8a 6764 json_nexthop_ll = json_object_new_object();
d62a17ae 6765 json_object_string_add(
445c2480 6766 json_nexthop_ll, "ip",
a4d82a8a
PZ
6767 inet_ntop(AF_INET6,
6768 &attr->mp_nexthop_local, buf,
6769 BUFSIZ));
6770 json_object_string_add(json_nexthop_ll, "afi",
6771 "ipv6");
6772 json_object_string_add(json_nexthop_ll, "scope",
445c2480 6773 "link-local");
d62a17ae 6774
a4d82a8a
PZ
6775 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
6776 &attr->mp_nexthop_local)
445c2480
DS
6777 != 0)
6778 && !attr->mp_nexthop_prefer_global)
d62a17ae 6779 json_object_boolean_true_add(
a4d82a8a 6780 json_nexthop_ll, "used");
445c2480
DS
6781 else
6782 json_object_boolean_true_add(
a4d82a8a 6783 json_nexthop_global, "used");
445c2480
DS
6784 } else
6785 json_object_boolean_true_add(
6786 json_nexthop_global, "used");
6787 } else {
6788 /* Display LL if LL/Global both in table unless
6789 * prefer-global is set */
6790 if (((attr->mp_nexthop_len == 32)
6791 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
6792 || (path->peer->conf_if)) {
6793 if (path->peer->conf_if) {
a4d82a8a 6794 len = vty_out(vty, "%s",
9b6d8fcf 6795 path->peer->conf_if);
445c2480
DS
6796 len = 16 - len; /* len of IPv6
6797 addr + max
6798 len of def
6799 ifname */
6800
6801 if (len < 1)
a4d82a8a 6802 vty_out(vty, "\n%*s", 36, " ");
445c2480 6803 else
a4d82a8a 6804 vty_out(vty, "%*s", len, " ");
d62a17ae 6805 } else {
6806 len = vty_out(
9df8b37c 6807 vty, "%s%s",
d62a17ae 6808 inet_ntop(
6809 AF_INET6,
445c2480 6810 &attr->mp_nexthop_local,
9df8b37c
PZ
6811 buf, BUFSIZ),
6812 vrf_id_str);
d62a17ae 6813 len = 16 - len;
6814
6815 if (len < 1)
a4d82a8a 6816 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 6817 else
a4d82a8a 6818 vty_out(vty, "%*s", len, " ");
d62a17ae 6819 }
445c2480 6820 } else {
a4d82a8a 6821 len = vty_out(
9df8b37c 6822 vty, "%s%s",
a4d82a8a
PZ
6823 inet_ntop(AF_INET6,
6824 &attr->mp_nexthop_global, buf,
9df8b37c
PZ
6825 BUFSIZ),
6826 vrf_id_str);
445c2480
DS
6827 len = 16 - len;
6828
6829 if (len < 1)
6830 vty_out(vty, "\n%*s", 36, " ");
6831 else
6832 vty_out(vty, "%*s", len, " ");
d62a17ae 6833 }
6834 }
445c2480 6835 }
718e3744 6836
445c2480
DS
6837 /* MED/Metric */
6838 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
6839 if (json_paths) {
6840
6841 /*
6842 * Adding "metric" field to match with corresponding
6843 * CLI. "med" will be deprecated in future.
6844 */
a4d82a8a 6845 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
6846 json_object_int_add(json_path, "metric", attr->med);
6847 } else
445c2480
DS
6848 vty_out(vty, "%10u", attr->med);
6849 else if (!json_paths)
6850 vty_out(vty, " ");
d62a17ae 6851
445c2480
DS
6852 /* Local Pref */
6853 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
6854 if (json_paths) {
6855
6856 /*
6857 * Adding "locPrf" field to match with corresponding
6858 * CLI. "localPref" will be deprecated in future.
6859 */
445c2480
DS
6860 json_object_int_add(json_path, "localpref",
6861 attr->local_pref);
50e05855
AD
6862 json_object_int_add(json_path, "locPrf",
6863 attr->local_pref);
6864 } else
445c2480
DS
6865 vty_out(vty, "%7u", attr->local_pref);
6866 else if (!json_paths)
6867 vty_out(vty, " ");
d62a17ae 6868
445c2480
DS
6869 if (json_paths)
6870 json_object_int_add(json_path, "weight", attr->weight);
6871 else
6872 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6873
445c2480
DS
6874 if (json_paths) {
6875 char buf[BUFSIZ];
a4d82a8a
PZ
6876 json_object_string_add(
6877 json_path, "peerId",
9b6d8fcf 6878 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 6879 }
b05a1c8b 6880
445c2480
DS
6881 /* Print aspath */
6882 if (attr->aspath) {
50e05855
AD
6883 if (json_paths) {
6884
6885 /*
6886 * Adding "path" field to match with corresponding
6887 * CLI. "aspath" will be deprecated in future.
6888 */
445c2480
DS
6889 json_object_string_add(json_path, "aspath",
6890 attr->aspath->str);
50e05855
AD
6891 json_object_string_add(json_path, "path",
6892 attr->aspath->str);
6893 } else
445c2480 6894 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6895 }
f1aa5d8a 6896
445c2480
DS
6897 /* Print origin */
6898 if (json_paths)
a4d82a8a
PZ
6899 json_object_string_add(json_path, "origin",
6900 bgp_origin_long_str[attr->origin]);
445c2480
DS
6901 else
6902 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6903
9df8b37c
PZ
6904 if (json_paths) {
6905 if (nexthop_self)
6906 json_object_boolean_true_add(json_path,
6907 "announceNexthopSelf");
6908 if (nexthop_othervrf) {
6909 json_object_string_add(json_path, "nhVrfName",
6910 nexthop_vrfname);
6911
6912 json_object_int_add(json_path, "nhVrfId",
6913 ((nexthop_vrfid == VRF_UNKNOWN)
6914 ? -1
6915 : (int)nexthop_vrfid));
6916 }
6917 }
6918
d62a17ae 6919 if (json_paths) {
6920 if (json_nexthop_global || json_nexthop_ll) {
6921 json_nexthops = json_object_new_array();
f1aa5d8a 6922
d62a17ae 6923 if (json_nexthop_global)
6924 json_object_array_add(json_nexthops,
6925 json_nexthop_global);
f1aa5d8a 6926
d62a17ae 6927 if (json_nexthop_ll)
6928 json_object_array_add(json_nexthops,
6929 json_nexthop_ll);
f1aa5d8a 6930
d62a17ae 6931 json_object_object_add(json_path, "nexthops",
6932 json_nexthops);
6933 }
6934
6935 json_object_array_add(json_paths, json_path);
6936 } else {
6937 vty_out(vty, "\n");
65efcfce 6938#if ENABLE_BGP_VNC
d62a17ae 6939 /* prints an additional line, indented, with VNC info, if
6940 * present */
6941 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 6942 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 6943#endif
d62a17ae 6944 }
6945}
718e3744 6946
6947/* called from terminal list command */
d62a17ae 6948void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 6949 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 6950{
6951 json_object *json_status = NULL;
6952 json_object *json_net = NULL;
6953 char buff[BUFSIZ];
50e05855 6954 char buf2[BUFSIZ];
d62a17ae 6955 /* Route status display. */
6956 if (use_json) {
6957 json_status = json_object_new_object();
6958 json_net = json_object_new_object();
6959 } else {
6960 vty_out(vty, "*");
6961 vty_out(vty, ">");
6962 vty_out(vty, " ");
6963 }
718e3744 6964
d62a17ae 6965 /* print prefix and mask */
50e05855 6966 if (use_json) {
d62a17ae 6967 json_object_string_add(
6968 json_net, "addrPrefix",
6969 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
50e05855 6970 json_object_int_add(json_net, "prefixLen", p->prefixlen);
37d4e0df 6971 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855
AD
6972 json_object_string_add(json_net, "network", buf2);
6973 } else
9c92b5f7 6974 route_vty_out_route(p, vty, NULL);
d62a17ae 6975
6976 /* Print attribute */
6977 if (attr) {
6978 if (use_json) {
6979 if (p->family == AF_INET
6980 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6981 || safi == SAFI_EVPN
6982 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6983 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6984 || safi == SAFI_EVPN)
6985 json_object_string_add(
6986 json_net, "nextHop",
6987 inet_ntoa(
6988 attr->mp_nexthop_global_in));
6989 else
6990 json_object_string_add(
6991 json_net, "nextHop",
6992 inet_ntoa(attr->nexthop));
6993 } else if (p->family == AF_INET6
6994 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6995 char buf[BUFSIZ];
6996
6997 json_object_string_add(
aa0a10fc 6998 json_net, "nextHopGlobal",
d62a17ae 6999 inet_ntop(AF_INET6,
7000 &attr->mp_nexthop_global, buf,
7001 BUFSIZ));
7002 }
7003
7004 if (attr->flag
7005 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7006 json_object_int_add(json_net, "metric",
7007 attr->med);
7008
50e05855
AD
7009 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7010
7011 /*
7012 * Adding "locPrf" field to match with
7013 * corresponding CLI. "localPref" will be
7014 * deprecated in future.
7015 */
d62a17ae 7016 json_object_int_add(json_net, "localPref",
7017 attr->local_pref);
50e05855
AD
7018 json_object_int_add(json_net, "locPrf",
7019 attr->local_pref);
7020 }
d62a17ae 7021
7022 json_object_int_add(json_net, "weight", attr->weight);
7023
7024 /* Print aspath */
50e05855
AD
7025 if (attr->aspath) {
7026
7027 /*
7028 * Adding "path" field to match with
7029 * corresponding CLI. "localPref" will be
7030 * deprecated in future.
7031 */
d62a17ae 7032 json_object_string_add(json_net, "asPath",
7033 attr->aspath->str);
50e05855
AD
7034 json_object_string_add(json_net, "path",
7035 attr->aspath->str);
7036 }
d62a17ae 7037
7038 /* Print origin */
7039 json_object_string_add(json_net, "bgpOriginCode",
7040 bgp_origin_str[attr->origin]);
7041 } else {
7042 if (p->family == AF_INET
7043 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7044 || safi == SAFI_EVPN
7045 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7046 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7047 || safi == SAFI_EVPN)
7048 vty_out(vty, "%-16s",
7049 inet_ntoa(
7050 attr->mp_nexthop_global_in));
7051 else
7052 vty_out(vty, "%-16s",
7053 inet_ntoa(attr->nexthop));
7054 } else if (p->family == AF_INET6
7055 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7056 int len;
7057 char buf[BUFSIZ];
7058
7059 len = vty_out(
7060 vty, "%s",
7061 inet_ntop(AF_INET6,
7062 &attr->mp_nexthop_global, buf,
7063 BUFSIZ));
7064 len = 16 - len;
7065 if (len < 1)
7066 vty_out(vty, "\n%*s", 36, " ");
7067 else
7068 vty_out(vty, "%*s", len, " ");
7069 }
7070 if (attr->flag
7071 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7072 vty_out(vty, "%10u", attr->med);
7073 else
7074 vty_out(vty, " ");
718e3744 7075
d62a17ae 7076 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7077 vty_out(vty, "%7u", attr->local_pref);
7078 else
7079 vty_out(vty, " ");
7080
7081 vty_out(vty, "%7u ", attr->weight);
7082
7083 /* Print aspath */
7084 if (attr->aspath)
7085 aspath_print_vty(vty, "%s", attr->aspath, " ");
7086
7087 /* Print origin */
7088 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7089 }
7090 }
7091 if (use_json) {
7092 json_object_boolean_true_add(json_status, "*");
7093 json_object_boolean_true_add(json_status, ">");
7094 json_object_object_add(json_net, "appliedStatusSymbols",
7095 json_status);
7096 char buf_cut[BUFSIZ];
7097 json_object_object_add(
7098 json_ar,
7099 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
7100 json_net);
7101 } else
7102 vty_out(vty, "\n");
7103}
7104
7105void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7106 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7107 json_object *json)
7108{
7109 json_object *json_out = NULL;
7110 struct attr *attr;
7111 mpls_label_t label = MPLS_INVALID_LABEL;
7112
9b6d8fcf 7113 if (!path->extra)
d62a17ae 7114 return;
7115
7116 if (json)
7117 json_out = json_object_new_object();
7118
7119 /* short status lead text */
9b6d8fcf 7120 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7121
7122 /* print prefix and mask */
7123 if (json == NULL) {
7124 if (!display)
9c92b5f7 7125 route_vty_out_route(p, vty, NULL);
d62a17ae 7126 else
7127 vty_out(vty, "%*s", 17, " ");
7128 }
7129
7130 /* Print attribute */
9b6d8fcf 7131 attr = path->attr;
d62a17ae 7132 if (attr) {
7133 if (((p->family == AF_INET)
7134 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 7135 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 7136 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7137 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7138 || safi == SAFI_EVPN) {
7139 if (json)
7140 json_object_string_add(
7141 json_out, "mpNexthopGlobalIn",
7142 inet_ntoa(
7143 attr->mp_nexthop_global_in));
7144 else
7145 vty_out(vty, "%-16s",
7146 inet_ntoa(
7147 attr->mp_nexthop_global_in));
7148 } else {
7149 if (json)
7150 json_object_string_add(
7151 json_out, "nexthop",
7152 inet_ntoa(attr->nexthop));
7153 else
7154 vty_out(vty, "%-16s",
7155 inet_ntoa(attr->nexthop));
7156 }
7157 } else if (((p->family == AF_INET6)
7158 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 7159 || (safi == SAFI_EVPN
d62a17ae 7160 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7161 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
ff44f570
DS
7162 char buf_a[512];
7163 char buf_b[512];
d62a17ae 7164 char buf_c[BUFSIZ];
7165 if (attr->mp_nexthop_len
7166 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7167 if (json)
7168 json_object_string_add(
7169 json_out, "mpNexthopGlobalIn",
7170 inet_ntop(
7171 AF_INET6,
7172 &attr->mp_nexthop_global,
11f9b450 7173 buf_a, sizeof(buf_a)));
d62a17ae 7174 else
7175 vty_out(vty, "%s",
7176 inet_ntop(
7177 AF_INET6,
7178 &attr->mp_nexthop_global,
11f9b450 7179 buf_a, sizeof(buf_a)));
d62a17ae 7180 } else if (attr->mp_nexthop_len
7181 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7182 if (json) {
7183 inet_ntop(AF_INET6,
7184 &attr->mp_nexthop_global,
11f9b450 7185 buf_a, sizeof(buf_a));
d62a17ae 7186 inet_ntop(AF_INET6,
7187 &attr->mp_nexthop_local,
11f9b450 7188 buf_b, sizeof(buf_b));
d62a17ae 7189 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
7190 json_object_string_add(
7191 json_out,
7192 "mpNexthopGlobalLocal", buf_c);
7193 } else
7194 vty_out(vty, "%s(%s)",
7195 inet_ntop(
7196 AF_INET6,
7197 &attr->mp_nexthop_global,
11f9b450 7198 buf_a, sizeof(buf_a)),
d62a17ae 7199 inet_ntop(
7200 AF_INET6,
7201 &attr->mp_nexthop_local,
11f9b450 7202 buf_b, sizeof(buf_b)));
d62a17ae 7203 }
7204 }
7205 }
7206
9b6d8fcf 7207 label = decode_label(&path->extra->label[0]);
d62a17ae 7208
7209 if (bgp_is_valid_label(&label)) {
7210 if (json) {
7211 json_object_int_add(json_out, "notag", label);
7212 json_object_array_add(json, json_out);
7213 } else {
7214 vty_out(vty, "notag/%d", label);
7215 vty_out(vty, "\n");
7216 }
7217 }
7218}
718e3744 7219
d62a17ae 7220void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7221 struct bgp_path_info *path, int display,
d62a17ae 7222 json_object *json_paths)
718e3744 7223{
d62a17ae 7224 struct attr *attr;
7225 char buf[BUFSIZ];
7226 json_object *json_path = NULL;
784d3a42 7227
d62a17ae 7228 if (json_paths)
7229 json_path = json_object_new_object();
856ca177 7230
9b6d8fcf 7231 if (!path->extra)
d62a17ae 7232 return;
718e3744 7233
d62a17ae 7234 /* short status lead text */
9b6d8fcf 7235 route_vty_short_status_out(vty, path, json_path);
856ca177 7236
d62a17ae 7237 /* print prefix and mask */
7238 if (!display)
9c92b5f7 7239 route_vty_out_route(p, vty, NULL);
d62a17ae 7240 else
7241 vty_out(vty, "%*s", 17, " ");
7242
7243 /* Print attribute */
9b6d8fcf 7244 attr = path->attr;
d62a17ae 7245 if (attr) {
7246 char buf1[BUFSIZ];
7247 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7248
7249 switch (af) {
7250 case AF_INET:
7251 vty_out(vty, "%-16s",
7252 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7253 BUFSIZ));
7254 break;
7255 case AF_INET6:
7256 vty_out(vty, "%s(%s)",
7257 inet_ntop(af, &attr->mp_nexthop_global, buf,
7258 BUFSIZ),
7259 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7260 BUFSIZ));
7261 break;
7262 default:
7263 vty_out(vty, "?");
7264 }
988258b4
QY
7265
7266 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7267
7268 vty_out(vty, "%s", str);
7269 XFREE(MTYPE_TMP, str);
7270
3714a385 7271 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
988258b4
QY
7272 vty_out(vty, "/%s",
7273 inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
3714a385 7274 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
988258b4
QY
7275 vty_out(vty, "/%s",
7276 inet_ntop(AF_INET6,
7277 &(attr->evpn_overlay.gw_ip.ipv6), buf,
7278 BUFSIZ));
7279 }
7280 if (attr->ecommunity) {
7281 char *mac = NULL;
7282 struct ecommunity_val *routermac = ecommunity_lookup(
7283 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7284 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7285 if (routermac)
7286 mac = ecom_mac2str((char *)routermac->val);
7287 if (mac) {
7288 vty_out(vty, "/%s", (char *)mac);
7289 XFREE(MTYPE_TMP, mac);
7290 }
7291 }
7292 vty_out(vty, "\n");
718e3744 7293 }
718e3744 7294
d62a17ae 7295}
718e3744 7296
d62a17ae 7297/* dampening route */
7298static void damp_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7299 struct bgp_path_info *path, int display,
4b7e6066 7300 safi_t safi, bool use_json, json_object *json)
d62a17ae 7301{
7302 struct attr *attr;
7303 int len;
7304 char timebuf[BGP_UPTIME_LEN];
7305
7306 /* short status lead text */
9b6d8fcf 7307 route_vty_short_status_out(vty, path, json);
d62a17ae 7308
7309 /* print prefix and mask */
7310 if (!use_json) {
7311 if (!display)
9c92b5f7 7312 route_vty_out_route(p, vty, NULL);
d62a17ae 7313 else
7314 vty_out(vty, "%*s", 17, " ");
7315 }
7316
9b6d8fcf 7317 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7318 len = 17 - len;
7319 if (len < 1) {
7320 if (!use_json)
7321 vty_out(vty, "\n%*s", 34, " ");
7322 } else {
7323 if (use_json)
7324 json_object_int_add(json, "peerHost", len);
7325 else
7326 vty_out(vty, "%*s", len, " ");
7327 }
7328
7329 if (use_json)
9b6d8fcf 7330 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
d62a17ae 7331 use_json, json);
7332 else
9b6d8fcf
DS
7333 vty_out(vty, "%s ",
7334 bgp_damp_reuse_time_vty(vty, path, timebuf,
7335 BGP_UPTIME_LEN, use_json,
7336 json));
d62a17ae 7337
7338 /* Print attribute */
9b6d8fcf 7339 attr = path->attr;
d62a17ae 7340 if (attr) {
7341 /* Print aspath */
7342 if (attr->aspath) {
7343 if (use_json)
7344 json_object_string_add(json, "asPath",
7345 attr->aspath->str);
7346 else
7347 aspath_print_vty(vty, "%s", attr->aspath, " ");
7348 }
7349
7350 /* Print origin */
7351 if (use_json)
7352 json_object_string_add(json, "origin",
7353 bgp_origin_str[attr->origin]);
7354 else
7355 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7356 }
7357 if (!use_json)
7358 vty_out(vty, "\n");
7359}
718e3744 7360
d62a17ae 7361/* flap route */
7362static void flap_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7363 struct bgp_path_info *path, int display,
4b7e6066 7364 safi_t safi, bool use_json, json_object *json)
784d3a42 7365{
d62a17ae 7366 struct attr *attr;
7367 struct bgp_damp_info *bdi;
7368 char timebuf[BGP_UPTIME_LEN];
7369 int len;
784d3a42 7370
9b6d8fcf 7371 if (!path->extra)
d62a17ae 7372 return;
784d3a42 7373
9b6d8fcf 7374 bdi = path->extra->damp_info;
784d3a42 7375
d62a17ae 7376 /* short status lead text */
9b6d8fcf 7377 route_vty_short_status_out(vty, path, json);
784d3a42 7378
d62a17ae 7379 /* print prefix and mask */
7380 if (!use_json) {
7381 if (!display)
9c92b5f7 7382 route_vty_out_route(p, vty, NULL);
d62a17ae 7383 else
7384 vty_out(vty, "%*s", 17, " ");
7385 }
784d3a42 7386
9b6d8fcf 7387 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7388 len = 16 - len;
7389 if (len < 1) {
7390 if (!use_json)
7391 vty_out(vty, "\n%*s", 33, " ");
7392 } else {
7393 if (use_json)
7394 json_object_int_add(json, "peerHost", len);
7395 else
7396 vty_out(vty, "%*s", len, " ");
7397 }
784d3a42 7398
d62a17ae 7399 len = vty_out(vty, "%d", bdi->flap);
7400 len = 5 - len;
7401 if (len < 1) {
7402 if (!use_json)
7403 vty_out(vty, " ");
7404 } else {
7405 if (use_json)
7406 json_object_int_add(json, "bdiFlap", len);
7407 else
7408 vty_out(vty, "%*s", len, " ");
7409 }
7410
7411 if (use_json)
7412 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7413 json);
7414 else
996c9314
LB
7415 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7416 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7417
9b6d8fcf
DS
7418 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
7419 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7420 if (use_json)
9b6d8fcf 7421 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 7422 BGP_UPTIME_LEN, use_json, json);
7423 else
7424 vty_out(vty, "%s ",
9b6d8fcf 7425 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 7426 BGP_UPTIME_LEN,
7427 use_json, json));
7428 } else {
7429 if (!use_json)
7430 vty_out(vty, "%*s ", 8, " ");
7431 }
7432
7433 /* Print attribute */
9b6d8fcf 7434 attr = path->attr;
d62a17ae 7435 if (attr) {
7436 /* Print aspath */
7437 if (attr->aspath) {
7438 if (use_json)
7439 json_object_string_add(json, "asPath",
7440 attr->aspath->str);
7441 else
7442 aspath_print_vty(vty, "%s", attr->aspath, " ");
7443 }
7444
7445 /* Print origin */
7446 if (use_json)
7447 json_object_string_add(json, "origin",
7448 bgp_origin_str[attr->origin]);
7449 else
7450 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7451 }
7452 if (!use_json)
7453 vty_out(vty, "\n");
7454}
7455
7456static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7457 int *first, const char *header,
7458 json_object *json_adv_to)
7459{
7460 char buf1[INET6_ADDRSTRLEN];
7461 json_object *json_peer = NULL;
7462
7463 if (json_adv_to) {
7464 /* 'advertised-to' is a dictionary of peers we have advertised
7465 * this
7466 * prefix too. The key is the peer's IP or swpX, the value is
7467 * the
7468 * hostname if we know it and "" if not.
7469 */
7470 json_peer = json_object_new_object();
7471
7472 if (peer->hostname)
7473 json_object_string_add(json_peer, "hostname",
7474 peer->hostname);
7475
7476 if (peer->conf_if)
7477 json_object_object_add(json_adv_to, peer->conf_if,
7478 json_peer);
7479 else
7480 json_object_object_add(
7481 json_adv_to,
7482 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7483 json_peer);
7484 } else {
7485 if (*first) {
7486 vty_out(vty, "%s", header);
7487 *first = 0;
7488 }
7489
7490 if (peer->hostname
7491 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7492 if (peer->conf_if)
7493 vty_out(vty, " %s(%s)", peer->hostname,
7494 peer->conf_if);
7495 else
7496 vty_out(vty, " %s(%s)", peer->hostname,
7497 sockunion2str(&peer->su, buf1,
7498 SU_ADDRSTRLEN));
7499 } else {
7500 if (peer->conf_if)
7501 vty_out(vty, " %s", peer->conf_if);
7502 else
7503 vty_out(vty, " %s",
7504 sockunion2str(&peer->su, buf1,
7505 SU_ADDRSTRLEN));
7506 }
7507 }
784d3a42
PG
7508}
7509
dcc68b5e
MS
7510static void route_vty_out_tx_ids(struct vty *vty,
7511 struct bgp_addpath_info_data *d)
7512{
7513 int i;
7514
7515 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
7516 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
7517 d->addpath_tx_id[i],
7518 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
7519 }
7520}
7521
d62a17ae 7522void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
9b6d8fcf 7523 struct bgp_path_info *path, afi_t afi, safi_t safi,
d62a17ae 7524 json_object *json_paths)
7525{
7526 char buf[INET6_ADDRSTRLEN];
7527 char buf1[BUFSIZ];
d62a17ae 7528 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 7529 struct attr *attr;
7530 int sockunion_vty_out(struct vty *, union sockunion *);
7531 time_t tbuf;
7532 json_object *json_bestpath = NULL;
7533 json_object *json_cluster_list = NULL;
7534 json_object *json_cluster_list_list = NULL;
7535 json_object *json_ext_community = NULL;
7536 json_object *json_last_update = NULL;
7fd077aa 7537 json_object *json_pmsi = NULL;
d62a17ae 7538 json_object *json_nexthop_global = NULL;
7539 json_object *json_nexthop_ll = NULL;
7540 json_object *json_nexthops = NULL;
7541 json_object *json_path = NULL;
7542 json_object *json_peer = NULL;
7543 json_object *json_string = NULL;
7544 json_object *json_adv_to = NULL;
7545 int first = 0;
7546 struct listnode *node, *nnode;
7547 struct peer *peer;
7548 int addpath_capable;
7549 int has_adj;
7550 unsigned int first_as;
1defdda8 7551 bool nexthop_self =
9b6d8fcf 7552 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 7553 int i;
d62a17ae 7554
7555 if (json_paths) {
7556 json_path = json_object_new_object();
7557 json_peer = json_object_new_object();
7558 json_nexthop_global = json_object_new_object();
7559 }
7560
d62a17ae 7561 if (!json_paths && safi == SAFI_EVPN) {
b57ba6d2 7562 char tag_buf[30];
d62a17ae 7563
7564 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7565 vty_out(vty, " Route %s", buf2);
7566 tag_buf[0] = '\0';
9b6d8fcf
DS
7567 if (path->extra && path->extra->num_labels) {
7568 bgp_evpn_label2str(path->extra->label,
7569 path->extra->num_labels, tag_buf,
a4d82a8a 7570 sizeof(tag_buf));
d62a17ae 7571 vty_out(vty, " VNI %s", tag_buf);
7572 }
7573 vty_out(vty, "\n");
9b6d8fcf 7574 if (path->extra && path->extra->parent) {
4b7e6066 7575 struct bgp_path_info *parent_ri;
d62a17ae 7576 struct bgp_node *rn, *prn;
7577
9b6d8fcf 7578 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 7579 rn = parent_ri->net;
7580 if (rn && rn->prn) {
7581 prn = rn->prn;
7582 vty_out(vty, " Imported from %s:%s\n",
7583 prefix_rd2str(
7584 (struct prefix_rd *)&prn->p,
06b9f471 7585 buf1, sizeof(buf1)),
d62a17ae 7586 buf2);
7587 }
7588 }
7589 }
d62a17ae 7590
9b6d8fcf 7591 attr = path->attr;
d62a17ae 7592
7593 if (attr) {
7594 /* Line1 display AS-path, Aggregator */
7595 if (attr->aspath) {
7596 if (json_paths) {
68e1a55b
DS
7597 if (!attr->aspath->json)
7598 aspath_str_update(attr->aspath, true);
d62a17ae 7599 json_object_lock(attr->aspath->json);
7600 json_object_object_add(json_path, "aspath",
7601 attr->aspath->json);
7602 } else {
7603 if (attr->aspath->segments)
7604 aspath_print_vty(vty, " %s",
7605 attr->aspath, "");
7606 else
7607 vty_out(vty, " Local");
7608 }
7609 }
7610
9b6d8fcf 7611 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
d62a17ae 7612 if (json_paths)
7613 json_object_boolean_true_add(json_path,
7614 "removed");
7615 else
7616 vty_out(vty, ", (removed)");
7617 }
7618
9b6d8fcf 7619 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
d62a17ae 7620 if (json_paths)
7621 json_object_boolean_true_add(json_path,
7622 "stale");
7623 else
7624 vty_out(vty, ", (stale)");
7625 }
7626
7627 if (CHECK_FLAG(attr->flag,
7628 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7629 if (json_paths) {
7630 json_object_int_add(json_path, "aggregatorAs",
7631 attr->aggregator_as);
7632 json_object_string_add(
7633 json_path, "aggregatorId",
7634 inet_ntoa(attr->aggregator_addr));
7635 } else {
7636 vty_out(vty, ", (aggregated by %u %s)",
7637 attr->aggregator_as,
7638 inet_ntoa(attr->aggregator_addr));
7639 }
7640 }
7641
9b6d8fcf 7642 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 7643 PEER_FLAG_REFLECTOR_CLIENT)) {
7644 if (json_paths)
7645 json_object_boolean_true_add(
7646 json_path, "rxedFromRrClient");
7647 else
7648 vty_out(vty, ", (Received from a RR-client)");
7649 }
7650
9b6d8fcf 7651 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 7652 PEER_FLAG_RSERVER_CLIENT)) {
7653 if (json_paths)
7654 json_object_boolean_true_add(
7655 json_path, "rxedFromRsClient");
7656 else
7657 vty_out(vty, ", (Received from a RS-client)");
7658 }
7659
9b6d8fcf 7660 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7661 if (json_paths)
7662 json_object_boolean_true_add(
7663 json_path, "dampeningHistoryEntry");
7664 else
7665 vty_out(vty, ", (history entry)");
9b6d8fcf 7666 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
d62a17ae 7667 if (json_paths)
7668 json_object_boolean_true_add(
7669 json_path, "dampeningSuppressed");
7670 else
7671 vty_out(vty, ", (suppressed due to dampening)");
7672 }
7673
7674 if (!json_paths)
7675 vty_out(vty, "\n");
7676
7677 /* Line2 display Next-hop, Neighbor, Router-id */
7678 /* Display the nexthop */
a4d82a8a
PZ
7679 if ((p->family == AF_INET || p->family == AF_ETHERNET
7680 || p->family == AF_EVPN)
d62a17ae 7681 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7682 || safi == SAFI_EVPN
7683 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7684 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7685 || safi == SAFI_EVPN) {
7686 if (json_paths)
7687 json_object_string_add(
7688 json_nexthop_global, "ip",
7689 inet_ntoa(
7690 attr->mp_nexthop_global_in));
7691 else
7692 vty_out(vty, " %s",
7693 inet_ntoa(
7694 attr->mp_nexthop_global_in));
7695 } else {
7696 if (json_paths)
7697 json_object_string_add(
7698 json_nexthop_global, "ip",
7699 inet_ntoa(attr->nexthop));
7700 else
7701 vty_out(vty, " %s",
7702 inet_ntoa(attr->nexthop));
7703 }
7704
7705 if (json_paths)
7706 json_object_string_add(json_nexthop_global,
7707 "afi", "ipv4");
7708 } else {
7709 if (json_paths) {
7710 json_object_string_add(
7711 json_nexthop_global, "ip",
7712 inet_ntop(AF_INET6,
7713 &attr->mp_nexthop_global, buf,
7714 INET6_ADDRSTRLEN));
7715 json_object_string_add(json_nexthop_global,
7716 "afi", "ipv6");
7717 json_object_string_add(json_nexthop_global,
7718 "scope", "global");
7719 } else {
7720 vty_out(vty, " %s",
7721 inet_ntop(AF_INET6,
7722 &attr->mp_nexthop_global, buf,
7723 INET6_ADDRSTRLEN));
7724 }
7725 }
7726
7727 /* Display the IGP cost or 'inaccessible' */
9b6d8fcf 7728 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 7729 if (json_paths)
7730 json_object_boolean_false_add(
7731 json_nexthop_global, "accessible");
7732 else
7733 vty_out(vty, " (inaccessible)");
7734 } else {
9b6d8fcf 7735 if (path->extra && path->extra->igpmetric) {
d62a17ae 7736 if (json_paths)
7737 json_object_int_add(
7738 json_nexthop_global, "metric",
9b6d8fcf 7739 path->extra->igpmetric);
d62a17ae 7740 else
7741 vty_out(vty, " (metric %u)",
9b6d8fcf 7742 path->extra->igpmetric);
d62a17ae 7743 }
7744
7745 /* IGP cost is 0, display this only for json */
7746 else {
7747 if (json_paths)
7748 json_object_int_add(json_nexthop_global,
7749 "metric", 0);
7750 }
7751
7752 if (json_paths)
7753 json_object_boolean_true_add(
7754 json_nexthop_global, "accessible");
7755 }
7756
7757 /* Display peer "from" output */
7758 /* This path was originated locally */
9b6d8fcf 7759 if (path->peer == bgp->peer_self) {
d62a17ae 7760
7761 if (safi == SAFI_EVPN
7762 || (p->family == AF_INET
7763 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7764 if (json_paths)
7765 json_object_string_add(
7766 json_peer, "peerId", "0.0.0.0");
7767 else
7768 vty_out(vty, " from 0.0.0.0 ");
7769 } else {
7770 if (json_paths)
7771 json_object_string_add(json_peer,
7772 "peerId", "::");
7773 else
7774 vty_out(vty, " from :: ");
7775 }
7776
7777 if (json_paths)
7778 json_object_string_add(
7779 json_peer, "routerId",
7780 inet_ntoa(bgp->router_id));
7781 else
7782 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7783 }
7784
7785 /* We RXed this path from one of our peers */
7786 else {
7787
7788 if (json_paths) {
7789 json_object_string_add(
7790 json_peer, "peerId",
9b6d8fcf 7791 sockunion2str(&path->peer->su, buf,
d62a17ae 7792 SU_ADDRSTRLEN));
7793 json_object_string_add(
7794 json_peer, "routerId",
7795 inet_ntop(AF_INET,
9b6d8fcf 7796 &path->peer->remote_id, buf1,
06b9f471 7797 sizeof(buf1)));
d62a17ae 7798
9b6d8fcf 7799 if (path->peer->hostname)
d62a17ae 7800 json_object_string_add(
7801 json_peer, "hostname",
9b6d8fcf 7802 path->peer->hostname);
d62a17ae 7803
9b6d8fcf 7804 if (path->peer->domainname)
d62a17ae 7805 json_object_string_add(
7806 json_peer, "domainname",
9b6d8fcf 7807 path->peer->domainname);
d62a17ae 7808
9b6d8fcf 7809 if (path->peer->conf_if)
d62a17ae 7810 json_object_string_add(
7811 json_peer, "interface",
9b6d8fcf 7812 path->peer->conf_if);
d62a17ae 7813 } else {
9b6d8fcf
DS
7814 if (path->peer->conf_if) {
7815 if (path->peer->hostname
d62a17ae 7816 && bgp_flag_check(
9b6d8fcf 7817 path->peer->bgp,
d62a17ae 7818 BGP_FLAG_SHOW_HOSTNAME))
7819 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
7820 path->peer->hostname,
7821 path->peer->conf_if);
d62a17ae 7822 else
7823 vty_out(vty, " from %s",
9b6d8fcf 7824 path->peer->conf_if);
d62a17ae 7825 } else {
9b6d8fcf 7826 if (path->peer->hostname
d62a17ae 7827 && bgp_flag_check(
9b6d8fcf 7828 path->peer->bgp,
d62a17ae 7829 BGP_FLAG_SHOW_HOSTNAME))
7830 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
7831 path->peer->hostname,
7832 path->peer->host);
d62a17ae 7833 else
7834 vty_out(vty, " from %s",
7835 sockunion2str(
9b6d8fcf 7836 &path->peer->su,
d62a17ae 7837 buf,
7838 SU_ADDRSTRLEN));
7839 }
7840
7841 if (attr->flag
7842 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7843 vty_out(vty, " (%s)",
7844 inet_ntoa(attr->originator_id));
7845 else
7846 vty_out(vty, " (%s)",
7847 inet_ntop(
7848 AF_INET,
9b6d8fcf 7849 &path->peer->remote_id,
06b9f471 7850 buf1, sizeof(buf1)));
d62a17ae 7851 }
7852 }
7853
9df8b37c
PZ
7854 /*
7855 * Note when vrfid of nexthop is different from that of prefix
7856 */
9b6d8fcf
DS
7857 if (path->extra && path->extra->bgp_orig) {
7858 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c
PZ
7859
7860 if (json_paths) {
7861 const char *vn;
7862
9b6d8fcf
DS
7863 if (path->extra->bgp_orig->inst_type
7864 == BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7865
03a6facf 7866 vn = VRF_DEFAULT_NAME;
9df8b37c 7867 else
9b6d8fcf 7868 vn = path->extra->bgp_orig->name;
9df8b37c
PZ
7869
7870 json_object_string_add(json_path, "nhVrfName",
7871 vn);
7872
7873 if (nexthop_vrfid == VRF_UNKNOWN) {
7874 json_object_int_add(json_path,
7875 "nhVrfId", -1);
7876 } else {
7877 json_object_int_add(json_path,
7878 "nhVrfId", (int)nexthop_vrfid);
7879 }
7880 } else {
7881 if (nexthop_vrfid == VRF_UNKNOWN)
7882 vty_out(vty, " vrf ?");
7883 else
7884 vty_out(vty, " vrf %u", nexthop_vrfid);
7885 }
7886 }
7887
7888 if (nexthop_self) {
7889 if (json_paths) {
7890 json_object_boolean_true_add(json_path,
7891 "announceNexthopSelf");
7892 } else {
7893 vty_out(vty, " announce-nh-self");
7894 }
7895 }
7896
d62a17ae 7897 if (!json_paths)
7898 vty_out(vty, "\n");
7899
7900 /* display the link-local nexthop */
7901 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7902 if (json_paths) {
7903 json_nexthop_ll = json_object_new_object();
7904 json_object_string_add(
7905 json_nexthop_ll, "ip",
7906 inet_ntop(AF_INET6,
7907 &attr->mp_nexthop_local, buf,
7908 INET6_ADDRSTRLEN));
7909 json_object_string_add(json_nexthop_ll, "afi",
7910 "ipv6");
7911 json_object_string_add(json_nexthop_ll, "scope",
7912 "link-local");
7913
7914 json_object_boolean_true_add(json_nexthop_ll,
7915 "accessible");
7916
7917 if (!attr->mp_nexthop_prefer_global)
7918 json_object_boolean_true_add(
7919 json_nexthop_ll, "used");
7920 else
7921 json_object_boolean_true_add(
7922 json_nexthop_global, "used");
7923 } else {
7924 vty_out(vty, " (%s) %s\n",
7925 inet_ntop(AF_INET6,
7926 &attr->mp_nexthop_local, buf,
7927 INET6_ADDRSTRLEN),
7928 attr->mp_nexthop_prefer_global
7929 ? "(prefer-global)"
7930 : "(used)");
7931 }
7932 }
7933 /* If we do not have a link-local nexthop then we must flag the
7934 global as "used" */
7935 else {
7936 if (json_paths)
7937 json_object_boolean_true_add(
7938 json_nexthop_global, "used");
7939 }
718e3744 7940
d62a17ae 7941 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7942 * Int/Ext/Local, Atomic, best */
7943 if (json_paths)
7944 json_object_string_add(
7945 json_path, "origin",
7946 bgp_origin_long_str[attr->origin]);
7947 else
7948 vty_out(vty, " Origin %s",
7949 bgp_origin_long_str[attr->origin]);
7950
7951 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
50e05855
AD
7952 if (json_paths) {
7953
7954 /*
7955 * Adding "metric" field to match with
7956 * corresponding CLI. "med" will be
7957 * deprecated in future.
7958 */
d62a17ae 7959 json_object_int_add(json_path, "med",
7960 attr->med);
50e05855
AD
7961 json_object_int_add(json_path, "metric",
7962 attr->med);
7963 } else
d62a17ae 7964 vty_out(vty, ", metric %u", attr->med);
7965 }
718e3744 7966
d62a17ae 7967 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7968 if (json_paths)
7969 json_object_int_add(json_path, "localpref",
7970 attr->local_pref);
7971 else
7972 vty_out(vty, ", localpref %u",
7973 attr->local_pref);
d62a17ae 7974 }
718e3744 7975
d62a17ae 7976 if (attr->weight != 0) {
7977 if (json_paths)
7978 json_object_int_add(json_path, "weight",
7979 attr->weight);
7980 else
7981 vty_out(vty, ", weight %u", attr->weight);
7982 }
718e3744 7983
d62a17ae 7984 if (attr->tag != 0) {
7985 if (json_paths)
7986 json_object_int_add(json_path, "tag",
7987 attr->tag);
7988 else
7989 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7990 attr->tag);
7991 }
718e3744 7992
9b6d8fcf 7993 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 7994 if (json_paths)
7995 json_object_boolean_false_add(json_path,
7996 "valid");
7997 else
7998 vty_out(vty, ", invalid");
9b6d8fcf 7999 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8000 if (json_paths)
8001 json_object_boolean_true_add(json_path,
8002 "valid");
8003 else
8004 vty_out(vty, ", valid");
8005 }
718e3744 8006
9b6d8fcf
DS
8007 if (path->peer != bgp->peer_self) {
8008 if (path->peer->as == path->peer->local_as) {
d62a17ae 8009 if (CHECK_FLAG(bgp->config,
8010 BGP_CONFIG_CONFEDERATION)) {
8011 if (json_paths)
8012 json_object_string_add(
8013 json_peer, "type",
8014 "confed-internal");
8015 else
8016 vty_out(vty,
8017 ", confed-internal");
8018 } else {
8019 if (json_paths)
8020 json_object_string_add(
8021 json_peer, "type",
8022 "internal");
8023 else
8024 vty_out(vty, ", internal");
8025 }
8026 } else {
8027 if (bgp_confederation_peers_check(
9b6d8fcf 8028 bgp, path->peer->as)) {
d62a17ae 8029 if (json_paths)
8030 json_object_string_add(
8031 json_peer, "type",
8032 "confed-external");
8033 else
8034 vty_out(vty,
8035 ", confed-external");
8036 } else {
8037 if (json_paths)
8038 json_object_string_add(
8039 json_peer, "type",
8040 "external");
8041 else
8042 vty_out(vty, ", external");
8043 }
8044 }
9b6d8fcf 8045 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
d62a17ae 8046 if (json_paths) {
8047 json_object_boolean_true_add(json_path,
8048 "aggregated");
8049 json_object_boolean_true_add(json_path,
8050 "local");
8051 } else {
8052 vty_out(vty, ", aggregated, local");
8053 }
9b6d8fcf 8054 } else if (path->type != ZEBRA_ROUTE_BGP) {
d62a17ae 8055 if (json_paths)
8056 json_object_boolean_true_add(json_path,
8057 "sourced");
8058 else
8059 vty_out(vty, ", sourced");
8060 } else {
8061 if (json_paths) {
8062 json_object_boolean_true_add(json_path,
8063 "sourced");
8064 json_object_boolean_true_add(json_path,
8065 "local");
8066 } else {
8067 vty_out(vty, ", sourced, local");
8068 }
8069 }
718e3744 8070
d62a17ae 8071 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
8072 if (json_paths)
8073 json_object_boolean_true_add(json_path,
8074 "atomicAggregate");
8075 else
8076 vty_out(vty, ", atomic-aggregate");
8077 }
718e3744 8078
9b6d8fcf
DS
8079 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8080 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8081 && bgp_path_info_mpath_count(path))) {
d62a17ae 8082 if (json_paths)
8083 json_object_boolean_true_add(json_path,
8084 "multipath");
8085 else
8086 vty_out(vty, ", multipath");
8087 }
856ca177 8088
d62a17ae 8089 // Mark the bestpath(s)
9b6d8fcf 8090 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
d62a17ae 8091 first_as = aspath_get_first_as(attr->aspath);
8092
8093 if (json_paths) {
8094 if (!json_bestpath)
8095 json_bestpath =
8096 json_object_new_object();
8097 json_object_int_add(json_bestpath,
8098 "bestpathFromAs", first_as);
8099 } else {
8100 if (first_as)
fb2b0934 8101 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 8102 first_as);
8103 else
8104 vty_out(vty,
8105 ", bestpath-from-AS Local");
8106 }
8107 }
718e3744 8108
9b6d8fcf 8109 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8110 if (json_paths) {
8111 if (!json_bestpath)
8112 json_bestpath =
8113 json_object_new_object();
8114 json_object_boolean_true_add(json_bestpath,
8115 "overall");
8116 } else
8117 vty_out(vty, ", best");
8118 }
718e3744 8119
d62a17ae 8120 if (json_bestpath)
8121 json_object_object_add(json_path, "bestpath",
8122 json_bestpath);
8123
8124 if (!json_paths)
8125 vty_out(vty, "\n");
8126
8127 /* Line 4 display Community */
8128 if (attr->community) {
8129 if (json_paths) {
a69ea8ae 8130 if (!attr->community->json)
a4d82a8a 8131 community_str(attr->community, true);
d62a17ae 8132 json_object_lock(attr->community->json);
8133 json_object_object_add(json_path, "community",
8134 attr->community->json);
8135 } else {
8136 vty_out(vty, " Community: %s\n",
8137 attr->community->str);
8138 }
8139 }
718e3744 8140
d62a17ae 8141 /* Line 5 display Extended-community */
8142 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8143 if (json_paths) {
8144 json_ext_community = json_object_new_object();
8145 json_object_string_add(json_ext_community,
8146 "string",
8147 attr->ecommunity->str);
8148 json_object_object_add(json_path,
8149 "extendedCommunity",
8150 json_ext_community);
8151 } else {
8152 vty_out(vty, " Extended Community: %s\n",
8153 attr->ecommunity->str);
8154 }
8155 }
adbac85e 8156
d62a17ae 8157 /* Line 6 display Large community */
b96879c0
DS
8158 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8159 if (json_paths) {
8d9b8ed9
PM
8160 if (!attr->lcommunity->json)
8161 lcommunity_str(attr->lcommunity, true);
8162 json_object_lock(attr->lcommunity->json);
b96879c0
DS
8163 json_object_object_add(json_path,
8164 "largeCommunity",
8d9b8ed9 8165 attr->lcommunity->json);
b96879c0
DS
8166 } else {
8167 vty_out(vty, " Large Community: %s\n",
8168 attr->lcommunity->str);
8169 }
8170 }
d62a17ae 8171
8172 /* Line 7 display Originator, Cluster-id */
8173 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8174 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8175 if (attr->flag
8176 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
8177 if (json_paths)
8178 json_object_string_add(
8179 json_path, "originatorId",
8180 inet_ntoa(attr->originator_id));
8181 else
8182 vty_out(vty, " Originator: %s",
8183 inet_ntoa(attr->originator_id));
8184 }
8185
8186 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8187 int i;
8188
8189 if (json_paths) {
8190 json_cluster_list =
8191 json_object_new_object();
8192 json_cluster_list_list =
8193 json_object_new_array();
8194
8195 for (i = 0;
8196 i < attr->cluster->length / 4;
8197 i++) {
8198 json_string = json_object_new_string(
8199 inet_ntoa(
8200 attr->cluster->list
8201 [i]));
8202 json_object_array_add(
8203 json_cluster_list_list,
8204 json_string);
8205 }
8206
8207 /* struct cluster_list does not have
8208 "str" variable like
8209 * aspath and community do. Add this
8210 someday if someone
8211 * asks for it.
8212 json_object_string_add(json_cluster_list,
8213 "string", attr->cluster->str);
8214 */
8215 json_object_object_add(
8216 json_cluster_list, "list",
8217 json_cluster_list_list);
8218 json_object_object_add(
8219 json_path, "clusterList",
8220 json_cluster_list);
8221 } else {
8222 vty_out(vty, ", Cluster list: ");
8223
8224 for (i = 0;
8225 i < attr->cluster->length / 4;
8226 i++) {
8227 vty_out(vty, "%s ",
8228 inet_ntoa(
8229 attr->cluster->list
8230 [i]));
8231 }
8232 }
8233 }
8234
8235 if (!json_paths)
8236 vty_out(vty, "\n");
8237 }
adbac85e 8238
9b6d8fcf
DS
8239 if (path->extra && path->extra->damp_info)
8240 bgp_damp_info_vty(vty, path, json_path);
d62a17ae 8241
6a527b2f 8242 /* Remote Label */
9b6d8fcf 8243 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
6a527b2f 8244 && safi != SAFI_EVPN) {
9b6d8fcf 8245 mpls_label_t label = label_pton(&path->extra->label[0]);
121e245d 8246
d62a17ae 8247 if (json_paths)
8248 json_object_int_add(json_path, "remoteLabel",
8249 label);
8250 else
8251 vty_out(vty, " Remote label: %d\n", label);
8252 }
b05a1c8b 8253
d62a17ae 8254 /* Label Index */
8255 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8256 if (json_paths)
8257 json_object_int_add(json_path, "labelIndex",
8258 attr->label_index);
8259 else
8260 vty_out(vty, " Label Index: %d\n",
8261 attr->label_index);
8262 }
520d5d76 8263
d62a17ae 8264 /* Line 8 display Addpath IDs */
dcc68b5e
MS
8265 if (path->addpath_rx_id
8266 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
d62a17ae 8267 if (json_paths) {
8268 json_object_int_add(json_path, "addpathRxId",
9b6d8fcf 8269 path->addpath_rx_id);
dcc68b5e
MS
8270
8271 /* Keep backwards compatibility with the old API
8272 * by putting TX All's ID in the old field
8273 */
8274 json_object_int_add(
8275 json_path, "addpathTxId",
8276 path->tx_addpath.addpath_tx_id
8277 [BGP_ADDPATH_ALL]);
8278
8279 /* ... but create a specific field for each
8280 * strategy
8281 */
8282 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8283 json_object_int_add(
8284 json_path,
8285 bgp_addpath_names(i)
8286 ->id_json_name,
8287 path->tx_addpath
8288 .addpath_tx_id[i]);
8289 }
d62a17ae 8290 } else {
dcc68b5e
MS
8291 vty_out(vty, " AddPath ID: RX %u, ",
8292 path->addpath_rx_id);
8293
8294 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 8295 }
8296 }
718e3744 8297
d62a17ae 8298 /* If we used addpath to TX a non-bestpath we need to display
dcc68b5e
MS
8299 * "Advertised to" on a path-by-path basis
8300 */
8301 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 8302 first = 1;
8303
8304 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8305 addpath_capable =
8306 bgp_addpath_encode_tx(peer, afi, safi);
8307 has_adj = bgp_adj_out_lookup(
dcc68b5e
MS
8308 peer, path->net,
8309 bgp_addpath_id_for_peer(
8310 peer, afi, safi,
8311 &path->tx_addpath));
d62a17ae 8312
8313 if ((addpath_capable && has_adj)
8314 || (!addpath_capable && has_adj
9b6d8fcf 8315 && CHECK_FLAG(path->flags,
1defdda8 8316 BGP_PATH_SELECTED))) {
d62a17ae 8317 if (json_path && !json_adv_to)
8318 json_adv_to =
8319 json_object_new_object();
8320
8321 route_vty_out_advertised_to(
8322 vty, peer, &first,
8323 " Advertised to:",
8324 json_adv_to);
8325 }
8326 }
8327
8328 if (json_path) {
8329 if (json_adv_to) {
8330 json_object_object_add(json_path,
8331 "advertisedTo",
8332 json_adv_to);
8333 }
8334 } else {
8335 if (!first) {
8336 vty_out(vty, "\n");
8337 }
8338 }
8339 }
b05a1c8b 8340
d62a17ae 8341 /* Line 9 display Uptime */
9b6d8fcf 8342 tbuf = time(NULL) - (bgp_clock() - path->uptime);
d62a17ae 8343 if (json_paths) {
8344 json_last_update = json_object_new_object();
8345 json_object_int_add(json_last_update, "epoch", tbuf);
8346 json_object_string_add(json_last_update, "string",
8347 ctime(&tbuf));
8348 json_object_object_add(json_path, "lastUpdate",
8349 json_last_update);
8350 } else
8351 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 8352
8353 /* Line 10 display PMSI tunnel attribute, if present */
8354 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 8355 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
8356 attr->pmsi_tnl_type,
8357 PMSI_TNLTYPE_STR_DEFAULT);
8358
7fd077aa 8359 if (json_paths) {
8360 json_pmsi = json_object_new_object();
b7d08f5a 8361 json_object_string_add(json_pmsi,
8362 "tunnelType", str);
7fd077aa 8363 json_object_object_add(json_path, "pmsi",
8364 json_pmsi);
8365 } else
8366 vty_out(vty, " PMSI Tunnel Type: %s\n",
b7d08f5a 8367 str);
7fd077aa 8368 }
8369
d62a17ae 8370 }
f1aa5d8a 8371
d62a17ae 8372 /* We've constructed the json object for this path, add it to the json
8373 * array of paths
8374 */
8375 if (json_paths) {
8376 if (json_nexthop_global || json_nexthop_ll) {
8377 json_nexthops = json_object_new_array();
f1aa5d8a 8378
d62a17ae 8379 if (json_nexthop_global)
8380 json_object_array_add(json_nexthops,
8381 json_nexthop_global);
f1aa5d8a 8382
d62a17ae 8383 if (json_nexthop_ll)
8384 json_object_array_add(json_nexthops,
8385 json_nexthop_ll);
f1aa5d8a 8386
d62a17ae 8387 json_object_object_add(json_path, "nexthops",
8388 json_nexthops);
8389 }
8390
8391 json_object_object_add(json_path, "peer", json_peer);
8392 json_object_array_add(json_paths, json_path);
8393 } else
8394 vty_out(vty, "\n");
b366b518
BB
8395}
8396
96ade3ed 8397#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8398#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8399#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8400
d62a17ae 8401static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8402 const char *prefix_list_str, afi_t afi,
8403 safi_t safi, enum bgp_show_type type);
8404static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8405 const char *filter, afi_t afi, safi_t safi,
8406 enum bgp_show_type type);
8407static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8408 const char *rmap_str, afi_t afi, safi_t safi,
8409 enum bgp_show_type type);
8410static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8411 const char *com, int exact, afi_t afi,
8412 safi_t safi);
8413static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8414 const char *prefix, afi_t afi, safi_t safi,
8415 enum bgp_show_type type);
a4d82a8a
PZ
8416static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
8417 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
8418static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8419 const char *comstr, int exact, afi_t afi,
9f049418 8420 safi_t safi, bool use_json);
d62a17ae 8421
1ae44dfc
LB
8422
8423static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8424 struct bgp_table *table, enum bgp_show_type type,
9f049418 8425 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
8426 int is_last, unsigned long *output_cum,
8427 unsigned long *total_cum,
9386b588 8428 unsigned long *json_header_depth)
d62a17ae 8429{
40381db7 8430 struct bgp_path_info *pi;
d62a17ae 8431 struct bgp_node *rn;
8432 int header = 1;
8433 int display;
1ae44dfc
LB
8434 unsigned long output_count = 0;
8435 unsigned long total_count = 0;
d62a17ae 8436 struct prefix *p;
d62a17ae 8437 char buf2[BUFSIZ];
8438 json_object *json_paths = NULL;
8439 int first = 1;
8440
1ae44dfc
LB
8441 if (output_cum && *output_cum != 0)
8442 header = 0;
8443
9386b588 8444 if (use_json && !*json_header_depth) {
d62a17ae 8445 vty_out(vty,
66f80d74 8446 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
8447 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8448 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 8449 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
8450 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
8451 ? VRF_DEFAULT_NAME
8452 : bgp->name,
01eced22
AD
8453 table->version, inet_ntoa(bgp->router_id),
8454 bgp->default_local_pref, bgp->as);
9386b588
PZ
8455 *json_header_depth = 2;
8456 if (rd) {
445c2480 8457 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
8458 ++*json_header_depth;
8459 }
d62a17ae 8460 }
718e3744 8461
445c2480
DS
8462 if (use_json && rd) {
8463 vty_out(vty, " \"%s\" : { ", rd);
8464 }
8465
d62a17ae 8466 /* Start processing of routes. */
98ce9a06 8467 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
8468 pi = bgp_node_get_bgp_path_info(rn);
8469 if (pi == NULL)
98ce9a06 8470 continue;
d62a17ae 8471
98ce9a06 8472 display = 0;
98ce9a06
DS
8473 if (use_json)
8474 json_paths = json_object_new_array();
8475 else
8476 json_paths = NULL;
d62a17ae 8477
6f94b685 8478 for (; pi; pi = pi->next) {
98ce9a06
DS
8479 total_count++;
8480 if (type == bgp_show_type_flap_statistics
8481 || type == bgp_show_type_flap_neighbor
8482 || type == bgp_show_type_dampend_paths
8483 || type == bgp_show_type_damp_neighbor) {
40381db7 8484 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
8485 continue;
8486 }
8487 if (type == bgp_show_type_regexp) {
8488 regex_t *regex = output_arg;
d62a17ae 8489
40381db7 8490 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
8491 == REG_NOMATCH)
8492 continue;
8493 }
8494 if (type == bgp_show_type_prefix_list) {
8495 struct prefix_list *plist = output_arg;
d62a17ae 8496
98ce9a06
DS
8497 if (prefix_list_apply(plist, &rn->p)
8498 != PREFIX_PERMIT)
8499 continue;
8500 }
8501 if (type == bgp_show_type_filter_list) {
8502 struct as_list *as_list = output_arg;
d62a17ae 8503
40381db7 8504 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
8505 != AS_FILTER_PERMIT)
8506 continue;
8507 }
8508 if (type == bgp_show_type_route_map) {
8509 struct route_map *rmap = output_arg;
9b6d8fcf 8510 struct bgp_path_info path;
98ce9a06
DS
8511 struct attr dummy_attr;
8512 int ret;
d62a17ae 8513
40381db7 8514 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 8515
40381db7 8516 path.peer = pi->peer;
9b6d8fcf 8517 path.attr = &dummy_attr;
d62a17ae 8518
a4d82a8a 8519 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 8520 &path);
98ce9a06
DS
8521 if (ret == RMAP_DENYMATCH)
8522 continue;
8523 }
8524 if (type == bgp_show_type_neighbor
8525 || type == bgp_show_type_flap_neighbor
8526 || type == bgp_show_type_damp_neighbor) {
8527 union sockunion *su = output_arg;
8528
40381db7
DS
8529 if (pi->peer == NULL
8530 || pi->peer->su_remote == NULL
8531 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
8532 continue;
8533 }
8534 if (type == bgp_show_type_cidr_only) {
d7c0a89a 8535 uint32_t destination;
d62a17ae 8536
98ce9a06
DS
8537 destination = ntohl(rn->p.u.prefix4.s_addr);
8538 if (IN_CLASSC(destination)
8539 && rn->p.prefixlen == 24)
8540 continue;
8541 if (IN_CLASSB(destination)
8542 && rn->p.prefixlen == 16)
8543 continue;
8544 if (IN_CLASSA(destination)
8545 && rn->p.prefixlen == 8)
8546 continue;
8547 }
8548 if (type == bgp_show_type_prefix_longer) {
f7813c7c 8549 p = output_arg;
98ce9a06
DS
8550 if (!prefix_match(p, &rn->p))
8551 continue;
8552 }
8553 if (type == bgp_show_type_community_all) {
40381db7 8554 if (!pi->attr->community)
98ce9a06
DS
8555 continue;
8556 }
8557 if (type == bgp_show_type_community) {
8558 struct community *com = output_arg;
d62a17ae 8559
40381db7
DS
8560 if (!pi->attr->community
8561 || !community_match(pi->attr->community,
98ce9a06
DS
8562 com))
8563 continue;
8564 }
8565 if (type == bgp_show_type_community_exact) {
8566 struct community *com = output_arg;
d62a17ae 8567
40381db7
DS
8568 if (!pi->attr->community
8569 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
8570 continue;
8571 }
8572 if (type == bgp_show_type_community_list) {
8573 struct community_list *list = output_arg;
d62a17ae 8574
40381db7 8575 if (!community_list_match(pi->attr->community,
a4d82a8a 8576 list))
98ce9a06
DS
8577 continue;
8578 }
a4d82a8a 8579 if (type == bgp_show_type_community_list_exact) {
98ce9a06 8580 struct community_list *list = output_arg;
d62a17ae 8581
98ce9a06 8582 if (!community_list_exact_match(
40381db7 8583 pi->attr->community, list))
98ce9a06
DS
8584 continue;
8585 }
8586 if (type == bgp_show_type_lcommunity) {
8587 struct lcommunity *lcom = output_arg;
d62a17ae 8588
40381db7
DS
8589 if (!pi->attr->lcommunity
8590 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
8591 lcom))
8592 continue;
8593 }
8594 if (type == bgp_show_type_lcommunity_list) {
8595 struct community_list *list = output_arg;
d62a17ae 8596
40381db7 8597 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 8598 list))
98ce9a06
DS
8599 continue;
8600 }
8601 if (type == bgp_show_type_lcommunity_all) {
40381db7 8602 if (!pi->attr->lcommunity)
98ce9a06
DS
8603 continue;
8604 }
8605 if (type == bgp_show_type_dampend_paths
8606 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
8607 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
8608 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
8609 continue;
8610 }
8611
8612 if (!use_json && header) {
996c9314 8613 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 8614 ", local router ID is %s, vrf id ",
98ce9a06
DS
8615 table->version,
8616 inet_ntoa(bgp->router_id));
9df8b37c
PZ
8617 if (bgp->vrf_id == VRF_UNKNOWN)
8618 vty_out(vty, "%s", VRFID_NONE_STR);
8619 else
8620 vty_out(vty, "%u", bgp->vrf_id);
8621 vty_out(vty, "\n");
01eced22
AD
8622 vty_out(vty, "Default local pref %u, ",
8623 bgp->default_local_pref);
8624 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 8625 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 8626 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 8627 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8628 if (type == bgp_show_type_dampend_paths
8629 || type == bgp_show_type_damp_neighbor)
98ce9a06 8630 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
8631 else if (type == bgp_show_type_flap_statistics
8632 || type == bgp_show_type_flap_neighbor)
98ce9a06 8633 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8634 else
98ce9a06
DS
8635 vty_out(vty, BGP_SHOW_HEADER);
8636 header = 0;
d62a17ae 8637 }
98ce9a06
DS
8638 if (rd != NULL && !display && !output_count) {
8639 if (!use_json)
8640 vty_out(vty,
8641 "Route Distinguisher: %s\n",
8642 rd);
d62a17ae 8643 }
98ce9a06
DS
8644 if (type == bgp_show_type_dampend_paths
8645 || type == bgp_show_type_damp_neighbor)
40381db7 8646 damp_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 8647 safi, use_json, json_paths);
98ce9a06
DS
8648 else if (type == bgp_show_type_flap_statistics
8649 || type == bgp_show_type_flap_neighbor)
40381db7 8650 flap_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 8651 safi, use_json, json_paths);
98ce9a06 8652 else
40381db7 8653 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 8654 json_paths);
98ce9a06 8655 display++;
d62a17ae 8656 }
8657
98ce9a06
DS
8658 if (display) {
8659 output_count++;
8660 if (!use_json)
8661 continue;
8662
8663 p = &rn->p;
625d2931
PG
8664 /* encode prefix */
8665 if (p->family == AF_FLOWSPEC) {
8666 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
8667
8668 bgp_fs_nlri_get_string((unsigned char *)
8669 p->u.prefix_flowspec.ptr,
8670 p->u.prefix_flowspec
8671 .prefixlen,
8672 retstr,
8673 NLRI_STRING_FORMAT_MIN,
8674 NULL);
8675 if (first)
8676 vty_out(vty, "\"%s/%d\": ",
8677 retstr,
8678 p->u.prefix_flowspec.prefixlen);
8679 else
8680 vty_out(vty, ",\"%s/%d\": ",
8681 retstr,
8682 p->u.prefix_flowspec.prefixlen);
8683 } else {
8684 prefix2str(p, buf2, sizeof(buf2));
8685 if (first)
8686 vty_out(vty, "\"%s\": ", buf2);
8687 else
8688 vty_out(vty, ",\"%s\": ", buf2);
8689 }
98ce9a06 8690 vty_out(vty, "%s",
23b2a7ef 8691 json_object_to_json_string(json_paths));
98ce9a06 8692 json_object_free(json_paths);
449feb8e 8693 json_paths = NULL;
98ce9a06
DS
8694 first = 0;
8695 }
8696 }
8697
1ae44dfc
LB
8698 if (output_cum) {
8699 output_count += *output_cum;
8700 *output_cum = output_count;
8701 }
8702 if (total_cum) {
8703 total_count += *total_cum;
8704 *total_cum = total_count;
8705 }
d62a17ae 8706 if (use_json) {
9386b588 8707 if (rd) {
a4d82a8a 8708 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
8709 }
8710 if (is_last) {
a4d82a8a
PZ
8711 unsigned long i;
8712 for (i = 0; i < *json_header_depth; ++i)
8713 vty_out(vty, " } ");
9386b588 8714 }
d62a17ae 8715 } else {
1ae44dfc
LB
8716 if (is_last) {
8717 /* No route is displayed */
8718 if (output_count == 0) {
8719 if (type == bgp_show_type_normal)
8720 vty_out(vty,
8721 "No BGP prefixes displayed, %ld exist\n",
8722 total_count);
8723 } else
d62a17ae 8724 vty_out(vty,
1ae44dfc
LB
8725 "\nDisplayed %ld routes and %ld total paths\n",
8726 output_count, total_count);
8727 }
d62a17ae 8728 }
718e3744 8729
d62a17ae 8730 return CMD_SUCCESS;
718e3744 8731}
8732
1ae44dfc
LB
8733int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8734 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 8735 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
8736{
8737 struct bgp_node *rn, *next;
8738 unsigned long output_cum = 0;
8739 unsigned long total_cum = 0;
9386b588 8740 unsigned long json_header_depth = 0;
67009e22 8741 struct bgp_table *itable;
0136788c
LB
8742 bool show_msg;
8743
8744 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
8745
8746 for (rn = bgp_table_top(table); rn; rn = next) {
8747 next = bgp_route_next(rn);
8748 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8749 continue;
67009e22
DS
8750
8751 itable = bgp_node_get_bgp_table_info(rn);
8752 if (itable != NULL) {
1ae44dfc 8753 struct prefix_rd prd;
06b9f471 8754 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8755
8756 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8757 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
8758 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
8759 use_json, rd, next == NULL, &output_cum,
8760 &total_cum, &json_header_depth);
0136788c
LB
8761 if (next == NULL)
8762 show_msg = false;
1ae44dfc
LB
8763 }
8764 }
0136788c
LB
8765 if (show_msg) {
8766 if (output_cum == 0)
8767 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
8768 total_cum);
8769 else
8770 vty_out(vty,
8771 "\nDisplayed %ld routes and %ld total paths\n",
8772 output_cum, total_cum);
8773 }
1ae44dfc
LB
8774 return CMD_SUCCESS;
8775}
d62a17ae 8776static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 8777 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 8778{
d62a17ae 8779 struct bgp_table *table;
9386b588 8780 unsigned long json_header_depth = 0;
fee0f4c6 8781
d62a17ae 8782 if (bgp == NULL) {
8783 bgp = bgp_get_default();
8784 }
fee0f4c6 8785
d62a17ae 8786 if (bgp == NULL) {
8787 if (!use_json)
8788 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8789 else
8790 vty_out(vty, "{}\n");
d62a17ae 8791 return CMD_WARNING;
8792 }
4dd6177e 8793
1ae44dfc 8794 table = bgp->rib[afi][safi];
d62a17ae 8795 /* use MPLS and ENCAP specific shows until they are merged */
8796 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
8797 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
8798 output_arg, use_json);
d62a17ae 8799 }
dba3c1d3
PG
8800
8801 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
8802 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
8803 output_arg, use_json,
8804 1, NULL, NULL);
8805 }
d62a17ae 8806 /* labeled-unicast routes live in the unicast table */
8807 else if (safi == SAFI_LABELED_UNICAST)
8808 safi = SAFI_UNICAST;
fee0f4c6 8809
1ae44dfc 8810 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 8811 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 8812}
8813
d62a17ae 8814static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 8815 safi_t safi, bool use_json)
f186de26 8816{
d62a17ae 8817 struct listnode *node, *nnode;
8818 struct bgp *bgp;
8819 int is_first = 1;
9f049418 8820 bool route_output = false;
f186de26 8821
d62a17ae 8822 if (use_json)
8823 vty_out(vty, "{\n");
9f689658 8824
d62a17ae 8825 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 8826 route_output = true;
d62a17ae 8827 if (use_json) {
8828 if (!is_first)
8829 vty_out(vty, ",\n");
8830 else
8831 is_first = 0;
8832
8833 vty_out(vty, "\"%s\":",
8834 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8835 ? VRF_DEFAULT_NAME
d62a17ae 8836 : bgp->name);
8837 } else {
8838 vty_out(vty, "\nInstance %s:\n",
8839 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8840 ? VRF_DEFAULT_NAME
d62a17ae 8841 : bgp->name);
8842 }
8843 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8844 use_json);
8845 }
9f689658 8846
d62a17ae 8847 if (use_json)
8848 vty_out(vty, "}\n");
9f049418
DS
8849 else if (!route_output)
8850 vty_out(vty, "%% BGP instance not found\n");
f186de26 8851}
8852
718e3744 8853/* Header of detailed BGP route information */
d62a17ae 8854void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8855 struct bgp_node *rn, struct prefix_rd *prd,
8856 afi_t afi, safi_t safi, json_object *json)
8857{
40381db7 8858 struct bgp_path_info *pi;
d62a17ae 8859 struct prefix *p;
8860 struct peer *peer;
8861 struct listnode *node, *nnode;
06b9f471 8862 char buf1[RD_ADDRSTRLEN];
d62a17ae 8863 char buf2[INET6_ADDRSTRLEN];
d62a17ae 8864 char buf3[EVPN_ROUTE_STRLEN];
0291c246 8865 char prefix_str[BUFSIZ];
d62a17ae 8866 int count = 0;
8867 int best = 0;
8868 int suppress = 0;
c5f1e1b2
C
8869 int accept_own = 0;
8870 int route_filter_translated_v4 = 0;
8871 int route_filter_v4 = 0;
8872 int route_filter_translated_v6 = 0;
8873 int route_filter_v6 = 0;
8874 int llgr_stale = 0;
8875 int no_llgr = 0;
8876 int accept_own_nexthop = 0;
8877 int blackhole = 0;
d62a17ae 8878 int no_export = 0;
8879 int no_advertise = 0;
8880 int local_as = 0;
c5f1e1b2 8881 int no_peer = 0;
d62a17ae 8882 int first = 1;
8883 int has_valid_label = 0;
8884 mpls_label_t label = 0;
8885 json_object *json_adv_to = NULL;
9bedbb1e 8886
d62a17ae 8887 p = &rn->p;
8888 has_valid_label = bgp_is_valid_label(&rn->local_label);
8889
8890 if (has_valid_label)
8891 label = label_pton(&rn->local_label);
8892
8893 if (json) {
8894 if (has_valid_label)
8895 json_object_int_add(json, "localLabel", label);
8896
60466a63
QY
8897 json_object_string_add(
8898 json, "prefix",
8899 prefix2str(p, prefix_str, sizeof(prefix_str)));
d62a17ae 8900 } else {
d62a17ae 8901 if (safi == SAFI_EVPN)
8902 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 8903 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 8904 : "",
8905 prd ? ":" : "",
8906 bgp_evpn_route2str((struct prefix_evpn *)p,
8907 buf3, sizeof(buf3)));
8908 else
8909 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8910 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8911 ? prefix_rd2str(prd, buf1,
06b9f471 8912 sizeof(buf1))
d62a17ae 8913 : ""),
8914 safi == SAFI_MPLS_VPN ? ":" : "",
8915 inet_ntop(p->family, &p->u.prefix, buf2,
8916 INET6_ADDRSTRLEN),
8917 p->prefixlen);
cd1964ff 8918
d62a17ae 8919 if (has_valid_label)
8920 vty_out(vty, "Local label: %d\n", label);
d62a17ae 8921 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 8922 vty_out(vty, "not allocated\n");
8923 }
718e3744 8924
6f94b685 8925 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 8926 count++;
40381db7 8927 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 8928 best = count;
40381db7 8929 if (pi->extra && pi->extra->suppress)
d62a17ae 8930 suppress = 1;
cee9c031 8931
40381db7 8932 if (pi->attr->community == NULL)
cee9c031
QY
8933 continue;
8934
8935 no_advertise += community_include(
40381db7
DS
8936 pi->attr->community, COMMUNITY_NO_ADVERTISE);
8937 no_export += community_include(pi->attr->community,
cee9c031 8938 COMMUNITY_NO_EXPORT);
40381db7 8939 local_as += community_include(pi->attr->community,
cee9c031 8940 COMMUNITY_LOCAL_AS);
40381db7 8941 accept_own += community_include(pi->attr->community,
cee9c031
QY
8942 COMMUNITY_ACCEPT_OWN);
8943 route_filter_translated_v4 += community_include(
40381db7 8944 pi->attr->community,
cee9c031
QY
8945 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
8946 route_filter_translated_v6 += community_include(
40381db7 8947 pi->attr->community,
cee9c031
QY
8948 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
8949 route_filter_v4 += community_include(
40381db7 8950 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 8951 route_filter_v6 += community_include(
40381db7
DS
8952 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
8953 llgr_stale += community_include(pi->attr->community,
cee9c031 8954 COMMUNITY_LLGR_STALE);
40381db7 8955 no_llgr += community_include(pi->attr->community,
cee9c031
QY
8956 COMMUNITY_NO_LLGR);
8957 accept_own_nexthop +=
40381db7 8958 community_include(pi->attr->community,
cee9c031 8959 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 8960 blackhole += community_include(pi->attr->community,
cee9c031 8961 COMMUNITY_BLACKHOLE);
40381db7 8962 no_peer += community_include(pi->attr->community,
cee9c031 8963 COMMUNITY_NO_PEER);
d62a17ae 8964 }
718e3744 8965 }
718e3744 8966
d62a17ae 8967 if (!json) {
8968 vty_out(vty, "Paths: (%d available", count);
8969 if (best) {
8970 vty_out(vty, ", best #%d", best);
8971 if (safi == SAFI_UNICAST)
8972 vty_out(vty, ", table %s",
8973 (bgp->inst_type
8974 == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8975 ? VRF_DEFAULT_NAME
d62a17ae 8976 : bgp->name);
8977 } else
8978 vty_out(vty, ", no best path");
8979
c5f1e1b2
C
8980 if (accept_own)
8981 vty_out(vty,
8982 ", accept own local route exported and imported in different VRF");
8983 else if (route_filter_translated_v4)
8984 vty_out(vty,
8985 ", mark translated RTs for VPNv4 route filtering");
8986 else if (route_filter_v4)
8987 vty_out(vty,
8988 ", attach RT as-is for VPNv4 route filtering");
8989 else if (route_filter_translated_v6)
8990 vty_out(vty,
8991 ", mark translated RTs for VPNv6 route filtering");
8992 else if (route_filter_v6)
8993 vty_out(vty,
8994 ", attach RT as-is for VPNv6 route filtering");
8995 else if (llgr_stale)
8996 vty_out(vty,
8997 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8998 else if (no_llgr)
8999 vty_out(vty,
9000 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9001 else if (accept_own_nexthop)
9002 vty_out(vty,
9003 ", accept local nexthop");
9004 else if (blackhole)
9005 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9006 else if (no_export)
9007 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9008 else if (no_advertise)
9009 vty_out(vty, ", not advertised to any peer");
d62a17ae 9010 else if (local_as)
9011 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9012 else if (no_peer)
9013 vty_out(vty,
9014 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9015
9016 if (suppress)
9017 vty_out(vty,
9018 ", Advertisements suppressed by an aggregate.");
9019 vty_out(vty, ")\n");
9020 }
718e3744 9021
d62a17ae 9022 /* If we are not using addpath then we can display Advertised to and
9023 * that will
9024 * show what peers we advertised the bestpath to. If we are using
9025 * addpath
9026 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9027 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9028 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9029 if (bgp_adj_out_lookup(peer, rn, 0)) {
9030 if (json && !json_adv_to)
9031 json_adv_to = json_object_new_object();
9032
9033 route_vty_out_advertised_to(
9034 vty, peer, &first,
9035 " Advertised to non peer-group peers:\n ",
9036 json_adv_to);
9037 }
9038 }
9039
9040 if (json) {
9041 if (json_adv_to) {
9042 json_object_object_add(json, "advertisedTo",
9043 json_adv_to);
9044 }
9045 } else {
9046 if (first)
9047 vty_out(vty, " Not advertised to any peer");
9048 vty_out(vty, "\n");
9049 }
9050 }
718e3744 9051}
9052
9053/* Display specified route of BGP table. */
d62a17ae 9054static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9055 struct bgp_table *rib, const char *ip_str,
9056 afi_t afi, safi_t safi,
9057 struct prefix_rd *prd, int prefix_check,
9f049418 9058 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9059{
9060 int ret;
9061 int header;
9062 int display = 0;
9063 struct prefix match;
9064 struct bgp_node *rn;
9065 struct bgp_node *rm;
40381db7 9066 struct bgp_path_info *pi;
d62a17ae 9067 struct bgp_table *table;
9068 json_object *json = NULL;
9069 json_object *json_paths = NULL;
9070
9071 /* Check IP address argument. */
9072 ret = str2prefix(ip_str, &match);
9073 if (!ret) {
9074 vty_out(vty, "address is malformed\n");
9075 return CMD_WARNING;
9076 }
718e3744 9077
d62a17ae 9078 match.family = afi2family(afi);
b05a1c8b 9079
d62a17ae 9080 if (use_json) {
9081 json = json_object_new_object();
9082 json_paths = json_object_new_array();
9083 }
718e3744 9084
d62a17ae 9085 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9086 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9087 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9088 continue;
67009e22
DS
9089 table = bgp_node_get_bgp_table_info(rn);
9090 if (!table)
ea47320b 9091 continue;
d62a17ae 9092
ea47320b
DL
9093 header = 1;
9094
9095 if ((rm = bgp_node_match(table, &match)) == NULL)
9096 continue;
d62a17ae 9097
ea47320b
DL
9098 if (prefix_check
9099 && rm->p.prefixlen != match.prefixlen) {
9100 bgp_unlock_node(rm);
9101 continue;
9102 }
d62a17ae 9103
6f94b685
DS
9104 for (pi = bgp_node_get_bgp_path_info(rm); pi;
9105 pi = pi->next) {
ea47320b 9106 if (header) {
60466a63
QY
9107 route_vty_out_detail_header(
9108 vty, bgp, rm,
9109 (struct prefix_rd *)&rn->p,
ea47320b
DL
9110 AFI_IP, safi, json);
9111 header = 0;
d62a17ae 9112 }
ea47320b
DL
9113 display++;
9114
360660c6
DS
9115 if (pathtype == BGP_PATH_SHOW_ALL
9116 || (pathtype == BGP_PATH_SHOW_BESTPATH
40381db7 9117 && CHECK_FLAG(pi->flags,
1defdda8 9118 BGP_PATH_SELECTED))
360660c6 9119 || (pathtype == BGP_PATH_SHOW_MULTIPATH
40381db7 9120 && (CHECK_FLAG(pi->flags,
1defdda8 9121 BGP_PATH_MULTIPATH)
40381db7 9122 || CHECK_FLAG(pi->flags,
1defdda8 9123 BGP_PATH_SELECTED))))
ea47320b 9124 route_vty_out_detail(vty, bgp, &rm->p,
40381db7 9125 pi, AFI_IP, safi,
ea47320b 9126 json_paths);
d62a17ae 9127 }
ea47320b
DL
9128
9129 bgp_unlock_node(rm);
d62a17ae 9130 }
98a9dbc7 9131 } else if (safi == SAFI_FLOWSPEC) {
63a0b7a9
PG
9132 display = bgp_flowspec_display_match_per_ip(afi, rib,
9133 &match, prefix_check,
9134 vty,
9135 use_json,
9136 json_paths);
d62a17ae 9137 } else {
9138 header = 1;
9139
9140 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9141 if (!prefix_check
9142 || rn->p.prefixlen == match.prefixlen) {
6f94b685
DS
9143 for (pi = bgp_node_get_bgp_path_info(rn); pi;
9144 pi = pi->next) {
d62a17ae 9145 if (header) {
9146 route_vty_out_detail_header(
9147 vty, bgp, rn, NULL, afi,
9148 safi, json);
9149 header = 0;
9150 }
9151 display++;
9152
360660c6
DS
9153 if (pathtype == BGP_PATH_SHOW_ALL
9154 || (pathtype
9155 == BGP_PATH_SHOW_BESTPATH
d62a17ae 9156 && CHECK_FLAG(
40381db7 9157 pi->flags,
1defdda8 9158 BGP_PATH_SELECTED))
360660c6
DS
9159 || (pathtype
9160 == BGP_PATH_SHOW_MULTIPATH
d62a17ae 9161 && (CHECK_FLAG(
40381db7 9162 pi->flags,
1defdda8 9163 BGP_PATH_MULTIPATH)
d62a17ae 9164 || CHECK_FLAG(
40381db7 9165 pi->flags,
1defdda8 9166 BGP_PATH_SELECTED))))
d62a17ae 9167 route_vty_out_detail(
40381db7 9168 vty, bgp, &rn->p, pi,
d62a17ae 9169 afi, safi, json_paths);
9170 }
9171 }
9172
9173 bgp_unlock_node(rn);
9174 }
9175 }
e5eee9af 9176
d62a17ae 9177 if (use_json) {
9178 if (display)
9179 json_object_object_add(json, "paths", json_paths);
9180
996c9314
LB
9181 vty_out(vty, "%s\n", json_object_to_json_string_ext(
9182 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 9183 json_object_free(json);
9184 } else {
9185 if (!display) {
9186 vty_out(vty, "%% Network not in table\n");
9187 return CMD_WARNING;
9188 }
9189 }
b05a1c8b 9190
d62a17ae 9191 return CMD_SUCCESS;
718e3744 9192}
9193
fee0f4c6 9194/* Display specified route of Main RIB */
d62a17ae 9195static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
9196 afi_t afi, safi_t safi, struct prefix_rd *prd,
9197 int prefix_check, enum bgp_path_type pathtype,
9f049418 9198 bool use_json)
d62a17ae 9199{
9b86009a 9200 if (!bgp) {
d62a17ae 9201 bgp = bgp_get_default();
9b86009a
RW
9202 if (!bgp) {
9203 if (!use_json)
9204 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9205 else
9206 vty_out(vty, "{}\n");
9b86009a
RW
9207 return CMD_WARNING;
9208 }
9209 }
d62a17ae 9210
9211 /* labeled-unicast routes live in the unicast table */
9212 if (safi == SAFI_LABELED_UNICAST)
9213 safi = SAFI_UNICAST;
9214
9215 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
9216 afi, safi, prd, prefix_check, pathtype,
9217 use_json);
9218}
9219
9220static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
9221 struct cmd_token **argv, afi_t afi, safi_t safi,
088f1098 9222 bool uj)
d62a17ae 9223{
9224 struct lcommunity *lcom;
9225 struct buffer *b;
9226 int i;
9227 char *str;
9228 int first = 0;
9229
9230 b = buffer_new(1024);
9231 for (i = 0; i < argc; i++) {
9232 if (first)
9233 buffer_putc(b, ' ');
9234 else {
9235 if (strmatch(argv[i]->text, "AA:BB:CC")) {
9236 first = 1;
9237 buffer_putstr(b, argv[i]->arg);
9238 }
9239 }
9240 }
9241 buffer_putc(b, '\0');
57d187bc 9242
d62a17ae 9243 str = buffer_getstr(b);
9244 buffer_free(b);
57d187bc 9245
d62a17ae 9246 lcom = lcommunity_str2com(str);
9247 XFREE(MTYPE_TMP, str);
9248 if (!lcom) {
9249 vty_out(vty, "%% Large-community malformed\n");
9250 return CMD_WARNING;
9251 }
57d187bc 9252
d62a17ae 9253 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
9254 uj);
57d187bc
JS
9255}
9256
d62a17ae 9257static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
9258 const char *lcom, afi_t afi, safi_t safi,
088f1098 9259 bool uj)
57d187bc 9260{
d62a17ae 9261 struct community_list *list;
57d187bc 9262
d62a17ae 9263 list = community_list_lookup(bgp_clist, lcom,
9264 LARGE_COMMUNITY_LIST_MASTER);
9265 if (list == NULL) {
9266 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9267 lcom);
9268 return CMD_WARNING;
9269 }
57d187bc 9270
d62a17ae 9271 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
9272 list, uj);
fee0f4c6 9273}
9274
52951b63
DS
9275DEFUN (show_ip_bgp_large_community_list,
9276 show_ip_bgp_large_community_list_cmd,
4dd6177e 9277 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
52951b63
DS
9278 SHOW_STR
9279 IP_STR
9280 BGP_STR
9281 BGP_INSTANCE_HELP_STR
9bedbb1e 9282 BGP_AFI_HELP_STR
4dd6177e 9283 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9284 "Display routes matching the large-community-list\n"
9285 "large-community-list number\n"
9286 "large-community-list name\n"
9287 JSON_STR)
9288{
d62a17ae 9289 char *vrf = NULL;
9290 afi_t afi = AFI_IP6;
9291 safi_t safi = SAFI_UNICAST;
9292 int idx = 0;
9293
9294 if (argv_find(argv, argc, "ip", &idx))
9295 afi = AFI_IP;
9296 if (argv_find(argv, argc, "view", &idx)
9297 || argv_find(argv, argc, "vrf", &idx))
9298 vrf = argv[++idx]->arg;
9299 if (argv_find(argv, argc, "ipv4", &idx)
9300 || argv_find(argv, argc, "ipv6", &idx)) {
9301 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9302 if (argv_find(argv, argc, "unicast", &idx)
9303 || argv_find(argv, argc, "multicast", &idx))
9304 safi = bgp_vty_safi_from_str(argv[idx]->text);
9305 }
9306
9f049418 9307 bool uj = use_json(argc, argv);
d62a17ae 9308
9309 struct bgp *bgp = bgp_lookup_by_name(vrf);
9310 if (bgp == NULL) {
9311 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9312 return CMD_WARNING;
9313 }
9314
9315 argv_find(argv, argc, "large-community-list", &idx);
9316 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
9317 uj);
52951b63
DS
9318}
9319DEFUN (show_ip_bgp_large_community,
9320 show_ip_bgp_large_community_cmd,
4dd6177e 9321 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
9322 SHOW_STR
9323 IP_STR
9324 BGP_STR
9325 BGP_INSTANCE_HELP_STR
9bedbb1e 9326 BGP_AFI_HELP_STR
4dd6177e 9327 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9328 "Display routes matching the large-communities\n"
9329 "List of large-community numbers\n"
9330 JSON_STR)
9331{
d62a17ae 9332 char *vrf = NULL;
9333 afi_t afi = AFI_IP6;
9334 safi_t safi = SAFI_UNICAST;
9335 int idx = 0;
9336
9337 if (argv_find(argv, argc, "ip", &idx))
9338 afi = AFI_IP;
9339 if (argv_find(argv, argc, "view", &idx)
9340 || argv_find(argv, argc, "vrf", &idx))
9341 vrf = argv[++idx]->arg;
9342 if (argv_find(argv, argc, "ipv4", &idx)
9343 || argv_find(argv, argc, "ipv6", &idx)) {
9344 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9345 if (argv_find(argv, argc, "unicast", &idx)
9346 || argv_find(argv, argc, "multicast", &idx))
9347 safi = bgp_vty_safi_from_str(argv[idx]->text);
9348 }
9349
9f049418 9350 bool uj = use_json(argc, argv);
d62a17ae 9351
9352 struct bgp *bgp = bgp_lookup_by_name(vrf);
9353 if (bgp == NULL) {
9354 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9355 return CMD_WARNING;
9356 }
9357
9358 if (argv_find(argv, argc, "AA:BB:CC", &idx))
9359 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
9360 else
9361 return bgp_show(vty, bgp, afi, safi,
9362 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
9363}
9364
d62a17ae 9365static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9366 safi_t safi);
e01ca200 9367
7b2ff250
DW
9368
9369/* BGP route print out function without JSON */
af462945
DS
9370DEFUN (show_ip_bgp,
9371 show_ip_bgp_cmd,
4dd6177e 9372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
9373 <dampening <parameters>\
9374 |route-map WORD\
9375 |prefix-list WORD\
9376 |filter-list WORD\
9377 |statistics\
7b2ff250
DW
9378 |community-list <(1-500)|WORD> [exact-match]\
9379 |A.B.C.D/M longer-prefixes\
9380 |X:X::X:X/M longer-prefixes\
9381 >",
718e3744 9382 SHOW_STR
9383 IP_STR
9384 BGP_STR
a636c635 9385 BGP_INSTANCE_HELP_STR
4f280b15 9386 BGP_AFI_HELP_STR
4dd6177e 9387 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 9388 "Display detailed information about dampening\n"
af462945 9389 "Display detail of configured dampening parameters\n"
a636c635
DW
9390 "Display routes matching the route-map\n"
9391 "A route-map to match on\n"
9392 "Display routes conforming to the prefix-list\n"
8c3deaae 9393 "Prefix-list name\n"
a636c635
DW
9394 "Display routes conforming to the filter-list\n"
9395 "Regular expression access list name\n"
e01ca200 9396 "BGP RIB advertisement statistics\n"
a636c635
DW
9397 "Display routes matching the community-list\n"
9398 "community-list number\n"
9399 "community-list name\n"
9400 "Exact match of the communities\n"
0c7b1b01 9401 "IPv4 prefix\n"
8c3deaae 9402 "Display route and more specific routes\n"
0c7b1b01 9403 "IPv6 prefix\n"
7b2ff250 9404 "Display route and more specific routes\n")
718e3744 9405{
d62a17ae 9406 afi_t afi = AFI_IP6;
9407 safi_t safi = SAFI_UNICAST;
9408 int exact_match = 0;
d62a17ae 9409 struct bgp *bgp = NULL;
9410 int idx = 0;
9411
9412 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9413 &bgp, false);
d62a17ae 9414 if (!idx)
9415 return CMD_WARNING;
9416
d62a17ae 9417 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 9418 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 9419 return bgp_show_dampening_parameters(vty, afi, safi);
9420 }
c016b6c7 9421
d62a17ae 9422 if (argv_find(argv, argc, "prefix-list", &idx))
9423 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
9424 safi, bgp_show_type_prefix_list);
9425
9426 if (argv_find(argv, argc, "filter-list", &idx))
9427 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
9428 safi, bgp_show_type_filter_list);
9429
9430 if (argv_find(argv, argc, "statistics", &idx))
9431 return bgp_table_stats(vty, bgp, afi, safi);
9432
9433 if (argv_find(argv, argc, "route-map", &idx))
9434 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
9435 safi, bgp_show_type_route_map);
9436
d62a17ae 9437 if (argv_find(argv, argc, "community-list", &idx)) {
9438 const char *clist_number_or_name = argv[++idx]->arg;
9439 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
9440 exact_match = 1;
9441 return bgp_show_community_list(vty, bgp, clist_number_or_name,
9442 exact_match, afi, safi);
9443 }
9444 /* prefix-longer */
9445 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9446 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9447 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
9448 safi,
9449 bgp_show_type_prefix_longer);
9450
7b2ff250
DW
9451 return CMD_WARNING;
9452}
9453
9454/* BGP route print out function with JSON */
9455DEFUN (show_ip_bgp_json,
9456 show_ip_bgp_json_cmd,
9457 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
9458 [cidr-only\
9459 |dampening <flap-statistics|dampened-paths>\
9460 |community [AA:NN|local-AS|no-advertise|no-export\
9461 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9462 |accept-own|accept-own-nexthop|route-filter-v6\
9463 |route-filter-v4|route-filter-translated-v6\
9464 |route-filter-translated-v4] [exact-match]\
9465 ] [json]",
7b2ff250
DW
9466 SHOW_STR
9467 IP_STR
9468 BGP_STR
9469 BGP_INSTANCE_HELP_STR
9470 BGP_AFI_HELP_STR
9471 BGP_SAFI_WITH_LABEL_HELP_STR
9472 "Display only routes with non-natural netmasks\n"
9473 "Display detailed information about dampening\n"
9474 "Display flap statistics of routes\n"
9475 "Display paths suppressed due to dampening\n"
9476 "Display routes matching the communities\n"
d0086e8e
AD
9477 COMMUNITY_AANN_STR
9478 "Do not send outside local AS (well-known community)\n"
9479 "Do not advertise to any peer (well-known community)\n"
9480 "Do not export to next AS (well-known community)\n"
9481 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
9482 "Do not export to any peer (well-known community)\n"
9483 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9484 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9485 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9486 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9487 "Should accept VPN route with local nexthop (well-known community)\n"
9488 "RT VPNv6 route filtering (well-known community)\n"
9489 "RT VPNv4 route filtering (well-known community)\n"
9490 "RT translated VPNv6 route filtering (well-known community)\n"
9491 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 9492 "Exact match of the communities\n"
7b2ff250
DW
9493 JSON_STR)
9494{
9495 afi_t afi = AFI_IP6;
9496 safi_t safi = SAFI_UNICAST;
9497 enum bgp_show_type sh_type = bgp_show_type_normal;
9498 struct bgp *bgp = NULL;
9499 int idx = 0;
d0086e8e 9500 int exact_match = 0;
9f049418
DS
9501 bool uj = use_json(argc, argv);
9502
9503 if (uj)
9504 argc--;
7b2ff250
DW
9505
9506 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9507 &bgp, uj);
7b2ff250
DW
9508 if (!idx)
9509 return CMD_WARNING;
9510
7b2ff250
DW
9511 if (argv_find(argv, argc, "cidr-only", &idx))
9512 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
9513 NULL, uj);
9514
9515 if (argv_find(argv, argc, "dampening", &idx)) {
9516 if (argv_find(argv, argc, "dampened-paths", &idx))
9517 return bgp_show(vty, bgp, afi, safi,
9518 bgp_show_type_dampend_paths, NULL, uj);
9519 else if (argv_find(argv, argc, "flap-statistics", &idx))
9520 return bgp_show(vty, bgp, afi, safi,
9521 bgp_show_type_flap_statistics, NULL,
9522 uj);
9523 }
9524
9525 if (argv_find(argv, argc, "community", &idx)) {
cf4898bc
QY
9526 char *maybecomm = idx + 1 < argc ? argv[idx + 1]->text : NULL;
9527 char *community = NULL;
d0086e8e 9528
cf4898bc
QY
9529 if (maybecomm && !strmatch(maybecomm, "json")
9530 && !strmatch(maybecomm, "exact-match"))
9531 community = maybecomm;
d0086e8e 9532
cf4898bc
QY
9533 if (argv_find(argv, argc, "exact-match", &idx))
9534 exact_match = 1;
d0086e8e 9535
cf4898bc
QY
9536 if (community)
9537 return bgp_show_community(vty, bgp, community,
9538 exact_match, afi, safi, uj);
9539 else
d0086e8e 9540 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
9541 bgp_show_type_community_all, NULL,
9542 uj));
7b2ff250 9543 }
d0086e8e 9544
1ae44dfc 9545 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 9546}
47fc97cc 9547
718e3744 9548DEFUN (show_ip_bgp_route,
9549 show_ip_bgp_route_cmd,
4dd6177e 9550 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 9551 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 9552 SHOW_STR
9553 IP_STR
9554 BGP_STR
a636c635 9555 BGP_INSTANCE_HELP_STR
4f280b15 9556 BGP_AFI_HELP_STR
4dd6177e 9557 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 9558 "Network in the BGP routing table to display\n"
0c7b1b01 9559 "IPv4 prefix\n"
8c3deaae 9560 "Network in the BGP routing table to display\n"
0c7b1b01 9561 "IPv6 prefix\n"
4092b06c 9562 "Display only the bestpath\n"
b05a1c8b 9563 "Display only multipaths\n"
9973d184 9564 JSON_STR)
4092b06c 9565{
d62a17ae 9566 int prefix_check = 0;
ae19d7dd 9567
d62a17ae 9568 afi_t afi = AFI_IP6;
9569 safi_t safi = SAFI_UNICAST;
9570 char *prefix = NULL;
9571 struct bgp *bgp = NULL;
9572 enum bgp_path_type path_type;
9f049418 9573 bool uj = use_json(argc, argv);
b05a1c8b 9574
d62a17ae 9575 int idx = 0;
ae19d7dd 9576
d62a17ae 9577 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9578 &bgp, uj);
d62a17ae 9579 if (!idx)
9580 return CMD_WARNING;
c41247f5 9581
d62a17ae 9582 if (!bgp) {
9583 vty_out(vty,
9584 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9585 return CMD_WARNING;
9586 }
a636c635 9587
d62a17ae 9588 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9589 if (argv_find(argv, argc, "A.B.C.D", &idx)
9590 || argv_find(argv, argc, "X:X::X:X", &idx))
9591 prefix_check = 0;
9592 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9593 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9594 prefix_check = 1;
9595
9596 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9597 && afi != AFI_IP6) {
9598 vty_out(vty,
9599 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9600 return CMD_WARNING;
9601 }
9602 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9603 && afi != AFI_IP) {
9604 vty_out(vty,
9605 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9606 return CMD_WARNING;
9607 }
9608
9609 prefix = argv[idx]->arg;
9610
9611 /* [<bestpath|multipath>] */
9612 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 9613 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 9614 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 9615 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 9616 else
360660c6 9617 path_type = BGP_PATH_SHOW_ALL;
a636c635 9618
d62a17ae 9619 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9620 path_type, uj);
4092b06c
DS
9621}
9622
8c3deaae
QY
9623DEFUN (show_ip_bgp_regexp,
9624 show_ip_bgp_regexp_cmd,
4dd6177e 9625 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9626 SHOW_STR
9627 IP_STR
9628 BGP_STR
b00b230a 9629 BGP_INSTANCE_HELP_STR
4f280b15 9630 BGP_AFI_HELP_STR
4dd6177e 9631 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9632 "Display routes matching the AS path regular expression\n"
9633 "A regular-expression to match the BGP AS paths\n")
9634{
d62a17ae 9635 afi_t afi = AFI_IP6;
9636 safi_t safi = SAFI_UNICAST;
9637 struct bgp *bgp = NULL;
8c3deaae 9638
d62a17ae 9639 int idx = 0;
9640 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9641 &bgp, false);
d62a17ae 9642 if (!idx)
9643 return CMD_WARNING;
8c3deaae 9644
d62a17ae 9645 // get index of regex
9646 argv_find(argv, argc, "regexp", &idx);
9647 idx++;
8c3deaae 9648
d62a17ae 9649 char *regstr = argv_concat(argv, argc, idx);
e889891d 9650 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 9651 bgp_show_type_regexp);
9652 XFREE(MTYPE_TMP, regstr);
9653 return rc;
8c3deaae
QY
9654}
9655
a636c635
DW
9656DEFUN (show_ip_bgp_instance_all,
9657 show_ip_bgp_instance_all_cmd,
4dd6177e 9658 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9659 SHOW_STR
a636c635 9660 IP_STR
4092b06c 9661 BGP_STR
a636c635 9662 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9663 BGP_AFI_HELP_STR
4dd6177e 9664 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9665 JSON_STR)
4092b06c 9666{
d62a17ae 9667 afi_t afi = AFI_IP;
9668 safi_t safi = SAFI_UNICAST;
9669 struct bgp *bgp = NULL;
d62a17ae 9670 int idx = 0;
9f049418 9671 bool uj = use_json(argc, argv);
ae19d7dd 9672
d62a17ae 9673 if (uj)
9674 argc--;
e3e29b32 9675
9f049418
DS
9676 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9677 &bgp, uj);
9678 if (!idx)
9679 return CMD_WARNING;
9680
d62a17ae 9681 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9682 return CMD_SUCCESS;
e3e29b32
LB
9683}
9684
a4d82a8a
PZ
9685static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9686 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 9687{
d62a17ae 9688 regex_t *regex;
9689 int rc;
e3e29b32 9690
d62a17ae 9691 regex = bgp_regcomp(regstr);
9692 if (!regex) {
9693 vty_out(vty, "Can't compile regexp %s\n", regstr);
9694 return CMD_WARNING;
9695 }
a636c635 9696
e889891d 9697 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 9698 bgp_regex_free(regex);
9699 return rc;
e3e29b32
LB
9700}
9701
d62a17ae 9702static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9703 const char *prefix_list_str, afi_t afi,
9704 safi_t safi, enum bgp_show_type type)
e3e29b32 9705{
d62a17ae 9706 struct prefix_list *plist;
718e3744 9707
d62a17ae 9708 plist = prefix_list_lookup(afi, prefix_list_str);
9709 if (plist == NULL) {
9710 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9711 prefix_list_str);
9712 return CMD_WARNING;
9713 }
718e3744 9714
d62a17ae 9715 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9716}
9717
d62a17ae 9718static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9719 const char *filter, afi_t afi, safi_t safi,
9720 enum bgp_show_type type)
4092b06c 9721{
d62a17ae 9722 struct as_list *as_list;
718e3744 9723
d62a17ae 9724 as_list = as_list_lookup(filter);
9725 if (as_list == NULL) {
9726 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9727 filter);
9728 return CMD_WARNING;
9729 }
a636c635 9730
d62a17ae 9731 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9732}
9733
d62a17ae 9734static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9735 const char *rmap_str, afi_t afi, safi_t safi,
9736 enum bgp_show_type type)
718e3744 9737{
d62a17ae 9738 struct route_map *rmap;
bb46e94f 9739
d62a17ae 9740 rmap = route_map_lookup_by_name(rmap_str);
9741 if (!rmap) {
9742 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9743 return CMD_WARNING;
9744 }
9745
9746 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9747}
9748
7f323236
DW
9749static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9750 const char *comstr, int exact, afi_t afi,
9f049418 9751 safi_t safi, bool use_json)
d62a17ae 9752{
9753 struct community *com;
d62a17ae 9754 int ret = 0;
9755
7f323236 9756 com = community_str2com(comstr);
d62a17ae 9757 if (!com) {
7f323236 9758 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 9759 return CMD_WARNING;
9760 }
9761
9762 ret = bgp_show(vty, bgp, afi, safi,
9763 (exact ? bgp_show_type_community_exact
9764 : bgp_show_type_community),
d0086e8e 9765 com, use_json);
3c1f53de 9766 community_free(&com);
46c3ce83 9767
d62a17ae 9768 return ret;
718e3744 9769}
9770
d62a17ae 9771static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9772 const char *com, int exact, afi_t afi,
9773 safi_t safi)
50ef26d4 9774{
d62a17ae 9775 struct community_list *list;
50ef26d4 9776
d62a17ae 9777 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9778 if (list == NULL) {
9779 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9780 return CMD_WARNING;
9781 }
718e3744 9782
d62a17ae 9783 return bgp_show(vty, bgp, afi, safi,
9784 (exact ? bgp_show_type_community_list_exact
9785 : bgp_show_type_community_list),
9786 list, 0);
50ef26d4 9787}
9788
d62a17ae 9789static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9790 const char *prefix, afi_t afi, safi_t safi,
9791 enum bgp_show_type type)
718e3744 9792{
d62a17ae 9793 int ret;
9794 struct prefix *p;
47fc97cc 9795
d62a17ae 9796 p = prefix_new();
95cbbd2a 9797
d62a17ae 9798 ret = str2prefix(prefix, p);
9799 if (!ret) {
9800 vty_out(vty, "%% Malformed Prefix\n");
9801 return CMD_WARNING;
9802 }
47e9b292 9803
d62a17ae 9804 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9805 prefix_free(p);
9806 return ret;
9807}
9808
9809static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
9f049418 9810 const char *ip_str, bool use_json)
d62a17ae 9811{
9812 int ret;
9813 struct peer *peer;
9814 union sockunion su;
9815
9816 /* Get peer sockunion. */
9817 ret = str2sockunion(ip_str, &su);
9818 if (ret < 0) {
9819 peer = peer_lookup_by_conf_if(bgp, ip_str);
9820 if (!peer) {
9821 peer = peer_lookup_by_hostname(bgp, ip_str);
9822
9823 if (!peer) {
9824 if (use_json) {
9825 json_object *json_no = NULL;
9826 json_no = json_object_new_object();
9827 json_object_string_add(
9828 json_no,
9829 "malformedAddressOrName",
9830 ip_str);
9831 vty_out(vty, "%s\n",
66f80d74 9832 json_object_to_json_string_ext(
a4d82a8a
PZ
9833 json_no,
9834 JSON_C_TO_STRING_PRETTY));
d62a17ae 9835 json_object_free(json_no);
9836 } else
9837 vty_out(vty,
9838 "%% Malformed address or name: %s\n",
9839 ip_str);
9840 return NULL;
9841 }
9842 }
9843 return peer;
9844 }
718e3744 9845
d62a17ae 9846 /* Peer structure lookup. */
9847 peer = peer_lookup(bgp, &su);
9848 if (!peer) {
9849 if (use_json) {
9850 json_object *json_no = NULL;
9851 json_no = json_object_new_object();
9852 json_object_string_add(json_no, "warning",
9e6e6f46 9853 "No such neighbor in this view/vrf");
d62a17ae 9854 vty_out(vty, "%s\n",
a4d82a8a
PZ
9855 json_object_to_json_string_ext(
9856 json_no, JSON_C_TO_STRING_PRETTY));
d62a17ae 9857 json_object_free(json_no);
9858 } else
9e6e6f46 9859 vty_out(vty, "No such neighbor in this view/vrf\n");
d62a17ae 9860 return NULL;
9861 }
2815e61f 9862
d62a17ae 9863 return peer;
9864}
9865
9866enum bgp_stats {
9867 BGP_STATS_MAXBITLEN = 0,
9868 BGP_STATS_RIB,
9869 BGP_STATS_PREFIXES,
9870 BGP_STATS_TOTPLEN,
9871 BGP_STATS_UNAGGREGATEABLE,
9872 BGP_STATS_MAX_AGGREGATEABLE,
9873 BGP_STATS_AGGREGATES,
9874 BGP_STATS_SPACE,
9875 BGP_STATS_ASPATH_COUNT,
9876 BGP_STATS_ASPATH_MAXHOPS,
9877 BGP_STATS_ASPATH_TOTHOPS,
9878 BGP_STATS_ASPATH_MAXSIZE,
9879 BGP_STATS_ASPATH_TOTSIZE,
9880 BGP_STATS_ASN_HIGHEST,
9881 BGP_STATS_MAX,
a636c635 9882};
2815e61f 9883
d62a17ae 9884static const char *table_stats_strs[] = {
9d303b37
DL
9885 [BGP_STATS_PREFIXES] = "Total Prefixes",
9886 [BGP_STATS_TOTPLEN] = "Average prefix length",
9887 [BGP_STATS_RIB] = "Total Advertisements",
9888 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9889 [BGP_STATS_MAX_AGGREGATEABLE] =
9890 "Maximum aggregateable prefixes",
9891 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9892 [BGP_STATS_SPACE] = "Address space advertised",
9893 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9894 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9895 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9896 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9897 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9898 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9899 [BGP_STATS_MAX] = NULL,
a636c635 9900};
2815e61f 9901
d62a17ae 9902struct bgp_table_stats {
9903 struct bgp_table *table;
9904 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 9905 double total_space;
ff7924f6
PJ
9906};
9907
a636c635
DW
9908#if 0
9909#define TALLY_SIGFIG 100000
9910static unsigned long
9911ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9912{
a636c635
DW
9913 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9914 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9915 unsigned long ret = newtot / count;
07d0c4ed 9916
a636c635
DW
9917 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9918 return ret + 1;
9919 else
9920 return ret;
9921}
9922#endif
ff7924f6 9923
d62a17ae 9924static int bgp_table_stats_walker(struct thread *t)
2815e61f 9925{
d62a17ae 9926 struct bgp_node *rn;
9927 struct bgp_node *top;
9928 struct bgp_table_stats *ts = THREAD_ARG(t);
9929 unsigned int space = 0;
a636c635 9930
d62a17ae 9931 if (!(top = bgp_table_top(ts->table)))
9932 return 0;
2815e61f 9933
d62a17ae 9934 switch (top->p.family) {
9935 case AF_INET:
9936 space = IPV4_MAX_BITLEN;
9937 break;
9938 case AF_INET6:
9939 space = IPV6_MAX_BITLEN;
9940 break;
9941 }
9942
9943 ts->counts[BGP_STATS_MAXBITLEN] = space;
9944
9945 for (rn = top; rn; rn = bgp_route_next(rn)) {
40381db7 9946 struct bgp_path_info *pi;
d62a17ae 9947 struct bgp_node *prn = bgp_node_parent_nolock(rn);
40381db7 9948 unsigned int pinum = 0;
d62a17ae 9949
9950 if (rn == top)
9951 continue;
9952
6f94b685 9953 if (!bgp_node_has_bgp_path_info_data(rn))
d62a17ae 9954 continue;
9955
9956 ts->counts[BGP_STATS_PREFIXES]++;
9957 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9958
a636c635
DW
9959#if 0
9960 ts->counts[BGP_STATS_AVGPLEN]
9961 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9962 ts->counts[BGP_STATS_AVGPLEN],
9963 rn->p.prefixlen);
9964#endif
d62a17ae 9965
9966 /* check if the prefix is included by any other announcements */
6f94b685 9967 while (prn && !bgp_node_has_bgp_path_info_data(prn))
d62a17ae 9968 prn = bgp_node_parent_nolock(prn);
9969
9970 if (prn == NULL || prn == top) {
9971 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9972 /* announced address space */
9973 if (space)
a4d82a8a
PZ
9974 ts->total_space +=
9975 pow(2.0, space - rn->p.prefixlen);
6f94b685 9976 } else if (bgp_node_has_bgp_path_info_data(prn))
d62a17ae 9977 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9978
6f94b685 9979 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 9980 pinum++;
d62a17ae 9981 ts->counts[BGP_STATS_RIB]++;
9982
40381db7
DS
9983 if (pi->attr
9984 && (CHECK_FLAG(pi->attr->flag,
d62a17ae 9985 ATTR_FLAG_BIT(
9986 BGP_ATTR_ATOMIC_AGGREGATE))))
9987 ts->counts[BGP_STATS_AGGREGATES]++;
9988
9989 /* as-path stats */
40381db7 9990 if (pi->attr && pi->attr->aspath) {
d62a17ae 9991 unsigned int hops =
40381db7 9992 aspath_count_hops(pi->attr->aspath);
d62a17ae 9993 unsigned int size =
40381db7
DS
9994 aspath_size(pi->attr->aspath);
9995 as_t highest = aspath_highest(pi->attr->aspath);
d62a17ae 9996
9997 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9998
9999 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10000 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
10001 hops;
10002
10003 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10004 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
10005 size;
10006
10007 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10008 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10009#if 0
07d0c4ed 10010 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10011 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10012 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10013 hops);
10014 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10015 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10016 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10017 size);
10018#endif
d62a17ae 10019 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10020 ts->counts[BGP_STATS_ASN_HIGHEST] =
10021 highest;
10022 }
10023 }
10024 }
10025 return 0;
2815e61f 10026}
ff7924f6 10027
d62a17ae 10028static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10029 safi_t safi)
2815e61f 10030{
d62a17ae 10031 struct bgp_table_stats ts;
10032 unsigned int i;
019386c2 10033
d62a17ae 10034 if (!bgp->rib[afi][safi]) {
10035 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10036 afi, safi);
10037 return CMD_WARNING;
10038 }
019386c2 10039
d62a17ae 10040 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 10041
d62a17ae 10042 /* labeled-unicast routes live in the unicast table */
10043 if (safi == SAFI_LABELED_UNICAST)
10044 safi = SAFI_UNICAST;
019386c2 10045
d62a17ae 10046 memset(&ts, 0, sizeof(ts));
10047 ts.table = bgp->rib[afi][safi];
10048 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10049
d62a17ae 10050 for (i = 0; i < BGP_STATS_MAX; i++) {
10051 if (!table_stats_strs[i])
10052 continue;
10053
10054 switch (i) {
a636c635
DW
10055#if 0
10056 case BGP_STATS_ASPATH_AVGHOPS:
10057 case BGP_STATS_ASPATH_AVGSIZE:
10058 case BGP_STATS_AVGPLEN:
10059 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10060 vty_out (vty, "%12.2f",
10061 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10062 break;
10063#endif
d62a17ae 10064 case BGP_STATS_ASPATH_TOTHOPS:
10065 case BGP_STATS_ASPATH_TOTSIZE:
10066 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10067 vty_out(vty, "%12.2f",
10068 ts.counts[i]
10069 ? (float)ts.counts[i]
10070 / (float)ts.counts
10071 [BGP_STATS_ASPATH_COUNT]
10072 : 0);
10073 break;
10074 case BGP_STATS_TOTPLEN:
10075 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10076 vty_out(vty, "%12.2f",
10077 ts.counts[i]
10078 ? (float)ts.counts[i]
10079 / (float)ts.counts
10080 [BGP_STATS_PREFIXES]
10081 : 0);
10082 break;
10083 case BGP_STATS_SPACE:
10084 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10085 vty_out(vty, "%12g\n", ts.total_space);
10086
10087 if (afi == AFI_IP6) {
10088 vty_out(vty, "%30s: ", "/32 equivalent ");
10089 vty_out(vty, "%12g\n",
a4d82a8a 10090 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10091 vty_out(vty, "%30s: ", "/48 equivalent ");
10092 vty_out(vty, "%12g\n",
a4d82a8a 10093 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10094 } else {
10095 vty_out(vty, "%30s: ", "% announced ");
10096 vty_out(vty, "%12.2f\n",
10097 ts.total_space * 100. * pow(2.0, -32));
10098 vty_out(vty, "%30s: ", "/8 equivalent ");
10099 vty_out(vty, "%12.2f\n",
a4d82a8a 10100 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10101 vty_out(vty, "%30s: ", "/24 equivalent ");
10102 vty_out(vty, "%12.2f\n",
a4d82a8a 10103 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10104 }
d62a17ae 10105 break;
10106 default:
10107 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10108 vty_out(vty, "%12llu", ts.counts[i]);
10109 }
ff7924f6 10110
d62a17ae 10111 vty_out(vty, "\n");
10112 }
10113 return CMD_SUCCESS;
10114}
10115
10116enum bgp_pcounts {
10117 PCOUNT_ADJ_IN = 0,
10118 PCOUNT_DAMPED,
10119 PCOUNT_REMOVED,
10120 PCOUNT_HISTORY,
10121 PCOUNT_STALE,
10122 PCOUNT_VALID,
10123 PCOUNT_ALL,
10124 PCOUNT_COUNTED,
10125 PCOUNT_PFCNT, /* the figure we display to users */
10126 PCOUNT_MAX,
a636c635 10127};
718e3744 10128
d62a17ae 10129static const char *pcount_strs[] = {
9d303b37
DL
10130 [PCOUNT_ADJ_IN] = "Adj-in",
10131 [PCOUNT_DAMPED] = "Damped",
10132 [PCOUNT_REMOVED] = "Removed",
10133 [PCOUNT_HISTORY] = "History",
10134 [PCOUNT_STALE] = "Stale",
10135 [PCOUNT_VALID] = "Valid",
10136 [PCOUNT_ALL] = "All RIB",
10137 [PCOUNT_COUNTED] = "PfxCt counted",
10138 [PCOUNT_PFCNT] = "Useable",
10139 [PCOUNT_MAX] = NULL,
a636c635 10140};
718e3744 10141
d62a17ae 10142struct peer_pcounts {
10143 unsigned int count[PCOUNT_MAX];
10144 const struct peer *peer;
10145 const struct bgp_table *table;
a636c635 10146};
47fc97cc 10147
d62a17ae 10148static int bgp_peer_count_walker(struct thread *t)
10149{
10150 struct bgp_node *rn;
10151 struct peer_pcounts *pc = THREAD_ARG(t);
10152 const struct peer *peer = pc->peer;
10153
10154 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10155 struct bgp_adj_in *ain;
40381db7 10156 struct bgp_path_info *pi;
d62a17ae 10157
10158 for (ain = rn->adj_in; ain; ain = ain->next)
10159 if (ain->peer == peer)
10160 pc->count[PCOUNT_ADJ_IN]++;
10161
6f94b685
DS
10162 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10163
40381db7 10164 if (pi->peer != peer)
d62a17ae 10165 continue;
10166
10167 pc->count[PCOUNT_ALL]++;
10168
40381db7 10169 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10170 pc->count[PCOUNT_DAMPED]++;
40381db7 10171 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10172 pc->count[PCOUNT_HISTORY]++;
40381db7 10173 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10174 pc->count[PCOUNT_REMOVED]++;
40381db7 10175 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10176 pc->count[PCOUNT_STALE]++;
40381db7 10177 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10178 pc->count[PCOUNT_VALID]++;
40381db7 10179 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10180 pc->count[PCOUNT_PFCNT]++;
10181
40381db7 10182 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10183 pc->count[PCOUNT_COUNTED]++;
40381db7 10184 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10185 flog_err(
10186 EC_LIB_DEVELOPMENT,
10187 "Attempting to count but flags say it is unusable");
d62a17ae 10188 } else {
40381db7 10189 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10190 flog_err(
10191 EC_LIB_DEVELOPMENT,
10192 "Not counted but flags say we should");
d62a17ae 10193 }
10194 }
10195 }
10196 return 0;
718e3744 10197}
10198
d62a17ae 10199static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10200 safi_t safi, bool use_json)
856ca177 10201{
d62a17ae 10202 struct peer_pcounts pcounts = {.peer = peer};
10203 unsigned int i;
10204 json_object *json = NULL;
10205 json_object *json_loop = NULL;
856ca177 10206
d62a17ae 10207 if (use_json) {
10208 json = json_object_new_object();
10209 json_loop = json_object_new_object();
10210 }
718e3744 10211
d62a17ae 10212 if (!peer || !peer->bgp || !peer->afc[afi][safi]
10213 || !peer->bgp->rib[afi][safi]) {
10214 if (use_json) {
10215 json_object_string_add(
10216 json, "warning",
10217 "No such neighbor or address family");
10218 vty_out(vty, "%s\n", json_object_to_json_string(json));
10219 json_object_free(json);
10220 } else
10221 vty_out(vty, "%% No such neighbor or address family\n");
10222
10223 return CMD_WARNING;
10224 }
2a71e9ce 10225
d62a17ae 10226 memset(&pcounts, 0, sizeof(pcounts));
10227 pcounts.peer = peer;
10228 pcounts.table = peer->bgp->rib[afi][safi];
10229
10230 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
10231 * stats for the thread-walk (i.e. ensure this can't be blamed on
10232 * on just vty_read()).
10233 */
d62a17ae 10234 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
10235
10236 if (use_json) {
10237 json_object_string_add(json, "prefixCountsFor", peer->host);
10238 json_object_string_add(json, "multiProtocol",
10239 afi_safi_print(afi, safi));
10240 json_object_int_add(json, "pfxCounter",
10241 peer->pcount[afi][safi]);
10242
10243 for (i = 0; i < PCOUNT_MAX; i++)
10244 json_object_int_add(json_loop, pcount_strs[i],
10245 pcounts.count[i]);
10246
10247 json_object_object_add(json, "ribTableWalkCounters", json_loop);
10248
10249 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10250 json_object_string_add(json, "pfxctDriftFor",
10251 peer->host);
10252 json_object_string_add(
10253 json, "recommended",
10254 "Please report this bug, with the above command output");
10255 }
996c9314
LB
10256 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10257 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10258 json_object_free(json);
10259 } else {
10260
10261 if (peer->hostname
10262 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10263 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10264 peer->hostname, peer->host,
10265 afi_safi_print(afi, safi));
10266 } else {
10267 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
10268 afi_safi_print(afi, safi));
10269 }
10270
10271 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
10272 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10273
10274 for (i = 0; i < PCOUNT_MAX; i++)
10275 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10276 pcounts.count[i]);
10277
10278 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10279 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10280 vty_out(vty,
10281 "Please report this bug, with the above command output\n");
10282 }
10283 }
10284
10285 return CMD_SUCCESS;
718e3744 10286}
10287
a636c635
DW
10288DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10289 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10290 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10291 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10292 SHOW_STR
10293 IP_STR
10294 BGP_STR
8386ac43 10295 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10296 BGP_AFI_HELP_STR
10297 BGP_SAFI_HELP_STR
0b16f239
DS
10298 "Detailed information on TCP and BGP neighbor connections\n"
10299 "Neighbor to display information about\n"
10300 "Neighbor to display information about\n"
91d37724 10301 "Neighbor on BGP configured interface\n"
a636c635 10302 "Display detailed prefix count information\n"
9973d184 10303 JSON_STR)
0b16f239 10304{
d62a17ae 10305 afi_t afi = AFI_IP6;
10306 safi_t safi = SAFI_UNICAST;
10307 struct peer *peer;
10308 int idx = 0;
10309 struct bgp *bgp = NULL;
9f049418
DS
10310 bool uj = use_json(argc, argv);
10311
10312 if (uj)
10313 argc--;
856ca177 10314
d62a17ae 10315 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10316 &bgp, uj);
d62a17ae 10317 if (!idx)
10318 return CMD_WARNING;
0b16f239 10319
d62a17ae 10320 argv_find(argv, argc, "neighbors", &idx);
10321 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
10322 if (!peer)
10323 return CMD_WARNING;
bb46e94f 10324
d62a17ae 10325 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 10326}
0b16f239 10327
d6902373
PG
10328#ifdef KEEP_OLD_VPN_COMMANDS
10329DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
10330 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
10331 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
10332 SHOW_STR
10333 IP_STR
10334 BGP_STR
d6902373 10335 BGP_VPNVX_HELP_STR
91d37724 10336 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
10337 "Detailed information on TCP and BGP neighbor connections\n"
10338 "Neighbor to display information about\n"
10339 "Neighbor to display information about\n"
91d37724 10340 "Neighbor on BGP configured interface\n"
a636c635 10341 "Display detailed prefix count information\n"
9973d184 10342 JSON_STR)
a636c635 10343{
d62a17ae 10344 int idx_peer = 6;
10345 struct peer *peer;
9f049418 10346 bool uj = use_json(argc, argv);
a636c635 10347
d62a17ae 10348 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
10349 if (!peer)
10350 return CMD_WARNING;
10351
10352 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
10353}
10354
d6902373
PG
10355DEFUN (show_ip_bgp_vpn_all_route_prefix,
10356 show_ip_bgp_vpn_all_route_prefix_cmd,
10357 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
10358 SHOW_STR
10359 IP_STR
10360 BGP_STR
d6902373 10361 BGP_VPNVX_HELP_STR
91d37724
QY
10362 "Display information about all VPNv4 NLRIs\n"
10363 "Network in the BGP routing table to display\n"
3a2d747c 10364 "Network in the BGP routing table to display\n"
9973d184 10365 JSON_STR)
91d37724 10366{
d62a17ae 10367 int idx = 0;
10368 char *network = NULL;
10369 struct bgp *bgp = bgp_get_default();
10370 if (!bgp) {
10371 vty_out(vty, "Can't find default instance\n");
10372 return CMD_WARNING;
10373 }
87e34b58 10374
d62a17ae 10375 if (argv_find(argv, argc, "A.B.C.D", &idx))
10376 network = argv[idx]->arg;
10377 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10378 network = argv[idx]->arg;
10379 else {
10380 vty_out(vty, "Unable to figure out Network\n");
10381 return CMD_WARNING;
10382 }
87e34b58 10383
d62a17ae 10384 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 10385 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 10386}
d6902373 10387#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 10388
4c63a661
PG
10389DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
10390 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
10391 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10392 SHOW_STR
10393 IP_STR
10394 BGP_STR
10395 L2VPN_HELP_STR
10396 EVPN_HELP_STR
10397 "Display information about all EVPN NLRIs\n"
10398 "Network in the BGP routing table to display\n"
10399 "Network in the BGP routing table to display\n"
10400 JSON_STR)
10401{
d62a17ae 10402 int idx = 0;
10403 char *network = NULL;
a636c635 10404
d62a17ae 10405 if (argv_find(argv, argc, "A.B.C.D", &idx))
10406 network = argv[idx]->arg;
10407 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10408 network = argv[idx]->arg;
10409 else {
10410 vty_out(vty, "Unable to figure out Network\n");
10411 return CMD_WARNING;
10412 }
10413 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
360660c6 10414 BGP_PATH_SHOW_ALL, use_json(argc, argv));
d62a17ae 10415}
10416
10417static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10418 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10419 const char *rmap_name, bool use_json,
6392aaa6 10420 json_object *json)
d62a17ae 10421{
10422 struct bgp_table *table;
10423 struct bgp_adj_in *ain;
10424 struct bgp_adj_out *adj;
10425 unsigned long output_count;
10426 unsigned long filtered_count;
10427 struct bgp_node *rn;
10428 int header1 = 1;
10429 struct bgp *bgp;
10430 int header2 = 1;
10431 struct attr attr;
10432 int ret;
10433 struct update_subgroup *subgrp;
10434 json_object *json_scode = NULL;
10435 json_object *json_ocode = NULL;
10436 json_object *json_ar = NULL;
10437 struct peer_af *paf;
f99def61 10438 bool route_filtered;
d62a17ae 10439
10440 if (use_json) {
10441 json_scode = json_object_new_object();
10442 json_ocode = json_object_new_object();
10443 json_ar = json_object_new_object();
10444
10445 json_object_string_add(json_scode, "suppressed", "s");
10446 json_object_string_add(json_scode, "damped", "d");
10447 json_object_string_add(json_scode, "history", "h");
10448 json_object_string_add(json_scode, "valid", "*");
10449 json_object_string_add(json_scode, "best", ">");
10450 json_object_string_add(json_scode, "multipath", "=");
10451 json_object_string_add(json_scode, "internal", "i");
10452 json_object_string_add(json_scode, "ribFailure", "r");
10453 json_object_string_add(json_scode, "stale", "S");
10454 json_object_string_add(json_scode, "removed", "R");
10455
10456 json_object_string_add(json_ocode, "igp", "i");
10457 json_object_string_add(json_ocode, "egp", "e");
10458 json_object_string_add(json_ocode, "incomplete", "?");
10459 }
a636c635 10460
d62a17ae 10461 bgp = peer->bgp;
a636c635 10462
d62a17ae 10463 if (!bgp) {
10464 if (use_json) {
10465 json_object_string_add(json, "alert", "no BGP");
10466 vty_out(vty, "%s\n", json_object_to_json_string(json));
10467 json_object_free(json);
10468 } else
10469 vty_out(vty, "%% No bgp\n");
10470 return;
10471 }
a636c635 10472
d62a17ae 10473 table = bgp->rib[afi][safi];
10474
10475 output_count = filtered_count = 0;
10476 subgrp = peer_subgroup(peer, afi, safi);
10477
6392aaa6 10478 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 10479 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
10480 if (use_json) {
10481 json_object_int_add(json, "bgpTableVersion",
10482 table->version);
10483 json_object_string_add(json, "bgpLocalRouterId",
10484 inet_ntoa(bgp->router_id));
01eced22
AD
10485 json_object_int_add(json, "defaultLocPrf",
10486 bgp->default_local_pref);
10487 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 10488 json_object_object_add(json, "bgpStatusCodes",
10489 json_scode);
10490 json_object_object_add(json, "bgpOriginCodes",
10491 json_ocode);
07d0c4ed
DA
10492 json_object_string_add(
10493 json, "bgpOriginatingDefaultNetwork",
10494 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10495 } else {
996c9314 10496 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 10497 ", local router ID is %s, vrf id ",
d62a17ae 10498 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
10499 if (bgp->vrf_id == VRF_UNKNOWN)
10500 vty_out(vty, "%s", VRFID_NONE_STR);
10501 else
10502 vty_out(vty, "%u", bgp->vrf_id);
10503 vty_out(vty, "\n");
01eced22
AD
10504 vty_out(vty, "Default local pref %u, ",
10505 bgp->default_local_pref);
10506 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 10507 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10508 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 10509 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10510
07d0c4ed
DA
10511 vty_out(vty, "Originating default network %s\n\n",
10512 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10513 }
10514 header1 = 0;
10515 }
a636c635 10516
d62a17ae 10517 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
10518 if (type == bgp_show_adj_route_received
10519 || type == bgp_show_adj_route_filtered) {
d62a17ae 10520 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 10521 if (ain->peer != peer || !ain->attr)
ea47320b 10522 continue;
6392aaa6 10523
ea47320b
DL
10524 if (header1) {
10525 if (use_json) {
10526 json_object_int_add(
60466a63 10527 json, "bgpTableVersion",
ea47320b
DL
10528 0);
10529 json_object_string_add(
10530 json,
10531 "bgpLocalRouterId",
10532 inet_ntoa(
10533 bgp->router_id));
01eced22
AD
10534 json_object_int_add(json,
10535 "defaultLocPrf",
10536 bgp->default_local_pref);
10537 json_object_int_add(json,
10538 "localAS", bgp->as);
ea47320b 10539 json_object_object_add(
60466a63 10540 json, "bgpStatusCodes",
ea47320b
DL
10541 json_scode);
10542 json_object_object_add(
60466a63 10543 json, "bgpOriginCodes",
ea47320b
DL
10544 json_ocode);
10545 } else {
10546 vty_out(vty,
9df8b37c 10547 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 10548 inet_ntoa(
9df8b37c
PZ
10549 bgp->router_id));
10550 if (bgp->vrf_id == VRF_UNKNOWN)
10551 vty_out(vty, "%s",
10552 VRFID_NONE_STR);
10553 else
10554 vty_out(vty, "%u",
10555 bgp->vrf_id);
10556 vty_out(vty, "\n");
01eced22
AD
10557 vty_out(vty,
10558 "Default local pref %u, ",
10559 bgp->default_local_pref);
10560 vty_out(vty, "local AS %u\n",
10561 bgp->as);
ea47320b
DL
10562 vty_out(vty,
10563 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10564 vty_out(vty,
10565 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
10566 vty_out(vty,
10567 BGP_SHOW_OCODE_HEADER);
d62a17ae 10568 }
ea47320b
DL
10569 header1 = 0;
10570 }
10571 if (header2) {
10572 if (!use_json)
10573 vty_out(vty, BGP_SHOW_HEADER);
10574 header2 = 0;
10575 }
6392aaa6
PM
10576
10577 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
10578 route_filtered = false;
10579
10580 /* Filter prefix using distribute list,
10581 * filter list or prefix list
10582 */
10583 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
10584 safi)) == FILTER_DENY)
10585 route_filtered = true;
10586
10587 /* Filter prefix using route-map */
6392aaa6 10588 ret = bgp_input_modifier(peer, &rn->p, &attr,
13c8e163 10589 afi, safi, rmap_name);
6392aaa6 10590
13c8e163
AD
10591 if (type == bgp_show_adj_route_filtered &&
10592 !route_filtered && ret != RMAP_DENY) {
b755861b 10593 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10594 continue;
d62a17ae 10595 }
6392aaa6 10596
13c8e163
AD
10597 if (type == bgp_show_adj_route_received &&
10598 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
10599 filtered_count++;
10600
10601 route_vty_out_tmp(vty, &rn->p, &attr, safi,
10602 use_json, json_ar);
b755861b 10603 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10604 output_count++;
d62a17ae 10605 }
6392aaa6 10606 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 10607 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 10608 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 10609 if (paf->peer != peer || !adj->attr)
924c3f6a 10610 continue;
d62a17ae 10611
924c3f6a
DS
10612 if (header1) {
10613 if (use_json) {
10614 json_object_int_add(
10615 json,
10616 "bgpTableVersion",
10617 table->version);
10618 json_object_string_add(
10619 json,
10620 "bgpLocalRouterId",
10621 inet_ntoa(
10622 bgp->router_id));
01eced22
AD
10623 json_object_int_add(
10624 json, "defaultLocPrf",
10625 bgp->default_local_pref
10626 );
10627 json_object_int_add(
10628 json, "localAS",
10629 bgp->as);
924c3f6a
DS
10630 json_object_object_add(
10631 json,
10632 "bgpStatusCodes",
10633 json_scode);
10634 json_object_object_add(
10635 json,
10636 "bgpOriginCodes",
10637 json_ocode);
10638 } else {
10639 vty_out(vty,
10640 "BGP table version is %" PRIu64
9df8b37c 10641 ", local router ID is %s, vrf id ",
924c3f6a
DS
10642 table->version,
10643 inet_ntoa(
10644 bgp->router_id));
9df8b37c
PZ
10645 if (bgp->vrf_id ==
10646 VRF_UNKNOWN)
10647 vty_out(vty,
10648 "%s",
10649 VRFID_NONE_STR);
10650 else
10651 vty_out(vty,
10652 "%u",
10653 bgp->vrf_id);
10654 vty_out(vty, "\n");
01eced22
AD
10655 vty_out(vty,
10656 "Default local pref %u, ",
10657 bgp->default_local_pref
10658 );
10659 vty_out(vty,
10660 "local AS %u\n",
10661 bgp->as);
924c3f6a
DS
10662 vty_out(vty,
10663 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10664 vty_out(vty,
10665 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
10666 vty_out(vty,
10667 BGP_SHOW_OCODE_HEADER);
a2addae8 10668 }
924c3f6a
DS
10669 header1 = 0;
10670 }
924c3f6a
DS
10671 if (header2) {
10672 if (!use_json)
10673 vty_out(vty,
10674 BGP_SHOW_HEADER);
10675 header2 = 0;
10676 }
d62a17ae 10677
b755861b
PM
10678 bgp_attr_dup(&attr, adj->attr);
10679 ret = bgp_output_modifier(
10680 peer, &rn->p, &attr, afi, safi,
10681 rmap_name);
f46d8e1e 10682
b755861b
PM
10683 if (ret != RMAP_DENY) {
10684 route_vty_out_tmp(vty, &rn->p,
10685 &attr, safi,
10686 use_json,
10687 json_ar);
10688 output_count++;
10689 } else {
10690 filtered_count++;
a2addae8 10691 }
b755861b
PM
10692
10693 bgp_attr_undup(&attr, adj->attr);
924c3f6a 10694 }
d62a17ae 10695 }
10696 }
d62a17ae 10697
d62a17ae 10698 if (use_json) {
6392aaa6
PM
10699 json_object_object_add(json, "advertisedRoutes", json_ar);
10700 json_object_int_add(json, "totalPrefixCounter", output_count);
10701 json_object_int_add(json, "filteredPrefixCounter",
10702 filtered_count);
10703
996c9314
LB
10704 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10705 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10706 json_object_free(json);
6392aaa6
PM
10707 } else if (output_count > 0) {
10708 if (filtered_count > 0)
10709 vty_out(vty,
10710 "\nTotal number of prefixes %ld (%ld filtered)\n",
10711 output_count, filtered_count);
10712 else
10713 vty_out(vty, "\nTotal number of prefixes %ld\n",
10714 output_count);
d62a17ae 10715 }
a636c635 10716}
2a71e9ce 10717
d62a17ae 10718static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10719 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10720 const char *rmap_name, bool use_json)
0b16f239 10721{
d62a17ae 10722 json_object *json = NULL;
0b16f239 10723
d62a17ae 10724 if (use_json)
10725 json = json_object_new_object();
0b16f239 10726
d62a17ae 10727 /* labeled-unicast routes live in the unicast table */
10728 if (safi == SAFI_LABELED_UNICAST)
10729 safi = SAFI_UNICAST;
4dd6177e 10730
d62a17ae 10731 if (!peer || !peer->afc[afi][safi]) {
10732 if (use_json) {
10733 json_object_string_add(
10734 json, "warning",
10735 "No such neighbor or address family");
10736 vty_out(vty, "%s\n", json_object_to_json_string(json));
10737 json_object_free(json);
10738 } else
10739 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10740
d62a17ae 10741 return CMD_WARNING;
10742 }
10743
6392aaa6
PM
10744 if ((type == bgp_show_adj_route_received
10745 || type == bgp_show_adj_route_filtered)
d62a17ae 10746 && !CHECK_FLAG(peer->af_flags[afi][safi],
10747 PEER_FLAG_SOFT_RECONFIG)) {
10748 if (use_json) {
10749 json_object_string_add(
10750 json, "warning",
10751 "Inbound soft reconfiguration not enabled");
10752 vty_out(vty, "%s\n", json_object_to_json_string(json));
10753 json_object_free(json);
10754 } else
10755 vty_out(vty,
10756 "%% Inbound soft reconfiguration not enabled\n");
10757
10758 return CMD_WARNING;
10759 }
0b16f239 10760
6392aaa6 10761 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 10762
d62a17ae 10763 return CMD_SUCCESS;
a636c635 10764}
50ef26d4 10765
a636c635
DW
10766DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10767 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10768 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 10769 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 10770 SHOW_STR
10771 IP_STR
10772 BGP_STR
a636c635 10773 BGP_INSTANCE_HELP_STR
7395a2c9 10774 BGP_AFI_HELP_STR
4dd6177e 10775 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10776 "Detailed information on TCP and BGP neighbor connections\n"
10777 "Neighbor to display information about\n"
10778 "Neighbor to display information about\n"
91d37724 10779 "Neighbor on BGP configured interface\n"
a636c635 10780 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
10781 "Display the received routes from neighbor\n"
10782 "Display the filtered routes received from neighbor\n"
a636c635
DW
10783 "Route-map to modify the attributes\n"
10784 "Name of the route map\n"
9973d184 10785 JSON_STR)
718e3744 10786{
d62a17ae 10787 afi_t afi = AFI_IP6;
10788 safi_t safi = SAFI_UNICAST;
10789 char *rmap_name = NULL;
10790 char *peerstr = NULL;
d62a17ae 10791 struct bgp *bgp = NULL;
10792 struct peer *peer;
6392aaa6 10793 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 10794 int idx = 0;
9f049418 10795 bool uj = use_json(argc, argv);
6392aaa6 10796
d62a17ae 10797 if (uj)
10798 argc--;
30a6a167 10799
9f049418
DS
10800 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10801 &bgp, uj);
10802 if (!idx)
10803 return CMD_WARNING;
10804
d62a17ae 10805 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10806 argv_find(argv, argc, "neighbors", &idx);
10807 peerstr = argv[++idx]->arg;
8c3deaae 10808
d62a17ae 10809 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10810 if (!peer)
10811 return CMD_WARNING;
856ca177 10812
d62a17ae 10813 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
10814 type = bgp_show_adj_route_advertised;
10815 else if (argv_find(argv, argc, "received-routes", &idx))
10816 type = bgp_show_adj_route_received;
10817 else if (argv_find(argv, argc, "filtered-routes", &idx))
10818 type = bgp_show_adj_route_filtered;
10819
d62a17ae 10820 if (argv_find(argv, argc, "route-map", &idx))
10821 rmap_name = argv[++idx]->arg;
95cbbd2a 10822
6392aaa6 10823 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
10824}
10825
718e3744 10826DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10827 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10828 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10829 SHOW_STR
10830 IP_STR
10831 BGP_STR
8c3deaae
QY
10832 "Address Family\n"
10833 "Address Family\n"
718e3744 10834 "Address Family modifier\n"
10835 "Detailed information on TCP and BGP neighbor connections\n"
10836 "Neighbor to display information about\n"
10837 "Neighbor to display information about\n"
91d37724 10838 "Neighbor on BGP configured interface\n"
718e3744 10839 "Display information received from a BGP neighbor\n"
856ca177 10840 "Display the prefixlist filter\n"
9973d184 10841 JSON_STR)
718e3744 10842{
d62a17ae 10843 afi_t afi = AFI_IP6;
10844 safi_t safi = SAFI_UNICAST;
10845 char *peerstr = NULL;
10846
10847 char name[BUFSIZ];
10848 union sockunion su;
10849 struct peer *peer;
10850 int count, ret;
10851
10852 int idx = 0;
10853
10854 /* show [ip] bgp */
10855 if (argv_find(argv, argc, "ip", &idx))
10856 afi = AFI_IP;
10857 /* [<ipv4|ipv6> [unicast]] */
10858 if (argv_find(argv, argc, "ipv4", &idx))
10859 afi = AFI_IP;
10860 if (argv_find(argv, argc, "ipv6", &idx))
10861 afi = AFI_IP6;
10862 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10863 argv_find(argv, argc, "neighbors", &idx);
10864 peerstr = argv[++idx]->arg;
10865
9f049418 10866 bool uj = use_json(argc, argv);
d62a17ae 10867
10868 ret = str2sockunion(peerstr, &su);
10869 if (ret < 0) {
10870 peer = peer_lookup_by_conf_if(NULL, peerstr);
10871 if (!peer) {
10872 if (uj)
10873 vty_out(vty, "{}\n");
10874 else
10875 vty_out(vty,
10876 "%% Malformed address or name: %s\n",
10877 peerstr);
10878 return CMD_WARNING;
10879 }
10880 } else {
10881 peer = peer_lookup(NULL, &su);
10882 if (!peer) {
10883 if (uj)
10884 vty_out(vty, "{}\n");
10885 else
10886 vty_out(vty, "No peer\n");
10887 return CMD_WARNING;
10888 }
10889 }
718e3744 10890
d62a17ae 10891 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10892 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10893 if (count) {
10894 if (!uj)
10895 vty_out(vty, "Address Family: %s\n",
10896 afi_safi_print(afi, safi));
10897 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10898 } else {
10899 if (uj)
10900 vty_out(vty, "{}\n");
10901 else
10902 vty_out(vty, "No functional output\n");
10903 }
718e3744 10904
d62a17ae 10905 return CMD_SUCCESS;
10906}
10907
10908static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10909 afi_t afi, safi_t safi,
9f049418 10910 enum bgp_show_type type, bool use_json)
d62a17ae 10911{
8a893163
DW
10912 /* labeled-unicast routes live in the unicast table */
10913 if (safi == SAFI_LABELED_UNICAST)
10914 safi = SAFI_UNICAST;
10915
d62a17ae 10916 if (!peer || !peer->afc[afi][safi]) {
10917 if (use_json) {
10918 json_object *json_no = NULL;
10919 json_no = json_object_new_object();
10920 json_object_string_add(
10921 json_no, "warning",
10922 "No such neighbor or address family");
10923 vty_out(vty, "%s\n",
10924 json_object_to_json_string(json_no));
10925 json_object_free(json_no);
10926 } else
10927 vty_out(vty, "%% No such neighbor or address family\n");
10928 return CMD_WARNING;
10929 }
47fc97cc 10930
d62a17ae 10931 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10932}
10933
dba3c1d3
PG
10934DEFUN (show_ip_bgp_flowspec_routes_detailed,
10935 show_ip_bgp_flowspec_routes_detailed_cmd,
10936 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
10937 SHOW_STR
10938 IP_STR
10939 BGP_STR
10940 BGP_INSTANCE_HELP_STR
10941 BGP_AFI_HELP_STR
10942 "SAFI Flowspec\n"
10943 "Detailed information on flowspec entries\n"
10944 JSON_STR)
10945{
10946 afi_t afi = AFI_IP;
10947 safi_t safi = SAFI_UNICAST;
10948 struct bgp *bgp = NULL;
10949 int idx = 0;
9f049418
DS
10950 bool uj = use_json(argc, argv);
10951
10952 if (uj)
10953 argc--;
dba3c1d3
PG
10954
10955 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10956 &bgp, uj);
dba3c1d3
PG
10957 if (!idx)
10958 return CMD_WARNING;
10959
9f049418 10960 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
10961}
10962
718e3744 10963DEFUN (show_ip_bgp_neighbor_routes,
10964 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10965 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10966 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10967 SHOW_STR
10968 IP_STR
10969 BGP_STR
8386ac43 10970 BGP_INSTANCE_HELP_STR
4f280b15 10971 BGP_AFI_HELP_STR
4dd6177e 10972 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10973 "Detailed information on TCP and BGP neighbor connections\n"
10974 "Neighbor to display information about\n"
10975 "Neighbor to display information about\n"
91d37724 10976 "Neighbor on BGP configured interface\n"
2525cf39 10977 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10978 "Display the dampened routes received from neighbor\n"
10979 "Display routes learned from neighbor\n"
9973d184 10980 JSON_STR)
718e3744 10981{
d62a17ae 10982 char *peerstr = NULL;
10983 struct bgp *bgp = NULL;
10984 afi_t afi = AFI_IP6;
10985 safi_t safi = SAFI_UNICAST;
10986 struct peer *peer;
10987 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 10988 int idx = 0;
9f049418
DS
10989 bool uj = use_json(argc, argv);
10990
10991 if (uj)
10992 argc--;
bb46e94f 10993
d62a17ae 10994 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10995 &bgp, uj);
d62a17ae 10996 if (!idx)
10997 return CMD_WARNING;
c493f2d8 10998
d62a17ae 10999 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11000 argv_find(argv, argc, "neighbors", &idx);
11001 peerstr = argv[++idx]->arg;
8c3deaae 11002
d62a17ae 11003 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11004 if (!peer)
d62a17ae 11005 return CMD_WARNING;
bb46e94f 11006
d62a17ae 11007 if (argv_find(argv, argc, "flap-statistics", &idx))
11008 sh_type = bgp_show_type_flap_neighbor;
11009 else if (argv_find(argv, argc, "dampened-routes", &idx))
11010 sh_type = bgp_show_type_damp_neighbor;
11011 else if (argv_find(argv, argc, "routes", &idx))
11012 sh_type = bgp_show_type_neighbor;
2525cf39 11013
d62a17ae 11014 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11015}
6b0655a2 11016
734b349e 11017struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11018
d62a17ae 11019struct bgp_distance {
11020 /* Distance value for the IP source prefix. */
d7c0a89a 11021 uint8_t distance;
718e3744 11022
d62a17ae 11023 /* Name of the access-list to be matched. */
11024 char *access_list;
718e3744 11025};
11026
4f280b15
LB
11027DEFUN (show_bgp_afi_vpn_rd_route,
11028 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11029 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
11030 SHOW_STR
11031 BGP_STR
11032 BGP_AFI_HELP_STR
11033 "Address Family modifier\n"
11034 "Display information for a route distinguisher\n"
11035 "Route Distinguisher\n"
7395a2c9
DS
11036 "Network in the BGP routing table to display\n"
11037 "Network in the BGP routing table to display\n"
11038 JSON_STR)
4f280b15 11039{
d62a17ae 11040 int ret;
11041 struct prefix_rd prd;
11042 afi_t afi = AFI_MAX;
11043 int idx = 0;
4f280b15 11044
ff6566f3
DS
11045 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11046 vty_out(vty, "%% Malformed Address Family\n");
11047 return CMD_WARNING;
11048 }
11049
d62a17ae 11050 ret = str2prefix_rd(argv[5]->arg, &prd);
11051 if (!ret) {
11052 vty_out(vty, "%% Malformed Route Distinguisher\n");
11053 return CMD_WARNING;
11054 }
ff6566f3 11055
d62a17ae 11056 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11057 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11058}
11059
d62a17ae 11060static struct bgp_distance *bgp_distance_new(void)
718e3744 11061{
d62a17ae 11062 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11063}
11064
d62a17ae 11065static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11066{
d62a17ae 11067 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11068}
11069
d62a17ae 11070static int bgp_distance_set(struct vty *vty, const char *distance_str,
11071 const char *ip_str, const char *access_list_str)
718e3744 11072{
d62a17ae 11073 int ret;
11074 afi_t afi;
11075 safi_t safi;
11076 struct prefix p;
d7c0a89a 11077 uint8_t distance;
d62a17ae 11078 struct bgp_node *rn;
11079 struct bgp_distance *bdistance;
718e3744 11080
d62a17ae 11081 afi = bgp_node_afi(vty);
11082 safi = bgp_node_safi(vty);
734b349e 11083
d62a17ae 11084 ret = str2prefix(ip_str, &p);
11085 if (ret == 0) {
11086 vty_out(vty, "Malformed prefix\n");
11087 return CMD_WARNING_CONFIG_FAILED;
11088 }
718e3744 11089
d62a17ae 11090 distance = atoi(distance_str);
718e3744 11091
d62a17ae 11092 /* Get BGP distance node. */
11093 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11094 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11095 if (bdistance)
d62a17ae 11096 bgp_unlock_node(rn);
ca2e160d 11097 else {
d62a17ae 11098 bdistance = bgp_distance_new();
5b00b40e 11099 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11100 }
718e3744 11101
d62a17ae 11102 /* Set distance value. */
11103 bdistance->distance = distance;
718e3744 11104
d62a17ae 11105 /* Reset access-list configuration. */
11106 if (bdistance->access_list) {
11107 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11108 bdistance->access_list = NULL;
11109 }
11110 if (access_list_str)
11111 bdistance->access_list =
11112 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11113
d62a17ae 11114 return CMD_SUCCESS;
718e3744 11115}
11116
d62a17ae 11117static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11118 const char *ip_str, const char *access_list_str)
718e3744 11119{
d62a17ae 11120 int ret;
11121 afi_t afi;
11122 safi_t safi;
11123 struct prefix p;
11124 int distance;
11125 struct bgp_node *rn;
11126 struct bgp_distance *bdistance;
718e3744 11127
d62a17ae 11128 afi = bgp_node_afi(vty);
11129 safi = bgp_node_safi(vty);
734b349e 11130
d62a17ae 11131 ret = str2prefix(ip_str, &p);
11132 if (ret == 0) {
11133 vty_out(vty, "Malformed prefix\n");
11134 return CMD_WARNING_CONFIG_FAILED;
11135 }
718e3744 11136
d62a17ae 11137 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11138 (struct prefix *)&p);
11139 if (!rn) {
11140 vty_out(vty, "Can't find specified prefix\n");
11141 return CMD_WARNING_CONFIG_FAILED;
11142 }
718e3744 11143
5b00b40e 11144 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11145 distance = atoi(distance_str);
1f9a9fff 11146
d62a17ae 11147 if (bdistance->distance != distance) {
11148 vty_out(vty, "Distance does not match configured\n");
11149 return CMD_WARNING_CONFIG_FAILED;
11150 }
718e3744 11151
d62a17ae 11152 if (bdistance->access_list)
11153 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11154 bgp_distance_free(bdistance);
718e3744 11155
6f94b685 11156 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 11157 bgp_unlock_node(rn);
11158 bgp_unlock_node(rn);
718e3744 11159
d62a17ae 11160 return CMD_SUCCESS;
718e3744 11161}
11162
718e3744 11163/* Apply BGP information to distance method. */
40381db7 11164uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11165 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11166{
11167 struct bgp_node *rn;
11168 struct prefix q;
11169 struct peer *peer;
11170 struct bgp_distance *bdistance;
11171 struct access_list *alist;
11172 struct bgp_static *bgp_static;
11173
11174 if (!bgp)
11175 return 0;
11176
40381db7 11177 peer = pinfo->peer;
d62a17ae 11178
11179 /* Check source address. */
11180 sockunion2hostprefix(&peer->su, &q);
11181 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11182 if (rn) {
5b00b40e 11183 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11184 bgp_unlock_node(rn);
11185
11186 if (bdistance->access_list) {
11187 alist = access_list_lookup(afi, bdistance->access_list);
11188 if (alist
11189 && access_list_apply(alist, p) == FILTER_PERMIT)
11190 return bdistance->distance;
11191 } else
11192 return bdistance->distance;
718e3744 11193 }
718e3744 11194
d62a17ae 11195 /* Backdoor check. */
11196 rn = bgp_node_lookup(bgp->route[afi][safi], p);
11197 if (rn) {
5a8ba9fc 11198 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 11199 bgp_unlock_node(rn);
718e3744 11200
d62a17ae 11201 if (bgp_static->backdoor) {
11202 if (bgp->distance_local[afi][safi])
11203 return bgp->distance_local[afi][safi];
11204 else
11205 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11206 }
718e3744 11207 }
718e3744 11208
d62a17ae 11209 if (peer->sort == BGP_PEER_EBGP) {
11210 if (bgp->distance_ebgp[afi][safi])
11211 return bgp->distance_ebgp[afi][safi];
11212 return ZEBRA_EBGP_DISTANCE_DEFAULT;
11213 } else {
11214 if (bgp->distance_ibgp[afi][safi])
11215 return bgp->distance_ibgp[afi][safi];
11216 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11217 }
718e3744 11218}
11219
11220DEFUN (bgp_distance,
11221 bgp_distance_cmd,
6147e2c6 11222 "distance bgp (1-255) (1-255) (1-255)",
718e3744 11223 "Define an administrative distance\n"
11224 "BGP distance\n"
11225 "Distance for routes external to the AS\n"
11226 "Distance for routes internal to the AS\n"
11227 "Distance for local routes\n")
11228{
d62a17ae 11229 VTY_DECLVAR_CONTEXT(bgp, bgp);
11230 int idx_number = 2;
11231 int idx_number_2 = 3;
11232 int idx_number_3 = 4;
11233 afi_t afi;
11234 safi_t safi;
718e3744 11235
d62a17ae 11236 afi = bgp_node_afi(vty);
11237 safi = bgp_node_safi(vty);
718e3744 11238
d62a17ae 11239 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
11240 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
11241 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
11242 return CMD_SUCCESS;
718e3744 11243}
11244
11245DEFUN (no_bgp_distance,
11246 no_bgp_distance_cmd,
a636c635 11247 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 11248 NO_STR
11249 "Define an administrative distance\n"
11250 "BGP distance\n"
11251 "Distance for routes external to the AS\n"
11252 "Distance for routes internal to the AS\n"
11253 "Distance for local routes\n")
11254{
d62a17ae 11255 VTY_DECLVAR_CONTEXT(bgp, bgp);
11256 afi_t afi;
11257 safi_t safi;
718e3744 11258
d62a17ae 11259 afi = bgp_node_afi(vty);
11260 safi = bgp_node_safi(vty);
718e3744 11261
d62a17ae 11262 bgp->distance_ebgp[afi][safi] = 0;
11263 bgp->distance_ibgp[afi][safi] = 0;
11264 bgp->distance_local[afi][safi] = 0;
11265 return CMD_SUCCESS;
718e3744 11266}
11267
718e3744 11268
11269DEFUN (bgp_distance_source,
11270 bgp_distance_source_cmd,
6147e2c6 11271 "distance (1-255) A.B.C.D/M",
718e3744 11272 "Define an administrative distance\n"
11273 "Administrative distance\n"
11274 "IP source prefix\n")
11275{
d62a17ae 11276 int idx_number = 1;
11277 int idx_ipv4_prefixlen = 2;
11278 bgp_distance_set(vty, argv[idx_number]->arg,
11279 argv[idx_ipv4_prefixlen]->arg, NULL);
11280 return CMD_SUCCESS;
718e3744 11281}
11282
11283DEFUN (no_bgp_distance_source,
11284 no_bgp_distance_source_cmd,
6147e2c6 11285 "no distance (1-255) A.B.C.D/M",
718e3744 11286 NO_STR
11287 "Define an administrative distance\n"
11288 "Administrative distance\n"
11289 "IP source prefix\n")
11290{
d62a17ae 11291 int idx_number = 2;
11292 int idx_ipv4_prefixlen = 3;
11293 bgp_distance_unset(vty, argv[idx_number]->arg,
11294 argv[idx_ipv4_prefixlen]->arg, NULL);
11295 return CMD_SUCCESS;
718e3744 11296}
11297
11298DEFUN (bgp_distance_source_access_list,
11299 bgp_distance_source_access_list_cmd,
6147e2c6 11300 "distance (1-255) A.B.C.D/M WORD",
718e3744 11301 "Define an administrative distance\n"
11302 "Administrative distance\n"
11303 "IP source prefix\n"
11304 "Access list name\n")
11305{
d62a17ae 11306 int idx_number = 1;
11307 int idx_ipv4_prefixlen = 2;
11308 int idx_word = 3;
11309 bgp_distance_set(vty, argv[idx_number]->arg,
11310 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11311 return CMD_SUCCESS;
718e3744 11312}
11313
11314DEFUN (no_bgp_distance_source_access_list,
11315 no_bgp_distance_source_access_list_cmd,
6147e2c6 11316 "no distance (1-255) A.B.C.D/M WORD",
718e3744 11317 NO_STR
11318 "Define an administrative distance\n"
11319 "Administrative distance\n"
11320 "IP source prefix\n"
11321 "Access list name\n")
11322{
d62a17ae 11323 int idx_number = 2;
11324 int idx_ipv4_prefixlen = 3;
11325 int idx_word = 4;
11326 bgp_distance_unset(vty, argv[idx_number]->arg,
11327 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11328 return CMD_SUCCESS;
718e3744 11329}
6b0655a2 11330
734b349e
MZ
11331DEFUN (ipv6_bgp_distance_source,
11332 ipv6_bgp_distance_source_cmd,
39e92c06 11333 "distance (1-255) X:X::X:X/M",
734b349e
MZ
11334 "Define an administrative distance\n"
11335 "Administrative distance\n"
11336 "IP source prefix\n")
11337{
d62a17ae 11338 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
11339 return CMD_SUCCESS;
734b349e
MZ
11340}
11341
11342DEFUN (no_ipv6_bgp_distance_source,
11343 no_ipv6_bgp_distance_source_cmd,
39e92c06 11344 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
11345 NO_STR
11346 "Define an administrative distance\n"
11347 "Administrative distance\n"
11348 "IP source prefix\n")
11349{
d62a17ae 11350 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
11351 return CMD_SUCCESS;
734b349e
MZ
11352}
11353
11354DEFUN (ipv6_bgp_distance_source_access_list,
11355 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11356 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11357 "Define an administrative distance\n"
11358 "Administrative distance\n"
11359 "IP source prefix\n"
11360 "Access list name\n")
11361{
d62a17ae 11362 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
11363 return CMD_SUCCESS;
734b349e
MZ
11364}
11365
11366DEFUN (no_ipv6_bgp_distance_source_access_list,
11367 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11368 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11369 NO_STR
11370 "Define an administrative distance\n"
11371 "Administrative distance\n"
11372 "IP source prefix\n"
11373 "Access list name\n")
11374{
d62a17ae 11375 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
11376 return CMD_SUCCESS;
734b349e
MZ
11377}
11378
718e3744 11379DEFUN (bgp_damp_set,
11380 bgp_damp_set_cmd,
31500417 11381 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11382 "BGP Specific commands\n"
11383 "Enable route-flap dampening\n"
11384 "Half-life time for the penalty\n"
11385 "Value to start reusing a route\n"
11386 "Value to start suppressing a route\n"
11387 "Maximum duration to suppress a stable route\n")
11388{
d62a17ae 11389 VTY_DECLVAR_CONTEXT(bgp, bgp);
11390 int idx_half_life = 2;
11391 int idx_reuse = 3;
11392 int idx_suppress = 4;
11393 int idx_max_suppress = 5;
11394 int half = DEFAULT_HALF_LIFE * 60;
11395 int reuse = DEFAULT_REUSE;
11396 int suppress = DEFAULT_SUPPRESS;
11397 int max = 4 * half;
11398
11399 if (argc == 6) {
11400 half = atoi(argv[idx_half_life]->arg) * 60;
11401 reuse = atoi(argv[idx_reuse]->arg);
11402 suppress = atoi(argv[idx_suppress]->arg);
11403 max = atoi(argv[idx_max_suppress]->arg) * 60;
11404 } else if (argc == 3) {
11405 half = atoi(argv[idx_half_life]->arg) * 60;
11406 max = 4 * half;
11407 }
718e3744 11408
d62a17ae 11409 if (suppress < reuse) {
11410 vty_out(vty,
11411 "Suppress value cannot be less than reuse value \n");
11412 return 0;
11413 }
7ebe9748 11414
d62a17ae 11415 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
11416 reuse, suppress, max);
718e3744 11417}
11418
718e3744 11419DEFUN (bgp_damp_unset,
11420 bgp_damp_unset_cmd,
d04c479d 11421 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11422 NO_STR
11423 "BGP Specific commands\n"
16cedbb0
QY
11424 "Enable route-flap dampening\n"
11425 "Half-life time for the penalty\n"
11426 "Value to start reusing a route\n"
11427 "Value to start suppressing a route\n"
11428 "Maximum duration to suppress a stable route\n")
718e3744 11429{
d62a17ae 11430 VTY_DECLVAR_CONTEXT(bgp, bgp);
11431 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 11432}
11433
718e3744 11434/* Display specified route of BGP table. */
d62a17ae 11435static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
11436 const char *ip_str, afi_t afi, safi_t safi,
11437 struct prefix_rd *prd, int prefix_check)
11438{
11439 int ret;
11440 struct prefix match;
11441 struct bgp_node *rn;
11442 struct bgp_node *rm;
40381db7
DS
11443 struct bgp_path_info *pi;
11444 struct bgp_path_info *pi_temp;
d62a17ae 11445 struct bgp *bgp;
11446 struct bgp_table *table;
11447
11448 /* BGP structure lookup. */
11449 if (view_name) {
11450 bgp = bgp_lookup_by_name(view_name);
11451 if (bgp == NULL) {
11452 vty_out(vty, "%% Can't find BGP instance %s\n",
11453 view_name);
11454 return CMD_WARNING;
11455 }
11456 } else {
11457 bgp = bgp_get_default();
11458 if (bgp == NULL) {
11459 vty_out(vty, "%% No BGP process is configured\n");
11460 return CMD_WARNING;
11461 }
718e3744 11462 }
718e3744 11463
d62a17ae 11464 /* Check IP address argument. */
11465 ret = str2prefix(ip_str, &match);
11466 if (!ret) {
11467 vty_out(vty, "%% address is malformed\n");
11468 return CMD_WARNING;
11469 }
718e3744 11470
d62a17ae 11471 match.family = afi2family(afi);
11472
11473 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
11474 || (safi == SAFI_EVPN)) {
11475 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11476 rn = bgp_route_next(rn)) {
11477 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11478 continue;
67009e22
DS
11479 table = bgp_node_get_bgp_table_info(rn);
11480 if (!table)
ea47320b
DL
11481 continue;
11482 if ((rm = bgp_node_match(table, &match)) == NULL)
11483 continue;
d62a17ae 11484
ea47320b
DL
11485 if (!prefix_check
11486 || rm->p.prefixlen == match.prefixlen) {
6f94b685 11487 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
11488 while (pi) {
11489 if (pi->extra && pi->extra->damp_info) {
11490 pi_temp = pi->next;
ea47320b 11491 bgp_damp_info_free(
40381db7 11492 pi->extra->damp_info,
60466a63 11493 1);
40381db7 11494 pi = pi_temp;
ea47320b 11495 } else
40381db7 11496 pi = pi->next;
d62a17ae 11497 }
ea47320b
DL
11498 }
11499
11500 bgp_unlock_node(rm);
d62a17ae 11501 }
11502 } else {
11503 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11504 != NULL) {
11505 if (!prefix_check
11506 || rn->p.prefixlen == match.prefixlen) {
6f94b685 11507 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
11508 while (pi) {
11509 if (pi->extra && pi->extra->damp_info) {
11510 pi_temp = pi->next;
d62a17ae 11511 bgp_damp_info_free(
40381db7 11512 pi->extra->damp_info,
d62a17ae 11513 1);
40381db7 11514 pi = pi_temp;
d62a17ae 11515 } else
40381db7 11516 pi = pi->next;
d62a17ae 11517 }
11518 }
11519
11520 bgp_unlock_node(rn);
11521 }
11522 }
718e3744 11523
d62a17ae 11524 return CMD_SUCCESS;
718e3744 11525}
11526
11527DEFUN (clear_ip_bgp_dampening,
11528 clear_ip_bgp_dampening_cmd,
11529 "clear ip bgp dampening",
11530 CLEAR_STR
11531 IP_STR
11532 BGP_STR
11533 "Clear route flap dampening information\n")
11534{
d62a17ae 11535 bgp_damp_info_clean();
11536 return CMD_SUCCESS;
718e3744 11537}
11538
11539DEFUN (clear_ip_bgp_dampening_prefix,
11540 clear_ip_bgp_dampening_prefix_cmd,
11541 "clear ip bgp dampening A.B.C.D/M",
11542 CLEAR_STR
11543 IP_STR
11544 BGP_STR
11545 "Clear route flap dampening information\n"
0c7b1b01 11546 "IPv4 prefix\n")
718e3744 11547{
d62a17ae 11548 int idx_ipv4_prefixlen = 4;
11549 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11550 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11551}
11552
11553DEFUN (clear_ip_bgp_dampening_address,
11554 clear_ip_bgp_dampening_address_cmd,
11555 "clear ip bgp dampening A.B.C.D",
11556 CLEAR_STR
11557 IP_STR
11558 BGP_STR
11559 "Clear route flap dampening information\n"
11560 "Network to clear damping information\n")
11561{
d62a17ae 11562 int idx_ipv4 = 4;
11563 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11564 SAFI_UNICAST, NULL, 0);
718e3744 11565}
11566
11567DEFUN (clear_ip_bgp_dampening_address_mask,
11568 clear_ip_bgp_dampening_address_mask_cmd,
11569 "clear ip bgp dampening A.B.C.D A.B.C.D",
11570 CLEAR_STR
11571 IP_STR
11572 BGP_STR
11573 "Clear route flap dampening information\n"
11574 "Network to clear damping information\n"
11575 "Network mask\n")
11576{
d62a17ae 11577 int idx_ipv4 = 4;
11578 int idx_ipv4_2 = 5;
11579 int ret;
11580 char prefix_str[BUFSIZ];
718e3744 11581
d62a17ae 11582 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11583 prefix_str);
11584 if (!ret) {
11585 vty_out(vty, "%% Inconsistent address and mask\n");
11586 return CMD_WARNING;
11587 }
718e3744 11588
d62a17ae 11589 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11590 NULL, 0);
718e3744 11591}
6b0655a2 11592
825d9834
DS
11593static void show_bgp_peerhash_entry(struct hash_backet *backet, void *arg)
11594{
11595 struct vty *vty = arg;
11596 struct peer *peer = backet->data;
11597 char buf[SU_ADDRSTRLEN];
11598
11599 vty_out(vty, "\tPeer: %s %s\n", peer->host,
11600 sockunion2str(&peer->su, buf, sizeof(buf)));
11601}
11602
11603DEFUN (show_bgp_peerhash,
11604 show_bgp_peerhash_cmd,
11605 "show bgp peerhash",
11606 SHOW_STR
11607 BGP_STR
11608 "Display information about the BGP peerhash\n")
11609{
11610 struct list *instances = bm->bgp;
11611 struct listnode *node;
11612 struct bgp *bgp;
11613
11614 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
11615 vty_out(vty, "BGP: %s\n", bgp->name);
11616 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
11617 vty);
11618 }
11619
11620 return CMD_SUCCESS;
11621}
11622
587ff0fd 11623/* also used for encap safi */
2b791107
DL
11624static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11625 afi_t afi, safi_t safi)
d62a17ae 11626{
11627 struct bgp_node *prn;
11628 struct bgp_node *rn;
11629 struct bgp_table *table;
11630 struct prefix *p;
11631 struct prefix_rd *prd;
11632 struct bgp_static *bgp_static;
11633 mpls_label_t label;
11634 char buf[SU_ADDRSTRLEN];
11635 char rdbuf[RD_ADDRSTRLEN];
11636
11637 /* Network configuration. */
11638 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 11639 prn = bgp_route_next(prn)) {
67009e22
DS
11640 table = bgp_node_get_bgp_table_info(prn);
11641 if (!table)
ea47320b 11642 continue;
d62a17ae 11643
60466a63 11644 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 11645 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 11646 if (bgp_static == NULL)
ea47320b 11647 continue;
d62a17ae 11648
ea47320b
DL
11649 p = &rn->p;
11650 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11651
ea47320b 11652 /* "network" configuration display. */
06b9f471 11653 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11654 label = decode_label(&bgp_static->label);
11655
11656 vty_out(vty, " network %s/%d rd %s",
11657 inet_ntop(p->family, &p->u.prefix, buf,
11658 SU_ADDRSTRLEN),
11659 p->prefixlen, rdbuf);
11660 if (safi == SAFI_MPLS_VPN)
11661 vty_out(vty, " label %u", label);
11662
11663 if (bgp_static->rmap.name)
11664 vty_out(vty, " route-map %s",
11665 bgp_static->rmap.name);
e2a86ad9
DS
11666
11667 if (bgp_static->backdoor)
11668 vty_out(vty, " backdoor");
11669
ea47320b
DL
11670 vty_out(vty, "\n");
11671 }
11672 }
d62a17ae 11673}
11674
2b791107
DL
11675static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11676 afi_t afi, safi_t safi)
d62a17ae 11677{
11678 struct bgp_node *prn;
11679 struct bgp_node *rn;
11680 struct bgp_table *table;
11681 struct prefix *p;
11682 struct prefix_rd *prd;
11683 struct bgp_static *bgp_static;
ff44f570 11684 char buf[PREFIX_STRLEN * 2];
d62a17ae 11685 char buf2[SU_ADDRSTRLEN];
11686 char rdbuf[RD_ADDRSTRLEN];
11687
11688 /* Network configuration. */
11689 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 11690 prn = bgp_route_next(prn)) {
67009e22
DS
11691 table = bgp_node_get_bgp_table_info(prn);
11692 if (!table)
ea47320b 11693 continue;
d62a17ae 11694
60466a63 11695 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 11696 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 11697 if (bgp_static == NULL)
ea47320b 11698 continue;
d62a17ae 11699
ea47320b
DL
11700 char *macrouter = NULL;
11701 char *esi = NULL;
d62a17ae 11702
ea47320b
DL
11703 if (bgp_static->router_mac)
11704 macrouter = prefix_mac2str(
11705 bgp_static->router_mac, NULL, 0);
11706 if (bgp_static->eth_s_id)
11707 esi = esi2str(bgp_static->eth_s_id);
11708 p = &rn->p;
11709 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11710
ea47320b 11711 /* "network" configuration display. */
06b9f471 11712 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11713 if (p->u.prefix_evpn.route_type == 5) {
11714 char local_buf[PREFIX_STRLEN];
3714a385 11715 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
11716 struct prefix_evpn *)p)
11717 ? AF_INET
11718 : AF_INET6;
3714a385 11719 inet_ntop(family,
11720 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
11721 local_buf, PREFIX_STRLEN);
11722 sprintf(buf, "%s/%u", local_buf,
3714a385 11723 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
11724 } else {
11725 prefix2str(p, buf, sizeof(buf));
11726 }
ea47320b 11727
a4d82a8a
PZ
11728 if (bgp_static->gatewayIp.family == AF_INET
11729 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
11730 inet_ntop(bgp_static->gatewayIp.family,
11731 &bgp_static->gatewayIp.u.prefix, buf2,
11732 sizeof(buf2));
ea47320b 11733 vty_out(vty,
7bcc8dac 11734 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 11735 buf, rdbuf,
11736 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 11737 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11738 macrouter);
11739
11740 if (macrouter)
11741 XFREE(MTYPE_TMP, macrouter);
11742 if (esi)
11743 XFREE(MTYPE_TMP, esi);
11744 }
11745 }
3da6fcd5
PG
11746}
11747
718e3744 11748/* Configuration of static route announcement and aggregate
11749 information. */
2b791107
DL
11750void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11751 safi_t safi)
d62a17ae 11752{
11753 struct bgp_node *rn;
11754 struct prefix *p;
11755 struct bgp_static *bgp_static;
11756 struct bgp_aggregate *bgp_aggregate;
11757 char buf[SU_ADDRSTRLEN];
11758
2b791107
DL
11759 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11760 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11761 return;
11762 }
d62a17ae 11763
2b791107
DL
11764 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11765 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11766 return;
11767 }
d62a17ae 11768
11769 /* Network configuration. */
11770 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 11771 rn = bgp_route_next(rn)) {
5a8ba9fc 11772 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 11773 if (bgp_static == NULL)
ea47320b 11774 continue;
d62a17ae 11775
ea47320b 11776 p = &rn->p;
d62a17ae 11777
ea47320b 11778 /* "network" configuration display. */
60466a63 11779 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
d7c0a89a 11780 uint32_t destination;
ea47320b 11781 struct in_addr netmask;
d62a17ae 11782
ea47320b
DL
11783 destination = ntohl(p->u.prefix4.s_addr);
11784 masklen2ip(p->prefixlen, &netmask);
11785 vty_out(vty, " network %s",
11786 inet_ntop(p->family, &p->u.prefix, buf,
11787 SU_ADDRSTRLEN));
d62a17ae 11788
ea47320b
DL
11789 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11790 || (IN_CLASSB(destination) && p->prefixlen == 16)
11791 || (IN_CLASSA(destination) && p->prefixlen == 8)
11792 || p->u.prefix4.s_addr == 0) {
11793 /* Natural mask is not display. */
11794 } else
11795 vty_out(vty, " mask %s", inet_ntoa(netmask));
11796 } else {
11797 vty_out(vty, " network %s/%d",
11798 inet_ntop(p->family, &p->u.prefix, buf,
11799 SU_ADDRSTRLEN),
11800 p->prefixlen);
11801 }
d62a17ae 11802
ea47320b
DL
11803 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11804 vty_out(vty, " label-index %u",
11805 bgp_static->label_index);
d62a17ae 11806
ea47320b
DL
11807 if (bgp_static->rmap.name)
11808 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
11809
11810 if (bgp_static->backdoor)
11811 vty_out(vty, " backdoor");
718e3744 11812
ea47320b
DL
11813 vty_out(vty, "\n");
11814 }
11815
d62a17ae 11816 /* Aggregate-address configuration. */
11817 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 11818 rn = bgp_route_next(rn)) {
b613a918 11819 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 11820 if (bgp_aggregate == NULL)
ea47320b 11821 continue;
d62a17ae 11822
ea47320b 11823 p = &rn->p;
d62a17ae 11824
ea47320b
DL
11825 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11826 struct in_addr netmask;
d62a17ae 11827
ea47320b
DL
11828 masklen2ip(p->prefixlen, &netmask);
11829 vty_out(vty, " aggregate-address %s %s",
11830 inet_ntop(p->family, &p->u.prefix, buf,
11831 SU_ADDRSTRLEN),
11832 inet_ntoa(netmask));
11833 } else {
11834 vty_out(vty, " aggregate-address %s/%d",
11835 inet_ntop(p->family, &p->u.prefix, buf,
11836 SU_ADDRSTRLEN),
11837 p->prefixlen);
11838 }
d62a17ae 11839
ea47320b
DL
11840 if (bgp_aggregate->as_set)
11841 vty_out(vty, " as-set");
d62a17ae 11842
ea47320b
DL
11843 if (bgp_aggregate->summary_only)
11844 vty_out(vty, " summary-only");
718e3744 11845
ea47320b
DL
11846 vty_out(vty, "\n");
11847 }
d62a17ae 11848}
734b349e 11849
2b791107 11850void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11851 safi_t safi)
d62a17ae 11852{
11853 struct bgp_node *rn;
11854 struct bgp_distance *bdistance;
11855
11856 /* Distance configuration. */
11857 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11858 && bgp->distance_local[afi][safi]
11859 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11860 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11861 || bgp->distance_local[afi][safi]
11862 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11863 vty_out(vty, " distance bgp %d %d %d\n",
11864 bgp->distance_ebgp[afi][safi],
11865 bgp->distance_ibgp[afi][safi],
11866 bgp->distance_local[afi][safi]);
11867 }
734b349e 11868
d62a17ae 11869 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 11870 rn = bgp_route_next(rn)) {
5b00b40e 11871 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11872 if (bdistance != NULL) {
d62a17ae 11873 char buf[PREFIX_STRLEN];
11874
d62a17ae 11875 vty_out(vty, " distance %d %s %s\n",
11876 bdistance->distance,
11877 prefix2str(&rn->p, buf, sizeof(buf)),
11878 bdistance->access_list ? bdistance->access_list
11879 : "");
11880 }
ca2e160d 11881 }
718e3744 11882}
11883
11884/* Allocate routing table structure and install commands. */
d62a17ae 11885void bgp_route_init(void)
11886{
11887 afi_t afi;
11888 safi_t safi;
11889
11890 /* Init BGP distance table. */
05c7a1cc 11891 FOREACH_AFI_SAFI (afi, safi)
960035b2 11892 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 11893
11894 /* IPv4 BGP commands. */
11895 install_element(BGP_NODE, &bgp_table_map_cmd);
11896 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 11897 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 11898
11899 install_element(BGP_NODE, &aggregate_address_cmd);
11900 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11901 install_element(BGP_NODE, &no_aggregate_address_cmd);
11902 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11903
11904 /* IPv4 unicast configuration. */
11905 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11906 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 11907 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 11908
11909 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11910 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11911 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11912 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11913
11914 /* IPv4 multicast configuration. */
11915 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11916 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 11917 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 11918 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11919 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11920 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11921 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11922
11923 /* IPv4 labeled-unicast configuration. */
11924 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11925 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11926 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11927 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11928 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11929
11930 install_element(VIEW_NODE,
11931 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11932 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11933 install_element(VIEW_NODE,
11934 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11935#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11936 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11937#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11938 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11939 install_element(VIEW_NODE,
11940 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11941
d62a17ae 11942 /* BGP dampening clear commands */
11943 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11944 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11945
d62a17ae 11946 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11947 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11948
11949 /* prefix count */
11950 install_element(ENABLE_NODE,
11951 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11952#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11953 install_element(ENABLE_NODE,
11954 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11955#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11956
d62a17ae 11957 /* New config IPv6 BGP commands. */
11958 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11959 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11960 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 11961
11962 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11963 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11964
11965 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11966
d62a17ae 11967 install_element(BGP_NODE, &bgp_distance_cmd);
11968 install_element(BGP_NODE, &no_bgp_distance_cmd);
11969 install_element(BGP_NODE, &bgp_distance_source_cmd);
11970 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11971 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11972 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11973 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11974 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11975 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11976 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11977 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11978 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11979 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11980 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11981 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11982 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11983 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11984 install_element(BGP_IPV4M_NODE,
11985 &no_bgp_distance_source_access_list_cmd);
11986 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11987 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11988 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11989 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11990 install_element(BGP_IPV6_NODE,
11991 &ipv6_bgp_distance_source_access_list_cmd);
11992 install_element(BGP_IPV6_NODE,
11993 &no_ipv6_bgp_distance_source_access_list_cmd);
11994 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11995 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11996 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11997 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11998 install_element(BGP_IPV6M_NODE,
11999 &ipv6_bgp_distance_source_access_list_cmd);
12000 install_element(BGP_IPV6M_NODE,
12001 &no_ipv6_bgp_distance_source_access_list_cmd);
12002
12003 install_element(BGP_NODE, &bgp_damp_set_cmd);
12004 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12005 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12006 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12007
12008 /* IPv4 Multicast Mode */
12009 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12010 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12011
12012 /* Large Communities */
12013 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12014 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12015
12016 /* show bgp ipv4 flowspec detailed */
12017 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12018
825d9834 12019 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12020}
12021
12022void bgp_route_finish(void)
12023{
12024 afi_t afi;
12025 safi_t safi;
12026
05c7a1cc
QY
12027 FOREACH_AFI_SAFI (afi, safi) {
12028 bgp_table_unlock(bgp_distance_table[afi][safi]);
12029 bgp_distance_table[afi][safi] = NULL;
12030 }
228da428 12031}