]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: prefix-sid srv6 l3vpn service tlv
[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
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
718e3744 44
45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
718e3744 72
65efcfce 73#if ENABLE_BGP_VNC
f8b6f499
LB
74#include "bgpd/rfapi/rfapi_backend.h"
75#include "bgpd/rfapi/vnc_import_bgp.h"
76#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 77#endif
aee875b5
PG
78#include "bgpd/bgp_encap_types.h"
79#include "bgpd/bgp_encap_tlv.h"
684a7227 80#include "bgpd/bgp_evpn.h"
3da6fcd5 81#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 82#include "bgpd/bgp_flowspec.h"
98a9dbc7 83#include "bgpd/bgp_flowspec_util.h"
45918cfb 84#include "bgpd/bgp_pbr.h"
65efcfce 85
e2a86ad9
DS
86#ifndef VTYSH_EXTRACT_PL
87#include "bgpd/bgp_route_clippy.c"
88#endif
aee875b5 89
718e3744 90/* Extern from bgp_dump.c */
dde72586
SH
91extern const char *bgp_origin_str[];
92extern const char *bgp_origin_long_str[];
6b0655a2 93
b7d08f5a 94/* PMSI strings. */
95#define PMSI_TNLTYPE_STR_NO_INFO "No info"
96#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
97static const struct message bgp_pmsi_tnltype_str[] = {
98 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
99 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
100 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
101 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
102 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
103 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
104 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
105 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 106 {0}
107};
b7d08f5a 108
9df8b37c
PZ
109#define VRFID_NONE_STR "-"
110
4a11bf2c
DL
111DEFINE_HOOK(bgp_process,
112 (struct bgp *bgp, afi_t afi, safi_t safi,
113 struct bgp_node *bn, struct peer *peer, bool withdraw),
114 (bgp, afi, safi, bn, peer, withdraw))
115
116
d62a17ae 117struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
118 safi_t safi, struct prefix *p,
119 struct prefix_rd *prd)
120{
121 struct bgp_node *rn;
122 struct bgp_node *prn = NULL;
123
124 assert(table);
125 if (!table)
126 return NULL;
127
128 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
129 || (safi == SAFI_EVPN)) {
130 prn = bgp_node_get(table, (struct prefix *)prd);
131
67009e22
DS
132 if (!bgp_node_has_bgp_path_info_data(prn))
133 bgp_node_set_bgp_table_info(
134 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 135 else
136 bgp_unlock_node(prn);
67009e22 137 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 138 }
718e3744 139
d62a17ae 140 rn = bgp_node_get(table, p);
718e3744 141
d62a17ae 142 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
143 || (safi == SAFI_EVPN))
144 rn->prn = prn;
718e3744 145
d62a17ae 146 return rn;
718e3744 147}
6b0655a2 148
d62a17ae 149struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
150 safi_t safi, struct prefix *p,
151 struct prefix_rd *prd)
128ea8ab 152{
d62a17ae 153 struct bgp_node *rn;
154 struct bgp_node *prn = NULL;
128ea8ab 155
d62a17ae 156 if (!table)
157 return NULL;
128ea8ab 158
d62a17ae 159 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
160 || (safi == SAFI_EVPN)) {
161 prn = bgp_node_lookup(table, (struct prefix *)prd);
162 if (!prn)
163 return NULL;
128ea8ab 164
6f94b685 165 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 166 bgp_unlock_node(prn);
167 return NULL;
168 }
128ea8ab 169
67009e22 170 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 171 }
128ea8ab 172
d62a17ae 173 rn = bgp_node_lookup(table, p);
128ea8ab 174
d62a17ae 175 return rn;
128ea8ab 176}
177
18ee8310
DS
178/* Allocate bgp_path_info_extra */
179static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 180{
4b7e6066
DS
181 struct bgp_path_info_extra *new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
183 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
184 new->label[0] = MPLS_INVALID_LABEL;
185 new->num_labels = 0;
3e3708cb
PG
186 new->bgp_fs_pbr = NULL;
187 new->bgp_fs_iprule = NULL;
d62a17ae 188 return new;
fb982c25
PJ
189}
190
a2e219fe 191void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 192{
4b7e6066 193 struct bgp_path_info_extra *e;
d62a17ae 194
c93a3b77
DS
195 if (!extra || !*extra)
196 return;
d62a17ae 197
c93a3b77
DS
198 e = *extra;
199 if (e->damp_info)
a935f597
DA
200 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
201 e->damp_info->safi);
d62a17ae 202
c93a3b77
DS
203 e->damp_info = NULL;
204 if (e->parent) {
40381db7 205 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 206
40381db7 207 if (bpi->net) {
0e70e6c8
DL
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
211 *
40381db7
DS
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
0e70e6c8
DL
215 */
216 unsigned refcount;
217
40381db7
DS
218 bpi = bgp_path_info_lock(bpi);
219 refcount = bpi->net->lock - 1;
220 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 221 if (!refcount)
40381db7
DS
222 bpi->net = NULL;
223 bgp_path_info_unlock(bpi);
0e70e6c8 224 }
18ee8310 225 bgp_path_info_unlock(e->parent);
c93a3b77 226 e->parent = NULL;
d62a17ae 227 }
c93a3b77
DS
228
229 if (e->bgp_orig)
230 bgp_unlock(e->bgp_orig);
c26edcda 231
ce3c0614
PG
232 if ((*extra)->bgp_fs_iprule)
233 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 234 if ((*extra)->bgp_fs_pbr)
6a154c88 235 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
236 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
237
238 *extra = NULL;
fb982c25
PJ
239}
240
18ee8310
DS
241/* Get bgp_path_info extra information for the given bgp_path_info, lazy
242 * allocated if required.
fb982c25 243 */
40381db7 244struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 245{
40381db7
DS
246 if (!pi->extra)
247 pi->extra = bgp_path_info_extra_new();
248 return pi->extra;
fb982c25
PJ
249}
250
718e3744 251/* Free bgp route information. */
9b6d8fcf 252static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 253{
05864da7 254 bgp_attr_unintern(&path->attr);
fb018d25 255
9b6d8fcf
DS
256 bgp_unlink_nexthop(path);
257 bgp_path_info_extra_free(&path->extra);
258 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
259 if (path->net)
260 bgp_addpath_free_info_data(&path->tx_addpath,
261 &path->net->tx_addpath);
718e3744 262
9b6d8fcf 263 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 264
9b6d8fcf 265 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 266}
267
9b6d8fcf 268struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 269{
9b6d8fcf
DS
270 path->lock++;
271 return path;
200df115 272}
273
9b6d8fcf 274struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 275{
9b6d8fcf
DS
276 assert(path && path->lock > 0);
277 path->lock--;
d62a17ae 278
9b6d8fcf 279 if (path->lock == 0) {
200df115 280#if 0
281 zlog_debug ("%s: unlocked and freeing", __func__);
282 zlog_backtrace (LOG_DEBUG);
283#endif
9b6d8fcf 284 bgp_path_info_free(path);
d62a17ae 285 return NULL;
286 }
200df115 287
288#if 0
9b6d8fcf 289 if (path->lock == 1)
200df115 290 {
291 zlog_debug ("%s: unlocked to 1", __func__);
292 zlog_backtrace (LOG_DEBUG);
293 }
294#endif
d62a17ae 295
9b6d8fcf 296 return path;
200df115 297}
298
40381db7 299void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 300{
4b7e6066 301 struct bgp_path_info *top;
718e3744 302
6f94b685 303 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 304
6f94b685 305 pi->next = top;
40381db7 306 pi->prev = NULL;
d62a17ae 307 if (top)
40381db7 308 top->prev = pi;
6f94b685 309 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 310
40381db7 311 bgp_path_info_lock(pi);
d62a17ae 312 bgp_lock_node(rn);
40381db7 313 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 314}
315
d62a17ae 316/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 317 completion callback *only* */
40381db7 318void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 319{
40381db7
DS
320 if (pi->next)
321 pi->next->prev = pi->prev;
322 if (pi->prev)
323 pi->prev->next = pi->next;
d62a17ae 324 else
6f94b685 325 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 326
40381db7
DS
327 bgp_path_info_mpath_dequeue(pi);
328 bgp_path_info_unlock(pi);
d62a17ae 329 bgp_unlock_node(rn);
718e3744 330}
331
40381db7 332void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 333{
40381db7 334 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 335 /* set of previous already took care of pcount */
40381db7 336 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 337}
338
18ee8310 339/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
340 called when a route is deleted and then quickly re-added before the
341 deletion has been processed */
40381db7 342void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 343{
40381db7 344 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 345 /* unset of previous already took care of pcount */
40381db7 346 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
347}
348
d62a17ae 349/* Adjust pcount as required */
40381db7 350static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 351{
d62a17ae 352 struct bgp_table *table;
67174041 353
d62a17ae 354 assert(rn && bgp_node_table(rn));
40381db7 355 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 356
d62a17ae 357 table = bgp_node_table(rn);
67174041 358
40381db7 359 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 360 return;
361
40381db7
DS
362 if (!BGP_PATH_COUNTABLE(pi)
363 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 364
40381db7 365 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 366
367 /* slight hack, but more robust against errors. */
40381db7
DS
368 if (pi->peer->pcount[table->afi][table->safi])
369 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 370 else
450971aa 371 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 372 "Asked to decrement 0 prefix count for peer");
40381db7
DS
373 } else if (BGP_PATH_COUNTABLE(pi)
374 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
375 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
376 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 377 }
1a392d46
PJ
378}
379
40381db7
DS
380static int bgp_label_index_differs(struct bgp_path_info *pi1,
381 struct bgp_path_info *pi2)
28d58fd7 382{
40381db7 383 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 384}
1a392d46 385
18ee8310 386/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
387 * This is here primarily to keep prefix-count in check.
388 */
40381db7 389void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 390 uint32_t flag)
1a392d46 391{
40381db7 392 SET_FLAG(pi->flags, flag);
d62a17ae 393
394 /* early bath if we know it's not a flag that changes countability state
395 */
396 if (!CHECK_FLAG(flag,
1defdda8 397 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 398 return;
399
40381db7 400 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
401}
402
40381db7 403void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 404 uint32_t flag)
1a392d46 405{
40381db7 406 UNSET_FLAG(pi->flags, flag);
d62a17ae 407
408 /* early bath if we know it's not a flag that changes countability state
409 */
410 if (!CHECK_FLAG(flag,
1defdda8 411 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 412 return;
413
40381db7 414 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
415}
416
718e3744 417/* Get MED value. If MED value is missing and "bgp bestpath
418 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 419static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 420{
421 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
422 return attr->med;
423 else {
424 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
425 return BGP_MED_MAX;
426 else
427 return 0;
428 }
718e3744 429}
430
40381db7 431void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 432{
40381db7
DS
433 if (pi->addpath_rx_id)
434 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
435 pi->addpath_rx_id);
d62a17ae 436 else
40381db7 437 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 438}
9fbdd100 439
d62a17ae 440/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
441 */
18ee8310
DS
442static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
443 struct bgp_path_info *exist, int *paths_eq,
444 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
445 char *pfx_buf, afi_t afi, safi_t safi,
446 enum bgp_path_selection_reason *reason)
d62a17ae 447{
448 struct attr *newattr, *existattr;
449 bgp_peer_sort_t new_sort;
450 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
451 uint32_t new_pref;
452 uint32_t exist_pref;
453 uint32_t new_med;
454 uint32_t exist_med;
455 uint32_t new_weight;
456 uint32_t exist_weight;
d62a17ae 457 uint32_t newm, existm;
458 struct in_addr new_id;
459 struct in_addr exist_id;
460 int new_cluster;
461 int exist_cluster;
462 int internal_as_route;
463 int confed_as_route;
04d14c8b 464 int ret = 0;
d62a17ae 465 char new_buf[PATH_ADDPATH_STR_BUFFER];
466 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
467 uint32_t new_mm_seq;
468 uint32_t exist_mm_seq;
6d8c603a 469 int nh_cmp;
d62a17ae 470
471 *paths_eq = 0;
472
473 /* 0. Null check. */
474 if (new == NULL) {
fdf81fa0 475 *reason = bgp_path_selection_none;
d62a17ae 476 if (debug)
477 zlog_debug("%s: new is NULL", pfx_buf);
478 return 0;
479 }
2ec1e66f 480
d62a17ae 481 if (debug)
18ee8310 482 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 483
d62a17ae 484 if (exist == NULL) {
fdf81fa0 485 *reason = bgp_path_selection_first;
d62a17ae 486 if (debug)
487 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
488 new_buf);
489 return 1;
490 }
2ec1e66f 491
d62a17ae 492 if (debug) {
18ee8310 493 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 494 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
495 pfx_buf, new_buf, new->flags, exist_buf,
496 exist->flags);
497 }
8ff56318 498
d62a17ae 499 newattr = new->attr;
500 existattr = exist->attr;
501
502 /* For EVPN routes, we cannot just go by local vs remote, we have to
503 * look at the MAC mobility sequence number, if present.
504 */
505 if (safi == SAFI_EVPN) {
506 /* This is an error condition described in RFC 7432 Section
507 * 15.2. The RFC
508 * states that in this scenario "the PE MUST alert the operator"
509 * but it
510 * does not state what other action to take. In order to provide
511 * some
512 * consistency in this scenario we are going to prefer the path
513 * with the
514 * sticky flag.
515 */
516 if (newattr->sticky != existattr->sticky) {
517 if (!debug) {
518 prefix2str(&new->net->p, pfx_buf,
519 sizeof(*pfx_buf)
520 * PREFIX2STR_BUFFER);
18ee8310
DS
521 bgp_path_info_path_with_addpath_rx_str(new,
522 new_buf);
523 bgp_path_info_path_with_addpath_rx_str(
524 exist, exist_buf);
d62a17ae 525 }
526
527 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 528 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
529 if (debug)
530 zlog_debug(
531 "%s: %s wins over %s due to sticky MAC flag",
532 pfx_buf, new_buf, exist_buf);
d62a17ae 533 return 1;
534 }
535
536 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 537 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
538 if (debug)
539 zlog_debug(
540 "%s: %s loses to %s due to sticky MAC flag",
541 pfx_buf, new_buf, exist_buf);
d62a17ae 542 return 0;
543 }
544 }
128ea8ab 545
d62a17ae 546 new_mm_seq = mac_mobility_seqnum(newattr);
547 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 548
d62a17ae 549 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 550 *reason = bgp_path_selection_evpn_seq;
d62a17ae 551 if (debug)
552 zlog_debug(
553 "%s: %s wins over %s due to MM seq %u > %u",
554 pfx_buf, new_buf, exist_buf, new_mm_seq,
555 exist_mm_seq);
556 return 1;
557 }
8ff56318 558
d62a17ae 559 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 560 *reason = bgp_path_selection_evpn_seq;
d62a17ae 561 if (debug)
562 zlog_debug(
563 "%s: %s loses to %s due to MM seq %u < %u",
564 pfx_buf, new_buf, exist_buf, new_mm_seq,
565 exist_mm_seq);
566 return 0;
567 }
6d8c603a
AK
568
569 /*
570 * if sequence numbers are the same path with the lowest IP
571 * wins
572 */
573 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
574 if (nh_cmp < 0) {
fdf81fa0 575 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
576 if (debug)
577 zlog_debug(
578 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
579 pfx_buf, new_buf, exist_buf, new_mm_seq,
580 inet_ntoa(new->attr->nexthop));
581 return 1;
582 }
583 if (nh_cmp > 0) {
fdf81fa0 584 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
585 if (debug)
586 zlog_debug(
587 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
588 pfx_buf, new_buf, exist_buf, new_mm_seq,
589 inet_ntoa(new->attr->nexthop));
590 return 0;
591 }
d62a17ae 592 }
9fbdd100 593
d62a17ae 594 /* 1. Weight check. */
d62a17ae 595 new_weight = newattr->weight;
596 exist_weight = existattr->weight;
8ff56318 597
d62a17ae 598 if (new_weight > exist_weight) {
fdf81fa0 599 *reason = bgp_path_selection_weight;
d62a17ae 600 if (debug)
601 zlog_debug("%s: %s wins over %s due to weight %d > %d",
602 pfx_buf, new_buf, exist_buf, new_weight,
603 exist_weight);
604 return 1;
605 }
718e3744 606
d62a17ae 607 if (new_weight < exist_weight) {
fdf81fa0 608 *reason = bgp_path_selection_weight;
d62a17ae 609 if (debug)
610 zlog_debug("%s: %s loses to %s due to weight %d < %d",
611 pfx_buf, new_buf, exist_buf, new_weight,
612 exist_weight);
613 return 0;
614 }
9fbdd100 615
d62a17ae 616 /* 2. Local preference check. */
617 new_pref = exist_pref = bgp->default_local_pref;
618
619 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
620 new_pref = newattr->local_pref;
621 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
622 exist_pref = existattr->local_pref;
623
624 if (new_pref > exist_pref) {
fdf81fa0 625 *reason = bgp_path_selection_local_pref;
d62a17ae 626 if (debug)
627 zlog_debug(
628 "%s: %s wins over %s due to localpref %d > %d",
629 pfx_buf, new_buf, exist_buf, new_pref,
630 exist_pref);
631 return 1;
632 }
718e3744 633
d62a17ae 634 if (new_pref < exist_pref) {
fdf81fa0 635 *reason = bgp_path_selection_local_pref;
d62a17ae 636 if (debug)
637 zlog_debug(
638 "%s: %s loses to %s due to localpref %d < %d",
639 pfx_buf, new_buf, exist_buf, new_pref,
640 exist_pref);
641 return 0;
642 }
9fbdd100 643
d62a17ae 644 /* 3. Local route check. We prefer:
645 * - BGP_ROUTE_STATIC
646 * - BGP_ROUTE_AGGREGATE
647 * - BGP_ROUTE_REDISTRIBUTE
648 */
90f4f482 649 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
650 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 651 *reason = bgp_path_selection_local_route;
d62a17ae 652 if (debug)
653 zlog_debug(
654 "%s: %s wins over %s due to preferred BGP_ROUTE type",
655 pfx_buf, new_buf, exist_buf);
656 return 1;
657 }
718e3744 658
90f4f482 659 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 660 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 661 *reason = bgp_path_selection_local_route;
d62a17ae 662 if (debug)
663 zlog_debug(
664 "%s: %s loses to %s due to preferred BGP_ROUTE type",
665 pfx_buf, new_buf, exist_buf);
666 return 0;
6811845b 667 }
718e3744 668
d62a17ae 669 /* 4. AS path length check. */
670 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
671 int exist_hops = aspath_count_hops(existattr->aspath);
672 int exist_confeds = aspath_count_confeds(existattr->aspath);
673
674 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
675 int aspath_hops;
676
677 aspath_hops = aspath_count_hops(newattr->aspath);
678 aspath_hops += aspath_count_confeds(newattr->aspath);
679
680 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 681 *reason = bgp_path_selection_confed_as_path;
d62a17ae 682 if (debug)
683 zlog_debug(
684 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
685 pfx_buf, new_buf, exist_buf,
686 aspath_hops,
687 (exist_hops + exist_confeds));
688 return 1;
689 }
690
691 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 692 *reason = bgp_path_selection_confed_as_path;
d62a17ae 693 if (debug)
694 zlog_debug(
695 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
696 pfx_buf, new_buf, exist_buf,
697 aspath_hops,
698 (exist_hops + exist_confeds));
699 return 0;
700 }
701 } else {
702 int newhops = aspath_count_hops(newattr->aspath);
703
704 if (newhops < exist_hops) {
fdf81fa0 705 *reason = bgp_path_selection_as_path;
d62a17ae 706 if (debug)
707 zlog_debug(
708 "%s: %s wins over %s due to aspath hopcount %d < %d",
709 pfx_buf, new_buf, exist_buf,
710 newhops, exist_hops);
711 return 1;
712 }
713
714 if (newhops > exist_hops) {
fdf81fa0 715 *reason = bgp_path_selection_as_path;
d62a17ae 716 if (debug)
717 zlog_debug(
718 "%s: %s loses to %s due to aspath hopcount %d > %d",
719 pfx_buf, new_buf, exist_buf,
720 newhops, exist_hops);
721 return 0;
722 }
723 }
724 }
9fbdd100 725
d62a17ae 726 /* 5. Origin check. */
727 if (newattr->origin < existattr->origin) {
fdf81fa0 728 *reason = bgp_path_selection_origin;
d62a17ae 729 if (debug)
730 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
731 pfx_buf, new_buf, exist_buf,
732 bgp_origin_long_str[newattr->origin],
733 bgp_origin_long_str[existattr->origin]);
734 return 1;
735 }
718e3744 736
d62a17ae 737 if (newattr->origin > existattr->origin) {
fdf81fa0 738 *reason = bgp_path_selection_origin;
d62a17ae 739 if (debug)
740 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
741 pfx_buf, new_buf, exist_buf,
742 bgp_origin_long_str[newattr->origin],
743 bgp_origin_long_str[existattr->origin]);
744 return 0;
745 }
718e3744 746
d62a17ae 747 /* 6. MED check. */
748 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
749 && aspath_count_hops(existattr->aspath) == 0);
750 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
751 && aspath_count_confeds(existattr->aspath) > 0
752 && aspath_count_hops(newattr->aspath) == 0
753 && aspath_count_hops(existattr->aspath) == 0);
754
755 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
756 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
757 || aspath_cmp_left(newattr->aspath, existattr->aspath)
758 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
759 || internal_as_route) {
760 new_med = bgp_med_value(new->attr, bgp);
761 exist_med = bgp_med_value(exist->attr, bgp);
762
763 if (new_med < exist_med) {
fdf81fa0 764 *reason = bgp_path_selection_med;
d62a17ae 765 if (debug)
766 zlog_debug(
767 "%s: %s wins over %s due to MED %d < %d",
768 pfx_buf, new_buf, exist_buf, new_med,
769 exist_med);
770 return 1;
771 }
8ff56318 772
d62a17ae 773 if (new_med > exist_med) {
fdf81fa0 774 *reason = bgp_path_selection_med;
d62a17ae 775 if (debug)
776 zlog_debug(
777 "%s: %s loses to %s due to MED %d > %d",
778 pfx_buf, new_buf, exist_buf, new_med,
779 exist_med);
780 return 0;
781 }
782 }
9fbdd100 783
d62a17ae 784 /* 7. Peer type check. */
785 new_sort = new->peer->sort;
786 exist_sort = exist->peer->sort;
787
788 if (new_sort == BGP_PEER_EBGP
789 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 790 *reason = bgp_path_selection_peer;
d62a17ae 791 if (debug)
792 zlog_debug(
793 "%s: %s wins over %s due to eBGP peer > iBGP peer",
794 pfx_buf, new_buf, exist_buf);
795 return 1;
796 }
718e3744 797
d62a17ae 798 if (exist_sort == BGP_PEER_EBGP
799 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 800 *reason = bgp_path_selection_peer;
d62a17ae 801 if (debug)
802 zlog_debug(
803 "%s: %s loses to %s due to iBGP peer < eBGP peer",
804 pfx_buf, new_buf, exist_buf);
805 return 0;
806 }
8ff56318 807
d62a17ae 808 /* 8. IGP metric check. */
809 newm = existm = 0;
8ff56318 810
d62a17ae 811 if (new->extra)
812 newm = new->extra->igpmetric;
813 if (exist->extra)
814 existm = exist->extra->igpmetric;
9fbdd100 815
d62a17ae 816 if (newm < existm) {
817 if (debug)
818 zlog_debug(
819 "%s: %s wins over %s due to IGP metric %d < %d",
820 pfx_buf, new_buf, exist_buf, newm, existm);
821 ret = 1;
822 }
718e3744 823
d62a17ae 824 if (newm > existm) {
825 if (debug)
826 zlog_debug(
827 "%s: %s loses to %s due to IGP metric %d > %d",
828 pfx_buf, new_buf, exist_buf, newm, existm);
829 ret = 0;
5e242b0d 830 }
5e242b0d 831
d62a17ae 832 /* 9. Same IGP metric. Compare the cluster list length as
833 representative of IGP hops metric. Rewrite the metric value
834 pair (newm, existm) with the cluster list length. Prefer the
835 path with smaller cluster list length. */
836 if (newm == existm) {
837 if (peer_sort(new->peer) == BGP_PEER_IBGP
838 && peer_sort(exist->peer) == BGP_PEER_IBGP
839 && (mpath_cfg == NULL
840 || CHECK_FLAG(
841 mpath_cfg->ibgp_flags,
842 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
843 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
844 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
845
846 if (newm < existm) {
847 if (debug)
848 zlog_debug(
849 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
850 pfx_buf, new_buf, exist_buf,
851 newm, existm);
852 ret = 1;
853 }
854
855 if (newm > existm) {
856 if (debug)
857 zlog_debug(
858 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
859 pfx_buf, new_buf, exist_buf,
860 newm, existm);
861 ret = 0;
862 }
863 }
864 }
31a4638f 865
d62a17ae 866 /* 10. confed-external vs. confed-internal */
867 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
868 if (new_sort == BGP_PEER_CONFED
869 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 870 *reason = bgp_path_selection_confed;
d62a17ae 871 if (debug)
872 zlog_debug(
873 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
874 pfx_buf, new_buf, exist_buf);
875 return 1;
876 }
718e3744 877
d62a17ae 878 if (exist_sort == BGP_PEER_CONFED
879 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 880 *reason = bgp_path_selection_confed;
d62a17ae 881 if (debug)
882 zlog_debug(
883 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
884 pfx_buf, new_buf, exist_buf);
885 return 0;
886 }
887 }
718e3744 888
d62a17ae 889 /* 11. Maximum path check. */
890 if (newm == existm) {
891 /* If one path has a label but the other does not, do not treat
892 * them as equals for multipath
893 */
a4d82a8a 894 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 895 != (exist->extra
b57ba6d2 896 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 897 if (debug)
898 zlog_debug(
899 "%s: %s and %s cannot be multipath, one has a label while the other does not",
900 pfx_buf, new_buf, exist_buf);
901 } else if (bgp_flag_check(bgp,
902 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
903
904 /*
905 * For the two paths, all comparison steps till IGP
906 * metric
907 * have succeeded - including AS_PATH hop count. Since
908 * 'bgp
909 * bestpath as-path multipath-relax' knob is on, we
910 * don't need
911 * an exact match of AS_PATH. Thus, mark the paths are
912 * equal.
913 * That will trigger both these paths to get into the
914 * multipath
915 * array.
916 */
917 *paths_eq = 1;
918
919 if (debug)
920 zlog_debug(
921 "%s: %s and %s are equal via multipath-relax",
922 pfx_buf, new_buf, exist_buf);
923 } else if (new->peer->sort == BGP_PEER_IBGP) {
924 if (aspath_cmp(new->attr->aspath,
925 exist->attr->aspath)) {
926 *paths_eq = 1;
927
928 if (debug)
929 zlog_debug(
930 "%s: %s and %s are equal via matching aspaths",
931 pfx_buf, new_buf, exist_buf);
932 }
933 } else if (new->peer->as == exist->peer->as) {
934 *paths_eq = 1;
935
936 if (debug)
937 zlog_debug(
938 "%s: %s and %s are equal via same remote-as",
939 pfx_buf, new_buf, exist_buf);
940 }
941 } else {
942 /*
943 * TODO: If unequal cost ibgp multipath is enabled we can
944 * mark the paths as equal here instead of returning
945 */
946 if (debug) {
947 if (ret == 1)
948 zlog_debug(
949 "%s: %s wins over %s after IGP metric comparison",
950 pfx_buf, new_buf, exist_buf);
951 else
952 zlog_debug(
953 "%s: %s loses to %s after IGP metric comparison",
954 pfx_buf, new_buf, exist_buf);
955 }
fdf81fa0 956 *reason = bgp_path_selection_igp_metric;
d62a17ae 957 return ret;
958 }
718e3744 959
d62a17ae 960 /* 12. If both paths are external, prefer the path that was received
961 first (the oldest one). This step minimizes route-flap, since a
962 newer path won't displace an older one, even if it was the
963 preferred route based on the additional decision criteria below. */
964 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
965 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 966 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 967 *reason = bgp_path_selection_older;
d62a17ae 968 if (debug)
969 zlog_debug(
970 "%s: %s wins over %s due to oldest external",
971 pfx_buf, new_buf, exist_buf);
972 return 1;
973 }
9fbdd100 974
1defdda8 975 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 976 *reason = bgp_path_selection_older;
d62a17ae 977 if (debug)
978 zlog_debug(
979 "%s: %s loses to %s due to oldest external",
980 pfx_buf, new_buf, exist_buf);
981 return 0;
982 }
983 }
718e3744 984
d62a17ae 985 /* 13. Router-ID comparision. */
986 /* If one of the paths is "stale", the corresponding peer router-id will
987 * be 0 and would always win over the other path. If originator id is
988 * used for the comparision, it will decide which path is better.
989 */
990 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
991 new_id.s_addr = newattr->originator_id.s_addr;
992 else
993 new_id.s_addr = new->peer->remote_id.s_addr;
994 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
995 exist_id.s_addr = existattr->originator_id.s_addr;
996 else
997 exist_id.s_addr = exist->peer->remote_id.s_addr;
998
999 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1000 *reason = bgp_path_selection_router_id;
d62a17ae 1001 if (debug)
1002 zlog_debug(
1003 "%s: %s wins over %s due to Router-ID comparison",
1004 pfx_buf, new_buf, exist_buf);
1005 return 1;
1006 }
718e3744 1007
d62a17ae 1008 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1009 *reason = bgp_path_selection_router_id;
d62a17ae 1010 if (debug)
1011 zlog_debug(
1012 "%s: %s loses to %s due to Router-ID comparison",
1013 pfx_buf, new_buf, exist_buf);
1014 return 0;
1015 }
9fbdd100 1016
d62a17ae 1017 /* 14. Cluster length comparision. */
1018 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1019 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1020
1021 if (new_cluster < exist_cluster) {
fdf81fa0 1022 *reason = bgp_path_selection_cluster_length;
d62a17ae 1023 if (debug)
1024 zlog_debug(
1025 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1026 pfx_buf, new_buf, exist_buf, new_cluster,
1027 exist_cluster);
1028 return 1;
1029 }
718e3744 1030
d62a17ae 1031 if (new_cluster > exist_cluster) {
fdf81fa0 1032 *reason = bgp_path_selection_cluster_length;
d62a17ae 1033 if (debug)
1034 zlog_debug(
1035 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1036 pfx_buf, new_buf, exist_buf, new_cluster,
1037 exist_cluster);
1038 return 0;
1039 }
9fbdd100 1040
d62a17ae 1041 /* 15. Neighbor address comparision. */
1042 /* Do this only if neither path is "stale" as stale paths do not have
1043 * valid peer information (as the connection may or may not be up).
1044 */
1defdda8 1045 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1046 *reason = bgp_path_selection_stale;
d62a17ae 1047 if (debug)
1048 zlog_debug(
1049 "%s: %s wins over %s due to latter path being STALE",
1050 pfx_buf, new_buf, exist_buf);
1051 return 1;
1052 }
0de5153c 1053
1defdda8 1054 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1055 *reason = bgp_path_selection_stale;
d62a17ae 1056 if (debug)
1057 zlog_debug(
1058 "%s: %s loses to %s due to former path being STALE",
1059 pfx_buf, new_buf, exist_buf);
1060 return 0;
1061 }
718e3744 1062
d62a17ae 1063 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1064 if (new->peer->su_remote == NULL) {
1065 *reason = bgp_path_selection_local_configured;
d62a17ae 1066 return 0;
fdf81fa0
DS
1067 }
1068 if (exist->peer->su_remote == NULL) {
1069 *reason = bgp_path_selection_local_configured;
d62a17ae 1070 return 1;
fdf81fa0 1071 }
9fbdd100 1072
d62a17ae 1073 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1074
1075 if (ret == 1) {
fdf81fa0 1076 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1077 if (debug)
1078 zlog_debug(
1079 "%s: %s loses to %s due to Neighor IP comparison",
1080 pfx_buf, new_buf, exist_buf);
1081 return 0;
1082 }
1083
1084 if (ret == -1) {
fdf81fa0 1085 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1086 if (debug)
1087 zlog_debug(
1088 "%s: %s wins over %s due to Neighor IP comparison",
1089 pfx_buf, new_buf, exist_buf);
1090 return 1;
1091 }
9fbdd100 1092
fdf81fa0 1093 *reason = bgp_path_selection_default;
d62a17ae 1094 if (debug)
1095 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1096 pfx_buf, new_buf, exist_buf);
718e3744 1097
d62a17ae 1098 return 1;
718e3744 1099}
1100
65efcfce
LB
1101/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1102 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1103 * multipath is enabled
65efcfce 1104 * This version is compatible with */
18ee8310
DS
1105int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1106 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1107 afi_t afi, safi_t safi,
1108 enum bgp_path_selection_reason *reason)
d62a17ae 1109{
1110 int paths_eq;
1111 int ret;
18ee8310 1112 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1113 afi, safi, reason);
d62a17ae 1114
1115 if (paths_eq)
1116 ret = 0;
1117 else {
1118 if (ret == 1)
1119 ret = -1;
1120 else
1121 ret = 1;
1122 }
1123 return ret;
65efcfce
LB
1124}
1125
d62a17ae 1126static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1127 struct attr *attr, afi_t afi,
1128 safi_t safi)
718e3744 1129{
d62a17ae 1130 struct bgp_filter *filter;
718e3744 1131
d62a17ae 1132 filter = &peer->filter[afi][safi];
718e3744 1133
d62a17ae 1134#define FILTER_EXIST_WARN(F, f, filter) \
1135 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1136 zlog_debug("%s: Could not find configured input %s-list %s!", \
1137 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1138
1139 if (DISTRIBUTE_IN_NAME(filter)) {
1140 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1141
1142 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1143 return FILTER_DENY;
1144 }
1145
1146 if (PREFIX_LIST_IN_NAME(filter)) {
1147 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1148
1149 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1150 return FILTER_DENY;
1151 }
1152
1153 if (FILTER_LIST_IN_NAME(filter)) {
1154 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1155
1156 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1157 == AS_FILTER_DENY)
1158 return FILTER_DENY;
1159 }
1160
1161 return FILTER_PERMIT;
650f76c2 1162#undef FILTER_EXIST_WARN
718e3744 1163}
1164
d62a17ae 1165static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1166 struct attr *attr, afi_t afi,
1167 safi_t safi)
718e3744 1168{
d62a17ae 1169 struct bgp_filter *filter;
1170
1171 filter = &peer->filter[afi][safi];
1172
1173#define FILTER_EXIST_WARN(F, f, filter) \
1174 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1175 zlog_debug("%s: Could not find configured output %s-list %s!", \
1176 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1177
d62a17ae 1178 if (DISTRIBUTE_OUT_NAME(filter)) {
1179 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1180
d62a17ae 1181 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1182 return FILTER_DENY;
1183 }
1184
1185 if (PREFIX_LIST_OUT_NAME(filter)) {
1186 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1187
d62a17ae 1188 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1189 == PREFIX_DENY)
1190 return FILTER_DENY;
1191 }
718e3744 1192
d62a17ae 1193 if (FILTER_LIST_OUT_NAME(filter)) {
1194 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1195
d62a17ae 1196 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1197 == AS_FILTER_DENY)
1198 return FILTER_DENY;
1199 }
718e3744 1200
d62a17ae 1201 return FILTER_PERMIT;
650f76c2 1202#undef FILTER_EXIST_WARN
718e3744 1203}
1204
1205/* If community attribute includes no_export then return 1. */
d62a17ae 1206static int bgp_community_filter(struct peer *peer, struct attr *attr)
1207{
1208 if (attr->community) {
1209 /* NO_ADVERTISE check. */
1210 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1211 return 1;
1212
1213 /* NO_EXPORT check. */
1214 if (peer->sort == BGP_PEER_EBGP
1215 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1216 return 1;
1217
1218 /* NO_EXPORT_SUBCONFED check. */
1219 if (peer->sort == BGP_PEER_EBGP
1220 || peer->sort == BGP_PEER_CONFED)
1221 if (community_include(attr->community,
1222 COMMUNITY_NO_EXPORT_SUBCONFED))
1223 return 1;
1224 }
1225 return 0;
718e3744 1226}
1227
1228/* Route reflection loop check. */
d62a17ae 1229static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1230{
d62a17ae 1231 struct in_addr cluster_id;
718e3744 1232
d62a17ae 1233 if (attr->cluster) {
1234 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1235 cluster_id = peer->bgp->cluster_id;
1236 else
1237 cluster_id = peer->bgp->router_id;
1238
1239 if (cluster_loop_check(attr->cluster, cluster_id))
1240 return 1;
1241 }
1242 return 0;
718e3744 1243}
6b0655a2 1244
d62a17ae 1245static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1246 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1247 const char *rmap_name, mpls_label_t *label,
196c6b09 1248 uint32_t num_labels, struct bgp_node *rn)
718e3744 1249{
d62a17ae 1250 struct bgp_filter *filter;
82b692c0
LK
1251 struct bgp_path_info rmap_path = { 0 };
1252 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1253 route_map_result_t ret;
1254 struct route_map *rmap = NULL;
718e3744 1255
d62a17ae 1256 filter = &peer->filter[afi][safi];
718e3744 1257
d62a17ae 1258 /* Apply default weight value. */
1259 if (peer->weight[afi][safi])
1260 attr->weight = peer->weight[afi][safi];
718e3744 1261
d62a17ae 1262 if (rmap_name) {
1263 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1264
d62a17ae 1265 if (rmap == NULL)
1266 return RMAP_DENY;
1267 } else {
1268 if (ROUTE_MAP_IN_NAME(filter)) {
1269 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1270
d62a17ae 1271 if (rmap == NULL)
1272 return RMAP_DENY;
1273 }
1274 }
0b16f239 1275
d62a17ae 1276 /* Route map apply. */
1277 if (rmap) {
40381db7 1278 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1279 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1280 rmap_path.peer = peer;
1281 rmap_path.attr = attr;
82b692c0 1282 rmap_path.extra = &extra;
196c6b09
LK
1283 rmap_path.net = rn;
1284
82b692c0
LK
1285 extra.num_labels = num_labels;
1286 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1287 memcpy(extra.label, label,
1288 num_labels * sizeof(mpls_label_t));
718e3744 1289
d62a17ae 1290 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1291
d62a17ae 1292 /* Apply BGP route map to the attribute. */
40381db7 1293 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1294
d62a17ae 1295 peer->rmap_type = 0;
0b16f239 1296
1f2263be 1297 if (ret == RMAP_DENYMATCH)
d62a17ae 1298 return RMAP_DENY;
0b16f239 1299 }
d62a17ae 1300 return RMAP_PERMIT;
0b16f239
DS
1301}
1302
d62a17ae 1303static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1304 struct attr *attr, afi_t afi, safi_t safi,
1305 const char *rmap_name)
0b16f239 1306{
40381db7 1307 struct bgp_path_info rmap_path;
d62a17ae 1308 route_map_result_t ret;
1309 struct route_map *rmap = NULL;
d7c0a89a 1310 uint8_t rmap_type;
0b16f239 1311
b787157a
DS
1312 /*
1313 * So if we get to this point and have no rmap_name
1314 * we want to just show the output as it currently
1315 * exists.
1316 */
1317 if (!rmap_name)
1318 return RMAP_PERMIT;
0b16f239 1319
d62a17ae 1320 /* Apply default weight value. */
1321 if (peer->weight[afi][safi])
1322 attr->weight = peer->weight[afi][safi];
0b16f239 1323
b787157a 1324 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1325
b787157a
DS
1326 /*
1327 * If we have a route map name and we do not find
1328 * the routemap that means we have an implicit
1329 * deny.
1330 */
1331 if (rmap == NULL)
1332 return RMAP_DENY;
0b16f239 1333
40381db7 1334 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1335 /* Route map apply. */
b787157a 1336 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1337 rmap_path.peer = peer;
1338 rmap_path.attr = attr;
0b16f239 1339
0f672529 1340 rmap_type = peer->rmap_type;
b787157a 1341 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1342
b787157a 1343 /* Apply BGP route map to the attribute. */
40381db7 1344 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1345
0f672529 1346 peer->rmap_type = rmap_type;
b787157a
DS
1347
1348 if (ret == RMAP_DENYMATCH)
1349 /*
1350 * caller has multiple error paths with bgp_attr_flush()
1351 */
1352 return RMAP_DENY;
ac41b2a2 1353
d62a17ae 1354 return RMAP_PERMIT;
718e3744 1355}
6b0655a2 1356
5000f21c 1357/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1358static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1359 struct peer *peer, struct attr *attr)
1360{
1361 if (peer->sort == BGP_PEER_EBGP
1362 && (peer_af_flag_check(peer, afi, safi,
1363 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1364 || peer_af_flag_check(peer, afi, safi,
1365 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1366 || peer_af_flag_check(peer, afi, safi,
1367 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1368 || peer_af_flag_check(peer, afi, safi,
1369 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1370 // Take action on the entire aspath
1371 if (peer_af_flag_check(peer, afi, safi,
1372 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1373 || peer_af_flag_check(peer, afi, safi,
1374 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1375 if (peer_af_flag_check(
1376 peer, afi, safi,
1377 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1378 attr->aspath = aspath_replace_private_asns(
bf26b80e 1379 attr->aspath, bgp->as, peer->as);
d62a17ae 1380
1381 // The entire aspath consists of private ASNs so create
1382 // an empty aspath
1383 else if (aspath_private_as_check(attr->aspath))
1384 attr->aspath = aspath_empty_get();
1385
1386 // There are some public and some private ASNs, remove
1387 // the private ASNs
1388 else
1389 attr->aspath = aspath_remove_private_asns(
bf26b80e 1390 attr->aspath, peer->as);
d62a17ae 1391 }
1392
1393 // 'all' was not specified so the entire aspath must be private
1394 // ASNs
1395 // for us to do anything
1396 else if (aspath_private_as_check(attr->aspath)) {
1397 if (peer_af_flag_check(
1398 peer, afi, safi,
1399 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1400 attr->aspath = aspath_replace_private_asns(
bf26b80e 1401 attr->aspath, bgp->as, peer->as);
d62a17ae 1402 else
1403 attr->aspath = aspath_empty_get();
1404 }
1405 }
5000f21c
DS
1406}
1407
c7122e14 1408/* If this is an EBGP peer with as-override */
d62a17ae 1409static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1410 struct peer *peer, struct attr *attr)
1411{
1412 if (peer->sort == BGP_PEER_EBGP
1413 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1414 if (aspath_single_asn_check(attr->aspath, peer->as))
1415 attr->aspath = aspath_replace_specific_asn(
1416 attr->aspath, peer->as, bgp->as);
1417 }
1418}
1419
7f323236
DW
1420void bgp_attr_add_gshut_community(struct attr *attr)
1421{
1422 struct community *old;
1423 struct community *new;
1424 struct community *merge;
1425 struct community *gshut;
1426
1427 old = attr->community;
1428 gshut = community_str2com("graceful-shutdown");
1429
990f4f91 1430 assert(gshut);
1431
7f323236
DW
1432 if (old) {
1433 merge = community_merge(community_dup(old), gshut);
1434
a4d82a8a 1435 if (old->refcnt == 0)
3c1f53de 1436 community_free(&old);
7f323236
DW
1437
1438 new = community_uniq_sort(merge);
3c1f53de 1439 community_free(&merge);
7f323236
DW
1440 } else {
1441 new = community_dup(gshut);
1442 }
1443
3c1f53de 1444 community_free(&gshut);
7f323236
DW
1445 attr->community = new;
1446 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1447
1448 /* When we add the graceful-shutdown community we must also
1449 * lower the local-preference */
1450 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1451 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1452}
1453
1454
d7c0a89a 1455static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1456{
960035b2 1457 if (family == AF_INET) {
d62a17ae 1458 attr->nexthop.s_addr = 0;
960035b2
PZ
1459 attr->mp_nexthop_global_in.s_addr = 0;
1460 }
d62a17ae 1461 if (family == AF_INET6)
1462 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1463 if (family == AF_EVPN)
1464 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1465}
1466
40381db7 1467int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1468 struct update_subgroup *subgrp, struct prefix *p,
1469 struct attr *attr)
1470{
1471 struct bgp_filter *filter;
1472 struct peer *from;
1473 struct peer *peer;
1474 struct peer *onlypeer;
1475 struct bgp *bgp;
40381db7 1476 struct attr *piattr;
d62a17ae 1477 char buf[PREFIX_STRLEN];
b68885f9 1478 route_map_result_t ret;
d62a17ae 1479 int transparent;
1480 int reflect;
1481 afi_t afi;
1482 safi_t safi;
1483 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1484
1485 if (DISABLE_BGP_ANNOUNCE)
1486 return 0;
1487
1488 afi = SUBGRP_AFI(subgrp);
1489 safi = SUBGRP_SAFI(subgrp);
1490 peer = SUBGRP_PEER(subgrp);
1491 onlypeer = NULL;
1492 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1493 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1494
40381db7 1495 from = pi->peer;
d62a17ae 1496 filter = &peer->filter[afi][safi];
1497 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1498 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1499 : pi->attr;
3f9c7369 1500
65efcfce 1501#if ENABLE_BGP_VNC
d62a17ae 1502 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1503 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1504 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1505
1506 /*
1507 * direct and direct_ext type routes originate internally even
1508 * though they can have peer pointers that reference other
1509 * systems
1510 */
1511 prefix2str(p, buf, PREFIX_STRLEN);
1512 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1513 __func__, buf);
1514 samepeer_safe = 1;
1515 }
65efcfce
LB
1516#endif
1517
ddb5b488
PZ
1518 if (((afi == AFI_IP) || (afi == AFI_IP6))
1519 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1520 && (pi->type == ZEBRA_ROUTE_BGP)
1521 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1522
1523 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1524
1525 samepeer_safe = 1;
1526 }
1527
d62a17ae 1528 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1529 * pi is valid */
1530 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1531 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1532 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1533 return 0;
1534 }
adbac85e 1535
d62a17ae 1536 /* If this is not the bestpath then check to see if there is an enabled
1537 * addpath
1538 * feature that requires us to advertise it */
40381db7 1539 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1540 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1541 return 0;
1542 }
1543 }
06370dac 1544
d62a17ae 1545 /* Aggregate-address suppress check. */
40381db7 1546 if (pi->extra && pi->extra->suppress)
d62a17ae 1547 if (!UNSUPPRESS_MAP_NAME(filter)) {
1548 return 0;
1549 }
3f9c7369 1550
13b7e7f0
DS
1551 /*
1552 * If we are doing VRF 2 VRF leaking via the import
1553 * statement, we want to prevent the route going
1554 * off box as that the RT and RD created are localy
1555 * significant and globaly useless.
1556 */
40381db7
DS
1557 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1558 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1559 return 0;
1560
d62a17ae 1561 /* If it's labeled safi, make sure the route has a valid label. */
1562 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1563 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1564 if (!bgp_is_valid_label(&label)) {
1565 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1566 zlog_debug("u%" PRIu64 ":s%" PRIu64
1567 " %s/%d is filtered - no label (%p)",
1568 subgrp->update_group->id, subgrp->id,
1569 inet_ntop(p->family, &p->u.prefix,
1570 buf, SU_ADDRSTRLEN),
1571 p->prefixlen, &label);
1572 return 0;
1573 }
1574 }
cd1964ff 1575
d62a17ae 1576 /* Do not send back route to sender. */
1577 if (onlypeer && from == onlypeer) {
1578 return 0;
1579 }
3f9c7369 1580
d62a17ae 1581 /* Do not send the default route in the BGP table if the neighbor is
1582 * configured for default-originate */
1583 if (CHECK_FLAG(peer->af_flags[afi][safi],
1584 PEER_FLAG_DEFAULT_ORIGINATE)) {
1585 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1586 return 0;
1587 else if (p->family == AF_INET6 && p->prefixlen == 0)
1588 return 0;
1589 }
4125bb67 1590
d62a17ae 1591 /* Transparency check. */
1592 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1593 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1594 transparent = 1;
1595 else
1596 transparent = 0;
1597
1598 /* If community is not disabled check the no-export and local. */
40381db7 1599 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1600 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1601 zlog_debug(
1602 "subgrpannouncecheck: community filter check fail");
1603 return 0;
1604 }
3f9c7369 1605
d62a17ae 1606 /* If the attribute has originator-id and it is same as remote
1607 peer's id. */
40381db7
DS
1608 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1609 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1610 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1611 zlog_debug(
1612 "%s [Update:SEND] %s originator-id is same as "
1613 "remote router-id",
1614 onlypeer->host,
1615 prefix2str(p, buf, sizeof(buf)));
1616 return 0;
1617 }
3f9c7369 1618
d62a17ae 1619 /* ORF prefix-list filter check */
1620 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1621 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1622 || CHECK_FLAG(peer->af_cap[afi][safi],
1623 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1624 if (peer->orf_plist[afi][safi]) {
1625 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1626 == PREFIX_DENY) {
1627 if (bgp_debug_update(NULL, p,
1628 subgrp->update_group, 0))
1629 zlog_debug(
1630 "%s [Update:SEND] %s is filtered via ORF",
1631 peer->host,
1632 prefix2str(p, buf,
1633 sizeof(buf)));
1634 return 0;
1635 }
1636 }
1637
1638 /* Output filter check. */
40381db7 1639 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1640 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1641 zlog_debug("%s [Update:SEND] %s is filtered",
1642 peer->host, prefix2str(p, buf, sizeof(buf)));
1643 return 0;
1644 }
3f9c7369 1645
d62a17ae 1646 /* AS path loop check. */
2b31007c
RZ
1647 if (onlypeer && onlypeer->as_path_loop_detection
1648 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1649 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1650 zlog_debug(
1651 "%s [Update:SEND] suppress announcement to peer AS %u "
1652 "that is part of AS path.",
1653 onlypeer->host, onlypeer->as);
1654 return 0;
1655 }
3f9c7369 1656
d62a17ae 1657 /* If we're a CONFED we need to loop check the CONFED ID too */
1658 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1659 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1660 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1661 zlog_debug(
1662 "%s [Update:SEND] suppress announcement to peer AS %u"
1663 " is AS path.",
1664 peer->host, bgp->confed_id);
1665 return 0;
1666 }
3f9c7369 1667 }
3f9c7369 1668
d62a17ae 1669 /* Route-Reflect check. */
1670 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1671 reflect = 1;
1672 else
1673 reflect = 0;
1674
1675 /* IBGP reflection check. */
1676 if (reflect && !samepeer_safe) {
1677 /* A route from a Client peer. */
1678 if (CHECK_FLAG(from->af_flags[afi][safi],
1679 PEER_FLAG_REFLECTOR_CLIENT)) {
1680 /* Reflect to all the Non-Client peers and also to the
1681 Client peers other than the originator. Originator
1682 check
1683 is already done. So there is noting to do. */
1684 /* no bgp client-to-client reflection check. */
1685 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1686 if (CHECK_FLAG(peer->af_flags[afi][safi],
1687 PEER_FLAG_REFLECTOR_CLIENT))
1688 return 0;
1689 } else {
1690 /* A route from a Non-client peer. Reflect to all other
1691 clients. */
1692 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1693 PEER_FLAG_REFLECTOR_CLIENT))
1694 return 0;
1695 }
1696 }
3f9c7369 1697
d62a17ae 1698 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1699 *attr = *piattr;
d62a17ae 1700
1701 /* If local-preference is not set. */
1702 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1703 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1704 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1705 attr->local_pref = bgp->default_local_pref;
3f9c7369 1706 }
3f9c7369 1707
d62a17ae 1708 /* If originator-id is not set and the route is to be reflected,
1709 set the originator id */
1710 if (reflect
1711 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1712 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1713 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1714 }
3f9c7369 1715
d62a17ae 1716 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1717 */
1718 if (peer->sort == BGP_PEER_EBGP
1719 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1720 if (from != bgp->peer_self && !transparent
1721 && !CHECK_FLAG(peer->af_flags[afi][safi],
1722 PEER_FLAG_MED_UNCHANGED))
1723 attr->flag &=
1724 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1725 }
3f9c7369 1726
d62a17ae 1727 /* Since the nexthop attribute can vary per peer, it is not explicitly
1728 * set
1729 * in announce check, only certain flags and length (or number of
1730 * nexthops
1731 * -- for IPv6/MP_REACH) are set here in order to guide the update
1732 * formation
1733 * code in setting the nexthop(s) on a per peer basis in
1734 * reformat_peer().
1735 * Typically, the source nexthop in the attribute is preserved but in
1736 * the
1737 * scenarios where we know it will always be overwritten, we reset the
1738 * nexthop to "0" in an attempt to achieve better Update packing. An
1739 * example of this is when a prefix from each of 2 IBGP peers needs to
1740 * be
1741 * announced to an EBGP peer (and they have the same attributes barring
1742 * their nexthop).
1743 */
1744 if (reflect)
1745 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1746
1747#define NEXTHOP_IS_V6 \
1748 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1749 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1750 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1751 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1752
1753 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1754 * if
1755 * the peer (group) is configured to receive link-local nexthop
1756 * unchanged
c728d027
DA
1757 * and it is available in the prefix OR we're not reflecting the route,
1758 * link-local nexthop address is valid and
d62a17ae 1759 * the peer (group) to whom we're going to announce is on a shared
1760 * network
1761 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1762 * By checking if nexthop LL address is valid we are sure that
1763 * we do not announce LL address as `::`.
d62a17ae 1764 */
1765 if (NEXTHOP_IS_V6) {
1766 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1767 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1768 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1769 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1770 || (!reflect
1771 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1772 && peer->shared_network
d62a17ae 1773 && (from == bgp->peer_self
1774 || peer->sort == BGP_PEER_EBGP))) {
1775 attr->mp_nexthop_len =
1776 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1777 }
3f9c7369 1778
d62a17ae 1779 /* Clear off link-local nexthop in source, whenever it is not
1780 * needed to
1781 * ensure more prefixes share the same attribute for
1782 * announcement.
1783 */
1784 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1785 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1786 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1787 }
3f9c7369 1788
d62a17ae 1789 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1790 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1791
1792 /* Route map & unsuppress-map apply. */
40381db7 1793 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1794 struct bgp_path_info rmap_path = {0};
1795 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1796 struct attr dummy_attr = {0};
d62a17ae 1797
40381db7
DS
1798 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1799 rmap_path.peer = peer;
1800 rmap_path.attr = attr;
196c6b09 1801 rmap_path.net = rn;
d37ba549 1802
40381db7
DS
1803 if (pi->extra) {
1804 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1805 sizeof(struct bgp_path_info_extra));
40381db7 1806 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1807 }
1808
d62a17ae 1809 /* don't confuse inbound and outbound setting */
1810 RESET_FLAG(attr->rmap_change_flags);
1811
1812 /*
1813 * The route reflector is not allowed to modify the attributes
1814 * of the reflected IBGP routes unless explicitly allowed.
1815 */
1816 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1817 && !bgp_flag_check(bgp,
1818 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1819 dummy_attr = *attr;
40381db7 1820 rmap_path.attr = &dummy_attr;
d62a17ae 1821 }
3f9c7369 1822
d62a17ae 1823 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1824
40381db7 1825 if (pi->extra && pi->extra->suppress)
d62a17ae 1826 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1827 RMAP_BGP, &rmap_path);
d62a17ae 1828 else
1829 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1830 RMAP_BGP, &rmap_path);
d62a17ae 1831
1832 peer->rmap_type = 0;
1833
1834 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1835 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1836 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1837 peer->host, prefix2str(p, buf, sizeof(buf)));
1838
d62a17ae 1839 bgp_attr_flush(attr);
1840 return 0;
1841 }
3f9c7369 1842 }
3f9c7369 1843
9dac9fc8
DA
1844 /* RFC 8212 to prevent route leaks.
1845 * This specification intends to improve this situation by requiring the
1846 * explicit configuration of both BGP Import and Export Policies for any
1847 * External BGP (EBGP) session such as customers, peers, or
1848 * confederation boundaries for all enabled address families. Through
1849 * codification of the aforementioned requirement, operators will
1850 * benefit from consistent behavior across different BGP
1851 * implementations.
1852 */
1853 if (peer->bgp->ebgp_requires_policy
1854 == DEFAULT_EBGP_POLICY_ENABLED)
1855 if (!bgp_outbound_policy_exists(peer, filter))
1856 return 0;
1857
fb29348a
DA
1858 /* draft-ietf-idr-deprecate-as-set-confed-set
1859 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1860 * Eventually, This document (if approved) updates RFC 4271
1861 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1862 * and obsoletes RFC 6472.
1863 */
1864 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
1865 if (aspath_check_as_sets(attr->aspath))
1866 return 0;
1867
7f323236 1868 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1869 if (peer->sort == BGP_PEER_IBGP
1870 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1871 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1872 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1873 } else {
1874 bgp_attr_add_gshut_community(attr);
1875 }
1876 }
1877
d62a17ae 1878 /* After route-map has been applied, we check to see if the nexthop to
1879 * be carried in the attribute (that is used for the announcement) can
1880 * be cleared off or not. We do this in all cases where we would be
1881 * setting the nexthop to "ourselves". For IPv6, we only need to
1882 * consider
1883 * the global nexthop here; the link-local nexthop would have been
1884 * cleared
1885 * already, and if not, it is required by the update formation code.
1886 * Also see earlier comments in this function.
1887 */
1888 /*
1889 * If route-map has performed some operation on the nexthop or the peer
1890 * configuration says to pass it unchanged, we cannot reset the nexthop
1891 * here, so only attempt to do it if these aren't true. Note that the
1892 * route-map handler itself might have cleared the nexthop, if for
1893 * example,
1894 * it is configured as 'peer-address'.
1895 */
1896 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1897 piattr->rmap_change_flags)
d62a17ae 1898 && !transparent
1899 && !CHECK_FLAG(peer->af_flags[afi][safi],
1900 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1901 /* We can reset the nexthop, if setting (or forcing) it to
1902 * 'self' */
1903 if (CHECK_FLAG(peer->af_flags[afi][safi],
1904 PEER_FLAG_NEXTHOP_SELF)
1905 || CHECK_FLAG(peer->af_flags[afi][safi],
1906 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1907 if (!reflect
1908 || CHECK_FLAG(peer->af_flags[afi][safi],
1909 PEER_FLAG_FORCE_NEXTHOP_SELF))
1910 subgroup_announce_reset_nhop(
1911 (peer_cap_enhe(peer, afi, safi)
1912 ? AF_INET6
1913 : p->family),
1914 attr);
1915 } else if (peer->sort == BGP_PEER_EBGP) {
1916 /* Can also reset the nexthop if announcing to EBGP, but
1917 * only if
1918 * no peer in the subgroup is on a shared subnet.
1919 * Note: 3rd party nexthop currently implemented for
1920 * IPv4 only.
1921 */
737af885
BS
1922 if ((p->family == AF_INET) &&
1923 (!bgp_subgrp_multiaccess_check_v4(
1924 piattr->nexthop,
1925 subgrp)))
d62a17ae 1926 subgroup_announce_reset_nhop(
1927 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1928 ? AF_INET6
1929 : p->family),
737af885
BS
1930 attr);
1931
1932 if ((p->family == AF_INET6) &&
1933 (!bgp_subgrp_multiaccess_check_v6(
1934 piattr->mp_nexthop_global,
1935 subgrp)))
1936 subgroup_announce_reset_nhop(
1937 (peer_cap_enhe(peer, afi, safi)
1938 ? AF_INET6
1939 : p->family),
1940 attr);
1941
1942
1943
40381db7 1944 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1945 /*
1946 * This flag is used for leaked vpn-vrf routes
1947 */
1948 int family = p->family;
1949
1950 if (peer_cap_enhe(peer, afi, safi))
1951 family = AF_INET6;
1952
1953 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1954 zlog_debug(
1defdda8 1955 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1956 __func__, family2str(family));
1957 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1958 }
63696f1d 1959 }
960035b2 1960
63696f1d 1961 /* If IPv6/MP and nexthop does not have any override and happens
1962 * to
1963 * be a link-local address, reset it so that we don't pass along
1964 * the
1965 * source's link-local IPv6 address to recipients who may not be
1966 * on
1967 * the same interface.
1968 */
1969 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1970 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1971 subgroup_announce_reset_nhop(AF_INET6, attr);
d62a17ae 1972 }
3f9c7369 1973
d62a17ae 1974 return 1;
3f9c7369
DS
1975}
1976
d62a17ae 1977void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1978 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1979 struct bgp_path_info_pair *result, afi_t afi,
1980 safi_t safi)
1981{
1982 struct bgp_path_info *new_select;
1983 struct bgp_path_info *old_select;
40381db7
DS
1984 struct bgp_path_info *pi;
1985 struct bgp_path_info *pi1;
1986 struct bgp_path_info *pi2;
1987 struct bgp_path_info *nextpi = NULL;
d62a17ae 1988 int paths_eq, do_mpath, debug;
1989 struct list mp_list;
1990 char pfx_buf[PREFIX2STR_BUFFER];
1991 char path_buf[PATH_ADDPATH_STR_BUFFER];
1992
1993 bgp_mp_list_init(&mp_list);
1994 do_mpath =
1995 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1996
1997 debug = bgp_debug_bestpath(&rn->p);
1998
1999 if (debug)
2000 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2001
2002 /* bgp deterministic-med */
2003 new_select = NULL;
2004 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
2005
1defdda8 2006 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
2007 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2008 pi1 = pi1->next)
40381db7 2009 bgp_path_info_unset_flag(rn, pi1,
18ee8310 2010 BGP_PATH_DMED_SELECTED);
d62a17ae 2011
6f94b685
DS
2012 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2013 pi1 = pi1->next) {
40381db7 2014 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2015 continue;
40381db7 2016 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2017 continue;
ea8b2282 2018 if (pi1->peer != bgp->peer_self)
40381db7 2019 if (pi1->peer->status != Established)
d62a17ae 2020 continue;
2021
40381db7
DS
2022 new_select = pi1;
2023 if (pi1->next) {
2024 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2025 if (CHECK_FLAG(pi2->flags,
1defdda8 2026 BGP_PATH_DMED_CHECK))
d62a17ae 2027 continue;
40381db7 2028 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2029 continue;
ea8b2282 2030 if (pi2->peer != bgp->peer_self
d62a17ae 2031 && !CHECK_FLAG(
ea8b2282
DS
2032 pi2->peer->sflags,
2033 PEER_STATUS_NSF_WAIT))
40381db7 2034 if (pi2->peer->status
d62a17ae 2035 != Established)
2036 continue;
2037
121e245d
DS
2038 if (!aspath_cmp_left(pi1->attr->aspath,
2039 pi2->attr->aspath)
2040 && !aspath_cmp_left_confed(
40381db7 2041 pi1->attr->aspath,
121e245d
DS
2042 pi2->attr->aspath))
2043 continue;
d62a17ae 2044
121e245d
DS
2045 if (bgp_path_info_cmp(
2046 bgp, pi2, new_select,
2047 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2048 pfx_buf, afi, safi,
2049 &rn->reason)) {
121e245d
DS
2050 bgp_path_info_unset_flag(
2051 rn, new_select,
2052 BGP_PATH_DMED_SELECTED);
2053 new_select = pi2;
d62a17ae 2054 }
121e245d
DS
2055
2056 bgp_path_info_set_flag(
2057 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2058 }
2059 }
18ee8310
DS
2060 bgp_path_info_set_flag(rn, new_select,
2061 BGP_PATH_DMED_CHECK);
2062 bgp_path_info_set_flag(rn, new_select,
2063 BGP_PATH_DMED_SELECTED);
d62a17ae 2064
2065 if (debug) {
18ee8310
DS
2066 bgp_path_info_path_with_addpath_rx_str(
2067 new_select, path_buf);
c66faab1 2068 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2069 pfx_buf, path_buf,
2070 aspath_get_first_as(
2071 new_select->attr->aspath));
2072 }
2073 }
2074 }
96450faf 2075
d62a17ae 2076 /* Check old selected route and new selected route. */
2077 old_select = NULL;
2078 new_select = NULL;
6f94b685
DS
2079 for (pi = bgp_node_get_bgp_path_info(rn);
2080 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2081 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2082 old_select = pi;
d62a17ae 2083
40381db7 2084 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2085 /* reap REMOVED routes, if needs be
2086 * selected route must stay for a while longer though
2087 */
40381db7
DS
2088 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2089 && (pi != old_select))
2090 bgp_path_info_reap(rn, pi);
d62a17ae 2091
ddb5b488 2092 if (debug)
40381db7
DS
2093 zlog_debug("%s: pi %p in holddown", __func__,
2094 pi);
ddb5b488 2095
d62a17ae 2096 continue;
2097 }
96450faf 2098
40381db7
DS
2099 if (pi->peer && pi->peer != bgp->peer_self
2100 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2101 if (pi->peer->status != Established) {
ddb5b488
PZ
2102
2103 if (debug)
2104 zlog_debug(
40381db7
DS
2105 "%s: pi %p non self peer %s not estab state",
2106 __func__, pi, pi->peer->host);
ddb5b488 2107
d62a17ae 2108 continue;
ddb5b488 2109 }
9fbdd100 2110
d62a17ae 2111 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2112 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2113 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2114 if (debug)
40381db7 2115 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2116 continue;
2117 }
9fbdd100 2118
40381db7 2119 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2120
40381db7 2121 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2122 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2123 new_select = pi;
d62a17ae 2124 }
2125 }
718e3744 2126
d62a17ae 2127 /* Now that we know which path is the bestpath see if any of the other
2128 * paths
2129 * qualify as multipaths
2130 */
2131 if (debug) {
2132 if (new_select)
18ee8310
DS
2133 bgp_path_info_path_with_addpath_rx_str(new_select,
2134 path_buf);
d62a17ae 2135 else
2136 sprintf(path_buf, "NONE");
2137 zlog_debug(
2138 "%s: After path selection, newbest is %s oldbest was %s",
2139 pfx_buf, path_buf,
2140 old_select ? old_select->peer->host : "NONE");
96450faf 2141 }
9fbdd100 2142
d62a17ae 2143 if (do_mpath && new_select) {
6f94b685
DS
2144 for (pi = bgp_node_get_bgp_path_info(rn);
2145 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2146
2147 if (debug)
18ee8310 2148 bgp_path_info_path_with_addpath_rx_str(
40381db7 2149 pi, path_buf);
d62a17ae 2150
40381db7 2151 if (pi == new_select) {
d62a17ae 2152 if (debug)
2153 zlog_debug(
2154 "%s: %s is the bestpath, add to the multipath list",
2155 pfx_buf, path_buf);
40381db7 2156 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2157 continue;
2158 }
2159
40381db7 2160 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2161 continue;
2162
40381db7
DS
2163 if (pi->peer && pi->peer != bgp->peer_self
2164 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2165 PEER_STATUS_NSF_WAIT))
40381db7 2166 if (pi->peer->status != Established)
d62a17ae 2167 continue;
2168
40381db7 2169 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2170 if (debug)
2171 zlog_debug(
2172 "%s: %s has the same nexthop as the bestpath, skip it",
2173 pfx_buf, path_buf);
2174 continue;
2175 }
2176
40381db7 2177 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2178 mpath_cfg, debug, pfx_buf, afi, safi,
2179 &rn->reason);
d62a17ae 2180
2181 if (paths_eq) {
2182 if (debug)
2183 zlog_debug(
2184 "%s: %s is equivalent to the bestpath, add to the multipath list",
2185 pfx_buf, path_buf);
40381db7 2186 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2187 }
2188 }
2189 }
fee0f4c6 2190
18ee8310
DS
2191 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2192 mpath_cfg);
2193 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2194 bgp_mp_list_clear(&mp_list);
96450faf 2195
dcc68b5e
MS
2196 bgp_addpath_update_ids(bgp, rn, afi, safi);
2197
d62a17ae 2198 result->old = old_select;
2199 result->new = new_select;
96450faf 2200
d62a17ae 2201 return;
fee0f4c6 2202}
2203
3f9c7369
DS
2204/*
2205 * A new route/change in bestpath of an existing route. Evaluate the path
2206 * for advertisement to the subgroup.
2207 */
d62a17ae 2208int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2209 struct bgp_path_info *selected,
d62a17ae 2210 struct bgp_node *rn,
d7c0a89a 2211 uint32_t addpath_tx_id)
d62a17ae 2212{
2213 struct prefix *p;
2214 struct peer *onlypeer;
2215 struct attr attr;
2216 afi_t afi;
2217 safi_t safi;
adbac85e 2218
d62a17ae 2219 p = &rn->p;
2220 afi = SUBGRP_AFI(subgrp);
2221 safi = SUBGRP_SAFI(subgrp);
2222 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2223 : NULL);
2224
e0207895
PZ
2225 if (BGP_DEBUG(update, UPDATE_OUT)) {
2226 char buf_prefix[PREFIX_STRLEN];
2227 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2228 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2229 selected);
e0207895
PZ
2230 }
2231
d62a17ae 2232 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2233 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2234 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2235 return 0;
2236
2237 memset(&attr, 0, sizeof(struct attr));
2238 /* It's initialized in bgp_announce_check() */
2239
2240 /* Announcement to the subgroup. If the route is filtered withdraw it.
2241 */
2242 if (selected) {
2243 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2244 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2245 else
2246 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2247 addpath_tx_id);
d62a17ae 2248 }
2249
2250 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2251 else {
2252 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2253 }
558d1fec 2254
d62a17ae 2255 return 0;
200df115 2256}
fee0f4c6 2257
3064bf43 2258/*
e1072051 2259 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2260 * This is called at the end of route processing.
3064bf43 2261 */
d62a17ae 2262void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2263{
40381db7 2264 struct bgp_path_info *pi;
3064bf43 2265
6f94b685 2266 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2267 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2268 continue;
40381db7
DS
2269 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2270 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2271 }
3064bf43 2272}
2273
2274/*
2275 * Has the route changed from the RIB's perspective? This is invoked only
2276 * if the route selection returns the same best route as earlier - to
2277 * determine if we need to update zebra or not.
2278 */
4b7e6066
DS
2279int bgp_zebra_has_route_changed(struct bgp_node *rn,
2280 struct bgp_path_info *selected)
d62a17ae 2281{
4b7e6066 2282 struct bgp_path_info *mpinfo;
d62a17ae 2283
2bb9eff4
DS
2284 /* If this is multipath, check all selected paths for any nexthop
2285 * change or attribute change. Some attribute changes (e.g., community)
2286 * aren't of relevance to the RIB, but we'll update zebra to ensure
2287 * we handle the case of BGP nexthop change. This is the behavior
2288 * when the best path has an attribute change anyway.
d62a17ae 2289 */
1defdda8
DS
2290 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2291 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2292 return 1;
2293
2bb9eff4
DS
2294 /*
2295 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2296 */
18ee8310
DS
2297 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2298 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2299 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2300 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2301 return 1;
2302 }
3064bf43 2303
d62a17ae 2304 /* Nothing has changed from the RIB's perspective. */
2305 return 0;
3064bf43 2306}
2307
d62a17ae 2308struct bgp_process_queue {
2309 struct bgp *bgp;
a4d82a8a 2310 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2311#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2312 unsigned int flags;
2313 unsigned int queued;
200df115 2314};
2315
3103e8d2
DS
2316/*
2317 * old_select = The old best path
2318 * new_select = the new best path
2319 *
2320 * if (!old_select && new_select)
2321 * We are sending new information on.
2322 *
2323 * if (old_select && new_select) {
2324 * if (new_select != old_select)
2325 * We have a new best path send a change
2326 * else
2327 * We've received a update with new attributes that needs
2328 * to be passed on.
2329 * }
2330 *
2331 * if (old_select && !new_select)
2332 * We have no eligible route that we can announce or the rn
2333 * is being removed.
2334 */
aac24838
JB
2335static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2336 afi_t afi, safi_t safi)
d62a17ae 2337{
4b7e6066
DS
2338 struct bgp_path_info *new_select;
2339 struct bgp_path_info *old_select;
2340 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2341 char pfx_buf[PREFIX2STR_BUFFER];
2342 int debug = 0;
d62a17ae 2343
f4c713ae
LB
2344 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2345 if (rn)
2346 debug = bgp_debug_bestpath(&rn->p);
2347 if (debug) {
2348 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2349 zlog_debug(
2350 "%s: bgp delete in progress, ignoring event, p=%s",
2351 __func__, pfx_buf);
2352 }
2353 return;
2354 }
d62a17ae 2355 /* Is it end of initial update? (after startup) */
2356 if (!rn) {
2357 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2358 sizeof(bgp->update_delay_zebra_resume_time));
2359
2360 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2361 FOREACH_AFI_SAFI (afi, safi) {
2362 if (bgp_fibupd_safi(safi))
2363 bgp_zebra_announce_table(bgp, afi, safi);
2364 }
d62a17ae 2365 bgp->main_peers_update_hold = 0;
2366
2367 bgp_start_routeadv(bgp);
aac24838 2368 return;
d62a17ae 2369 }
cb1faec9 2370
b575a12c
A
2371 struct prefix *p = &rn->p;
2372
ddb5b488
PZ
2373 debug = bgp_debug_bestpath(&rn->p);
2374 if (debug) {
2375 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2376 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2377 afi2str(afi), safi2str(safi));
2378 }
2379
d62a17ae 2380 /* Best path selection. */
2381 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2382 afi, safi);
2383 old_select = old_and_new.old;
2384 new_select = old_and_new.new;
2385
2386 /* Do we need to allocate or free labels?
2387 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2388 * necessary to do this upon changes to best path. Exceptions:
2389 * - label index has changed -> recalculate resulting label
2390 * - path_info sub_type changed -> switch to/from implicit-null
2391 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2392 */
318cac96 2393 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2394 if (new_select) {
2395 if (!old_select
2396 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2397 || new_select->sub_type != old_select->sub_type
2398 || !bgp_is_valid_label(&rn->local_label)) {
2399 /* Enforced penultimate hop popping:
2400 * implicit-null for local routes, aggregate
2401 * and redistributed routes
2402 */
d62a17ae 2403 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2404 || new_select->sub_type
2405 == BGP_ROUTE_AGGREGATE
2406 || new_select->sub_type
2407 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2408 if (CHECK_FLAG(
2409 rn->flags,
2410 BGP_NODE_REGISTERED_FOR_LABEL))
2411 bgp_unregister_for_label(rn);
70e98a7f 2412 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2413 &rn->local_label);
2414 bgp_set_valid_label(&rn->local_label);
2415 } else
2416 bgp_register_for_label(rn, new_select);
2417 }
a4d82a8a
PZ
2418 } else if (CHECK_FLAG(rn->flags,
2419 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2420 bgp_unregister_for_label(rn);
318cac96
DW
2421 }
2422 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2423 bgp_unregister_for_label(rn);
d62a17ae 2424 }
cd1964ff 2425
ddb5b488
PZ
2426 if (debug) {
2427 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2428 zlog_debug(
2429 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2430 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2431 old_select, new_select);
2432 }
2433
d62a17ae 2434 /* If best route remains the same and this is not due to user-initiated
2435 * clear, see exactly what needs to be done.
2436 */
d62a17ae 2437 if (old_select && old_select == new_select
2438 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2439 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2440 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2441 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2442#if ENABLE_BGP_VNC
d62a17ae 2443 vnc_import_bgp_add_route(bgp, p, old_select);
2444 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2445#endif
bb744275 2446 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2447 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2448
2449 if (new_select->type == ZEBRA_ROUTE_BGP
2450 && (new_select->sub_type == BGP_ROUTE_NORMAL
2451 || new_select->sub_type
2452 == BGP_ROUTE_IMPORTED))
2453
2454 bgp_zebra_announce(rn, p, old_select,
2455 bgp, afi, safi);
2456 }
d62a17ae 2457 }
1defdda8 2458 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2459 bgp_zebra_clear_route_change_flags(rn);
2460
2461 /* If there is a change of interest to peers, reannounce the
2462 * route. */
1defdda8 2463 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2464 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2465 group_announce_route(bgp, afi, safi, rn, new_select);
2466
2467 /* unicast routes must also be annouced to
2468 * labeled-unicast update-groups */
2469 if (safi == SAFI_UNICAST)
2470 group_announce_route(bgp, afi,
2471 SAFI_LABELED_UNICAST, rn,
2472 new_select);
2473
1defdda8 2474 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2475 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2476 }
fee0f4c6 2477
d62a17ae 2478 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2479 return;
d62a17ae 2480 }
8ad7271d 2481
d62a17ae 2482 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2483 */
2484 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2485
2486 /* bestpath has changed; bump version */
2487 if (old_select || new_select) {
2488 bgp_bump_version(rn);
2489
2490 if (!bgp->t_rmap_def_originate_eval) {
2491 bgp_lock(bgp);
2492 thread_add_timer(
2493 bm->master,
2494 update_group_refresh_default_originate_route_map,
2495 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2496 &bgp->t_rmap_def_originate_eval);
2497 }
2498 }
3f9c7369 2499
d62a17ae 2500 if (old_select)
18ee8310 2501 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2502 if (new_select) {
ddb5b488
PZ
2503 if (debug)
2504 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2505 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2506 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2507 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2508 }
338b3424 2509
65efcfce 2510#if ENABLE_BGP_VNC
d62a17ae 2511 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2512 if (old_select != new_select) {
2513 if (old_select) {
2514 vnc_import_bgp_exterior_del_route(bgp, p,
2515 old_select);
2516 vnc_import_bgp_del_route(bgp, p, old_select);
2517 }
2518 if (new_select) {
2519 vnc_import_bgp_exterior_add_route(bgp, p,
2520 new_select);
2521 vnc_import_bgp_add_route(bgp, p, new_select);
2522 }
2523 }
2524 }
65efcfce
LB
2525#endif
2526
d62a17ae 2527 group_announce_route(bgp, afi, safi, rn, new_select);
2528
2529 /* unicast routes must also be annouced to labeled-unicast update-groups
2530 */
2531 if (safi == SAFI_UNICAST)
2532 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2533 new_select);
2534
2535 /* FIB update. */
2536 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2537 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2538 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2539 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2540 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2541 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2542
2543 /* if this is an evpn imported type-5 prefix,
2544 * we need to withdraw the route first to clear
2545 * the nh neigh and the RMAC entry.
2546 */
2547 if (old_select &&
2548 is_route_parent_evpn(old_select))
2549 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2550
d62a17ae 2551 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2552 } else {
d62a17ae 2553 /* Withdraw the route from the kernel. */
2554 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2555 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2556 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2557 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2558
568e10ca 2559 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2560 }
718e3744 2561 }
3064bf43 2562
5424b7ba
MK
2563 /* advertise/withdraw type-5 routes */
2564 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2565 if (advertise_type5_routes(bgp, afi) &&
2566 new_select &&
2567 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2568
2569 /* apply the route-map */
2570 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2571 route_map_result_t ret;
7e4ed18e 2572
3518f352
DS
2573 ret = route_map_apply(
2574 bgp->adv_cmd_rmap[afi][safi].map,
2575 &rn->p, RMAP_BGP, new_select);
b68885f9 2576 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2577 bgp_evpn_advertise_type5_route(
2578 bgp, &rn->p, new_select->attr,
2579 afi, safi);
c27ee4c4 2580 else
2581 bgp_evpn_withdraw_type5_route(
2582 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2583 } else {
2584 bgp_evpn_advertise_type5_route(bgp,
2585 &rn->p,
2586 new_select->attr,
2587 afi, safi);
2588
2589 }
f106e3a7 2590 } else if (advertise_type5_routes(bgp, afi) &&
2591 old_select &&
2592 is_route_injectable_into_evpn(old_select))
31310b25 2593 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2594 }
2595
d62a17ae 2596 /* Clear any route change flags. */
2597 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2598
18ee8310 2599 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2600 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2601 bgp_path_info_reap(rn, old_select);
d62a17ae 2602
2603 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2604 return;
718e3744 2605}
2606
aac24838 2607static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2608{
aac24838
JB
2609 struct bgp_process_queue *pqnode = data;
2610 struct bgp *bgp = pqnode->bgp;
d62a17ae 2611 struct bgp_table *table;
ac021f40 2612 struct bgp_node *rn;
aac24838
JB
2613
2614 /* eoiu marker */
2615 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2616 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2617 /* should always have dedicated wq call */
2618 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2619 return WQ_SUCCESS;
2620 }
2621
ac021f40
LB
2622 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2623 rn = STAILQ_FIRST(&pqnode->pqueue);
2624 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2625 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2626 table = bgp_node_table(rn);
ac021f40 2627 /* note, new RNs may be added as part of processing */
aac24838 2628 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2629
aac24838 2630 bgp_unlock_node(rn);
d62a17ae 2631 bgp_table_unlock(table);
2632 }
aac24838
JB
2633
2634 return WQ_SUCCESS;
2635}
2636
2637static void bgp_processq_del(struct work_queue *wq, void *data)
2638{
2639 struct bgp_process_queue *pqnode = data;
2640
2641 bgp_unlock(pqnode->bgp);
2642
2643 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2644}
2645
d62a17ae 2646void bgp_process_queue_init(void)
200df115 2647{
0ce1ca80 2648 if (!bm->process_main_queue)
d62a17ae 2649 bm->process_main_queue =
2650 work_queue_new(bm->master, "process_main_queue");
2651
aac24838 2652 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2653 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2654 bm->process_main_queue->spec.max_retries = 0;
2655 bm->process_main_queue->spec.hold = 50;
2656 /* Use a higher yield value of 50ms for main queue processing */
2657 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2658}
2659
cfe8d15a 2660static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2661{
2662 struct bgp_process_queue *pqnode;
2663
a4d82a8a
PZ
2664 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2665 sizeof(struct bgp_process_queue));
aac24838
JB
2666
2667 /* unlocked in bgp_processq_del */
2668 pqnode->bgp = bgp_lock(bgp);
2669 STAILQ_INIT(&pqnode->pqueue);
2670
aac24838
JB
2671 return pqnode;
2672}
2673
d62a17ae 2674void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2675{
aac24838
JB
2676#define ARBITRARY_PROCESS_QLEN 10000
2677 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2678 struct bgp_process_queue *pqnode;
cfe8d15a 2679 int pqnode_reuse = 0;
495f0b13 2680
d62a17ae 2681 /* already scheduled for processing? */
2682 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2683 return;
2e02b9b2 2684
aac24838 2685 if (wq == NULL)
d62a17ae 2686 return;
2687
aac24838 2688 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2689 limit only if is from the same BGP view and it's not an EOIU marker
2690 */
aac24838
JB
2691 if (work_queue_item_count(wq)) {
2692 struct work_queue_item *item = work_queue_last_item(wq);
2693 pqnode = item->data;
228da428 2694
a4d82a8a
PZ
2695 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2696 || pqnode->bgp != bgp
2697 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2698 pqnode = bgp_processq_alloc(bgp);
2699 else
2700 pqnode_reuse = 1;
aac24838 2701 } else
cfe8d15a 2702 pqnode = bgp_processq_alloc(bgp);
aac24838 2703 /* all unlocked in bgp_process_wq */
d62a17ae 2704 bgp_table_lock(bgp_node_table(rn));
aac24838 2705
d62a17ae 2706 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2707 bgp_lock_node(rn);
2708
60466a63
QY
2709 /* can't be enqueued twice */
2710 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2711 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2712 pqnode->queued++;
2713
cfe8d15a
LB
2714 if (!pqnode_reuse)
2715 work_queue_add(wq, pqnode);
2716
d62a17ae 2717 return;
fee0f4c6 2718}
0a486e5f 2719
d62a17ae 2720void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2721{
d62a17ae 2722 struct bgp_process_queue *pqnode;
cb1faec9 2723
d62a17ae 2724 if (bm->process_main_queue == NULL)
2725 return;
2e02b9b2 2726
cfe8d15a 2727 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2728
aac24838 2729 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2730 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2731}
2732
d62a17ae 2733static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2734{
d62a17ae 2735 struct peer *peer;
0a486e5f 2736
d62a17ae 2737 peer = THREAD_ARG(thread);
2738 peer->t_pmax_restart = NULL;
0a486e5f 2739
d62a17ae 2740 if (bgp_debug_neighbor_events(peer))
2741 zlog_debug(
2742 "%s Maximum-prefix restart timer expired, restore peering",
2743 peer->host);
0a486e5f 2744
a9bafa95
DS
2745 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2746 zlog_debug("%s: %s peer_clear failed",
2747 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2748
d62a17ae 2749 return 0;
0a486e5f 2750}
2751
d62a17ae 2752int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2753 int always)
718e3744 2754{
d62a17ae 2755 iana_afi_t pkt_afi;
5c525538 2756 iana_safi_t pkt_safi;
9cabb64b 2757
d62a17ae 2758 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2759 return 0;
e0701b79 2760
d62a17ae 2761 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2762 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2763 PEER_STATUS_PREFIX_LIMIT)
2764 && !always)
2765 return 0;
e0701b79 2766
d62a17ae 2767 zlog_info(
a0a87037
DA
2768 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2769 " exceed, limit %" PRIu32,
5cb5f4d0 2770 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2771 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2772 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2773
2774 if (CHECK_FLAG(peer->af_flags[afi][safi],
2775 PEER_FLAG_MAX_PREFIX_WARNING))
2776 return 0;
2777
2778 /* Convert AFI, SAFI to values for packet. */
2779 pkt_afi = afi_int2iana(afi);
2780 pkt_safi = safi_int2iana(safi);
2781 {
d7c0a89a 2782 uint8_t ndata[7];
d62a17ae 2783
2784 ndata[0] = (pkt_afi >> 8);
2785 ndata[1] = pkt_afi;
2786 ndata[2] = pkt_safi;
2787 ndata[3] = (peer->pmax[afi][safi] >> 24);
2788 ndata[4] = (peer->pmax[afi][safi] >> 16);
2789 ndata[5] = (peer->pmax[afi][safi] >> 8);
2790 ndata[6] = (peer->pmax[afi][safi]);
2791
2792 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2793 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2794 BGP_NOTIFY_CEASE_MAX_PREFIX,
2795 ndata, 7);
2796 }
2797
2798 /* Dynamic peers will just close their connection. */
2799 if (peer_dynamic_neighbor(peer))
2800 return 1;
2801
2802 /* restart timer start */
2803 if (peer->pmax_restart[afi][safi]) {
2804 peer->v_pmax_restart =
2805 peer->pmax_restart[afi][safi] * 60;
2806
2807 if (bgp_debug_neighbor_events(peer))
2808 zlog_debug(
2809 "%s Maximum-prefix restart timer started for %d secs",
2810 peer->host, peer->v_pmax_restart);
2811
2812 BGP_TIMER_ON(peer->t_pmax_restart,
2813 bgp_maximum_prefix_restart_timer,
2814 peer->v_pmax_restart);
2815 }
2816
2817 return 1;
2818 } else
2819 UNSET_FLAG(peer->af_sflags[afi][safi],
2820 PEER_STATUS_PREFIX_LIMIT);
2821
2822 if (peer->pcount[afi][safi]
2823 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2824 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2825 PEER_STATUS_PREFIX_THRESHOLD)
2826 && !always)
2827 return 0;
2828
2829 zlog_info(
a0a87037
DA
2830 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2831 ", max %" PRIu32,
5cb5f4d0 2832 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2833 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2834 SET_FLAG(peer->af_sflags[afi][safi],
2835 PEER_STATUS_PREFIX_THRESHOLD);
2836 } else
2837 UNSET_FLAG(peer->af_sflags[afi][safi],
2838 PEER_STATUS_PREFIX_THRESHOLD);
2839 return 0;
718e3744 2840}
2841
b40d939b 2842/* Unconditionally remove the route from the RIB, without taking
2843 * damping into consideration (eg, because the session went down)
2844 */
40381db7 2845void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 2846 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2847{
40381db7 2848 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 2849
40381db7
DS
2850 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
2851 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 2852
4a11bf2c
DL
2853 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
2854
d62a17ae 2855 bgp_process(peer->bgp, rn, afi, safi);
2856}
2857
40381db7 2858static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 2859 struct peer *peer, afi_t afi, safi_t safi,
2860 struct prefix_rd *prd)
2861{
d62a17ae 2862 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 2863 * the bgp_path_info in the RIB for historical reference.
d62a17ae 2864 */
2865 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2866 && peer->sort == BGP_PEER_EBGP)
40381db7 2867 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 2868 == BGP_DAMP_SUPPRESSED) {
40381db7 2869 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 2870 safi);
2871 return;
2872 }
2873
65efcfce 2874#if ENABLE_BGP_VNC
d62a17ae 2875 if (safi == SAFI_MPLS_VPN) {
2876 struct bgp_node *prn = NULL;
2877 struct bgp_table *table = NULL;
2878
2879 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2880 (struct prefix *)prd);
67009e22
DS
2881 if (bgp_node_has_bgp_path_info_data(prn)) {
2882 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 2883
2884 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 2885 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 2886 }
2887 bgp_unlock_node(prn);
2888 }
2889 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 2890 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 2891
40381db7 2892 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 2893 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 2894 pi);
d62a17ae 2895 }
65efcfce 2896 }
d62a17ae 2897#endif
128ea8ab 2898
d62a17ae 2899 /* If this is an EVPN route, process for un-import. */
2900 if (safi == SAFI_EVPN)
40381db7 2901 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 2902
40381db7 2903 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 2904}
2905
4b7e6066
DS
2906struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
2907 struct peer *peer, struct attr *attr,
2908 struct bgp_node *rn)
fb018d25 2909{
4b7e6066 2910 struct bgp_path_info *new;
fb018d25 2911
d62a17ae 2912 /* Make new BGP info. */
4b7e6066 2913 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 2914 new->type = type;
2915 new->instance = instance;
2916 new->sub_type = sub_type;
2917 new->peer = peer;
2918 new->attr = attr;
2919 new->uptime = bgp_clock();
2920 new->net = rn;
d62a17ae 2921 return new;
fb018d25
DS
2922}
2923
d62a17ae 2924static void overlay_index_update(struct attr *attr,
2925 struct eth_segment_id *eth_s_id,
2926 union gw_addr *gw_ip)
684a7227 2927{
d62a17ae 2928 if (!attr)
2929 return;
684a7227 2930
d62a17ae 2931 if (eth_s_id == NULL) {
2932 memset(&(attr->evpn_overlay.eth_s_id), 0,
2933 sizeof(struct eth_segment_id));
2934 } else {
2935 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2936 sizeof(struct eth_segment_id));
2937 }
2938 if (gw_ip == NULL) {
2939 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2940 } else {
2941 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2942 sizeof(union gw_addr));
2943 }
684a7227
PG
2944}
2945
40381db7 2946static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 2947 struct eth_segment_id *eth_s_id,
2948 union gw_addr *gw_ip)
2949{
40381db7
DS
2950 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
2951 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
2952 union {
2953 struct eth_segment_id esi;
2954 union gw_addr ip;
2955 } temp;
d62a17ae 2956
2957 if (afi != AFI_L2VPN)
2958 return true;
11ebf4ed 2959
05864da7
DS
2960 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2961 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
2962
2963 if (gw_ip == NULL) {
2964 memset(&temp, 0, sizeof(temp));
40381db7 2965 path_gw_ip_remote = &temp.ip;
11ebf4ed 2966 } else
40381db7 2967 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2968
2969 if (eth_s_id == NULL) {
2970 memset(&temp, 0, sizeof(temp));
40381db7 2971 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2972 } else
40381db7 2973 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2974
40381db7 2975 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2976 return false;
11ebf4ed 2977
40381db7 2978 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2979 sizeof(struct eth_segment_id));
684a7227
PG
2980}
2981
c265ee22 2982/* Check if received nexthop is valid or not. */
d62a17ae 2983static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
949b0f24 2984 uint8_t type, uint8_t stype,
2985 struct attr *attr, struct bgp_node *rn)
d62a17ae 2986{
2987 int ret = 0;
2988
2989 /* Only validated for unicast and multicast currently. */
2990 /* Also valid for EVPN where the nexthop is an IP address. */
2991 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2992 return 0;
2993
2994 /* If NEXT_HOP is present, validate it. */
2995 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2996 if (attr->nexthop.s_addr == 0
2997 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
949b0f24 2998 || bgp_nexthop_self(bgp, afi, type, stype,
2999 attr, rn))
d62a17ae 3000 return 1;
3001 }
c265ee22 3002
d62a17ae 3003 /* If MP_NEXTHOP is present, validate it. */
3004 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3005 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3006 * it is not an IPv6 link-local address.
3007 */
3008 if (attr->mp_nexthop_len) {
3009 switch (attr->mp_nexthop_len) {
3010 case BGP_ATTR_NHLEN_IPV4:
3011 case BGP_ATTR_NHLEN_VPNV4:
3012 ret = (attr->mp_nexthop_global_in.s_addr == 0
3013 || IPV4_CLASS_DE(ntohl(
3014 attr->mp_nexthop_global_in.s_addr))
949b0f24 3015 || bgp_nexthop_self(bgp, afi, type, stype,
3016 attr, rn));
d62a17ae 3017 break;
3018
3019 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3020 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3021 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3022 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3023 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3024 || IN6_IS_ADDR_MULTICAST(
949b0f24 3025 &attr->mp_nexthop_global)
3026 || bgp_nexthop_self(bgp, afi, type, stype,
3027 attr, rn));
d62a17ae 3028 break;
3029
3030 default:
3031 ret = 1;
3032 break;
3033 }
3034 }
c265ee22 3035
d62a17ae 3036 return ret;
3037}
3038
d7c0a89a 3039int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3040 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3041 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3042 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3043 struct bgp_route_evpn *evpn)
d62a17ae 3044{
3045 int ret;
3046 int aspath_loop_count = 0;
3047 struct bgp_node *rn;
3048 struct bgp *bgp;
3049 struct attr new_attr;
3050 struct attr *attr_new;
40381db7 3051 struct bgp_path_info *pi;
4b7e6066
DS
3052 struct bgp_path_info *new;
3053 struct bgp_path_info_extra *extra;
d62a17ae 3054 const char *reason;
3055 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3056 int connected = 0;
3057 int do_loop_check = 1;
3058 int has_valid_label = 0;
7c312383 3059 afi_t nh_afi;
949b0f24 3060 uint8_t pi_type = 0;
3061 uint8_t pi_sub_type = 0;
3062
65efcfce 3063#if ENABLE_BGP_VNC
d62a17ae 3064 int vnc_implicit_withdraw = 0;
65efcfce 3065#endif
d62a17ae 3066 int same_attr = 0;
718e3744 3067
d62a17ae 3068 memset(&new_attr, 0, sizeof(struct attr));
3069 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3070 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3071
d62a17ae 3072 bgp = peer->bgp;
3073 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3074 /* TODO: Check to see if we can get rid of "is_valid_label" */
3075 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3076 has_valid_label = (num_labels > 0) ? 1 : 0;
3077 else
3078 has_valid_label = bgp_is_valid_label(label);
718e3744 3079
d62a17ae 3080 /* When peer's soft reconfiguration enabled. Record input packet in
3081 Adj-RIBs-In. */
3082 if (!soft_reconfig
3083 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3084 && peer != bgp->peer_self)
3085 bgp_adj_in_set(rn, peer, attr, addpath_id);
3086
3087 /* Check previously received route. */
6f94b685 3088 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3089 if (pi->peer == peer && pi->type == type
3090 && pi->sub_type == sub_type
3091 && pi->addpath_rx_id == addpath_id)
d62a17ae 3092 break;
3093
3094 /* AS path local-as loop check. */
3095 if (peer->change_local_as) {
c4368918
DW
3096 if (peer->allowas_in[afi][safi])
3097 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3098 else if (!CHECK_FLAG(peer->flags,
3099 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3100 aspath_loop_count = 1;
3101
3102 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3103 > aspath_loop_count) {
b4d46cc9 3104 peer->stat_pfx_aspath_loop++;
d62a17ae 3105 reason = "as-path contains our own AS;";
3106 goto filtered;
3107 }
718e3744 3108 }
718e3744 3109
d62a17ae 3110 /* If the peer is configured for "allowas-in origin" and the last ASN in
3111 * the
3112 * as-path is our ASN then we do not need to call aspath_loop_check
3113 */
3114 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3115 if (aspath_get_last_as(attr->aspath) == bgp->as)
3116 do_loop_check = 0;
3117
3118 /* AS path loop check. */
3119 if (do_loop_check) {
3120 if (aspath_loop_check(attr->aspath, bgp->as)
3121 > peer->allowas_in[afi][safi]
3122 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3123 && aspath_loop_check(attr->aspath, bgp->confed_id)
3124 > peer->allowas_in[afi][safi])) {
b4d46cc9 3125 peer->stat_pfx_aspath_loop++;
d62a17ae 3126 reason = "as-path contains our own AS;";
3127 goto filtered;
3128 }
3129 }
aac9ef6c 3130
d62a17ae 3131 /* Route reflector originator ID check. */
3132 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3133 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3134 peer->stat_pfx_originator_loop++;
d62a17ae 3135 reason = "originator is us;";
3136 goto filtered;
3137 }
718e3744 3138
d62a17ae 3139 /* Route reflector cluster ID check. */
3140 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3141 peer->stat_pfx_cluster_loop++;
d62a17ae 3142 reason = "reflected from the same cluster;";
3143 goto filtered;
3144 }
718e3744 3145
d62a17ae 3146 /* Apply incoming filter. */
3147 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3148 peer->stat_pfx_filter++;
d62a17ae 3149 reason = "filter;";
3150 goto filtered;
3151 }
718e3744 3152
a8b72dc6
DA
3153 /* RFC 8212 to prevent route leaks.
3154 * This specification intends to improve this situation by requiring the
3155 * explicit configuration of both BGP Import and Export Policies for any
3156 * External BGP (EBGP) session such as customers, peers, or
3157 * confederation boundaries for all enabled address families. Through
3158 * codification of the aforementioned requirement, operators will
3159 * benefit from consistent behavior across different BGP
3160 * implementations.
3161 */
3162 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3163 if (!bgp_inbound_policy_exists(peer,
3164 &peer->filter[afi][safi])) {
3165 reason = "inbound policy missing";
3166 goto filtered;
3167 }
3168
fb29348a
DA
3169 /* draft-ietf-idr-deprecate-as-set-confed-set
3170 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3171 * Eventually, This document (if approved) updates RFC 4271
3172 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3173 * and obsoletes RFC 6472.
3174 */
3175 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
3176 if (aspath_check_as_sets(attr->aspath)) {
3177 reason =
3178 "as-path contains AS_SET or AS_CONFED_SET type;";
3179 goto filtered;
3180 }
3181
6f4f49b2 3182 new_attr = *attr;
d62a17ae 3183
3184 /* Apply incoming route-map.
3185 * NB: new_attr may now contain newly allocated values from route-map
3186 * "set"
3187 * commands, so we need bgp_attr_flush in the error paths, until we
3188 * intern
3189 * the attr (which takes over the memory references) */
82b692c0 3190 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3191 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3192 peer->stat_pfx_filter++;
d62a17ae 3193 reason = "route-map;";
3194 bgp_attr_flush(&new_attr);
3195 goto filtered;
3196 }
718e3744 3197
05864da7 3198 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3199 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3200 /* remove from RIB previous entry */
3201 bgp_zebra_withdraw(p, pi, bgp, safi);
3202 }
3203
7f323236
DW
3204 if (peer->sort == BGP_PEER_EBGP) {
3205
a4d82a8a
PZ
3206 /* If we receive the graceful-shutdown community from an eBGP
3207 * peer we must lower local-preference */
3208 if (new_attr.community
3209 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3210 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3211 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3212
a4d82a8a
PZ
3213 /* If graceful-shutdown is configured then add the GSHUT
3214 * community to all paths received from eBGP peers */
3215 } else if (bgp_flag_check(peer->bgp,
3216 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3217 bgp_attr_add_gshut_community(&new_attr);
3218 }
3219 }
3220
949b0f24 3221 if (pi) {
3222 pi_type = pi->type;
3223 pi_sub_type = pi->sub_type;
3224 }
3225
d62a17ae 3226 /* next hop check. */
a4d82a8a 3227 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
949b0f24 3228 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type,
3229 pi_sub_type, &new_attr, rn)) {
b4d46cc9 3230 peer->stat_pfx_nh_invalid++;
d62a17ae 3231 reason = "martian or self next-hop;";
3232 bgp_attr_flush(&new_attr);
3233 goto filtered;
3234 }
718e3744 3235
5c14a191 3236 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3237 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3238 reason = "self mac;";
3239 goto filtered;
3240 }
3241
d62a17ae 3242 attr_new = bgp_attr_intern(&new_attr);
3243
3244 /* If the update is implicit withdraw. */
40381db7
DS
3245 if (pi) {
3246 pi->uptime = bgp_clock();
3247 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3248
4a11bf2c
DL
3249 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3250
d62a17ae 3251 /* Same attribute comes in. */
40381db7
DS
3252 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3253 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3254 && (!has_valid_label
40381db7 3255 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3256 num_labels * sizeof(mpls_label_t))
d62a17ae 3257 == 0)
3258 && (overlay_index_equal(
40381db7 3259 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3260 evpn == NULL ? NULL : &evpn->gw_ip))) {
3261 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3262 BGP_CONFIG_DAMPENING)
3263 && peer->sort == BGP_PEER_EBGP
40381db7 3264 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3265 if (bgp_debug_update(peer, p, NULL, 1)) {
3266 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3267 afi, safi, prd, p, label,
3268 num_labels, addpath_id ? 1 : 0,
3269 addpath_id, pfx_buf,
3270 sizeof(pfx_buf));
d62a17ae 3271 zlog_debug("%s rcvd %s", peer->host,
3272 pfx_buf);
3273 }
3274
40381db7 3275 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3276 != BGP_DAMP_SUPPRESSED) {
40381db7 3277 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3278 safi);
3279 bgp_process(bgp, rn, afi, safi);
3280 }
3281 } else /* Duplicate - odd */
3282 {
3283 if (bgp_debug_update(peer, p, NULL, 1)) {
3284 if (!peer->rcvd_attr_printed) {
3285 zlog_debug(
3286 "%s rcvd UPDATE w/ attr: %s",
3287 peer->host,
3288 peer->rcvd_attr_str);
3289 peer->rcvd_attr_printed = 1;
3290 }
3291
3292 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3293 afi, safi, prd, p, label,
3294 num_labels, addpath_id ? 1 : 0,
3295 addpath_id, pfx_buf,
3296 sizeof(pfx_buf));
d62a17ae 3297 zlog_debug(
3298 "%s rcvd %s...duplicate ignored",
3299 peer->host, pfx_buf);
3300 }
3301
3302 /* graceful restart STALE flag unset. */
40381db7 3303 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3304 bgp_path_info_unset_flag(
40381db7 3305 rn, pi, BGP_PATH_STALE);
d62a17ae 3306 bgp_process(bgp, rn, afi, safi);
3307 }
3308 }
3309
3310 bgp_unlock_node(rn);
3311 bgp_attr_unintern(&attr_new);
3312
3313 return 0;
3314 }
718e3744 3315
d62a17ae 3316 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3317 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3318 if (bgp_debug_update(peer, p, NULL, 1)) {
3319 bgp_debug_rdpfxpath2str(
a4d82a8a 3320 afi, safi, prd, p, label, num_labels,
d62a17ae 3321 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3322 sizeof(pfx_buf));
3323 zlog_debug(
3324 "%s rcvd %s, flapped quicker than processing",
3325 peer->host, pfx_buf);
3326 }
3327
40381db7 3328 bgp_path_info_restore(rn, pi);
d62a17ae 3329 }
718e3744 3330
d62a17ae 3331 /* Received Logging. */
3332 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3333 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3334 num_labels, addpath_id ? 1 : 0,
3335 addpath_id, pfx_buf,
3336 sizeof(pfx_buf));
d62a17ae 3337 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3338 }
718e3744 3339
d62a17ae 3340 /* graceful restart STALE flag unset. */
40381db7
DS
3341 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3342 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3343
3344 /* The attribute is changed. */
40381db7 3345 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3346
3347 /* implicit withdraw, decrement aggregate and pcount here.
3348 * only if update is accepted, they'll increment below.
3349 */
40381db7 3350 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3351
3352 /* Update bgp route dampening information. */
3353 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3354 && peer->sort == BGP_PEER_EBGP) {
3355 /* This is implicit withdraw so we should update
3356 dampening
3357 information. */
40381db7
DS
3358 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3359 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3360 }
65efcfce 3361#if ENABLE_BGP_VNC
d62a17ae 3362 if (safi == SAFI_MPLS_VPN) {
3363 struct bgp_node *prn = NULL;
3364 struct bgp_table *table = NULL;
3365
3366 prn = bgp_node_get(bgp->rib[afi][safi],
3367 (struct prefix *)prd);
67009e22
DS
3368 if (bgp_node_has_bgp_path_info_data(prn)) {
3369 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3370
3371 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3372 bgp, prd, table, p, pi);
d62a17ae 3373 }
3374 bgp_unlock_node(prn);
3375 }
3376 if ((afi == AFI_IP || afi == AFI_IP6)
3377 && (safi == SAFI_UNICAST)) {
40381db7 3378 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3379 /*
3380 * Implicit withdraw case.
3381 */
3382 ++vnc_implicit_withdraw;
40381db7
DS
3383 vnc_import_bgp_del_route(bgp, p, pi);
3384 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3385 }
3386 }
65efcfce 3387#endif
128ea8ab 3388
d62a17ae 3389 /* Special handling for EVPN update of an existing route. If the
3390 * extended community attribute has changed, we need to
3391 * un-import
3392 * the route using its existing extended community. It will be
3393 * subsequently processed for import with the new extended
3394 * community.
3395 */
3396 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3397 if ((pi->attr->flag
d62a17ae 3398 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3399 && (attr_new->flag
3400 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3401 int cmp;
3402
40381db7 3403 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3404 attr_new->ecommunity);
3405 if (!cmp) {
3406 if (bgp_debug_update(peer, p, NULL, 1))
3407 zlog_debug(
3408 "Change in EXT-COMM, existing %s new %s",
3409 ecommunity_str(
40381db7 3410 pi->attr->ecommunity),
d62a17ae 3411 ecommunity_str(
3412 attr_new->ecommunity));
3413 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3414 p, pi);
d62a17ae 3415 }
3416 }
3417 }
718e3744 3418
d62a17ae 3419 /* Update to new attribute. */
40381db7
DS
3420 bgp_attr_unintern(&pi->attr);
3421 pi->attr = attr_new;
d62a17ae 3422
3423 /* Update MPLS label */
3424 if (has_valid_label) {
40381db7 3425 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3426 if (extra->label != label) {
3427 memcpy(&extra->label, label,
dbd587da 3428 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3429 extra->num_labels = num_labels;
3430 }
b57ba6d2
MK
3431 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3432 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3433 }
718e3744 3434
e496b420
HS
3435 /* Update SRv6 SID */
3436 if (attr->srv6_l3vpn) {
3437 extra = bgp_path_info_extra_get(pi);
3438 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3439 sid_copy(&extra->sid[0],
3440 &attr->srv6_l3vpn->sid);
3441 extra->num_sids = 1;
3442 }
3443 } else if (attr->srv6_vpn) {
3444 extra = bgp_path_info_extra_get(pi);
3445 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3446 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3447 extra->num_sids = 1;
3448 }
3449 }
3450
65efcfce 3451#if ENABLE_BGP_VNC
d62a17ae 3452 if ((afi == AFI_IP || afi == AFI_IP6)
3453 && (safi == SAFI_UNICAST)) {
3454 if (vnc_implicit_withdraw) {
3455 /*
3456 * Add back the route with its new attributes
3457 * (e.g., nexthop).
3458 * The route is still selected, until the route
3459 * selection
3460 * queued by bgp_process actually runs. We have
3461 * to make this
3462 * update to the VNC side immediately to avoid
3463 * racing against
3464 * configuration changes (e.g., route-map
3465 * changes) which
3466 * trigger re-importation of the entire RIB.
3467 */
40381db7
DS
3468 vnc_import_bgp_add_route(bgp, p, pi);
3469 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3470 }
3471 }
65efcfce 3472#endif
d62a17ae 3473 /* Update Overlay Index */
3474 if (afi == AFI_L2VPN) {
3475 overlay_index_update(
40381db7 3476 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3477 evpn == NULL ? NULL : &evpn->gw_ip);
3478 }
65efcfce 3479
d62a17ae 3480 /* Update bgp route dampening information. */
3481 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3482 && peer->sort == BGP_PEER_EBGP) {
3483 /* Now we do normal update dampening. */
40381db7 3484 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3485 if (ret == BGP_DAMP_SUPPRESSED) {
3486 bgp_unlock_node(rn);
3487 return 0;
3488 }
3489 }
128ea8ab 3490
d62a17ae 3491 /* Nexthop reachability check - for unicast and
3492 * labeled-unicast.. */
7c312383
AD
3493 if (((afi == AFI_IP || afi == AFI_IP6)
3494 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3495 || (safi == SAFI_EVPN &&
3496 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3497 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3498 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3499 && !CHECK_FLAG(peer->flags,
3500 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3501 && !bgp_flag_check(
3502 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3503 connected = 1;
3504 else
3505 connected = 0;
3506
960035b2
PZ
3507 struct bgp *bgp_nexthop = bgp;
3508
40381db7
DS
3509 if (pi->extra && pi->extra->bgp_orig)
3510 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3511
7c312383
AD
3512 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3513
3514 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3515 pi, NULL, connected)
a4d82a8a 3516 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3517 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3518 else {
3519 if (BGP_DEBUG(nht, NHT)) {
3520 char buf1[INET6_ADDRSTRLEN];
3521 inet_ntop(AF_INET,
3522 (const void *)&attr_new
3523 ->nexthop,
3524 buf1, INET6_ADDRSTRLEN);
3525 zlog_debug("%s(%s): NH unresolved",
3526 __FUNCTION__, buf1);
3527 }
40381db7 3528 bgp_path_info_unset_flag(rn, pi,
18ee8310 3529 BGP_PATH_VALID);
d62a17ae 3530 }
3531 } else
40381db7 3532 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3533
3534#if ENABLE_BGP_VNC
3535 if (safi == SAFI_MPLS_VPN) {
3536 struct bgp_node *prn = NULL;
3537 struct bgp_table *table = NULL;
3538
3539 prn = bgp_node_get(bgp->rib[afi][safi],
3540 (struct prefix *)prd);
67009e22
DS
3541 if (bgp_node_has_bgp_path_info_data(prn)) {
3542 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3543
3544 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3545 bgp, prd, table, p, pi);
d62a17ae 3546 }
3547 bgp_unlock_node(prn);
3548 }
3549#endif
718e3744 3550
d62a17ae 3551 /* If this is an EVPN route and some attribute has changed,
3552 * process
3553 * route for import. If the extended community has changed, we
3554 * would
3555 * have done the un-import earlier and the import would result
3556 * in the
3557 * route getting injected into appropriate L2 VNIs. If it is
3558 * just
3559 * some other attribute change, the import will result in
3560 * updating
3561 * the attributes for the route in the VNI(s).
3562 */
7c312383
AD
3563 if (safi == SAFI_EVPN && !same_attr &&
3564 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3565 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3566
3567 /* Process change. */
40381db7 3568 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3569
3570 bgp_process(bgp, rn, afi, safi);
3571 bgp_unlock_node(rn);
558d1fec 3572
ddb5b488
PZ
3573 if (SAFI_UNICAST == safi
3574 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3575 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3576
40381db7 3577 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3578 }
3579 if ((SAFI_MPLS_VPN == safi)
3580 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3581
40381db7 3582 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3583 }
3584
28070ee3 3585#if ENABLE_BGP_VNC
d62a17ae 3586 if (SAFI_MPLS_VPN == safi) {
3587 mpls_label_t label_decoded = decode_label(label);
28070ee3 3588
d62a17ae 3589 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3590 type, sub_type, &label_decoded);
3591 }
3592 if (SAFI_ENCAP == safi) {
3593 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3594 type, sub_type, NULL);
3595 }
28070ee3
PZ
3596#endif
3597
d62a17ae 3598 return 0;
3599 } // End of implicit withdraw
718e3744 3600
d62a17ae 3601 /* Received Logging. */
3602 if (bgp_debug_update(peer, p, NULL, 1)) {
3603 if (!peer->rcvd_attr_printed) {
3604 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3605 peer->rcvd_attr_str);
3606 peer->rcvd_attr_printed = 1;
3607 }
718e3744 3608
a4d82a8a 3609 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3610 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3611 sizeof(pfx_buf));
3612 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3613 }
718e3744 3614
d62a17ae 3615 /* Make new BGP info. */
3616 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3617
d62a17ae 3618 /* Update MPLS label */
3619 if (has_valid_label) {
18ee8310 3620 extra = bgp_path_info_extra_get(new);
8ba71050 3621 if (extra->label != label) {
dbd587da
QY
3622 memcpy(&extra->label, label,
3623 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3624 extra->num_labels = num_labels;
3625 }
b57ba6d2
MK
3626 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3627 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3628 }
718e3744 3629
e496b420
HS
3630 /* Update SRv6 SID */
3631 if (safi == SAFI_MPLS_VPN) {
3632 extra = bgp_path_info_extra_get(new);
3633 if (attr->srv6_l3vpn) {
3634 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3635 extra->num_sids = 1;
3636 } else if (attr->srv6_vpn) {
3637 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3638 extra->num_sids = 1;
3639 }
3640 }
3641
d62a17ae 3642 /* Update Overlay Index */
3643 if (afi == AFI_L2VPN) {
3644 overlay_index_update(new->attr,
3645 evpn == NULL ? NULL : &evpn->eth_s_id,
3646 evpn == NULL ? NULL : &evpn->gw_ip);
3647 }
3648 /* Nexthop reachability check. */
7c312383
AD
3649 if (((afi == AFI_IP || afi == AFI_IP6)
3650 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3651 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3652 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3653 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3654 && !CHECK_FLAG(peer->flags,
3655 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3656 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3657 connected = 1;
3658 else
3659 connected = 0;
3660
7c312383
AD
3661 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3662
3663 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3664 connected)
a4d82a8a 3665 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3666 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3667 else {
3668 if (BGP_DEBUG(nht, NHT)) {
3669 char buf1[INET6_ADDRSTRLEN];
3670 inet_ntop(AF_INET,
3671 (const void *)&attr_new->nexthop,
3672 buf1, INET6_ADDRSTRLEN);
3673 zlog_debug("%s(%s): NH unresolved",
3674 __FUNCTION__, buf1);
3675 }
18ee8310 3676 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3677 }
3678 } else
18ee8310 3679 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3680
d62a17ae 3681 /* Addpath ID */
3682 new->addpath_rx_id = addpath_id;
3683
3684 /* Increment prefix */
3685 bgp_aggregate_increment(bgp, p, new, afi, safi);
3686
3687 /* Register new BGP information. */
18ee8310 3688 bgp_path_info_add(rn, new);
d62a17ae 3689
3690 /* route_node_get lock */
3691 bgp_unlock_node(rn);
558d1fec 3692
65efcfce 3693#if ENABLE_BGP_VNC
d62a17ae 3694 if (safi == SAFI_MPLS_VPN) {
3695 struct bgp_node *prn = NULL;
3696 struct bgp_table *table = NULL;
3697
3698 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3699 if (bgp_node_has_bgp_path_info_data(prn)) {
3700 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3701
3702 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3703 bgp, prd, table, p, new);
3704 }
3705 bgp_unlock_node(prn);
3706 }
65efcfce
LB
3707#endif
3708
d62a17ae 3709 /* If maximum prefix count is configured and current prefix
3710 count exeed it. */
3711 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3712 return -1;
718e3744 3713
d62a17ae 3714 /* If this is an EVPN route, process for import. */
7c312383 3715 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3716 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3717
4a11bf2c
DL
3718 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3719
d62a17ae 3720 /* Process change. */
3721 bgp_process(bgp, rn, afi, safi);
718e3744 3722
ddb5b488
PZ
3723 if (SAFI_UNICAST == safi
3724 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3725 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3726 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3727 }
3728 if ((SAFI_MPLS_VPN == safi)
3729 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3730
3731 vpn_leak_to_vrf_update(bgp, new);
3732 }
28070ee3 3733#if ENABLE_BGP_VNC
d62a17ae 3734 if (SAFI_MPLS_VPN == safi) {
3735 mpls_label_t label_decoded = decode_label(label);
28070ee3 3736
d62a17ae 3737 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3738 sub_type, &label_decoded);
3739 }
3740 if (SAFI_ENCAP == safi) {
3741 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3742 sub_type, NULL);
3743 }
28070ee3
PZ
3744#endif
3745
d62a17ae 3746 return 0;
718e3744 3747
d62a17ae 3748/* This BGP update is filtered. Log the reason then update BGP
3749 entry. */
3750filtered:
4a11bf2c
DL
3751 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3752
d62a17ae 3753 if (bgp_debug_update(peer, p, NULL, 1)) {
3754 if (!peer->rcvd_attr_printed) {
3755 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3756 peer->rcvd_attr_str);
3757 peer->rcvd_attr_printed = 1;
3758 }
718e3744 3759
a4d82a8a 3760 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3761 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3762 sizeof(pfx_buf));
3763 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3764 peer->host, pfx_buf, reason);
3765 }
128ea8ab 3766
40381db7 3767 if (pi) {
d62a17ae 3768 /* If this is an EVPN route, un-import it as it is now filtered.
3769 */
3770 if (safi == SAFI_EVPN)
40381db7 3771 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3772
ddb5b488
PZ
3773 if (SAFI_UNICAST == safi
3774 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3775 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3776
40381db7 3777 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3778 }
3779 if ((SAFI_MPLS_VPN == safi)
3780 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3781
40381db7 3782 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3783 }
3784
40381db7 3785 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3786 }
3787
3788 bgp_unlock_node(rn);
558d1fec 3789
97736e32 3790#if ENABLE_BGP_VNC
d62a17ae 3791 /*
3792 * Filtered update is treated as an implicit withdrawal (see
3793 * bgp_rib_remove()
3794 * a few lines above)
3795 */
3796 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3797 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3798 0);
3799 }
97736e32
PZ
3800#endif
3801
d62a17ae 3802 return 0;
718e3744 3803}
3804
d7c0a89a 3805int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3806 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3807 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3808 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3809{
d62a17ae 3810 struct bgp *bgp;
3811 char pfx_buf[BGP_PRD_PATH_STRLEN];
3812 struct bgp_node *rn;
40381db7 3813 struct bgp_path_info *pi;
718e3744 3814
28070ee3 3815#if ENABLE_BGP_VNC
d62a17ae 3816 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3817 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3818 0);
3819 }
28070ee3
PZ
3820#endif
3821
d62a17ae 3822 bgp = peer->bgp;
3823
3824 /* Lookup node. */
3825 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3826
3827 /* If peer is soft reconfiguration enabled. Record input packet for
3828 * further calculation.
3829 *
3830 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3831 * routes that are filtered. This tanks out Quagga RS pretty badly due
3832 * to
3833 * the iteration over all RS clients.
3834 * Since we need to remove the entry from adj_in anyway, do that first
3835 * and
3836 * if there was no entry, we don't need to do anything more.
3837 */
3838 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3839 && peer != bgp->peer_self)
3840 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
3841 peer->stat_pfx_dup_withdraw++;
3842
d62a17ae 3843 if (bgp_debug_update(peer, p, NULL, 1)) {
3844 bgp_debug_rdpfxpath2str(
a4d82a8a 3845 afi, safi, prd, p, label, num_labels,
d62a17ae 3846 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3847 sizeof(pfx_buf));
3848 zlog_debug(
3849 "%s withdrawing route %s not in adj-in",
3850 peer->host, pfx_buf);
3851 }
3852 bgp_unlock_node(rn);
3853 return 0;
3854 }
cd808e74 3855
d62a17ae 3856 /* Lookup withdrawn route. */
6f94b685 3857 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3858 if (pi->peer == peer && pi->type == type
3859 && pi->sub_type == sub_type
3860 && pi->addpath_rx_id == addpath_id)
d62a17ae 3861 break;
3862
3863 /* Logging. */
3864 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3865 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3866 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3867 sizeof(pfx_buf));
3868 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3869 pfx_buf);
3870 }
718e3744 3871
d62a17ae 3872 /* Withdraw specified route from routing table. */
40381db7
DS
3873 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3874 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3875 if (SAFI_UNICAST == safi
3876 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3877 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3878 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3879 }
3880 if ((SAFI_MPLS_VPN == safi)
3881 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3882
40381db7 3883 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3884 }
3885 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3886 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3887 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3888 sizeof(pfx_buf));
3889 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3890 }
718e3744 3891
d62a17ae 3892 /* Unlock bgp_node_get() lock. */
3893 bgp_unlock_node(rn);
3894
3895 return 0;
718e3744 3896}
6b0655a2 3897
d62a17ae 3898void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3899 int withdraw)
718e3744 3900{
d62a17ae 3901 struct update_subgroup *subgrp;
3902 subgrp = peer_subgroup(peer, afi, safi);
3903 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3904}
6182d65b 3905
718e3744 3906
3f9c7369
DS
3907/*
3908 * bgp_stop_announce_route_timer
3909 */
d62a17ae 3910void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3911{
d62a17ae 3912 if (!paf->t_announce_route)
3913 return;
3914
3915 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3916}
6b0655a2 3917
3f9c7369
DS
3918/*
3919 * bgp_announce_route_timer_expired
3920 *
3921 * Callback that is invoked when the route announcement timer for a
3922 * peer_af expires.
3923 */
d62a17ae 3924static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3925{
d62a17ae 3926 struct peer_af *paf;
3927 struct peer *peer;
558d1fec 3928
d62a17ae 3929 paf = THREAD_ARG(t);
3930 peer = paf->peer;
718e3744 3931
d62a17ae 3932 if (peer->status != Established)
3933 return 0;
3f9c7369 3934
d62a17ae 3935 if (!peer->afc_nego[paf->afi][paf->safi])
3936 return 0;
3f9c7369 3937
d62a17ae 3938 peer_af_announce_route(paf, 1);
3939 return 0;
718e3744 3940}
3941
3f9c7369
DS
3942/*
3943 * bgp_announce_route
3944 *
3945 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3946 */
d62a17ae 3947void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3948{
3949 struct peer_af *paf;
3950 struct update_subgroup *subgrp;
3951
3952 paf = peer_af_find(peer, afi, safi);
3953 if (!paf)
3954 return;
3955 subgrp = PAF_SUBGRP(paf);
3956
3957 /*
3958 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3959 * or a refresh has already been triggered.
3960 */
3961 if (!subgrp || paf->t_announce_route)
3962 return;
3963
3964 /*
3965 * Start a timer to stagger/delay the announce. This serves
3966 * two purposes - announcement can potentially be combined for
3967 * multiple peers and the announcement doesn't happen in the
3968 * vty context.
3969 */
3970 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3971 (subgrp->peer_count == 1)
3972 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3973 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3974 &paf->t_announce_route);
3f9c7369
DS
3975}
3976
3977/*
3978 * Announce routes from all AF tables to a peer.
3979 *
3980 * This should ONLY be called when there is a need to refresh the
3981 * routes to the peer based on a policy change for this peer alone
3982 * or a route refresh request received from the peer.
3983 * The operation will result in splitting the peer from its existing
3984 * subgroups and putting it in new subgroups.
3985 */
d62a17ae 3986void bgp_announce_route_all(struct peer *peer)
718e3744 3987{
d62a17ae 3988 afi_t afi;
3989 safi_t safi;
3990
05c7a1cc
QY
3991 FOREACH_AFI_SAFI (afi, safi)
3992 bgp_announce_route(peer, afi, safi);
718e3744 3993}
6b0655a2 3994
d62a17ae 3995static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3996 struct bgp_table *table,
3997 struct prefix_rd *prd)
718e3744 3998{
d62a17ae 3999 int ret;
4000 struct bgp_node *rn;
4001 struct bgp_adj_in *ain;
718e3744 4002
d62a17ae 4003 if (!table)
4004 table = peer->bgp->rib[afi][safi];
718e3744 4005
d62a17ae 4006 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4007 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
4008 if (ain->peer != peer)
4009 continue;
8692c506 4010
d7d15889 4011 struct bgp_path_info *pi;
d7c0a89a 4012 uint32_t num_labels = 0;
b57ba6d2 4013 mpls_label_t *label_pnt = NULL;
8cb687c2 4014 struct bgp_route_evpn evpn;
b57ba6d2 4015
d7d15889
DS
4016 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4017 pi = pi->next)
4018 if (pi->peer == peer)
4019 break;
4020
40381db7
DS
4021 if (pi && pi->extra)
4022 num_labels = pi->extra->num_labels;
b57ba6d2 4023 if (num_labels)
40381db7 4024 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4025 if (pi)
4026 memcpy(&evpn, &pi->attr->evpn_overlay,
4027 sizeof(evpn));
4028 else
4029 memset(&evpn, 0, sizeof(evpn));
8692c506 4030
ea47320b
DL
4031 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
4032 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4033 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4034 num_labels, 1, &evpn);
ea47320b
DL
4035
4036 if (ret < 0) {
4037 bgp_unlock_node(rn);
4038 return;
d62a17ae 4039 }
4040 }
718e3744 4041}
4042
d62a17ae 4043void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4044{
d62a17ae 4045 struct bgp_node *rn;
4046 struct bgp_table *table;
718e3744 4047
d62a17ae 4048 if (peer->status != Established)
4049 return;
718e3744 4050
d62a17ae 4051 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4052 && (safi != SAFI_EVPN))
4053 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4054 else
4055 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4056 rn = bgp_route_next(rn)) {
4057 table = bgp_node_get_bgp_table_info(rn);
4058 if (table != NULL) {
d62a17ae 4059 struct prefix_rd prd;
67009e22 4060
d62a17ae 4061 prd.family = AF_UNSPEC;
4062 prd.prefixlen = 64;
4063 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 4064
d62a17ae 4065 bgp_soft_reconfig_table(peer, afi, safi, table,
4066 &prd);
4067 }
67009e22 4068 }
718e3744 4069}
6b0655a2 4070
228da428 4071
d62a17ae 4072struct bgp_clear_node_queue {
4073 struct bgp_node *rn;
228da428
CC
4074};
4075
d62a17ae 4076static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4077{
d62a17ae 4078 struct bgp_clear_node_queue *cnq = data;
4079 struct bgp_node *rn = cnq->rn;
4080 struct peer *peer = wq->spec.data;
40381db7 4081 struct bgp_path_info *pi;
3103e8d2 4082 struct bgp *bgp;
d62a17ae 4083 afi_t afi = bgp_node_table(rn)->afi;
4084 safi_t safi = bgp_node_table(rn)->safi;
4085
4086 assert(rn && peer);
3103e8d2 4087 bgp = peer->bgp;
d62a17ae 4088
4089 /* It is possible that we have multiple paths for a prefix from a peer
4090 * if that peer is using AddPath.
4091 */
6f94b685 4092 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4093 if (pi->peer != peer)
ea47320b
DL
4094 continue;
4095
4096 /* graceful restart STALE flag set. */
4097 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4098 && peer->nsf[afi][safi]
40381db7
DS
4099 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4100 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4101 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4102 else {
4103 /* If this is an EVPN route, process for
4104 * un-import. */
4105 if (safi == SAFI_EVPN)
40381db7
DS
4106 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4107 pi);
3103e8d2
DS
4108 /* Handle withdraw for VRF route-leaking and L3VPN */
4109 if (SAFI_UNICAST == safi
4110 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4111 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4112 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4113 bgp, pi);
960035b2 4114 }
3103e8d2 4115 if (SAFI_MPLS_VPN == safi &&
960035b2 4116 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4117 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4118 }
3103e8d2 4119
40381db7 4120 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4121 }
ea47320b 4122 }
d62a17ae 4123 return WQ_SUCCESS;
200df115 4124}
4125
d62a17ae 4126static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4127{
d62a17ae 4128 struct bgp_clear_node_queue *cnq = data;
4129 struct bgp_node *rn = cnq->rn;
4130 struct bgp_table *table = bgp_node_table(rn);
228da428 4131
d62a17ae 4132 bgp_unlock_node(rn);
4133 bgp_table_unlock(table);
4134 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4135}
4136
d62a17ae 4137static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4138{
d62a17ae 4139 struct peer *peer = wq->spec.data;
64e580a7 4140
d62a17ae 4141 /* Tickle FSM to start moving again */
4142 BGP_EVENT_ADD(peer, Clearing_Completed);
4143
4144 peer_unlock(peer); /* bgp_clear_route */
200df115 4145}
718e3744 4146
d62a17ae 4147static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4148{
d62a17ae 4149 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4150
4151 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4152#undef CLEAR_QUEUE_NAME_LEN
4153
0ce1ca80 4154 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4155 peer->clear_node_queue->spec.hold = 10;
4156 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4157 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4158 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4159 peer->clear_node_queue->spec.max_retries = 0;
4160
4161 /* we only 'lock' this peer reference when the queue is actually active
4162 */
4163 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4164}
4165
d62a17ae 4166static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4167 struct bgp_table *table)
65ca75e0 4168{
d62a17ae 4169 struct bgp_node *rn;
4170 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4171
d62a17ae 4172 if (!table)
4173 table = peer->bgp->rib[afi][safi];
dc83d712 4174
d62a17ae 4175 /* If still no table => afi/safi isn't configured at all or smth. */
4176 if (!table)
4177 return;
dc83d712 4178
d62a17ae 4179 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4180 struct bgp_path_info *pi, *next;
d62a17ae 4181 struct bgp_adj_in *ain;
4182 struct bgp_adj_in *ain_next;
4183
4184 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4185 * queued for every clearing peer, regardless of whether it is
4186 * relevant to the peer at hand.
4187 *
4188 * Overview: There are 3 different indices which need to be
4189 * scrubbed, potentially, when a peer is removed:
4190 *
4191 * 1 peer's routes visible via the RIB (ie accepted routes)
4192 * 2 peer's routes visible by the (optional) peer's adj-in index
4193 * 3 other routes visible by the peer's adj-out index
4194 *
4195 * 3 there is no hurry in scrubbing, once the struct peer is
4196 * removed from bgp->peer, we could just GC such deleted peer's
4197 * adj-outs at our leisure.
4198 *
4199 * 1 and 2 must be 'scrubbed' in some way, at least made
4200 * invisible via RIB index before peer session is allowed to be
4201 * brought back up. So one needs to know when such a 'search' is
4202 * complete.
4203 *
4204 * Ideally:
4205 *
4206 * - there'd be a single global queue or a single RIB walker
4207 * - rather than tracking which route_nodes still need to be
4208 * examined on a peer basis, we'd track which peers still
4209 * aren't cleared
4210 *
4211 * Given that our per-peer prefix-counts now should be reliable,
4212 * this may actually be achievable. It doesn't seem to be a huge
4213 * problem at this time,
4214 *
4215 * It is possible that we have multiple paths for a prefix from
4216 * a peer
4217 * if that peer is using AddPath.
4218 */
4219 ain = rn->adj_in;
4220 while (ain) {
4221 ain_next = ain->next;
4222
4223 if (ain->peer == peer) {
4224 bgp_adj_in_remove(rn, ain);
4225 bgp_unlock_node(rn);
4226 }
4227
4228 ain = ain_next;
4229 }
4230
6f94b685 4231 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4232 next = pi->next;
4233 if (pi->peer != peer)
d62a17ae 4234 continue;
4235
4236 if (force)
40381db7 4237 bgp_path_info_reap(rn, pi);
d62a17ae 4238 else {
4239 struct bgp_clear_node_queue *cnq;
4240
4241 /* both unlocked in bgp_clear_node_queue_del */
4242 bgp_table_lock(bgp_node_table(rn));
4243 bgp_lock_node(rn);
4244 cnq = XCALLOC(
4245 MTYPE_BGP_CLEAR_NODE_QUEUE,
4246 sizeof(struct bgp_clear_node_queue));
4247 cnq->rn = rn;
4248 work_queue_add(peer->clear_node_queue, cnq);
4249 break;
4250 }
4251 }
4252 }
4253 return;
4254}
4255
4256void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4257{
4258 struct bgp_node *rn;
4259 struct bgp_table *table;
4260
4261 if (peer->clear_node_queue == NULL)
4262 bgp_clear_node_queue_init(peer);
4263
4264 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4265 * Idle until it receives a Clearing_Completed event. This protects
4266 * against peers which flap faster than we can we clear, which could
4267 * lead to:
4268 *
4269 * a) race with routes from the new session being installed before
4270 * clear_route_node visits the node (to delete the route of that
4271 * peer)
4272 * b) resource exhaustion, clear_route_node likely leads to an entry
4273 * on the process_main queue. Fast-flapping could cause that queue
4274 * to grow and grow.
4275 */
4276
4277 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4278 * the unlock will happen upon work-queue completion; other wise, the
4279 * unlock happens at the end of this function.
4280 */
4281 if (!peer->clear_node_queue->thread)
4282 peer_lock(peer);
4283
4284 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4285 bgp_clear_route_table(peer, afi, safi, NULL);
4286 else
4287 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4288 rn = bgp_route_next(rn)) {
4289 table = bgp_node_get_bgp_table_info(rn);
4290 if (!table)
4291 continue;
4292
4293 bgp_clear_route_table(peer, afi, safi, table);
4294 }
d62a17ae 4295
4296 /* unlock if no nodes got added to the clear-node-queue. */
4297 if (!peer->clear_node_queue->thread)
4298 peer_unlock(peer);
718e3744 4299}
d62a17ae 4300
4301void bgp_clear_route_all(struct peer *peer)
718e3744 4302{
d62a17ae 4303 afi_t afi;
4304 safi_t safi;
718e3744 4305
05c7a1cc
QY
4306 FOREACH_AFI_SAFI (afi, safi)
4307 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4308
4309#if ENABLE_BGP_VNC
d62a17ae 4310 rfapiProcessPeerDown(peer);
65efcfce 4311#endif
718e3744 4312}
4313
d62a17ae 4314void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4315{
d62a17ae 4316 struct bgp_table *table;
4317 struct bgp_node *rn;
4318 struct bgp_adj_in *ain;
4319 struct bgp_adj_in *ain_next;
718e3744 4320
d62a17ae 4321 table = peer->bgp->rib[afi][safi];
718e3744 4322
d62a17ae 4323 /* It is possible that we have multiple paths for a prefix from a peer
4324 * if that peer is using AddPath.
4325 */
4326 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4327 ain = rn->adj_in;
43143c8f 4328
d62a17ae 4329 while (ain) {
4330 ain_next = ain->next;
43143c8f 4331
d62a17ae 4332 if (ain->peer == peer) {
4333 bgp_adj_in_remove(rn, ain);
4334 bgp_unlock_node(rn);
4335 }
43143c8f 4336
d62a17ae 4337 ain = ain_next;
4338 }
4339 }
718e3744 4340}
93406d87 4341
d62a17ae 4342void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4343{
4344 struct bgp_node *rn;
40381db7 4345 struct bgp_path_info *pi;
d62a17ae 4346 struct bgp_table *table;
4347
4348 if (safi == SAFI_MPLS_VPN) {
4349 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4350 rn = bgp_route_next(rn)) {
4351 struct bgp_node *rm;
d62a17ae 4352
4353 /* look for neighbor in tables */
67009e22
DS
4354 table = bgp_node_get_bgp_table_info(rn);
4355 if (!table)
ea47320b
DL
4356 continue;
4357
4358 for (rm = bgp_table_top(table); rm;
4359 rm = bgp_route_next(rm))
6f94b685
DS
4360 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4361 pi = pi->next) {
40381db7 4362 if (pi->peer != peer)
ea47320b 4363 continue;
40381db7 4364 if (!CHECK_FLAG(pi->flags,
1defdda8 4365 BGP_PATH_STALE))
ea47320b
DL
4366 break;
4367
40381db7 4368 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4369 break;
4370 }
d62a17ae 4371 }
4372 } else {
4373 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4374 rn = bgp_route_next(rn))
6f94b685
DS
4375 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4376 pi = pi->next) {
40381db7 4377 if (pi->peer != peer)
ea47320b 4378 continue;
40381db7 4379 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4380 break;
40381db7 4381 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4382 break;
4383 }
d62a17ae 4384 }
93406d87 4385}
6b0655a2 4386
9dac9fc8
DA
4387int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4388{
e0df4c04
DA
4389 if (peer->sort == BGP_PEER_IBGP)
4390 return 1;
4391
9dac9fc8
DA
4392 if (peer->sort == BGP_PEER_EBGP
4393 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4394 || FILTER_LIST_OUT_NAME(filter)
4395 || DISTRIBUTE_OUT_NAME(filter)))
4396 return 1;
4397 return 0;
4398}
4399
4400int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4401{
e0df4c04
DA
4402 if (peer->sort == BGP_PEER_IBGP)
4403 return 1;
4404
9dac9fc8
DA
4405 if (peer->sort == BGP_PEER_EBGP
4406 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4407 || FILTER_LIST_IN_NAME(filter)
4408 || DISTRIBUTE_IN_NAME(filter)))
4409 return 1;
4410 return 0;
4411}
4412
568e10ca 4413static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4414 safi_t safi)
bb86c601 4415{
d62a17ae 4416 struct bgp_node *rn;
40381db7 4417 struct bgp_path_info *pi;
4b7e6066 4418 struct bgp_path_info *next;
bb86c601 4419
d62a17ae 4420 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4421 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4422 next = pi->next;
1b7bb747
CS
4423
4424 /* Unimport EVPN routes from VRFs */
4425 if (safi == SAFI_EVPN)
4426 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4427 SAFI_EVPN,
4428 &rn->p, pi);
4429
40381db7
DS
4430 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4431 && pi->type == ZEBRA_ROUTE_BGP
4432 && (pi->sub_type == BGP_ROUTE_NORMAL
4433 || pi->sub_type == BGP_ROUTE_AGGREGATE
4434 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4435
d62a17ae 4436 if (bgp_fibupd_safi(safi))
40381db7
DS
4437 bgp_zebra_withdraw(&rn->p, pi, bgp,
4438 safi);
4439 bgp_path_info_reap(rn, pi);
d62a17ae 4440 }
4441 }
bb86c601
LB
4442}
4443
718e3744 4444/* Delete all kernel routes. */
d62a17ae 4445void bgp_cleanup_routes(struct bgp *bgp)
4446{
4447 afi_t afi;
4448 struct bgp_node *rn;
67009e22 4449 struct bgp_table *table;
d62a17ae 4450
4451 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4452 if (afi == AFI_L2VPN)
4453 continue;
568e10ca 4454 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4455 SAFI_UNICAST);
d62a17ae 4456 /*
4457 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4458 */
4459 if (afi != AFI_L2VPN) {
4460 safi_t safi;
4461 safi = SAFI_MPLS_VPN;
4462 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4463 rn = bgp_route_next(rn)) {
67009e22
DS
4464 table = bgp_node_get_bgp_table_info(rn);
4465 if (table != NULL) {
4466 bgp_cleanup_table(bgp, table, safi);
4467 bgp_table_finish(&table);
4468 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4469 bgp_unlock_node(rn);
4470 }
4471 }
4472 safi = SAFI_ENCAP;
4473 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4474 rn = bgp_route_next(rn)) {
67009e22
DS
4475 table = bgp_node_get_bgp_table_info(rn);
4476 if (table != NULL) {
4477 bgp_cleanup_table(bgp, table, safi);
4478 bgp_table_finish(&table);
4479 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4480 bgp_unlock_node(rn);
4481 }
4482 }
4483 }
4484 }
4485 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4486 rn = bgp_route_next(rn)) {
67009e22
DS
4487 table = bgp_node_get_bgp_table_info(rn);
4488 if (table != NULL) {
4489 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4490 bgp_table_finish(&table);
4491 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4492 bgp_unlock_node(rn);
4493 }
bb86c601 4494 }
718e3744 4495}
4496
d62a17ae 4497void bgp_reset(void)
718e3744 4498{
d62a17ae 4499 vty_reset();
4500 bgp_zclient_reset();
4501 access_list_reset();
4502 prefix_list_reset();
718e3744 4503}
6b0655a2 4504
d62a17ae 4505static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4506{
d62a17ae 4507 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4508 && CHECK_FLAG(peer->af_cap[afi][safi],
4509 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4510}
4511
718e3744 4512/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4513 value. */
d62a17ae 4514int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4515 struct bgp_nlri *packet)
4516{
d7c0a89a
QY
4517 uint8_t *pnt;
4518 uint8_t *lim;
d62a17ae 4519 struct prefix p;
4520 int psize;
4521 int ret;
4522 afi_t afi;
4523 safi_t safi;
4524 int addpath_encoded;
d7c0a89a 4525 uint32_t addpath_id;
d62a17ae 4526
d62a17ae 4527 pnt = packet->nlri;
4528 lim = pnt + packet->length;
4529 afi = packet->afi;
4530 safi = packet->safi;
4531 addpath_id = 0;
4532 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4533
4534 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4535 syntactic validity. If the field is syntactically incorrect,
4536 then the Error Subcode is set to Invalid Network Field. */
4537 for (; pnt < lim; pnt += psize) {
4538 /* Clear prefix structure. */
4539 memset(&p, 0, sizeof(struct prefix));
4540
4541 if (addpath_encoded) {
4542
4543 /* When packet overflow occurs return immediately. */
761ed665 4544 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4545 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4546
a3a850a1 4547 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4548 addpath_id = ntohl(addpath_id);
d62a17ae 4549 pnt += BGP_ADDPATH_ID_LEN;
4550 }
718e3744 4551
d62a17ae 4552 /* Fetch prefix length. */
4553 p.prefixlen = *pnt++;
4554 /* afi/safi validity already verified by caller,
4555 * bgp_update_receive */
4556 p.family = afi2family(afi);
4557
4558 /* Prefix length check. */
4559 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4560 flog_err(
e50f7cfd 4561 EC_BGP_UPDATE_RCV,
14454c9f 4562 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4563 peer->host, p.prefixlen, packet->afi);
513386b5 4564 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4565 }
6b0655a2 4566
d62a17ae 4567 /* Packet size overflow check. */
4568 psize = PSIZE(p.prefixlen);
4569
4570 /* When packet overflow occur return immediately. */
4571 if (pnt + psize > lim) {
af4c2728 4572 flog_err(
e50f7cfd 4573 EC_BGP_UPDATE_RCV,
d62a17ae 4574 "%s [Error] Update packet error (prefix length %d overflows packet)",
4575 peer->host, p.prefixlen);
513386b5 4576 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4577 }
4578
4579 /* Defensive coding, double-check the psize fits in a struct
4580 * prefix */
4581 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4582 flog_err(
e50f7cfd 4583 EC_BGP_UPDATE_RCV,
d62a17ae 4584 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4585 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4586 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4587 }
4588
4589 /* Fetch prefix from NLRI packet. */
a85297a7 4590 memcpy(p.u.val, pnt, psize);
d62a17ae 4591
4592 /* Check address. */
4593 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4594 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4595 /* From RFC4271 Section 6.3:
4596 *
4597 * If a prefix in the NLRI field is semantically
4598 * incorrect
4599 * (e.g., an unexpected multicast IP address),
4600 * an error SHOULD
4601 * be logged locally, and the prefix SHOULD be
4602 * ignored.
a4d82a8a 4603 */
af4c2728 4604 flog_err(
e50f7cfd 4605 EC_BGP_UPDATE_RCV,
d62a17ae 4606 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4607 peer->host, inet_ntoa(p.u.prefix4));
4608 continue;
4609 }
4610 }
4611
4612 /* Check address. */
4613 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4614 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4615 char buf[BUFSIZ];
4616
af4c2728 4617 flog_err(
e50f7cfd 4618 EC_BGP_UPDATE_RCV,
d62a17ae 4619 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4620 peer->host,
4621 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4622 BUFSIZ));
4623
4624 continue;
4625 }
4626 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4627 char buf[BUFSIZ];
4628
af4c2728 4629 flog_err(
e50f7cfd 4630 EC_BGP_UPDATE_RCV,
d62a17ae 4631 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4632 peer->host,
4633 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4634 BUFSIZ));
4635
4636 continue;
4637 }
4638 }
4639
4640 /* Normal process. */
4641 if (attr)
4642 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4643 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4644 NULL, NULL, 0, 0, NULL);
d62a17ae 4645 else
4646 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4647 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4648 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4649 NULL);
d62a17ae 4650
513386b5
DA
4651 /* Do not send BGP notification twice when maximum-prefix count
4652 * overflow. */
4653 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4654 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4655
4656 /* Address family configuration mismatch. */
d62a17ae 4657 if (ret < 0)
513386b5 4658 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4659 }
4660
4661 /* Packet length consistency check. */
4662 if (pnt != lim) {
af4c2728 4663 flog_err(
e50f7cfd 4664 EC_BGP_UPDATE_RCV,
d62a17ae 4665 "%s [Error] Update packet error (prefix length mismatch with total length)",
4666 peer->host);
513386b5 4667 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4668 }
6b0655a2 4669
513386b5 4670 return BGP_NLRI_PARSE_OK;
718e3744 4671}
4672
d62a17ae 4673static struct bgp_static *bgp_static_new(void)
718e3744 4674{
d62a17ae 4675 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4676}
4677
d62a17ae 4678static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4679{
0a22ddfb 4680 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4681 route_map_counter_decrement(bgp_static->rmap.map);
4682
0a22ddfb 4683 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4684 XFREE(MTYPE_BGP_STATIC, bgp_static);
4685}
4686
4687void bgp_static_update(struct bgp *bgp, struct prefix *p,
4688 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4689{
4690 struct bgp_node *rn;
40381db7 4691 struct bgp_path_info *pi;
4b7e6066 4692 struct bgp_path_info *new;
40381db7 4693 struct bgp_path_info rmap_path;
d62a17ae 4694 struct attr attr;
4695 struct attr *attr_new;
b68885f9 4696 route_map_result_t ret;
65efcfce 4697#if ENABLE_BGP_VNC
d62a17ae 4698 int vnc_implicit_withdraw = 0;
65efcfce 4699#endif
fee0f4c6 4700
d62a17ae 4701 assert(bgp_static);
4702 if (!bgp_static)
4703 return;
dd8103a9 4704
d62a17ae 4705 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4706
d62a17ae 4707 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4708
d62a17ae 4709 attr.nexthop = bgp_static->igpnexthop;
4710 attr.med = bgp_static->igpmetric;
4711 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4712
d62a17ae 4713 if (bgp_static->atomic)
4714 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4715
d62a17ae 4716 /* Store label index, if required. */
4717 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4718 attr.label_index = bgp_static->label_index;
4719 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4720 }
718e3744 4721
d62a17ae 4722 /* Apply route-map. */
4723 if (bgp_static->rmap.name) {
4724 struct attr attr_tmp = attr;
80ced710 4725
40381db7
DS
4726 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4727 rmap_path.peer = bgp->peer_self;
4728 rmap_path.attr = &attr_tmp;
fee0f4c6 4729
d62a17ae 4730 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4731
40381db7
DS
4732 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4733 &rmap_path);
fee0f4c6 4734
d62a17ae 4735 bgp->peer_self->rmap_type = 0;
718e3744 4736
d62a17ae 4737 if (ret == RMAP_DENYMATCH) {
4738 /* Free uninterned attribute. */
4739 bgp_attr_flush(&attr_tmp);
718e3744 4740
d62a17ae 4741 /* Unintern original. */
4742 aspath_unintern(&attr.aspath);
4743 bgp_static_withdraw(bgp, p, afi, safi);
4744 return;
4745 }
7f323236
DW
4746
4747 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4748 bgp_attr_add_gshut_community(&attr_tmp);
4749
d62a17ae 4750 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4751 } else {
4752
4753 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4754 bgp_attr_add_gshut_community(&attr);
4755
d62a17ae 4756 attr_new = bgp_attr_intern(&attr);
7f323236 4757 }
718e3744 4758
6f94b685 4759 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4760 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4761 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4762 break;
4763
40381db7
DS
4764 if (pi) {
4765 if (attrhash_cmp(pi->attr, attr_new)
4766 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4767 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4768 bgp_unlock_node(rn);
4769 bgp_attr_unintern(&attr_new);
4770 aspath_unintern(&attr.aspath);
4771 return;
4772 } else {
4773 /* The attribute is changed. */
40381db7 4774 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4775
4776 /* Rewrite BGP route information. */
40381db7
DS
4777 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4778 bgp_path_info_restore(rn, pi);
d62a17ae 4779 else
40381db7 4780 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4781#if ENABLE_BGP_VNC
d62a17ae 4782 if ((afi == AFI_IP || afi == AFI_IP6)
4783 && (safi == SAFI_UNICAST)) {
40381db7 4784 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4785 /*
4786 * Implicit withdraw case.
40381db7 4787 * We have to do this before pi is
d62a17ae 4788 * changed
4789 */
4790 ++vnc_implicit_withdraw;
40381db7 4791 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4792 vnc_import_bgp_exterior_del_route(
40381db7 4793 bgp, p, pi);
d62a17ae 4794 }
4795 }
65efcfce 4796#endif
40381db7
DS
4797 bgp_attr_unintern(&pi->attr);
4798 pi->attr = attr_new;
4799 pi->uptime = bgp_clock();
65efcfce 4800#if ENABLE_BGP_VNC
d62a17ae 4801 if ((afi == AFI_IP || afi == AFI_IP6)
4802 && (safi == SAFI_UNICAST)) {
4803 if (vnc_implicit_withdraw) {
40381db7 4804 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4805 vnc_import_bgp_exterior_add_route(
40381db7 4806 bgp, p, pi);
d62a17ae 4807 }
4808 }
65efcfce 4809#endif
718e3744 4810
d62a17ae 4811 /* Nexthop reachability check. */
4812 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4813 && (safi == SAFI_UNICAST
4814 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4815
4816 struct bgp *bgp_nexthop = bgp;
4817
40381db7
DS
4818 if (pi->extra && pi->extra->bgp_orig)
4819 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4820
4821 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4822 afi, pi, NULL, 0))
4823 bgp_path_info_set_flag(rn, pi,
18ee8310 4824 BGP_PATH_VALID);
d62a17ae 4825 else {
4826 if (BGP_DEBUG(nht, NHT)) {
4827 char buf1[INET6_ADDRSTRLEN];
4828 inet_ntop(p->family,
4829 &p->u.prefix, buf1,
4830 INET6_ADDRSTRLEN);
4831 zlog_debug(
4832 "%s(%s): Route not in table, not advertising",
4833 __FUNCTION__, buf1);
4834 }
18ee8310 4835 bgp_path_info_unset_flag(
40381db7 4836 rn, pi, BGP_PATH_VALID);
d62a17ae 4837 }
4838 } else {
4839 /* Delete the NHT structure if any, if we're
4840 * toggling between
4841 * enabling/disabling import check. We
4842 * deregister the route
4843 * from NHT to avoid overloading NHT and the
4844 * process interaction
4845 */
40381db7
DS
4846 bgp_unlink_nexthop(pi);
4847 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4848 }
4849 /* Process change. */
40381db7 4850 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4851 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4852
4853 if (SAFI_UNICAST == safi
4854 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4855 || bgp->inst_type
4856 == BGP_INSTANCE_TYPE_DEFAULT)) {
4857 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4858 pi);
ddb5b488
PZ
4859 }
4860
d62a17ae 4861 bgp_unlock_node(rn);
4862 aspath_unintern(&attr.aspath);
4863 return;
4864 }
718e3744 4865 }
718e3744 4866
d62a17ae 4867 /* Make new BGP info. */
4868 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4869 attr_new, rn);
4870 /* Nexthop reachability check. */
4871 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4872 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4873 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4874 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4875 else {
4876 if (BGP_DEBUG(nht, NHT)) {
4877 char buf1[INET6_ADDRSTRLEN];
4878 inet_ntop(p->family, &p->u.prefix, buf1,
4879 INET6_ADDRSTRLEN);
4880 zlog_debug(
4881 "%s(%s): Route not in table, not advertising",
4882 __FUNCTION__, buf1);
4883 }
18ee8310 4884 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4885 }
4886 } else {
4887 /* Delete the NHT structure if any, if we're toggling between
4888 * enabling/disabling import check. We deregister the route
4889 * from NHT to avoid overloading NHT and the process interaction
4890 */
4891 bgp_unlink_nexthop(new);
4892
18ee8310 4893 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4894 }
078430f6 4895
d62a17ae 4896 /* Aggregate address increment. */
4897 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4898
d62a17ae 4899 /* Register new BGP information. */
18ee8310 4900 bgp_path_info_add(rn, new);
718e3744 4901
d62a17ae 4902 /* route_node_get lock */
4903 bgp_unlock_node(rn);
4904
4905 /* Process change. */
4906 bgp_process(bgp, rn, afi, safi);
4907
ddb5b488
PZ
4908 if (SAFI_UNICAST == safi
4909 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4910 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4911 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4912 }
4913
d62a17ae 4914 /* Unintern original. */
4915 aspath_unintern(&attr.aspath);
718e3744 4916}
4917
d62a17ae 4918void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4919 safi_t safi)
718e3744 4920{
d62a17ae 4921 struct bgp_node *rn;
40381db7 4922 struct bgp_path_info *pi;
718e3744 4923
d62a17ae 4924 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4925
d62a17ae 4926 /* Check selected route and self inserted route. */
6f94b685 4927 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4928 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4929 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4930 break;
4931
4932 /* Withdraw static BGP route from routing table. */
40381db7 4933 if (pi) {
ddb5b488
PZ
4934 if (SAFI_UNICAST == safi
4935 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4936 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4937 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4938 }
40381db7
DS
4939 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4940 bgp_unlink_nexthop(pi);
4941 bgp_path_info_delete(rn, pi);
d62a17ae 4942 bgp_process(bgp, rn, afi, safi);
4943 }
718e3744 4944
d62a17ae 4945 /* Unlock bgp_node_lookup. */
4946 bgp_unlock_node(rn);
718e3744 4947}
4948
137446f9
LB
4949/*
4950 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4951 */
d62a17ae 4952static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4953 afi_t afi, safi_t safi,
4954 struct prefix_rd *prd)
718e3744 4955{
d62a17ae 4956 struct bgp_node *rn;
40381db7 4957 struct bgp_path_info *pi;
718e3744 4958
d62a17ae 4959 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4960
d62a17ae 4961 /* Check selected route and self inserted route. */
6f94b685 4962 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4963 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4964 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4965 break;
718e3744 4966
d62a17ae 4967 /* Withdraw static BGP route from routing table. */
40381db7 4968 if (pi) {
65efcfce 4969#if ENABLE_BGP_VNC
d62a17ae 4970 rfapiProcessWithdraw(
40381db7 4971 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4972 1); /* Kill, since it is an administrative change */
65efcfce 4973#endif
ddb5b488
PZ
4974 if (SAFI_MPLS_VPN == safi
4975 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4976 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4977 }
40381db7
DS
4978 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4979 bgp_path_info_delete(rn, pi);
d62a17ae 4980 bgp_process(bgp, rn, afi, safi);
4981 }
718e3744 4982
d62a17ae 4983 /* Unlock bgp_node_lookup. */
4984 bgp_unlock_node(rn);
718e3744 4985}
4986
d62a17ae 4987static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4988 struct bgp_static *bgp_static, afi_t afi,
4989 safi_t safi)
137446f9 4990{
d62a17ae 4991 struct bgp_node *rn;
4b7e6066 4992 struct bgp_path_info *new;
d62a17ae 4993 struct attr *attr_new;
4994 struct attr attr = {0};
40381db7 4995 struct bgp_path_info *pi;
65efcfce 4996#if ENABLE_BGP_VNC
d62a17ae 4997 mpls_label_t label = 0;
65efcfce 4998#endif
d7c0a89a 4999 uint32_t num_labels = 0;
d62a17ae 5000 union gw_addr add;
137446f9 5001
d62a17ae 5002 assert(bgp_static);
137446f9 5003
b57ba6d2
MK
5004 if (bgp_static->label != MPLS_INVALID_LABEL)
5005 num_labels = 1;
d62a17ae 5006 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5007 &bgp_static->prd);
137446f9 5008
d62a17ae 5009 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5010
d62a17ae 5011 attr.nexthop = bgp_static->igpnexthop;
5012 attr.med = bgp_static->igpmetric;
5013 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5014
d62a17ae 5015 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5016 || (safi == SAFI_ENCAP)) {
5017 if (afi == AFI_IP) {
5018 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5019 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5020 }
5021 }
5022 if (afi == AFI_L2VPN) {
5023 if (bgp_static->gatewayIp.family == AF_INET)
5024 add.ipv4.s_addr =
5025 bgp_static->gatewayIp.u.prefix4.s_addr;
5026 else if (bgp_static->gatewayIp.family == AF_INET6)
5027 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5028 sizeof(struct in6_addr));
5029 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5030 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5031 struct bgp_encap_type_vxlan bet;
5032 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5033 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5034 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5035 }
5036 if (bgp_static->router_mac) {
5037 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5038 }
5039 }
5040 /* Apply route-map. */
5041 if (bgp_static->rmap.name) {
5042 struct attr attr_tmp = attr;
40381db7 5043 struct bgp_path_info rmap_path;
b68885f9 5044 route_map_result_t ret;
137446f9 5045
40381db7
DS
5046 rmap_path.peer = bgp->peer_self;
5047 rmap_path.attr = &attr_tmp;
137446f9 5048
d62a17ae 5049 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5050
40381db7
DS
5051 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5052 &rmap_path);
137446f9 5053
d62a17ae 5054 bgp->peer_self->rmap_type = 0;
137446f9 5055
d62a17ae 5056 if (ret == RMAP_DENYMATCH) {
5057 /* Free uninterned attribute. */
5058 bgp_attr_flush(&attr_tmp);
137446f9 5059
d62a17ae 5060 /* Unintern original. */
5061 aspath_unintern(&attr.aspath);
5062 bgp_static_withdraw_safi(bgp, p, afi, safi,
5063 &bgp_static->prd);
5064 return;
5065 }
137446f9 5066
d62a17ae 5067 attr_new = bgp_attr_intern(&attr_tmp);
5068 } else {
5069 attr_new = bgp_attr_intern(&attr);
5070 }
137446f9 5071
6f94b685 5072 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5073 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5074 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5075 break;
5076
40381db7 5077 if (pi) {
d62a17ae 5078 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5079 if (attrhash_cmp(pi->attr, attr_new)
5080 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5081 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5082 bgp_unlock_node(rn);
5083 bgp_attr_unintern(&attr_new);
5084 aspath_unintern(&attr.aspath);
5085 return;
5086 } else {
5087 /* The attribute is changed. */
40381db7 5088 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5089
5090 /* Rewrite BGP route information. */
40381db7
DS
5091 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5092 bgp_path_info_restore(rn, pi);
d62a17ae 5093 else
40381db7
DS
5094 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5095 bgp_attr_unintern(&pi->attr);
5096 pi->attr = attr_new;
5097 pi->uptime = bgp_clock();
65efcfce 5098#if ENABLE_BGP_VNC
40381db7
DS
5099 if (pi->extra)
5100 label = decode_label(&pi->extra->label[0]);
65efcfce 5101#endif
137446f9 5102
d62a17ae 5103 /* Process change. */
40381db7 5104 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5105 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5106
5107 if (SAFI_MPLS_VPN == safi
5108 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5109 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5110 }
65efcfce 5111#if ENABLE_BGP_VNC
40381db7
DS
5112 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5113 pi->attr, afi, safi, pi->type,
5114 pi->sub_type, &label);
65efcfce 5115#endif
d62a17ae 5116 bgp_unlock_node(rn);
5117 aspath_unintern(&attr.aspath);
5118 return;
5119 }
5120 }
137446f9
LB
5121
5122
d62a17ae 5123 /* Make new BGP info. */
5124 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5125 attr_new, rn);
1defdda8 5126 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5127 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5128 if (num_labels) {
5129 new->extra->label[0] = bgp_static->label;
5130 new->extra->num_labels = num_labels;
5131 }
65efcfce 5132#if ENABLE_BGP_VNC
d62a17ae 5133 label = decode_label(&bgp_static->label);
65efcfce 5134#endif
137446f9 5135
d62a17ae 5136 /* Aggregate address increment. */
5137 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5138
d62a17ae 5139 /* Register new BGP information. */
18ee8310 5140 bgp_path_info_add(rn, new);
d62a17ae 5141 /* route_node_get lock */
5142 bgp_unlock_node(rn);
137446f9 5143
d62a17ae 5144 /* Process change. */
5145 bgp_process(bgp, rn, afi, safi);
137446f9 5146
ddb5b488
PZ
5147 if (SAFI_MPLS_VPN == safi
5148 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5149 vpn_leak_to_vrf_update(bgp, new);
5150 }
65efcfce 5151#if ENABLE_BGP_VNC
d62a17ae 5152 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5153 safi, new->type, new->sub_type, &label);
65efcfce
LB
5154#endif
5155
d62a17ae 5156 /* Unintern original. */
5157 aspath_unintern(&attr.aspath);
137446f9
LB
5158}
5159
718e3744 5160/* Configure static BGP network. When user don't run zebra, static
5161 route should be installed as valid. */
e2a86ad9
DS
5162static int bgp_static_set(struct vty *vty, const char *negate,
5163 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5164 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5165{
5166 VTY_DECLVAR_CONTEXT(bgp, bgp);
5167 int ret;
5168 struct prefix p;
5169 struct bgp_static *bgp_static;
5170 struct bgp_node *rn;
d7c0a89a 5171 uint8_t need_update = 0;
d62a17ae 5172
5173 /* Convert IP prefix string to struct prefix. */
5174 ret = str2prefix(ip_str, &p);
5175 if (!ret) {
5176 vty_out(vty, "%% Malformed prefix\n");
5177 return CMD_WARNING_CONFIG_FAILED;
5178 }
5179 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5180 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5181 return CMD_WARNING_CONFIG_FAILED;
5182 }
718e3744 5183
d62a17ae 5184 apply_mask(&p);
718e3744 5185
e2a86ad9 5186 if (negate) {
718e3744 5187
e2a86ad9
DS
5188 /* Set BGP static route configuration. */
5189 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5190
e2a86ad9 5191 if (!rn) {
a4d82a8a 5192 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5193 return CMD_WARNING_CONFIG_FAILED;
5194 }
5195
5a8ba9fc 5196 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5197
e2a86ad9
DS
5198 if ((label_index != BGP_INVALID_LABEL_INDEX)
5199 && (label_index != bgp_static->label_index)) {
5200 vty_out(vty,
5201 "%% label-index doesn't match static route\n");
5202 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5203 }
d62a17ae 5204
e2a86ad9
DS
5205 if ((rmap && bgp_static->rmap.name)
5206 && strcmp(rmap, bgp_static->rmap.name)) {
5207 vty_out(vty,
5208 "%% route-map name doesn't match static route\n");
5209 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5210 }
718e3744 5211
e2a86ad9
DS
5212 /* Update BGP RIB. */
5213 if (!bgp_static->backdoor)
5214 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5215
e2a86ad9
DS
5216 /* Clear configuration. */
5217 bgp_static_free(bgp_static);
5a8ba9fc 5218 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5219 bgp_unlock_node(rn);
5220 bgp_unlock_node(rn);
5221 } else {
718e3744 5222
e2a86ad9
DS
5223 /* Set BGP static route configuration. */
5224 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5225
5a8ba9fc 5226 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5227 if (bgp_static) {
e2a86ad9 5228 /* Configuration change. */
e2a86ad9
DS
5229 /* Label index cannot be changed. */
5230 if (bgp_static->label_index != label_index) {
5231 vty_out(vty, "%% cannot change label-index\n");
5232 return CMD_WARNING_CONFIG_FAILED;
5233 }
d62a17ae 5234
e2a86ad9 5235 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5236 if (bgp_static->valid
5237 && bgp_static->backdoor != backdoor)
e2a86ad9 5238 need_update = 1;
718e3744 5239
e2a86ad9 5240 bgp_static->backdoor = backdoor;
718e3744 5241
e2a86ad9 5242 if (rmap) {
0a22ddfb
QY
5243 XFREE(MTYPE_ROUTE_MAP_NAME,
5244 bgp_static->rmap.name);
b4897fa5 5245 route_map_counter_decrement(
5246 bgp_static->rmap.map);
e2a86ad9
DS
5247 bgp_static->rmap.name =
5248 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5249 bgp_static->rmap.map =
5250 route_map_lookup_by_name(rmap);
b4897fa5 5251 route_map_counter_increment(
5252 bgp_static->rmap.map);
e2a86ad9 5253 } else {
0a22ddfb
QY
5254 XFREE(MTYPE_ROUTE_MAP_NAME,
5255 bgp_static->rmap.name);
b4897fa5 5256 route_map_counter_decrement(
5257 bgp_static->rmap.map);
e2a86ad9
DS
5258 bgp_static->rmap.name = NULL;
5259 bgp_static->rmap.map = NULL;
5260 bgp_static->valid = 0;
5261 }
5262 bgp_unlock_node(rn);
5263 } else {
5264 /* New configuration. */
5265 bgp_static = bgp_static_new();
5266 bgp_static->backdoor = backdoor;
5267 bgp_static->valid = 0;
5268 bgp_static->igpmetric = 0;
5269 bgp_static->igpnexthop.s_addr = 0;
5270 bgp_static->label_index = label_index;
718e3744 5271
e2a86ad9 5272 if (rmap) {
0a22ddfb
QY
5273 XFREE(MTYPE_ROUTE_MAP_NAME,
5274 bgp_static->rmap.name);
b4897fa5 5275 route_map_counter_decrement(
5276 bgp_static->rmap.map);
e2a86ad9
DS
5277 bgp_static->rmap.name =
5278 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5279 bgp_static->rmap.map =
5280 route_map_lookup_by_name(rmap);
b4897fa5 5281 route_map_counter_increment(
5282 bgp_static->rmap.map);
e2a86ad9 5283 }
5a8ba9fc 5284 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5285 }
d62a17ae 5286
e2a86ad9
DS
5287 bgp_static->valid = 1;
5288 if (need_update)
5289 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5290
e2a86ad9
DS
5291 if (!bgp_static->backdoor)
5292 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5293 }
d62a17ae 5294
5295 return CMD_SUCCESS;
5296}
5297
5298void bgp_static_add(struct bgp *bgp)
5299{
5300 afi_t afi;
5301 safi_t safi;
5302 struct bgp_node *rn;
5303 struct bgp_node *rm;
5304 struct bgp_table *table;
5305 struct bgp_static *bgp_static;
5306
05c7a1cc
QY
5307 FOREACH_AFI_SAFI (afi, safi)
5308 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5309 rn = bgp_route_next(rn)) {
67009e22 5310 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5311 continue;
ea47320b 5312
05c7a1cc
QY
5313 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5314 || (safi == SAFI_EVPN)) {
67009e22 5315 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5316
5317 for (rm = bgp_table_top(table); rm;
5318 rm = bgp_route_next(rm)) {
a78beeb5 5319 bgp_static =
5a8ba9fc
DS
5320 bgp_node_get_bgp_static_info(
5321 rm);
05c7a1cc
QY
5322 bgp_static_update_safi(bgp, &rm->p,
5323 bgp_static, afi,
5324 safi);
d62a17ae 5325 }
05c7a1cc 5326 } else {
5a8ba9fc
DS
5327 bgp_static_update(
5328 bgp, &rn->p,
5329 bgp_node_get_bgp_static_info(rn), afi,
5330 safi);
ea47320b 5331 }
05c7a1cc 5332 }
6aeb9e78
DS
5333}
5334
718e3744 5335/* Called from bgp_delete(). Delete all static routes from the BGP
5336 instance. */
d62a17ae 5337void bgp_static_delete(struct bgp *bgp)
5338{
5339 afi_t afi;
5340 safi_t safi;
5341 struct bgp_node *rn;
5342 struct bgp_node *rm;
5343 struct bgp_table *table;
5344 struct bgp_static *bgp_static;
5345
05c7a1cc
QY
5346 FOREACH_AFI_SAFI (afi, safi)
5347 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5348 rn = bgp_route_next(rn)) {
67009e22 5349 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5350 continue;
ea47320b 5351
05c7a1cc
QY
5352 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5353 || (safi == SAFI_EVPN)) {
67009e22 5354 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5355
5356 for (rm = bgp_table_top(table); rm;
5357 rm = bgp_route_next(rm)) {
a78beeb5 5358 bgp_static =
5a8ba9fc
DS
5359 bgp_node_get_bgp_static_info(
5360 rm);
c7d14ba6
PG
5361 if (!bgp_static)
5362 continue;
5363
05c7a1cc
QY
5364 bgp_static_withdraw_safi(
5365 bgp, &rm->p, AFI_IP, safi,
5366 (struct prefix_rd *)&rn->p);
ea47320b 5367 bgp_static_free(bgp_static);
5a8ba9fc 5368 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5369 bgp_unlock_node(rn);
d62a17ae 5370 }
05c7a1cc 5371 } else {
5a8ba9fc 5372 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5373 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5374 bgp_static_free(bgp_static);
5a8ba9fc 5375 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5376 bgp_unlock_node(rn);
ea47320b 5377 }
05c7a1cc 5378 }
d62a17ae 5379}
5380
5381void bgp_static_redo_import_check(struct bgp *bgp)
5382{
5383 afi_t afi;
5384 safi_t safi;
5385 struct bgp_node *rn;
5386 struct bgp_node *rm;
5387 struct bgp_table *table;
5388 struct bgp_static *bgp_static;
5389
5390 /* Use this flag to force reprocessing of the route */
5391 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5392 FOREACH_AFI_SAFI (afi, safi) {
5393 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5394 rn = bgp_route_next(rn)) {
67009e22 5395 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5396 continue;
ea47320b 5397
05c7a1cc
QY
5398 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5399 || (safi == SAFI_EVPN)) {
67009e22 5400 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5401
5402 for (rm = bgp_table_top(table); rm;
5403 rm = bgp_route_next(rm)) {
a78beeb5 5404 bgp_static =
5a8ba9fc
DS
5405 bgp_node_get_bgp_static_info(
5406 rm);
05c7a1cc
QY
5407 bgp_static_update_safi(bgp, &rm->p,
5408 bgp_static, afi,
5409 safi);
d62a17ae 5410 }
05c7a1cc 5411 } else {
5a8ba9fc 5412 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5413 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5414 safi);
ea47320b 5415 }
05c7a1cc
QY
5416 }
5417 }
d62a17ae 5418 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5419}
5420
5421static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5422 safi_t safi)
5423{
5424 struct bgp_table *table;
5425 struct bgp_node *rn;
40381db7 5426 struct bgp_path_info *pi;
d62a17ae 5427
dfb6fd1d
NT
5428 /* Do not install the aggregate route if BGP is in the
5429 * process of termination.
5430 */
5431 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5432 (bgp->peer_self == NULL))
5433 return;
5434
d62a17ae 5435 table = bgp->rib[afi][safi];
5436 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5437 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5438 if (pi->peer == bgp->peer_self
5439 && ((pi->type == ZEBRA_ROUTE_BGP
5440 && pi->sub_type == BGP_ROUTE_STATIC)
5441 || (pi->type != ZEBRA_ROUTE_BGP
5442 && pi->sub_type
d62a17ae 5443 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5444 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5445 safi);
40381db7
DS
5446 bgp_unlink_nexthop(pi);
5447 bgp_path_info_delete(rn, pi);
d62a17ae 5448 bgp_process(bgp, rn, afi, safi);
5449 }
5450 }
5451 }
ad4cbda1 5452}
5453
5454/*
5455 * Purge all networks and redistributed routes from routing table.
5456 * Invoked upon the instance going down.
5457 */
d62a17ae 5458void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5459{
d62a17ae 5460 afi_t afi;
5461 safi_t safi;
ad4cbda1 5462
05c7a1cc
QY
5463 FOREACH_AFI_SAFI (afi, safi)
5464 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5465}
5466
137446f9
LB
5467/*
5468 * gpz 110624
5469 * Currently this is used to set static routes for VPN and ENCAP.
5470 * I think it can probably be factored with bgp_static_set.
5471 */
d62a17ae 5472int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5473 const char *ip_str, const char *rd_str,
5474 const char *label_str, const char *rmap_str,
5475 int evpn_type, const char *esi, const char *gwip,
5476 const char *ethtag, const char *routermac)
5477{
5478 VTY_DECLVAR_CONTEXT(bgp, bgp);
5479 int ret;
5480 struct prefix p;
5481 struct prefix_rd prd;
5482 struct bgp_node *prn;
5483 struct bgp_node *rn;
5484 struct bgp_table *table;
5485 struct bgp_static *bgp_static;
5486 mpls_label_t label = MPLS_INVALID_LABEL;
5487 struct prefix gw_ip;
5488
5489 /* validate ip prefix */
5490 ret = str2prefix(ip_str, &p);
5491 if (!ret) {
5492 vty_out(vty, "%% Malformed prefix\n");
5493 return CMD_WARNING_CONFIG_FAILED;
5494 }
5495 apply_mask(&p);
5496 if ((afi == AFI_L2VPN)
5497 && (bgp_build_evpn_prefix(evpn_type,
5498 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5499 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5500 return CMD_WARNING_CONFIG_FAILED;
5501 }
718e3744 5502
d62a17ae 5503 ret = str2prefix_rd(rd_str, &prd);
5504 if (!ret) {
5505 vty_out(vty, "%% Malformed rd\n");
5506 return CMD_WARNING_CONFIG_FAILED;
5507 }
718e3744 5508
d62a17ae 5509 if (label_str) {
5510 unsigned long label_val;
5511 label_val = strtoul(label_str, NULL, 10);
5512 encode_label(label_val, &label);
5513 }
9bedbb1e 5514
d62a17ae 5515 if (safi == SAFI_EVPN) {
5516 if (esi && str2esi(esi, NULL) == 0) {
5517 vty_out(vty, "%% Malformed ESI\n");
5518 return CMD_WARNING_CONFIG_FAILED;
5519 }
5520 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5521 vty_out(vty, "%% Malformed Router MAC\n");
5522 return CMD_WARNING_CONFIG_FAILED;
5523 }
5524 if (gwip) {
5525 memset(&gw_ip, 0, sizeof(struct prefix));
5526 ret = str2prefix(gwip, &gw_ip);
5527 if (!ret) {
5528 vty_out(vty, "%% Malformed GatewayIp\n");
5529 return CMD_WARNING_CONFIG_FAILED;
5530 }
5531 if ((gw_ip.family == AF_INET
3714a385 5532 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5533 (struct prefix_evpn *)&p))
5534 || (gw_ip.family == AF_INET6
3714a385 5535 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5536 (struct prefix_evpn *)&p))) {
5537 vty_out(vty,
5538 "%% GatewayIp family differs with IP prefix\n");
5539 return CMD_WARNING_CONFIG_FAILED;
5540 }
5541 }
5542 }
5543 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5544 if (!bgp_node_has_bgp_path_info_data(prn))
5545 bgp_node_set_bgp_table_info(prn,
5546 bgp_table_init(bgp, afi, safi));
67009e22 5547 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5548
5549 rn = bgp_node_get(table, &p);
5550
67009e22 5551 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5552 vty_out(vty, "%% Same network configuration exists\n");
5553 bgp_unlock_node(rn);
5554 } else {
5555 /* New configuration. */
5556 bgp_static = bgp_static_new();
5557 bgp_static->backdoor = 0;
5558 bgp_static->valid = 0;
5559 bgp_static->igpmetric = 0;
5560 bgp_static->igpnexthop.s_addr = 0;
5561 bgp_static->label = label;
5562 bgp_static->prd = prd;
5563
5564 if (rmap_str) {
0a22ddfb 5565 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5566 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5567 bgp_static->rmap.name =
5568 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5569 bgp_static->rmap.map =
5570 route_map_lookup_by_name(rmap_str);
b4897fa5 5571 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5572 }
718e3744 5573
d62a17ae 5574 if (safi == SAFI_EVPN) {
5575 if (esi) {
5576 bgp_static->eth_s_id =
5577 XCALLOC(MTYPE_ATTR,
5578 sizeof(struct eth_segment_id));
5579 str2esi(esi, bgp_static->eth_s_id);
5580 }
5581 if (routermac) {
5582 bgp_static->router_mac =
28328ea9 5583 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5584 (void)prefix_str2mac(routermac,
5585 bgp_static->router_mac);
d62a17ae 5586 }
5587 if (gwip)
5588 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5589 }
5a8ba9fc 5590 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5591
d62a17ae 5592 bgp_static->valid = 1;
5593 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5594 }
718e3744 5595
d62a17ae 5596 return CMD_SUCCESS;
718e3744 5597}
5598
5599/* Configure static BGP network. */
d62a17ae 5600int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5601 const char *ip_str, const char *rd_str,
5602 const char *label_str, int evpn_type, const char *esi,
5603 const char *gwip, const char *ethtag)
5604{
5605 VTY_DECLVAR_CONTEXT(bgp, bgp);
5606 int ret;
5607 struct prefix p;
5608 struct prefix_rd prd;
5609 struct bgp_node *prn;
5610 struct bgp_node *rn;
5611 struct bgp_table *table;
5612 struct bgp_static *bgp_static;
5613 mpls_label_t label = MPLS_INVALID_LABEL;
5614
5615 /* Convert IP prefix string to struct prefix. */
5616 ret = str2prefix(ip_str, &p);
5617 if (!ret) {
5618 vty_out(vty, "%% Malformed prefix\n");
5619 return CMD_WARNING_CONFIG_FAILED;
5620 }
5621 apply_mask(&p);
5622 if ((afi == AFI_L2VPN)
5623 && (bgp_build_evpn_prefix(evpn_type,
5624 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5625 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5626 return CMD_WARNING_CONFIG_FAILED;
5627 }
5628 ret = str2prefix_rd(rd_str, &prd);
5629 if (!ret) {
5630 vty_out(vty, "%% Malformed rd\n");
5631 return CMD_WARNING_CONFIG_FAILED;
5632 }
718e3744 5633
d62a17ae 5634 if (label_str) {
5635 unsigned long label_val;
5636 label_val = strtoul(label_str, NULL, 10);
5637 encode_label(label_val, &label);
5638 }
718e3744 5639
d62a17ae 5640 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5641 if (!bgp_node_has_bgp_path_info_data(prn))
5642 bgp_node_set_bgp_table_info(prn,
5643 bgp_table_init(bgp, afi, safi));
d62a17ae 5644 else
5645 bgp_unlock_node(prn);
67009e22 5646 table = bgp_node_get_bgp_table_info(prn);
718e3744 5647
d62a17ae 5648 rn = bgp_node_lookup(table, &p);
6b0655a2 5649
d62a17ae 5650 if (rn) {
5651 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5652
5a8ba9fc 5653 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5654 bgp_static_free(bgp_static);
5a8ba9fc 5655 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5656 bgp_unlock_node(rn);
5657 bgp_unlock_node(rn);
5658 } else
5659 vty_out(vty, "%% Can't find the route\n");
5660
5661 return CMD_SUCCESS;
5662}
5663
5664static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5665 const char *rmap_name)
5666{
5667 VTY_DECLVAR_CONTEXT(bgp, bgp);
5668 struct bgp_rmap *rmap;
5669
5670 rmap = &bgp->table_map[afi][safi];
5671 if (rmap_name) {
0a22ddfb 5672 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5673 route_map_counter_decrement(rmap->map);
d62a17ae 5674 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5675 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5676 route_map_counter_increment(rmap->map);
d62a17ae 5677 } else {
0a22ddfb 5678 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5679 route_map_counter_decrement(rmap->map);
d62a17ae 5680 rmap->name = NULL;
5681 rmap->map = NULL;
5682 }
73ac8160 5683
d62a17ae 5684 if (bgp_fibupd_safi(safi))
5685 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5686
d62a17ae 5687 return CMD_SUCCESS;
73ac8160
DS
5688}
5689
d62a17ae 5690static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5691 const char *rmap_name)
73ac8160 5692{
d62a17ae 5693 VTY_DECLVAR_CONTEXT(bgp, bgp);
5694 struct bgp_rmap *rmap;
73ac8160 5695
d62a17ae 5696 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5697 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5698 route_map_counter_decrement(rmap->map);
d62a17ae 5699 rmap->name = NULL;
5700 rmap->map = NULL;
73ac8160 5701
d62a17ae 5702 if (bgp_fibupd_safi(safi))
5703 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5704
d62a17ae 5705 return CMD_SUCCESS;
73ac8160
DS
5706}
5707
2b791107 5708void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5709 safi_t safi)
73ac8160 5710{
d62a17ae 5711 if (bgp->table_map[afi][safi].name) {
d62a17ae 5712 vty_out(vty, " table-map %s\n",
5713 bgp->table_map[afi][safi].name);
5714 }
73ac8160
DS
5715}
5716
73ac8160
DS
5717DEFUN (bgp_table_map,
5718 bgp_table_map_cmd,
5719 "table-map WORD",
5720 "BGP table to RIB route download filter\n"
5721 "Name of the route map\n")
5722{
d62a17ae 5723 int idx_word = 1;
5724 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5725 argv[idx_word]->arg);
73ac8160
DS
5726}
5727DEFUN (no_bgp_table_map,
5728 no_bgp_table_map_cmd,
5729 "no table-map WORD",
3a2d747c 5730 NO_STR
73ac8160
DS
5731 "BGP table to RIB route download filter\n"
5732 "Name of the route map\n")
5733{
d62a17ae 5734 int idx_word = 2;
5735 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5736 argv[idx_word]->arg);
73ac8160
DS
5737}
5738
e2a86ad9
DS
5739DEFPY(bgp_network,
5740 bgp_network_cmd,
5741 "[no] network \
5742 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5743 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5744 backdoor$backdoor}]",
5745 NO_STR
5746 "Specify a network to announce via BGP\n"
5747 "IPv4 prefix\n"
5748 "Network number\n"
5749 "Network mask\n"
5750 "Network mask\n"
5751 "Route-map to modify the attributes\n"
5752 "Name of the route map\n"
5753 "Label index to associate with the prefix\n"
5754 "Label index value\n"
5755 "Specify a BGP backdoor route\n")
5756{
5757 char addr_prefix_str[BUFSIZ];
5758
5759 if (address_str) {
5760 int ret;
718e3744 5761
e2a86ad9
DS
5762 ret = netmask_str2prefix_str(address_str, netmask_str,
5763 addr_prefix_str);
5764 if (!ret) {
5765 vty_out(vty, "%% Inconsistent address and mask\n");
5766 return CMD_WARNING_CONFIG_FAILED;
5767 }
d62a17ae 5768 }
718e3744 5769
a4d82a8a
PZ
5770 return bgp_static_set(
5771 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5772 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5773 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5774}
5775
e2a86ad9
DS
5776DEFPY(ipv6_bgp_network,
5777 ipv6_bgp_network_cmd,
5778 "[no] network X:X::X:X/M$prefix \
5779 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5780 NO_STR
5781 "Specify a network to announce via BGP\n"
5782 "IPv6 prefix\n"
5783 "Route-map to modify the attributes\n"
5784 "Name of the route map\n"
5785 "Label index to associate with the prefix\n"
5786 "Label index value\n")
718e3744 5787{
a4d82a8a
PZ
5788 return bgp_static_set(
5789 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5790 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5791}
5792
d62a17ae 5793static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5794{
d62a17ae 5795 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5796}
5797
d62a17ae 5798static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5799{
20894f50
DA
5800 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
5801 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 5802 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5803}
718e3744 5804
40381db7 5805static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5806 struct aspath *aspath,
3da2cc32 5807 struct community *comm,
dd18c5a9
DS
5808 struct ecommunity *ecomm,
5809 struct lcommunity *lcomm)
eaaf8adb
DS
5810{
5811 static struct aspath *ae = NULL;
5812
5813 if (!ae)
5814 ae = aspath_empty();
5815
40381db7 5816 if (!pi)
eaaf8adb
DS
5817 return 0;
5818
40381db7 5819 if (origin != pi->attr->origin)
eaaf8adb
DS
5820 return 0;
5821
40381db7 5822 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5823 return 0;
5824
40381db7 5825 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5826 return 0;
5827
3da2cc32 5828 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5829 return 0;
5830
dd18c5a9
DS
5831 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5832 return 0;
5833
40381db7 5834 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5835 return 0;
5836
eaaf8adb
DS
5837 return 1;
5838}
5839
c701010e
DS
5840static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5841 struct prefix *p, uint8_t origin,
5842 struct aspath *aspath,
5843 struct community *community,
3da2cc32 5844 struct ecommunity *ecommunity,
dd18c5a9 5845 struct lcommunity *lcommunity,
c701010e
DS
5846 uint8_t atomic_aggregate,
5847 struct bgp_aggregate *aggregate)
5848{
5849 struct bgp_node *rn;
5850 struct bgp_table *table;
6f94b685 5851 struct bgp_path_info *pi, *orig, *new;
20894f50 5852 struct attr *attr;
c701010e
DS
5853
5854 table = bgp->rib[afi][safi];
5855
5856 rn = bgp_node_get(table, p);
eaaf8adb 5857
6f94b685 5858 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5859 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5860 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5861 break;
5862
c701010e 5863 if (aggregate->count > 0) {
eaaf8adb
DS
5864 /*
5865 * If the aggregate information has not changed
5866 * no need to re-install it again.
5867 */
6f94b685 5868 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5869 ecommunity, lcommunity)) {
eaaf8adb
DS
5870 bgp_unlock_node(rn);
5871
5872 if (aspath)
5873 aspath_free(aspath);
5874 if (community)
3c1f53de 5875 community_free(&community);
3da2cc32
DS
5876 if (ecommunity)
5877 ecommunity_free(&ecommunity);
dd18c5a9
DS
5878 if (lcommunity)
5879 lcommunity_free(&lcommunity);
eaaf8adb
DS
5880
5881 return;
5882 }
5883
5884 /*
5885 * Mark the old as unusable
5886 */
40381db7
DS
5887 if (pi)
5888 bgp_path_info_delete(rn, pi);
eaaf8adb 5889
20894f50
DA
5890 attr = bgp_attr_aggregate_intern(
5891 bgp, origin, aspath, community, ecommunity, lcommunity,
5892 aggregate, atomic_aggregate, p);
5893
5894 if (!attr) {
5895 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
5896 return;
5897 }
5898
3da2cc32 5899 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
5900 bgp->peer_self, attr, rn);
5901
1defdda8 5902 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5903
18ee8310 5904 bgp_path_info_add(rn, new);
c701010e
DS
5905 bgp_process(bgp, rn, afi, safi);
5906 } else {
6f94b685 5907 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5908 if (pi->peer == bgp->peer_self
5909 && pi->type == ZEBRA_ROUTE_BGP
5910 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5911 break;
5912
5913 /* Withdraw static BGP route from routing table. */
40381db7
DS
5914 if (pi) {
5915 bgp_path_info_delete(rn, pi);
c701010e
DS
5916 bgp_process(bgp, rn, afi, safi);
5917 }
5918 }
5919
5920 bgp_unlock_node(rn);
5921}
5922
b5d58c32 5923/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 5924void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 5925 afi_t afi, safi_t safi,
d62a17ae 5926 struct bgp_aggregate *aggregate)
5927{
5928 struct bgp_table *table;
5929 struct bgp_node *top;
5930 struct bgp_node *rn;
d7c0a89a 5931 uint8_t origin;
d62a17ae 5932 struct aspath *aspath = NULL;
d62a17ae 5933 struct community *community = NULL;
3da2cc32 5934 struct ecommunity *ecommunity = NULL;
dd18c5a9 5935 struct lcommunity *lcommunity = NULL;
40381db7 5936 struct bgp_path_info *pi;
d62a17ae 5937 unsigned long match = 0;
d7c0a89a 5938 uint8_t atomic_aggregate = 0;
d62a17ae 5939
9f822fa2
S
5940 /* If the bgp instance is being deleted or self peer is deleted
5941 * then do not create aggregate route
5942 */
5943 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5944 (bgp->peer_self == NULL))
5945 return;
5946
d62a17ae 5947 /* ORIGIN attribute: If at least one route among routes that are
5948 aggregated has ORIGIN with the value INCOMPLETE, then the
5949 aggregated route must have the ORIGIN attribute with the value
5950 INCOMPLETE. Otherwise, if at least one route among routes that
5951 are aggregated has ORIGIN with the value EGP, then the aggregated
5952 route must have the origin attribute with the value EGP. In all
5953 other case the value of the ORIGIN attribute of the aggregated
5954 route is INTERNAL. */
5955 origin = BGP_ORIGIN_IGP;
718e3744 5956
d62a17ae 5957 table = bgp->rib[afi][safi];
718e3744 5958
d62a17ae 5959 top = bgp_node_get(table, p);
5960 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5961 rn = bgp_route_next_until(rn, top)) {
5962 if (rn->p.prefixlen <= p->prefixlen)
5963 continue;
d62a17ae 5964
c2ff8b3e 5965 match = 0;
d62a17ae 5966
6f94b685 5967 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5968 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5969 continue;
718e3744 5970
40381db7 5971 if (pi->attr->flag
c2ff8b3e
DS
5972 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5973 atomic_aggregate = 1;
d62a17ae 5974
40381db7 5975 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5976 continue;
d62a17ae 5977
f273fef1
DS
5978 /*
5979 * summary-only aggregate route suppress
5980 * aggregated route announcements.
5981 */
c2ff8b3e 5982 if (aggregate->summary_only) {
40381db7
DS
5983 (bgp_path_info_extra_get(pi))->suppress++;
5984 bgp_path_info_set_flag(rn, pi,
18ee8310 5985 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5986 match++;
d62a17ae 5987 }
c2ff8b3e
DS
5988
5989 aggregate->count++;
5990
f273fef1
DS
5991 /*
5992 * If at least one route among routes that are
5993 * aggregated has ORIGIN with the value INCOMPLETE,
5994 * then the aggregated route MUST have the ORIGIN
5995 * attribute with the value INCOMPLETE. Otherwise, if
5996 * at least one route among routes that are aggregated
5997 * has ORIGIN with the value EGP, then the aggregated
5998 * route MUST have the ORIGIN attribute with the value
5999 * EGP.
6000 */
fc968841
NT
6001 switch (pi->attr->origin) {
6002 case BGP_ORIGIN_INCOMPLETE:
6003 aggregate->incomplete_origin_count++;
6004 break;
6005 case BGP_ORIGIN_EGP:
6006 aggregate->egp_origin_count++;
6007 break;
6008 default:
6009 /*Do nothing.
6010 */
6011 break;
6012 }
c2ff8b3e
DS
6013
6014 if (!aggregate->as_set)
6015 continue;
6016
f273fef1
DS
6017 /*
6018 * as-set aggregate route generate origin, as path,
6019 * and community aggregation.
6020 */
fc968841
NT
6021 /* Compute aggregate route's as-path.
6022 */
ef51a7d8 6023 bgp_compute_aggregate_aspath_hash(aggregate,
6024 pi->attr->aspath);
c2ff8b3e 6025
fc968841
NT
6026 /* Compute aggregate route's community.
6027 */
6028 if (pi->attr->community)
21fec674 6029 bgp_compute_aggregate_community_hash(
fc968841
NT
6030 aggregate,
6031 pi->attr->community);
dd18c5a9 6032
fc968841
NT
6033 /* Compute aggregate route's extended community.
6034 */
6035 if (pi->attr->ecommunity)
4edd83f9 6036 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6037 aggregate,
6038 pi->attr->ecommunity);
6039
6040 /* Compute aggregate route's large community.
6041 */
6042 if (pi->attr->lcommunity)
f1eb1f05 6043 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6044 aggregate,
6045 pi->attr->lcommunity);
d62a17ae 6046 }
c2ff8b3e
DS
6047 if (match)
6048 bgp_process(bgp, rn, afi, safi);
6049 }
21fec674 6050 if (aggregate->as_set) {
ef51a7d8 6051 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6052 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6053 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6054 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6055 }
6056
f1eb1f05 6057
d62a17ae 6058 bgp_unlock_node(top);
718e3744 6059
718e3744 6060
fc968841
NT
6061 if (aggregate->incomplete_origin_count > 0)
6062 origin = BGP_ORIGIN_INCOMPLETE;
6063 else if (aggregate->egp_origin_count > 0)
6064 origin = BGP_ORIGIN_EGP;
d62a17ae 6065
fc968841
NT
6066 if (aggregate->as_set) {
6067 if (aggregate->aspath)
6068 /* Retrieve aggregate route's as-path.
6069 */
6070 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6071
fc968841
NT
6072 if (aggregate->community)
6073 /* Retrieve aggregate route's community.
6074 */
6075 community = community_dup(aggregate->community);
3da2cc32 6076
fc968841
NT
6077 if (aggregate->ecommunity)
6078 /* Retrieve aggregate route's ecommunity.
6079 */
6080 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6081
fc968841
NT
6082 if (aggregate->lcommunity)
6083 /* Retrieve aggregate route's lcommunity.
6084 */
6085 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6086 }
718e3744 6087
c701010e 6088 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6089 ecommunity, lcommunity, atomic_aggregate,
6090 aggregate);
718e3744 6091}
6092
20894f50 6093void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6094 safi_t safi, struct bgp_aggregate *aggregate)
6095{
6096 struct bgp_table *table;
6097 struct bgp_node *top;
6098 struct bgp_node *rn;
40381db7 6099 struct bgp_path_info *pi;
3b7db173
DS
6100 unsigned long match;
6101
6102 table = bgp->rib[afi][safi];
6103
6104 /* If routes exists below this node, generate aggregate routes. */
6105 top = bgp_node_get(table, p);
6106 for (rn = bgp_node_get(table, p); rn;
6107 rn = bgp_route_next_until(rn, top)) {
6108 if (rn->p.prefixlen <= p->prefixlen)
6109 continue;
6110 match = 0;
6111
6f94b685 6112 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6113 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6114 continue;
6115
40381db7 6116 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6117 continue;
6118
40381db7
DS
6119 if (aggregate->summary_only && pi->extra) {
6120 pi->extra->suppress--;
3b7db173 6121
40381db7 6122 if (pi->extra->suppress == 0) {
18ee8310 6123 bgp_path_info_set_flag(
40381db7 6124 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6125 match++;
6126 }
6127 }
6128 aggregate->count--;
fc968841
NT
6129
6130 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6131 aggregate->incomplete_origin_count--;
6132 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6133 aggregate->egp_origin_count--;
6134
6135 if (aggregate->as_set) {
6136 /* Remove as-path from aggregate.
6137 */
ef51a7d8 6138 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6139 aggregate,
6140 pi->attr->aspath);
6141
6142 if (pi->attr->community)
6143 /* Remove community from aggregate.
6144 */
21fec674 6145 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6146 aggregate,
6147 pi->attr->community);
6148
6149 if (pi->attr->ecommunity)
6150 /* Remove ecommunity from aggregate.
6151 */
4edd83f9 6152 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6153 aggregate,
6154 pi->attr->ecommunity);
6155
6156 if (pi->attr->lcommunity)
6157 /* Remove lcommunity from aggregate.
6158 */
f1eb1f05 6159 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6160 aggregate,
6161 pi->attr->lcommunity);
6162 }
6163
3b7db173
DS
6164 }
6165
6166 /* If this node was suppressed, process the change. */
6167 if (match)
6168 bgp_process(bgp, rn, afi, safi);
6169 }
f1eb1f05 6170 if (aggregate->as_set) {
ef51a7d8 6171 aspath_free(aggregate->aspath);
6172 aggregate->aspath = NULL;
21fec674 6173 if (aggregate->community)
6174 community_free(&aggregate->community);
4edd83f9 6175 if (aggregate->ecommunity)
6176 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6177 if (aggregate->lcommunity)
6178 lcommunity_free(&aggregate->lcommunity);
6179 }
6180
3b7db173
DS
6181 bgp_unlock_node(top);
6182}
718e3744 6183
fc968841
NT
6184static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6185 struct bgp_path_info *pinew, afi_t afi,
6186 safi_t safi,
6187 struct bgp_aggregate *aggregate)
6188{
6189 uint8_t origin;
6190 struct aspath *aspath = NULL;
6191 uint8_t atomic_aggregate = 0;
6192 struct community *community = NULL;
6193 struct ecommunity *ecommunity = NULL;
6194 struct lcommunity *lcommunity = NULL;
6195
6196 /* ORIGIN attribute: If at least one route among routes that are
6197 * aggregated has ORIGIN with the value INCOMPLETE, then the
6198 * aggregated route must have the ORIGIN attribute with the value
6199 * INCOMPLETE. Otherwise, if at least one route among routes that
6200 * are aggregated has ORIGIN with the value EGP, then the aggregated
6201 * route must have the origin attribute with the value EGP. In all
6202 * other case the value of the ORIGIN attribute of the aggregated
6203 * route is INTERNAL.
6204 */
6205 origin = BGP_ORIGIN_IGP;
6206
6207 aggregate->count++;
6208
6209 if (aggregate->summary_only)
6210 (bgp_path_info_extra_get(pinew))->suppress++;
6211
6212 switch (pinew->attr->origin) {
6213 case BGP_ORIGIN_INCOMPLETE:
6214 aggregate->incomplete_origin_count++;
6215 break;
6216 case BGP_ORIGIN_EGP:
6217 aggregate->egp_origin_count++;
6218 break;
6219 default:
6220 /* Do nothing.
6221 */
6222 break;
6223 }
6224
6225 if (aggregate->incomplete_origin_count > 0)
6226 origin = BGP_ORIGIN_INCOMPLETE;
6227 else if (aggregate->egp_origin_count > 0)
6228 origin = BGP_ORIGIN_EGP;
6229
6230 if (aggregate->as_set) {
6231 /* Compute aggregate route's as-path.
6232 */
6233 bgp_compute_aggregate_aspath(aggregate,
6234 pinew->attr->aspath);
6235
6236 /* Compute aggregate route's community.
6237 */
6238 if (pinew->attr->community)
6239 bgp_compute_aggregate_community(
6240 aggregate,
6241 pinew->attr->community);
6242
6243 /* Compute aggregate route's extended community.
6244 */
6245 if (pinew->attr->ecommunity)
6246 bgp_compute_aggregate_ecommunity(
6247 aggregate,
6248 pinew->attr->ecommunity);
6249
6250 /* Compute aggregate route's large community.
6251 */
6252 if (pinew->attr->lcommunity)
6253 bgp_compute_aggregate_lcommunity(
6254 aggregate,
6255 pinew->attr->lcommunity);
6256
6257 /* Retrieve aggregate route's as-path.
6258 */
6259 if (aggregate->aspath)
6260 aspath = aspath_dup(aggregate->aspath);
6261
6262 /* Retrieve aggregate route's community.
6263 */
6264 if (aggregate->community)
6265 community = community_dup(aggregate->community);
6266
6267 /* Retrieve aggregate route's ecommunity.
6268 */
6269 if (aggregate->ecommunity)
6270 ecommunity = ecommunity_dup(aggregate->ecommunity);
6271
6272 /* Retrieve aggregate route's lcommunity.
6273 */
6274 if (aggregate->lcommunity)
6275 lcommunity = lcommunity_dup(aggregate->lcommunity);
6276 }
6277
6278 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6279 aspath, community, ecommunity,
6280 lcommunity, atomic_aggregate, aggregate);
6281}
6282
6283static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6284 safi_t safi,
6285 struct bgp_path_info *pi,
6286 struct bgp_aggregate *aggregate,
6287 struct prefix *aggr_p)
6288{
6289 uint8_t origin;
6290 struct aspath *aspath = NULL;
6291 uint8_t atomic_aggregate = 0;
6292 struct community *community = NULL;
6293 struct ecommunity *ecommunity = NULL;
6294 struct lcommunity *lcommunity = NULL;
6295 unsigned long match = 0;
6296
6297 if (BGP_PATH_HOLDDOWN(pi))
6298 return;
6299
6300 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6301 return;
6302
6303 if (aggregate->summary_only
6304 && pi->extra
6305 && pi->extra->suppress > 0) {
6306 pi->extra->suppress--;
6307
6308 if (pi->extra->suppress == 0) {
6309 bgp_path_info_set_flag(pi->net, pi,
6310 BGP_PATH_ATTR_CHANGED);
6311 match++;
6312 }
6313 }
6314
6315 if (aggregate->count > 0)
6316 aggregate->count--;
6317
6318 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6319 aggregate->incomplete_origin_count--;
6320 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6321 aggregate->egp_origin_count--;
6322
6323 if (aggregate->as_set) {
6324 /* Remove as-path from aggregate.
6325 */
6326 bgp_remove_aspath_from_aggregate(aggregate,
6327 pi->attr->aspath);
6328
6329 if (pi->attr->community)
6330 /* Remove community from aggregate.
6331 */
6332 bgp_remove_community_from_aggregate(
6333 aggregate,
6334 pi->attr->community);
6335
6336 if (pi->attr->ecommunity)
6337 /* Remove ecommunity from aggregate.
6338 */
6339 bgp_remove_ecommunity_from_aggregate(
6340 aggregate,
6341 pi->attr->ecommunity);
6342
6343 if (pi->attr->lcommunity)
6344 /* Remove lcommunity from aggregate.
6345 */
6346 bgp_remove_lcommunity_from_aggregate(
6347 aggregate,
6348 pi->attr->lcommunity);
6349 }
6350
6351 /* If this node was suppressed, process the change. */
6352 if (match)
6353 bgp_process(bgp, pi->net, afi, safi);
6354
6355 origin = BGP_ORIGIN_IGP;
6356 if (aggregate->incomplete_origin_count > 0)
6357 origin = BGP_ORIGIN_INCOMPLETE;
6358 else if (aggregate->egp_origin_count > 0)
6359 origin = BGP_ORIGIN_EGP;
6360
6361 if (aggregate->as_set) {
6362 /* Retrieve aggregate route's as-path.
6363 */
6364 if (aggregate->aspath)
6365 aspath = aspath_dup(aggregate->aspath);
6366
6367 /* Retrieve aggregate route's community.
6368 */
6369 if (aggregate->community)
6370 community = community_dup(aggregate->community);
6371
6372 /* Retrieve aggregate route's ecommunity.
6373 */
6374 if (aggregate->ecommunity)
6375 ecommunity = ecommunity_dup(aggregate->ecommunity);
6376
6377 /* Retrieve aggregate route's lcommunity.
6378 */
6379 if (aggregate->lcommunity)
6380 lcommunity = lcommunity_dup(aggregate->lcommunity);
6381 }
6382
6383 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6384 aspath, community, ecommunity,
6385 lcommunity, atomic_aggregate, aggregate);
6386}
6387
d62a17ae 6388void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6389 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6390{
d62a17ae 6391 struct bgp_node *child;
6392 struct bgp_node *rn;
6393 struct bgp_aggregate *aggregate;
6394 struct bgp_table *table;
718e3744 6395
d62a17ae 6396 table = bgp->aggregate[afi][safi];
f018db83 6397
d62a17ae 6398 /* No aggregates configured. */
6399 if (bgp_table_top_nolock(table) == NULL)
6400 return;
f018db83 6401
d62a17ae 6402 if (p->prefixlen == 0)
6403 return;
718e3744 6404
40381db7 6405 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6406 return;
718e3744 6407
d62a17ae 6408 child = bgp_node_get(table, p);
718e3744 6409
d62a17ae 6410 /* Aggregate address configuration check. */
b1e62edd 6411 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6412 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6413 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6414 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6415 safi, aggregate);
d62a17ae 6416 }
b1e62edd 6417 }
d62a17ae 6418 bgp_unlock_node(child);
718e3744 6419}
6420
d62a17ae 6421void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6422 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6423{
d62a17ae 6424 struct bgp_node *child;
6425 struct bgp_node *rn;
6426 struct bgp_aggregate *aggregate;
6427 struct bgp_table *table;
718e3744 6428
d62a17ae 6429 table = bgp->aggregate[afi][safi];
718e3744 6430
d62a17ae 6431 /* No aggregates configured. */
6432 if (bgp_table_top_nolock(table) == NULL)
6433 return;
718e3744 6434
d62a17ae 6435 if (p->prefixlen == 0)
6436 return;
718e3744 6437
d62a17ae 6438 child = bgp_node_get(table, p);
718e3744 6439
d62a17ae 6440 /* Aggregate address configuration check. */
b1e62edd 6441 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6442 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6443 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6444 bgp_remove_route_from_aggregate(bgp, afi, safi,
6445 del, aggregate, &rn->p);
d62a17ae 6446 }
b1e62edd 6447 }
d62a17ae 6448 bgp_unlock_node(child);
6449}
718e3744 6450
718e3744 6451/* Aggregate route attribute. */
6452#define AGGREGATE_SUMMARY_ONLY 1
6453#define AGGREGATE_AS_SET 1
fb29348a 6454#define AGGREGATE_AS_UNSET 0
718e3744 6455
d62a17ae 6456static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6457 afi_t afi, safi_t safi)
718e3744 6458{
d62a17ae 6459 VTY_DECLVAR_CONTEXT(bgp, bgp);
6460 int ret;
6461 struct prefix p;
6462 struct bgp_node *rn;
6463 struct bgp_aggregate *aggregate;
718e3744 6464
d62a17ae 6465 /* Convert string to prefix structure. */
6466 ret = str2prefix(prefix_str, &p);
6467 if (!ret) {
6468 vty_out(vty, "Malformed prefix\n");
6469 return CMD_WARNING_CONFIG_FAILED;
6470 }
6471 apply_mask(&p);
6472
6473 /* Old configuration check. */
6474 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6475 if (!rn) {
6476 vty_out(vty,
6477 "%% There is no aggregate-address configuration.\n");
6478 return CMD_WARNING_CONFIG_FAILED;
6479 }
f6269b4f 6480
b613a918 6481 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6482 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6483 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6484 NULL, NULL, 0, aggregate);
d62a17ae 6485
6486 /* Unlock aggregate address configuration. */
b613a918 6487 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6488
6489 if (aggregate->community)
6490 community_free(&aggregate->community);
6491
6492 if (aggregate->community_hash) {
6493 /* Delete all communities in the hash.
6494 */
6495 hash_clean(aggregate->community_hash,
6496 bgp_aggr_community_remove);
6497 /* Free up the community_hash.
6498 */
6499 hash_free(aggregate->community_hash);
6500 }
6501
6502 if (aggregate->ecommunity)
6503 ecommunity_free(&aggregate->ecommunity);
6504
6505 if (aggregate->ecommunity_hash) {
6506 /* Delete all ecommunities in the hash.
6507 */
6508 hash_clean(aggregate->ecommunity_hash,
6509 bgp_aggr_ecommunity_remove);
6510 /* Free up the ecommunity_hash.
6511 */
6512 hash_free(aggregate->ecommunity_hash);
6513 }
6514
6515 if (aggregate->lcommunity)
6516 lcommunity_free(&aggregate->lcommunity);
6517
6518 if (aggregate->lcommunity_hash) {
6519 /* Delete all lcommunities in the hash.
6520 */
6521 hash_clean(aggregate->lcommunity_hash,
6522 bgp_aggr_lcommunity_remove);
6523 /* Free up the lcommunity_hash.
6524 */
6525 hash_free(aggregate->lcommunity_hash);
6526 }
6527
6528 if (aggregate->aspath)
6529 aspath_free(aggregate->aspath);
6530
6531 if (aggregate->aspath_hash) {
6532 /* Delete all as-paths in the hash.
6533 */
6534 hash_clean(aggregate->aspath_hash,
6535 bgp_aggr_aspath_remove);
6536 /* Free up the aspath_hash.
6537 */
6538 hash_free(aggregate->aspath_hash);
6539 }
6540
d62a17ae 6541 bgp_aggregate_free(aggregate);
6542 bgp_unlock_node(rn);
6543 bgp_unlock_node(rn);
6544
6545 return CMD_SUCCESS;
6546}
6547
6548static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6549 safi_t safi, const char *rmap, uint8_t summary_only,
6550 uint8_t as_set)
d62a17ae 6551{
6552 VTY_DECLVAR_CONTEXT(bgp, bgp);
6553 int ret;
6554 struct prefix p;
6555 struct bgp_node *rn;
6556 struct bgp_aggregate *aggregate;
fb29348a 6557 uint8_t as_set_new = as_set;
d62a17ae 6558
6559 /* Convert string to prefix structure. */
6560 ret = str2prefix(prefix_str, &p);
6561 if (!ret) {
6562 vty_out(vty, "Malformed prefix\n");
6563 return CMD_WARNING_CONFIG_FAILED;
6564 }
6565 apply_mask(&p);
6566
3624ac81
DS
6567 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6568 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6569 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6570 prefix_str);
6571 return CMD_WARNING_CONFIG_FAILED;
6572 }
6573
d62a17ae 6574 /* Old configuration check. */
6575 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6576 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6577
20894f50 6578 if (aggregate) {
d62a17ae 6579 vty_out(vty, "There is already same aggregate network.\n");
6580 /* try to remove the old entry */
6581 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6582 if (ret) {
6583 vty_out(vty, "Error deleting aggregate.\n");
6584 bgp_unlock_node(rn);
6585 return CMD_WARNING_CONFIG_FAILED;
6586 }
6587 }
718e3744 6588
d62a17ae 6589 /* Make aggregate address structure. */
6590 aggregate = bgp_aggregate_new();
6591 aggregate->summary_only = summary_only;
fb29348a
DA
6592
6593 /* Network operators MUST NOT locally generate any new
6594 * announcements containing AS_SET or AS_CONFED_SET. If they have
6595 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6596 * SHOULD withdraw those routes and re-announce routes for the
6597 * aggregate or component prefixes (i.e., the more-specific routes
6598 * subsumed by the previously aggregated route) without AS_SET
6599 * or AS_CONFED_SET in the updates.
6600 */
6601 if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
6602 if (as_set == AGGREGATE_AS_SET) {
6603 as_set_new = AGGREGATE_AS_UNSET;
6604 zlog_warn(
6605 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6606 __func__);
6607 vty_out(vty,
6608 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6609 }
6610 }
6611
6612 aggregate->as_set = as_set_new;
d62a17ae 6613 aggregate->safi = safi;
20894f50
DA
6614
6615 if (rmap) {
6616 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6617 route_map_counter_decrement(aggregate->rmap.map);
6618 aggregate->rmap.name =
6619 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6620 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6621 route_map_counter_increment(aggregate->rmap.map);
6622 }
b613a918 6623 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6624
d62a17ae 6625 /* Aggregate address insert into BGP routing table. */
fc968841 6626 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6627
d62a17ae 6628 return CMD_SUCCESS;
718e3744 6629}
6630
6631DEFUN (aggregate_address,
6632 aggregate_address_cmd,
20894f50 6633 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6634 "Configure BGP aggregate entries\n"
6635 "Aggregate prefix\n"
6636 "Generate AS set path information\n"
a636c635
DW
6637 "Filter more specific routes from updates\n"
6638 "Filter more specific routes from updates\n"
20894f50
DA
6639 "Generate AS set path information\n"
6640 "Apply route map to aggregate network\n"
6641 "Name of route map\n")
718e3744 6642{
d62a17ae 6643 int idx = 0;
6644 argv_find(argv, argc, "A.B.C.D/M", &idx);
6645 char *prefix = argv[idx]->arg;
20894f50 6646 char *rmap = NULL;
fb29348a
DA
6647 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6648 : AGGREGATE_AS_UNSET;
d62a17ae 6649 idx = 0;
6650 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6651 ? AGGREGATE_SUMMARY_ONLY
6652 : 0;
e3e6107d 6653
20894f50
DA
6654 idx = 0;
6655 argv_find(argv, argc, "WORD", &idx);
6656 if (idx)
6657 rmap = argv[idx]->arg;
6658
d62a17ae 6659 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6660 rmap, summary_only, as_set);
718e3744 6661}
6662
e3e6107d
QY
6663DEFUN (aggregate_address_mask,
6664 aggregate_address_mask_cmd,
20894f50 6665 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6666 "Configure BGP aggregate entries\n"
6667 "Aggregate address\n"
6668 "Aggregate mask\n"
6669 "Generate AS set path information\n"
a636c635
DW
6670 "Filter more specific routes from updates\n"
6671 "Filter more specific routes from updates\n"
20894f50
DA
6672 "Generate AS set path information\n"
6673 "Apply route map to aggregate network\n"
6674 "Name of route map\n")
718e3744 6675{
d62a17ae 6676 int idx = 0;
6677 argv_find(argv, argc, "A.B.C.D", &idx);
6678 char *prefix = argv[idx]->arg;
6679 char *mask = argv[idx + 1]->arg;
cf40d052 6680 bool rmap_found;
20894f50 6681 char *rmap = NULL;
fb29348a
DA
6682 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6683 : AGGREGATE_AS_UNSET;
d62a17ae 6684 idx = 0;
6685 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6686 ? AGGREGATE_SUMMARY_ONLY
6687 : 0;
6688
cf40d052
DS
6689 rmap_found = argv_find(argv, argc, "WORD", &idx);
6690 if (rmap_found)
20894f50
DA
6691 rmap = argv[idx]->arg;
6692
d62a17ae 6693 char prefix_str[BUFSIZ];
6694 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6695
6696 if (!ret) {
6697 vty_out(vty, "%% Inconsistent address and mask\n");
6698 return CMD_WARNING_CONFIG_FAILED;
6699 }
718e3744 6700
d62a17ae 6701 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6702 rmap, summary_only, as_set);
718e3744 6703}
6704
718e3744 6705DEFUN (no_aggregate_address,
6706 no_aggregate_address_cmd,
b84da0db 6707 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6708 NO_STR
6709 "Configure BGP aggregate entries\n"
a636c635
DW
6710 "Aggregate prefix\n"
6711 "Generate AS set path information\n"
e3e6107d
QY
6712 "Filter more specific routes from updates\n"
6713 "Filter more specific routes from updates\n"
b84da0db
DA
6714 "Generate AS set path information\n"
6715 "Apply route map to aggregate network\n"
6716 "Name of route map\n")
718e3744 6717{
d62a17ae 6718 int idx = 0;
6719 argv_find(argv, argc, "A.B.C.D/M", &idx);
6720 char *prefix = argv[idx]->arg;
6721 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6722}
6723
718e3744 6724DEFUN (no_aggregate_address_mask,
6725 no_aggregate_address_mask_cmd,
b84da0db 6726 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6727 NO_STR
6728 "Configure BGP aggregate entries\n"
6729 "Aggregate address\n"
a636c635
DW
6730 "Aggregate mask\n"
6731 "Generate AS set path information\n"
e3e6107d
QY
6732 "Filter more specific routes from updates\n"
6733 "Filter more specific routes from updates\n"
b84da0db
DA
6734 "Generate AS set path information\n"
6735 "Apply route map to aggregate network\n"
6736 "Name of route map\n")
718e3744 6737{
d62a17ae 6738 int idx = 0;
6739 argv_find(argv, argc, "A.B.C.D", &idx);
6740 char *prefix = argv[idx]->arg;
6741 char *mask = argv[idx + 1]->arg;
718e3744 6742
d62a17ae 6743 char prefix_str[BUFSIZ];
6744 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6745
d62a17ae 6746 if (!ret) {
6747 vty_out(vty, "%% Inconsistent address and mask\n");
6748 return CMD_WARNING_CONFIG_FAILED;
6749 }
718e3744 6750
d62a17ae 6751 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6752}
6753
718e3744 6754DEFUN (ipv6_aggregate_address,
6755 ipv6_aggregate_address_cmd,
20894f50 6756 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6757 "Configure BGP aggregate entries\n"
6758 "Aggregate prefix\n"
5101fece 6759 "Generate AS set path information\n"
6760 "Filter more specific routes from updates\n"
6761 "Filter more specific routes from updates\n"
20894f50
DA
6762 "Generate AS set path information\n"
6763 "Apply route map to aggregate network\n"
6764 "Name of route map\n")
718e3744 6765{
d62a17ae 6766 int idx = 0;
6767 argv_find(argv, argc, "X:X::X:X/M", &idx);
6768 char *prefix = argv[idx]->arg;
20894f50 6769 char *rmap = NULL;
273fae13 6770 bool rmap_found;
fb29348a
DA
6771 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6772 : AGGREGATE_AS_UNSET;
5101fece 6773
6774 idx = 0;
d62a17ae 6775 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6776 ? AGGREGATE_SUMMARY_ONLY
6777 : 0;
20894f50 6778
273fae13
DA
6779 rmap_found = argv_find(argv, argc, "WORD", &idx);
6780 if (rmap_found)
20894f50
DA
6781 rmap = argv[idx]->arg;
6782
6783 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6784 sum_only, as_set);
718e3744 6785}
6786
6787DEFUN (no_ipv6_aggregate_address,
6788 no_ipv6_aggregate_address_cmd,
b84da0db 6789 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6790 NO_STR
6791 "Configure BGP aggregate entries\n"
16cedbb0 6792 "Aggregate prefix\n"
5101fece 6793 "Generate AS set path information\n"
6794 "Filter more specific routes from updates\n"
6795 "Filter more specific routes from updates\n"
b84da0db
DA
6796 "Generate AS set path information\n"
6797 "Apply route map to aggregate network\n"
6798 "Name of route map\n")
718e3744 6799{
d62a17ae 6800 int idx = 0;
6801 argv_find(argv, argc, "X:X::X:X/M", &idx);
6802 char *prefix = argv[idx]->arg;
6803 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6804}
6805
718e3744 6806/* Redistribute route treatment. */
d62a17ae 6807void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6808 const union g_addr *nexthop, ifindex_t ifindex,
6809 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6810 uint8_t type, unsigned short instance,
6811 route_tag_t tag)
d62a17ae 6812{
4b7e6066 6813 struct bgp_path_info *new;
40381db7
DS
6814 struct bgp_path_info *bpi;
6815 struct bgp_path_info rmap_path;
d62a17ae 6816 struct bgp_node *bn;
6817 struct attr attr;
6818 struct attr *new_attr;
6819 afi_t afi;
b68885f9 6820 route_map_result_t ret;
d62a17ae 6821 struct bgp_redist *red;
6822
6823 /* Make default attribute. */
6824 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
6825 /*
6826 * This must not be NULL to satisfy Coverity SA
6827 */
6828 assert(attr.aspath);
9de1f7ff 6829
a4d82a8a 6830 switch (nhtype) {
9de1f7ff
DS
6831 case NEXTHOP_TYPE_IFINDEX:
6832 break;
6833 case NEXTHOP_TYPE_IPV4:
6834 case NEXTHOP_TYPE_IPV4_IFINDEX:
6835 attr.nexthop = nexthop->ipv4;
6836 break;
6837 case NEXTHOP_TYPE_IPV6:
6838 case NEXTHOP_TYPE_IPV6_IFINDEX:
6839 attr.mp_nexthop_global = nexthop->ipv6;
6840 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6841 break;
6842 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6843 switch (p->family) {
6844 case AF_INET:
9de1f7ff 6845 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6846 break;
6847 case AF_INET6:
9de1f7ff
DS
6848 memset(&attr.mp_nexthop_global, 0,
6849 sizeof(attr.mp_nexthop_global));
74489921 6850 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6851 break;
74489921 6852 }
9de1f7ff 6853 break;
d62a17ae 6854 }
74489921 6855 attr.nh_ifindex = ifindex;
f04a80a5 6856
d62a17ae 6857 attr.med = metric;
6858 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6859 attr.tag = tag;
718e3744 6860
d62a17ae 6861 afi = family2afi(p->family);
6aeb9e78 6862
d62a17ae 6863 red = bgp_redist_lookup(bgp, afi, type, instance);
6864 if (red) {
6865 struct attr attr_new;
718e3744 6866
d62a17ae 6867 /* Copy attribute for modification. */
6f4f49b2 6868 attr_new = attr;
718e3744 6869
d62a17ae 6870 if (red->redist_metric_flag)
6871 attr_new.med = red->redist_metric;
718e3744 6872
d62a17ae 6873 /* Apply route-map. */
6874 if (red->rmap.name) {
40381db7
DS
6875 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6876 rmap_path.peer = bgp->peer_self;
6877 rmap_path.attr = &attr_new;
718e3744 6878
d62a17ae 6879 SET_FLAG(bgp->peer_self->rmap_type,
6880 PEER_RMAP_TYPE_REDISTRIBUTE);
6881
6882 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6883 &rmap_path);
d62a17ae 6884
6885 bgp->peer_self->rmap_type = 0;
6886
6887 if (ret == RMAP_DENYMATCH) {
6888 /* Free uninterned attribute. */
6889 bgp_attr_flush(&attr_new);
6890
6891 /* Unintern original. */
6892 aspath_unintern(&attr.aspath);
6893 bgp_redistribute_delete(bgp, p, type, instance);
6894 return;
6895 }
6896 }
6897
7f323236
DW
6898 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6899 bgp_attr_add_gshut_community(&attr_new);
6900
d62a17ae 6901 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6902 SAFI_UNICAST, p, NULL);
6903
6904 new_attr = bgp_attr_intern(&attr_new);
6905
6f94b685
DS
6906 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6907 bpi = bpi->next)
40381db7
DS
6908 if (bpi->peer == bgp->peer_self
6909 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6910 break;
6911
40381db7 6912 if (bpi) {
d62a17ae 6913 /* Ensure the (source route) type is updated. */
40381db7
DS
6914 bpi->type = type;
6915 if (attrhash_cmp(bpi->attr, new_attr)
6916 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6917 bgp_attr_unintern(&new_attr);
6918 aspath_unintern(&attr.aspath);
6919 bgp_unlock_node(bn);
6920 return;
6921 } else {
6922 /* The attribute is changed. */
40381db7 6923 bgp_path_info_set_flag(bn, bpi,
18ee8310 6924 BGP_PATH_ATTR_CHANGED);
d62a17ae 6925
6926 /* Rewrite BGP route information. */
40381db7
DS
6927 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6928 bgp_path_info_restore(bn, bpi);
d62a17ae 6929 else
40381db7
DS
6930 bgp_aggregate_decrement(
6931 bgp, p, bpi, afi, SAFI_UNICAST);
6932 bgp_attr_unintern(&bpi->attr);
6933 bpi->attr = new_attr;
6934 bpi->uptime = bgp_clock();
d62a17ae 6935
6936 /* Process change. */
40381db7 6937 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6938 SAFI_UNICAST);
6939 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6940 bgp_unlock_node(bn);
6941 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6942
6943 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6944 || (bgp->inst_type
6945 == BGP_INSTANCE_TYPE_DEFAULT)) {
6946
6947 vpn_leak_from_vrf_update(
40381db7 6948 bgp_get_default(), bgp, bpi);
ddb5b488 6949 }
d62a17ae 6950 return;
6951 }
6952 }
6953
6954 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6955 bgp->peer_self, new_attr, bn);
1defdda8 6956 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6957
6958 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6959 bgp_path_info_add(bn, new);
d62a17ae 6960 bgp_unlock_node(bn);
6961 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6962
6963 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6964 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6965
6966 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6967 }
d62a17ae 6968 }
6969
6970 /* Unintern original. */
6971 aspath_unintern(&attr.aspath);
718e3744 6972}
6973
d7c0a89a
QY
6974void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6975 unsigned short instance)
718e3744 6976{
d62a17ae 6977 afi_t afi;
6978 struct bgp_node *rn;
40381db7 6979 struct bgp_path_info *pi;
d62a17ae 6980 struct bgp_redist *red;
718e3744 6981
d62a17ae 6982 afi = family2afi(p->family);
718e3744 6983
d62a17ae 6984 red = bgp_redist_lookup(bgp, afi, type, instance);
6985 if (red) {
6986 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6987 SAFI_UNICAST, p, NULL);
6988
6f94b685 6989 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6990 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6991 break;
6992
40381db7 6993 if (pi) {
ddb5b488
PZ
6994 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6995 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6996
6997 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6998 bgp, pi);
ddb5b488 6999 }
40381db7
DS
7000 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
7001 bgp_path_info_delete(rn, pi);
d62a17ae 7002 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7003 }
7004 bgp_unlock_node(rn);
7005 }
7006}
7007
7008/* Withdraw specified route type's route. */
7009void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7010 unsigned short instance)
d62a17ae 7011{
7012 struct bgp_node *rn;
40381db7 7013 struct bgp_path_info *pi;
d62a17ae 7014 struct bgp_table *table;
7015
7016 table = bgp->rib[afi][SAFI_UNICAST];
7017
7018 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 7019 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
7020 if (pi->peer == bgp->peer_self && pi->type == type
7021 && pi->instance == instance)
d62a17ae 7022 break;
7023
40381db7 7024 if (pi) {
ddb5b488
PZ
7025 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7026 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7027
7028 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7029 bgp, pi);
ddb5b488 7030 }
40381db7 7031 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 7032 SAFI_UNICAST);
40381db7 7033 bgp_path_info_delete(rn, pi);
d62a17ae 7034 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7035 }
718e3744 7036 }
718e3744 7037}
6b0655a2 7038
718e3744 7039/* Static function to display route. */
9c92b5f7
MK
7040static void route_vty_out_route(struct prefix *p, struct vty *vty,
7041 json_object *json)
718e3744 7042{
be054588 7043 int len = 0;
d62a17ae 7044 char buf[BUFSIZ];
50e05855 7045 char buf2[BUFSIZ];
718e3744 7046
d62a17ae 7047 if (p->family == AF_INET) {
c6462ff4 7048 if (!json) {
89e5e9f0
PM
7049 len = vty_out(
7050 vty, "%s/%d",
7051 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7052 p->prefixlen);
c6462ff4
MK
7053 } else {
7054 json_object_string_add(json, "prefix",
7055 inet_ntop(p->family,
7056 &p->u.prefix, buf,
7057 BUFSIZ));
7058 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7059 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7060 json_object_string_add(json, "network", buf2);
c6462ff4 7061 }
d62a17ae 7062 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7063 prefix2str(p, buf, PREFIX_STRLEN);
7064 len = vty_out(vty, "%s", buf);
7065 } else if (p->family == AF_EVPN) {
57f7feb6 7066 if (!json)
60466a63
QY
7067 len = vty_out(
7068 vty, "%s",
7069 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7070 BUFSIZ));
57f7feb6 7071 else
60466a63 7072 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7073 } else if (p->family == AF_FLOWSPEC) {
7074 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7075 json ?
7076 NLRI_STRING_FORMAT_JSON_SIMPLE :
7077 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7078 } else {
c6462ff4 7079 if (!json)
60466a63
QY
7080 len = vty_out(
7081 vty, "%s/%d",
7082 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7083 p->prefixlen);
50e05855
AD
7084 else {
7085 json_object_string_add(json, "prefix",
7086 inet_ntop(p->family,
7087 &p->u.prefix, buf,
7088 BUFSIZ));
7089 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7090 prefix2str(p, buf2, PREFIX_STRLEN);
7091 json_object_string_add(json, "network", buf2);
7092 }
9c92b5f7 7093 }
d62a17ae 7094
9c92b5f7
MK
7095 if (!json) {
7096 len = 17 - len;
7097 if (len < 1)
7098 vty_out(vty, "\n%*s", 20, " ");
7099 else
7100 vty_out(vty, "%*s", len, " ");
7101 }
718e3744 7102}
7103
d62a17ae 7104enum bgp_display_type {
7105 normal_list,
718e3744 7106};
7107
18ee8310 7108/* Print the short form route status for a bgp_path_info */
4b7e6066 7109static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7110 struct bgp_path_info *path,
d62a17ae 7111 json_object *json_path)
718e3744 7112{
d62a17ae 7113 if (json_path) {
b05a1c8b 7114
d62a17ae 7115 /* Route status display. */
9b6d8fcf 7116 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7117 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7118
9b6d8fcf 7119 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7120 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7121
9b6d8fcf 7122 if (path->extra && path->extra->suppress)
d62a17ae 7123 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7124
9b6d8fcf
DS
7125 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7126 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7127 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7128
d62a17ae 7129 /* Selected */
9b6d8fcf 7130 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7131 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7132
9b6d8fcf 7133 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7134 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7135
9b6d8fcf 7136 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7137 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7138
9b6d8fcf 7139 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7140 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7141
d62a17ae 7142 /* Internal route. */
9b6d8fcf
DS
7143 if ((path->peer->as)
7144 && (path->peer->as == path->peer->local_as))
d62a17ae 7145 json_object_string_add(json_path, "pathFrom",
7146 "internal");
7147 else
7148 json_object_string_add(json_path, "pathFrom",
7149 "external");
b05a1c8b 7150
d62a17ae 7151 return;
7152 }
b05a1c8b 7153
d62a17ae 7154 /* Route status display. */
9b6d8fcf 7155 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7156 vty_out(vty, "R");
9b6d8fcf 7157 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7158 vty_out(vty, "S");
9b6d8fcf 7159 else if (path->extra && path->extra->suppress)
d62a17ae 7160 vty_out(vty, "s");
9b6d8fcf
DS
7161 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7162 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7163 vty_out(vty, "*");
7164 else
7165 vty_out(vty, " ");
7166
7167 /* Selected */
9b6d8fcf 7168 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7169 vty_out(vty, "h");
9b6d8fcf 7170 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7171 vty_out(vty, "d");
9b6d8fcf 7172 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7173 vty_out(vty, ">");
9b6d8fcf 7174 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7175 vty_out(vty, "=");
7176 else
7177 vty_out(vty, " ");
718e3744 7178
d62a17ae 7179 /* Internal route. */
9b6d8fcf
DS
7180 if (path->peer && (path->peer->as)
7181 && (path->peer->as == path->peer->local_as))
d62a17ae 7182 vty_out(vty, "i");
7183 else
7184 vty_out(vty, " ");
b40d939b 7185}
7186
515c2602 7187static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
25b5da8d 7188{
515c2602
DA
7189 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)
7190 && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
25b5da8d
DA
7191 return peer->hostname;
7192 return NULL;
7193}
7194
b40d939b 7195/* called from terminal list command */
4b7e6066 7196void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7197 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7198 json_object *json_paths)
d62a17ae 7199{
515c2602 7200 struct attr *attr = path->attr;
d62a17ae 7201 json_object *json_path = NULL;
7202 json_object *json_nexthops = NULL;
7203 json_object *json_nexthop_global = NULL;
7204 json_object *json_nexthop_ll = NULL;
6f214dd3 7205 json_object *json_ext_community = NULL;
9df8b37c 7206 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7207 bool nexthop_self =
9b6d8fcf 7208 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7209 bool nexthop_othervrf = false;
43089216 7210 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7211 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
515c2602 7212 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 7213
7214 if (json_paths)
7215 json_path = json_object_new_object();
7216
7217 /* short status lead text */
9b6d8fcf 7218 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7219
7220 if (!json_paths) {
7221 /* print prefix and mask */
7222 if (!display)
9c92b5f7 7223 route_vty_out_route(p, vty, json_path);
d62a17ae 7224 else
7225 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7226 } else {
b682f6de 7227 route_vty_out_route(p, vty, json_path);
d62a17ae 7228 }
47fc97cc 7229
9df8b37c
PZ
7230 /*
7231 * If vrf id of nexthop is different from that of prefix,
7232 * set up printable string to append
7233 */
9b6d8fcf 7234 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7235 const char *self = "";
7236
7237 if (nexthop_self)
7238 self = "<";
7239
7240 nexthop_othervrf = true;
9b6d8fcf 7241 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7242
9b6d8fcf 7243 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7244 snprintf(vrf_id_str, sizeof(vrf_id_str),
7245 "@%s%s", VRFID_NONE_STR, self);
7246 else
7247 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7248 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7249
9b6d8fcf
DS
7250 if (path->extra->bgp_orig->inst_type
7251 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7252
9b6d8fcf 7253 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7254 } else {
7255 const char *self = "";
7256
7257 if (nexthop_self)
7258 self = "<";
7259
7260 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7261 }
7262
445c2480
DS
7263 /*
7264 * For ENCAP and EVPN routes, nexthop address family is not
7265 * neccessarily the same as the prefix address family.
7266 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7267 * EVPN routes are also exchanged with a MP nexthop. Currently,
7268 * this
7269 * is only IPv4, the value will be present in either
7270 * attr->nexthop or
7271 * attr->mp_nexthop_global_in
7272 */
7273 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7274 char buf[BUFSIZ];
7275 char nexthop[128];
7276 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7277
7278 switch (af) {
7279 case AF_INET:
7280 sprintf(nexthop, "%s",
a4d82a8a
PZ
7281 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7282 BUFSIZ));
445c2480
DS
7283 break;
7284 case AF_INET6:
7285 sprintf(nexthop, "%s",
a4d82a8a
PZ
7286 inet_ntop(af, &attr->mp_nexthop_global, buf,
7287 BUFSIZ));
445c2480
DS
7288 break;
7289 default:
7290 sprintf(nexthop, "?");
7291 break;
d62a17ae 7292 }
d62a17ae 7293
445c2480
DS
7294 if (json_paths) {
7295 json_nexthop_global = json_object_new_object();
7296
515c2602
DA
7297 json_object_string_add(json_nexthop_global, "ip",
7298 nexthop);
7299
7300 if (nexthop_hostname)
7301 json_object_string_add(json_nexthop_global,
7302 "hostname",
7303 nexthop_hostname);
7304
7305 json_object_string_add(json_nexthop_global, "afi",
7306 (af == AF_INET) ? "ipv4"
7307 : "ipv6");
445c2480
DS
7308 json_object_boolean_true_add(json_nexthop_global,
7309 "used");
7310 } else
25b5da8d 7311 vty_out(vty, "%s%s",
515c2602 7312 nexthop_hostname ? nexthop_hostname : nexthop,
25b5da8d 7313 vrf_id_str);
445c2480
DS
7314 } else if (safi == SAFI_EVPN) {
7315 if (json_paths) {
7316 json_nexthop_global = json_object_new_object();
7317
515c2602
DA
7318 json_object_string_add(json_nexthop_global, "ip",
7319 inet_ntoa(attr->nexthop));
7320
7321 if (nexthop_hostname)
7322 json_object_string_add(json_nexthop_global,
7323 "hostname",
7324 nexthop_hostname);
7325
a4d82a8a
PZ
7326 json_object_string_add(json_nexthop_global, "afi",
7327 "ipv4");
445c2480
DS
7328 json_object_boolean_true_add(json_nexthop_global,
7329 "used");
7330 } else
25b5da8d 7331 vty_out(vty, "%-16s%s",
515c2602
DA
7332 nexthop_hostname ? nexthop_hostname
7333 : inet_ntoa(attr->nexthop),
9df8b37c 7334 vrf_id_str);
d33fc23b 7335 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7336 if (attr->nexthop.s_addr != 0) {
7337 if (json_paths) {
7338 json_nexthop_global = json_object_new_object();
515c2602 7339
026b914a
PG
7340 json_object_string_add(json_nexthop_global,
7341 "afi", "ipv4");
515c2602
DA
7342 json_object_string_add(
7343 json_nexthop_global, "ip",
7344 inet_ntoa(attr->nexthop));
7345
7346 if (nexthop_hostname)
7347 json_object_string_add(
7348 json_nexthop_global, "hostname",
7349 nexthop_hostname);
7350
50e05855
AD
7351 json_object_boolean_true_add(
7352 json_nexthop_global,
026b914a
PG
7353 "used");
7354 } else {
25b5da8d 7355 vty_out(vty, "%-16s",
515c2602
DA
7356 nexthop_hostname
7357 ? nexthop_hostname
25b5da8d 7358 : inet_ntoa(attr->nexthop));
026b914a
PG
7359 }
7360 }
d33fc23b 7361 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7362 if (json_paths) {
7363 json_nexthop_global = json_object_new_object();
d62a17ae 7364
515c2602
DA
7365 json_object_string_add(json_nexthop_global, "ip",
7366 inet_ntoa(attr->nexthop));
7367
7368 if (nexthop_hostname)
7369 json_object_string_add(json_nexthop_global,
7370 "hostname",
7371 nexthop_hostname);
445c2480 7372
a4d82a8a
PZ
7373 json_object_string_add(json_nexthop_global, "afi",
7374 "ipv4");
445c2480
DS
7375 json_object_boolean_true_add(json_nexthop_global,
7376 "used");
7377 } else {
9df8b37c
PZ
7378 char buf[BUFSIZ];
7379
d87ff2dd 7380 snprintf(buf, sizeof(buf), "%s%s",
515c2602
DA
7381 nexthop_hostname ? nexthop_hostname
7382 : inet_ntoa(attr->nexthop),
25b5da8d 7383 vrf_id_str);
9df8b37c 7384 vty_out(vty, "%-16s", buf);
d62a17ae 7385 }
445c2480 7386 }
b05a1c8b 7387
445c2480 7388 /* IPv6 Next Hop */
a4d82a8a 7389 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7390 int len;
7391 char buf[BUFSIZ];
d62a17ae 7392
445c2480
DS
7393 if (json_paths) {
7394 json_nexthop_global = json_object_new_object();
a4d82a8a 7395 json_object_string_add(
515c2602
DA
7396 json_nexthop_global, "ip",
7397 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7398 buf, BUFSIZ));
7399
7400 if (nexthop_hostname)
7401 json_object_string_add(json_nexthop_global,
7402 "hostname",
7403 nexthop_hostname);
7404
a4d82a8a
PZ
7405 json_object_string_add(json_nexthop_global, "afi",
7406 "ipv6");
7407 json_object_string_add(json_nexthop_global, "scope",
7408 "global");
445c2480
DS
7409
7410 /* We display both LL & GL if both have been
7411 * received */
0606039c
DA
7412 if ((attr->mp_nexthop_len
7413 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7414 || (path->peer->conf_if)) {
a4d82a8a 7415 json_nexthop_ll = json_object_new_object();
d62a17ae 7416 json_object_string_add(
515c2602
DA
7417 json_nexthop_ll, "ip",
7418 inet_ntop(AF_INET6,
7419 &attr->mp_nexthop_local, buf,
7420 BUFSIZ));
7421
7422 if (nexthop_hostname)
7423 json_object_string_add(
7424 json_nexthop_ll, "hostname",
7425 nexthop_hostname);
7426
a4d82a8a
PZ
7427 json_object_string_add(json_nexthop_ll, "afi",
7428 "ipv6");
7429 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7430 "link-local");
d62a17ae 7431
a4d82a8a
PZ
7432 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7433 &attr->mp_nexthop_local)
445c2480
DS
7434 != 0)
7435 && !attr->mp_nexthop_prefer_global)
d62a17ae 7436 json_object_boolean_true_add(
a4d82a8a 7437 json_nexthop_ll, "used");
445c2480
DS
7438 else
7439 json_object_boolean_true_add(
a4d82a8a 7440 json_nexthop_global, "used");
445c2480
DS
7441 } else
7442 json_object_boolean_true_add(
7443 json_nexthop_global, "used");
7444 } else {
7445 /* Display LL if LL/Global both in table unless
7446 * prefer-global is set */
0606039c
DA
7447 if (((attr->mp_nexthop_len
7448 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7449 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7450 || (path->peer->conf_if)) {
7451 if (path->peer->conf_if) {
a4d82a8a 7452 len = vty_out(vty, "%s",
9b6d8fcf 7453 path->peer->conf_if);
445c2480
DS
7454 len = 16 - len; /* len of IPv6
7455 addr + max
7456 len of def
7457 ifname */
7458
7459 if (len < 1)
a4d82a8a 7460 vty_out(vty, "\n%*s", 36, " ");
445c2480 7461 else
a4d82a8a 7462 vty_out(vty, "%*s", len, " ");
d62a17ae 7463 } else {
7464 len = vty_out(
9df8b37c 7465 vty, "%s%s",
515c2602
DA
7466 nexthop_hostname
7467 ? nexthop_hostname
25b5da8d
DA
7468 : inet_ntop(
7469 AF_INET6,
7470 &attr->mp_nexthop_local,
7471 buf, BUFSIZ),
9df8b37c 7472 vrf_id_str);
d62a17ae 7473 len = 16 - len;
7474
7475 if (len < 1)
a4d82a8a 7476 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7477 else
a4d82a8a 7478 vty_out(vty, "%*s", len, " ");
d62a17ae 7479 }
445c2480 7480 } else {
a4d82a8a 7481 len = vty_out(
9df8b37c 7482 vty, "%s%s",
515c2602
DA
7483 nexthop_hostname
7484 ? nexthop_hostname
25b5da8d
DA
7485 : inet_ntop(
7486 AF_INET6,
7487 &attr->mp_nexthop_global,
7488 buf, BUFSIZ),
7489 vrf_id_str);
445c2480
DS
7490 len = 16 - len;
7491
7492 if (len < 1)
7493 vty_out(vty, "\n%*s", 36, " ");
7494 else
7495 vty_out(vty, "%*s", len, " ");
d62a17ae 7496 }
7497 }
445c2480 7498 }
718e3744 7499
445c2480
DS
7500 /* MED/Metric */
7501 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7502 if (json_paths) {
7503
7504 /*
7505 * Adding "metric" field to match with corresponding
7506 * CLI. "med" will be deprecated in future.
7507 */
a4d82a8a 7508 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7509 json_object_int_add(json_path, "metric", attr->med);
7510 } else
445c2480
DS
7511 vty_out(vty, "%10u", attr->med);
7512 else if (!json_paths)
7513 vty_out(vty, " ");
d62a17ae 7514
445c2480
DS
7515 /* Local Pref */
7516 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7517 if (json_paths) {
7518
7519 /*
7520 * Adding "locPrf" field to match with corresponding
7521 * CLI. "localPref" will be deprecated in future.
7522 */
445c2480
DS
7523 json_object_int_add(json_path, "localpref",
7524 attr->local_pref);
50e05855
AD
7525 json_object_int_add(json_path, "locPrf",
7526 attr->local_pref);
7527 } else
445c2480
DS
7528 vty_out(vty, "%7u", attr->local_pref);
7529 else if (!json_paths)
7530 vty_out(vty, " ");
d62a17ae 7531
445c2480
DS
7532 if (json_paths)
7533 json_object_int_add(json_path, "weight", attr->weight);
7534 else
7535 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7536
445c2480
DS
7537 if (json_paths) {
7538 char buf[BUFSIZ];
a4d82a8a
PZ
7539 json_object_string_add(
7540 json_path, "peerId",
9b6d8fcf 7541 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7542 }
b05a1c8b 7543
445c2480
DS
7544 /* Print aspath */
7545 if (attr->aspath) {
50e05855
AD
7546 if (json_paths) {
7547
7548 /*
7549 * Adding "path" field to match with corresponding
7550 * CLI. "aspath" will be deprecated in future.
7551 */
445c2480
DS
7552 json_object_string_add(json_path, "aspath",
7553 attr->aspath->str);
50e05855
AD
7554 json_object_string_add(json_path, "path",
7555 attr->aspath->str);
7556 } else
445c2480 7557 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7558 }
f1aa5d8a 7559
445c2480
DS
7560 /* Print origin */
7561 if (json_paths)
a4d82a8a
PZ
7562 json_object_string_add(json_path, "origin",
7563 bgp_origin_long_str[attr->origin]);
445c2480
DS
7564 else
7565 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7566
9df8b37c 7567 if (json_paths) {
6f214dd3
CS
7568 if (safi == SAFI_EVPN &&
7569 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7570 json_ext_community = json_object_new_object();
7571 json_object_string_add(json_ext_community,
7572 "string",
7573 attr->ecommunity->str);
7574 json_object_object_add(json_path,
7575 "extendedCommunity",
7576 json_ext_community);
7577 }
7578
9df8b37c
PZ
7579 if (nexthop_self)
7580 json_object_boolean_true_add(json_path,
7581 "announceNexthopSelf");
7582 if (nexthop_othervrf) {
7583 json_object_string_add(json_path, "nhVrfName",
7584 nexthop_vrfname);
7585
7586 json_object_int_add(json_path, "nhVrfId",
7587 ((nexthop_vrfid == VRF_UNKNOWN)
7588 ? -1
7589 : (int)nexthop_vrfid));
7590 }
7591 }
7592
d62a17ae 7593 if (json_paths) {
7594 if (json_nexthop_global || json_nexthop_ll) {
7595 json_nexthops = json_object_new_array();
f1aa5d8a 7596
d62a17ae 7597 if (json_nexthop_global)
7598 json_object_array_add(json_nexthops,
7599 json_nexthop_global);
f1aa5d8a 7600
d62a17ae 7601 if (json_nexthop_ll)
7602 json_object_array_add(json_nexthops,
7603 json_nexthop_ll);
f1aa5d8a 7604
d62a17ae 7605 json_object_object_add(json_path, "nexthops",
7606 json_nexthops);
7607 }
7608
7609 json_object_array_add(json_paths, json_path);
7610 } else {
7611 vty_out(vty, "\n");
6f214dd3
CS
7612
7613 if (safi == SAFI_EVPN &&
7614 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7615 vty_out(vty, "%*s", 20, " ");
7616 vty_out(vty, "%s\n", attr->ecommunity->str);
7617 }
7618
65efcfce 7619#if ENABLE_BGP_VNC
d62a17ae 7620 /* prints an additional line, indented, with VNC info, if
7621 * present */
7622 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7623 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7624#endif
d62a17ae 7625 }
7626}
718e3744 7627
7628/* called from terminal list command */
d62a17ae 7629void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7630 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7631{
7632 json_object *json_status = NULL;
7633 json_object *json_net = NULL;
7634 char buff[BUFSIZ];
dc387b0f 7635
d62a17ae 7636 /* Route status display. */
7637 if (use_json) {
7638 json_status = json_object_new_object();
7639 json_net = json_object_new_object();
7640 } else {
7641 vty_out(vty, "*");
7642 vty_out(vty, ">");
7643 vty_out(vty, " ");
7644 }
718e3744 7645
d62a17ae 7646 /* print prefix and mask */
50e05855 7647 if (use_json) {
dc387b0f
LK
7648 if (safi == SAFI_EVPN)
7649 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7650 else if (p->family == AF_INET || p->family == AF_INET6) {
7651 json_object_string_add(
7652 json_net, "addrPrefix",
7653 inet_ntop(p->family, &p->u.prefix, buff,
7654 BUFSIZ));
7655 json_object_int_add(json_net, "prefixLen",
7656 p->prefixlen);
7657 prefix2str(p, buff, PREFIX_STRLEN);
7658 json_object_string_add(json_net, "network", buff);
7659 }
50e05855 7660 } else
9c92b5f7 7661 route_vty_out_route(p, vty, NULL);
d62a17ae 7662
7663 /* Print attribute */
7664 if (attr) {
7665 if (use_json) {
7666 if (p->family == AF_INET
7667 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7668 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7669 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7670 json_object_string_add(
7671 json_net, "nextHop",
7672 inet_ntoa(
7673 attr->mp_nexthop_global_in));
7674 else
7675 json_object_string_add(
7676 json_net, "nextHop",
7677 inet_ntoa(attr->nexthop));
7678 } else if (p->family == AF_INET6
7679 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7680 char buf[BUFSIZ];
7681
7682 json_object_string_add(
aa0a10fc 7683 json_net, "nextHopGlobal",
d62a17ae 7684 inet_ntop(AF_INET6,
7685 &attr->mp_nexthop_global, buf,
7686 BUFSIZ));
dc387b0f
LK
7687 } else if (p->family == AF_EVPN &&
7688 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7689 json_object_string_add(json_net,
7690 "nextHop", inet_ntoa(
7691 attr->mp_nexthop_global_in));
d62a17ae 7692
7693 if (attr->flag
7694 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7695 json_object_int_add(json_net, "metric",
7696 attr->med);
7697
50e05855
AD
7698 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7699
7700 /*
7701 * Adding "locPrf" field to match with
7702 * corresponding CLI. "localPref" will be
7703 * deprecated in future.
7704 */
d62a17ae 7705 json_object_int_add(json_net, "localPref",
7706 attr->local_pref);
50e05855
AD
7707 json_object_int_add(json_net, "locPrf",
7708 attr->local_pref);
7709 }
d62a17ae 7710
7711 json_object_int_add(json_net, "weight", attr->weight);
7712
7713 /* Print aspath */
50e05855
AD
7714 if (attr->aspath) {
7715
7716 /*
7717 * Adding "path" field to match with
7718 * corresponding CLI. "localPref" will be
7719 * deprecated in future.
7720 */
d62a17ae 7721 json_object_string_add(json_net, "asPath",
7722 attr->aspath->str);
50e05855
AD
7723 json_object_string_add(json_net, "path",
7724 attr->aspath->str);
7725 }
d62a17ae 7726
7727 /* Print origin */
7728 json_object_string_add(json_net, "bgpOriginCode",
7729 bgp_origin_str[attr->origin]);
7730 } else {
7731 if (p->family == AF_INET
7732 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7733 || safi == SAFI_EVPN
7734 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7735 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7736 || safi == SAFI_EVPN)
7737 vty_out(vty, "%-16s",
7738 inet_ntoa(
7739 attr->mp_nexthop_global_in));
7740 else
7741 vty_out(vty, "%-16s",
7742 inet_ntoa(attr->nexthop));
7743 } else if (p->family == AF_INET6
7744 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7745 int len;
7746 char buf[BUFSIZ];
7747
7748 len = vty_out(
7749 vty, "%s",
7750 inet_ntop(AF_INET6,
7751 &attr->mp_nexthop_global, buf,
7752 BUFSIZ));
7753 len = 16 - len;
7754 if (len < 1)
7755 vty_out(vty, "\n%*s", 36, " ");
7756 else
7757 vty_out(vty, "%*s", len, " ");
7758 }
7759 if (attr->flag
7760 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7761 vty_out(vty, "%10u", attr->med);
7762 else
7763 vty_out(vty, " ");
718e3744 7764
d62a17ae 7765 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7766 vty_out(vty, "%7u", attr->local_pref);
7767 else
7768 vty_out(vty, " ");
7769
7770 vty_out(vty, "%7u ", attr->weight);
7771
7772 /* Print aspath */
7773 if (attr->aspath)
7774 aspath_print_vty(vty, "%s", attr->aspath, " ");
7775
7776 /* Print origin */
7777 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7778 }
7779 }
7780 if (use_json) {
7781 json_object_boolean_true_add(json_status, "*");
7782 json_object_boolean_true_add(json_status, ">");
7783 json_object_object_add(json_net, "appliedStatusSymbols",
7784 json_status);
1608ff77 7785
dc387b0f
LK
7786 prefix2str(p, buff, PREFIX_STRLEN);
7787 json_object_object_add(json_ar, buff, json_net);
d62a17ae 7788 } else
7789 vty_out(vty, "\n");
7790}
7791
7792void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7793 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7794 json_object *json)
7795{
7796 json_object *json_out = NULL;
7797 struct attr *attr;
7798 mpls_label_t label = MPLS_INVALID_LABEL;
7799
9b6d8fcf 7800 if (!path->extra)
d62a17ae 7801 return;
7802
7803 if (json)
7804 json_out = json_object_new_object();
7805
7806 /* short status lead text */
9b6d8fcf 7807 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7808
7809 /* print prefix and mask */
7810 if (json == NULL) {
7811 if (!display)
9c92b5f7 7812 route_vty_out_route(p, vty, NULL);
d62a17ae 7813 else
7814 vty_out(vty, "%*s", 17, " ");
7815 }
7816
7817 /* Print attribute */
9b6d8fcf 7818 attr = path->attr;
05864da7
DS
7819 if (((p->family == AF_INET)
7820 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7821 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7822 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7823 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7824 || safi == SAFI_EVPN) {
7825 if (json)
7826 json_object_string_add(
7827 json_out, "mpNexthopGlobalIn",
7828 inet_ntoa(attr->mp_nexthop_global_in));
7829 else
7830 vty_out(vty, "%-16s",
7831 inet_ntoa(attr->mp_nexthop_global_in));
7832 } else {
7833 if (json)
7834 json_object_string_add(
7835 json_out, "nexthop",
7836 inet_ntoa(attr->nexthop));
7837 else
7838 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
7839 }
7840 } else if (((p->family == AF_INET6)
7841 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7842 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7843 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7844 char buf_a[512];
7845
7846 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7847 if (json)
7848 json_object_string_add(
7849 json_out, "mpNexthopGlobalIn",
7850 inet_ntop(AF_INET6,
7851 &attr->mp_nexthop_global,
7852 buf_a, sizeof(buf_a)));
7853 else
7854 vty_out(vty, "%s",
7855 inet_ntop(AF_INET6,
7856 &attr->mp_nexthop_global,
7857 buf_a, sizeof(buf_a)));
7858 } else if (attr->mp_nexthop_len
7859 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7860 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
7861 &attr->mp_nexthop_global,
7862 &attr->mp_nexthop_local);
7863 if (json)
7864 json_object_string_add(json_out,
7865 "mpNexthopGlobalLocal",
7866 buf_a);
7867 else
7868 vty_out(vty, "%s", buf_a);
d62a17ae 7869 }
7870 }
7871
9b6d8fcf 7872 label = decode_label(&path->extra->label[0]);
d62a17ae 7873
7874 if (bgp_is_valid_label(&label)) {
7875 if (json) {
7876 json_object_int_add(json_out, "notag", label);
7877 json_object_array_add(json, json_out);
7878 } else {
7879 vty_out(vty, "notag/%d", label);
7880 vty_out(vty, "\n");
7881 }
7882 }
7883}
718e3744 7884
d62a17ae 7885void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7886 struct bgp_path_info *path, int display,
d62a17ae 7887 json_object *json_paths)
718e3744 7888{
d62a17ae 7889 struct attr *attr;
14f51eba 7890 char buf[BUFSIZ] = {0};
d62a17ae 7891 json_object *json_path = NULL;
14f51eba
LK
7892 json_object *json_nexthop = NULL;
7893 json_object *json_overlay = NULL;
856ca177 7894
9b6d8fcf 7895 if (!path->extra)
d62a17ae 7896 return;
718e3744 7897
14f51eba
LK
7898 if (json_paths) {
7899 json_path = json_object_new_object();
7900 json_overlay = json_object_new_object();
7901 json_nexthop = json_object_new_object();
7902 }
7903
d62a17ae 7904 /* short status lead text */
9b6d8fcf 7905 route_vty_short_status_out(vty, path, json_path);
856ca177 7906
d62a17ae 7907 /* print prefix and mask */
7908 if (!display)
14f51eba 7909 route_vty_out_route(p, vty, json_path);
d62a17ae 7910 else
7911 vty_out(vty, "%*s", 17, " ");
7912
7913 /* Print attribute */
9b6d8fcf 7914 attr = path->attr;
05864da7
DS
7915 char buf1[BUFSIZ];
7916 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 7917
05864da7
DS
7918 switch (af) {
7919 case AF_INET:
7920 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
7921 if (!json_path) {
7922 vty_out(vty, "%-16s", buf);
7923 } else {
7924 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 7925
05864da7 7926 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 7927
05864da7
DS
7928 json_object_object_add(json_path, "nexthop",
7929 json_nexthop);
7930 }
7931 break;
7932 case AF_INET6:
7933 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
7934 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
7935 if (!json_path) {
7936 vty_out(vty, "%s(%s)", buf, buf1);
7937 } else {
7938 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 7939
05864da7
DS
7940 json_object_string_add(json_nexthop, "ipv6LinkLocal",
7941 buf1);
14f51eba 7942
05864da7 7943 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 7944
05864da7
DS
7945 json_object_object_add(json_path, "nexthop",
7946 json_nexthop);
7947 }
7948 break;
7949 default:
7950 if (!json_path) {
7951 vty_out(vty, "?");
7952 } else {
7953 json_object_string_add(json_nexthop, "Error",
7954 "Unsupported address-family");
d62a17ae 7955 }
05864da7 7956 }
988258b4 7957
05864da7 7958 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 7959
05864da7
DS
7960 if (!json_path)
7961 vty_out(vty, "%s", str);
7962 else
7963 json_object_string_add(json_overlay, "esi", str);
25b5da8d 7964
05864da7 7965 XFREE(MTYPE_TMP, str);
988258b4 7966
05864da7
DS
7967 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
7968 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
7969 BUFSIZ);
7970 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
7971 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
7972 BUFSIZ);
7973 }
14f51eba 7974
05864da7
DS
7975 if (!json_path)
7976 vty_out(vty, "/%s", buf);
7977 else
7978 json_object_string_add(json_overlay, "gw", buf);
7979
7980 if (attr->ecommunity) {
7981 char *mac = NULL;
7982 struct ecommunity_val *routermac = ecommunity_lookup(
7983 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7984 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7985
7986 if (routermac)
7987 mac = ecom_mac2str((char *)routermac->val);
7988 if (mac) {
7989 if (!json_path) {
7990 vty_out(vty, "/%s", (char *)mac);
7991 } else {
7992 json_object_string_add(json_overlay, "rmac",
7993 mac);
988258b4 7994 }
05864da7 7995 XFREE(MTYPE_TMP, mac);
988258b4 7996 }
05864da7 7997 }
718e3744 7998
05864da7
DS
7999 if (!json_path) {
8000 vty_out(vty, "\n");
8001 } else {
8002 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8003
05864da7 8004 json_object_array_add(json_paths, json_path);
14f51eba 8005 }
d62a17ae 8006}
718e3744 8007
d62a17ae 8008/* dampening route */
8009static void damp_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8010 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8011 safi_t safi, bool use_json, json_object *json)
d62a17ae 8012{
8013 struct attr *attr;
8014 int len;
8015 char timebuf[BGP_UPTIME_LEN];
8016
8017 /* short status lead text */
9b6d8fcf 8018 route_vty_short_status_out(vty, path, json);
d62a17ae 8019
8020 /* print prefix and mask */
8021 if (!use_json) {
8022 if (!display)
9c92b5f7 8023 route_vty_out_route(p, vty, NULL);
d62a17ae 8024 else
8025 vty_out(vty, "%*s", 17, " ");
8026 }
8027
9b6d8fcf 8028 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8029 len = 17 - len;
8030 if (len < 1) {
8031 if (!use_json)
8032 vty_out(vty, "\n%*s", 34, " ");
8033 } else {
8034 if (use_json)
8035 json_object_int_add(json, "peerHost", len);
8036 else
8037 vty_out(vty, "%*s", len, " ");
8038 }
8039
8040 if (use_json)
a935f597
DA
8041 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8042 safi, use_json, json);
d62a17ae 8043 else
9b6d8fcf
DS
8044 vty_out(vty, "%s ",
8045 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8046 BGP_UPTIME_LEN, afi, safi,
8047 use_json, json));
d62a17ae 8048
8049 /* Print attribute */
9b6d8fcf 8050 attr = path->attr;
d62a17ae 8051
05864da7
DS
8052 /* Print aspath */
8053 if (attr->aspath) {
d62a17ae 8054 if (use_json)
05864da7
DS
8055 json_object_string_add(json, "asPath",
8056 attr->aspath->str);
d62a17ae 8057 else
05864da7 8058 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8059 }
05864da7
DS
8060
8061 /* Print origin */
8062 if (use_json)
8063 json_object_string_add(json, "origin",
8064 bgp_origin_str[attr->origin]);
8065 else
8066 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8067
d62a17ae 8068 if (!use_json)
8069 vty_out(vty, "\n");
8070}
718e3744 8071
d62a17ae 8072/* flap route */
8073static void flap_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8074 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8075 safi_t safi, bool use_json, json_object *json)
784d3a42 8076{
d62a17ae 8077 struct attr *attr;
8078 struct bgp_damp_info *bdi;
8079 char timebuf[BGP_UPTIME_LEN];
8080 int len;
784d3a42 8081
9b6d8fcf 8082 if (!path->extra)
d62a17ae 8083 return;
784d3a42 8084
9b6d8fcf 8085 bdi = path->extra->damp_info;
784d3a42 8086
d62a17ae 8087 /* short status lead text */
9b6d8fcf 8088 route_vty_short_status_out(vty, path, json);
784d3a42 8089
d62a17ae 8090 /* print prefix and mask */
8091 if (!use_json) {
8092 if (!display)
9c92b5f7 8093 route_vty_out_route(p, vty, NULL);
d62a17ae 8094 else
8095 vty_out(vty, "%*s", 17, " ");
8096 }
784d3a42 8097
9b6d8fcf 8098 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8099 len = 16 - len;
8100 if (len < 1) {
8101 if (!use_json)
8102 vty_out(vty, "\n%*s", 33, " ");
8103 } else {
8104 if (use_json)
8105 json_object_int_add(json, "peerHost", len);
8106 else
8107 vty_out(vty, "%*s", len, " ");
8108 }
784d3a42 8109
d62a17ae 8110 len = vty_out(vty, "%d", bdi->flap);
8111 len = 5 - len;
8112 if (len < 1) {
8113 if (!use_json)
8114 vty_out(vty, " ");
8115 } else {
8116 if (use_json)
8117 json_object_int_add(json, "bdiFlap", len);
8118 else
8119 vty_out(vty, "%*s", len, " ");
8120 }
8121
8122 if (use_json)
8123 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8124 json);
8125 else
996c9314
LB
8126 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8127 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8128
9b6d8fcf
DS
8129 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8130 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8131 if (use_json)
9b6d8fcf 8132 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8133 BGP_UPTIME_LEN, afi, safi,
8134 use_json, json);
d62a17ae 8135 else
8136 vty_out(vty, "%s ",
9b6d8fcf 8137 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8138 BGP_UPTIME_LEN, afi,
8139 safi, use_json, json));
d62a17ae 8140 } else {
8141 if (!use_json)
8142 vty_out(vty, "%*s ", 8, " ");
8143 }
8144
8145 /* Print attribute */
9b6d8fcf 8146 attr = path->attr;
d62a17ae 8147
05864da7
DS
8148 /* Print aspath */
8149 if (attr->aspath) {
d62a17ae 8150 if (use_json)
05864da7
DS
8151 json_object_string_add(json, "asPath",
8152 attr->aspath->str);
d62a17ae 8153 else
05864da7 8154 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8155 }
05864da7
DS
8156
8157 /* Print origin */
8158 if (use_json)
8159 json_object_string_add(json, "origin",
8160 bgp_origin_str[attr->origin]);
8161 else
8162 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8163
d62a17ae 8164 if (!use_json)
8165 vty_out(vty, "\n");
8166}
8167
8168static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8169 int *first, const char *header,
8170 json_object *json_adv_to)
8171{
8172 char buf1[INET6_ADDRSTRLEN];
8173 json_object *json_peer = NULL;
8174
8175 if (json_adv_to) {
8176 /* 'advertised-to' is a dictionary of peers we have advertised
8177 * this
8178 * prefix too. The key is the peer's IP or swpX, the value is
8179 * the
8180 * hostname if we know it and "" if not.
8181 */
8182 json_peer = json_object_new_object();
8183
8184 if (peer->hostname)
8185 json_object_string_add(json_peer, "hostname",
8186 peer->hostname);
8187
8188 if (peer->conf_if)
8189 json_object_object_add(json_adv_to, peer->conf_if,
8190 json_peer);
8191 else
8192 json_object_object_add(
8193 json_adv_to,
8194 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8195 json_peer);
8196 } else {
8197 if (*first) {
8198 vty_out(vty, "%s", header);
8199 *first = 0;
8200 }
8201
8202 if (peer->hostname
8203 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8204 if (peer->conf_if)
8205 vty_out(vty, " %s(%s)", peer->hostname,
8206 peer->conf_if);
8207 else
8208 vty_out(vty, " %s(%s)", peer->hostname,
8209 sockunion2str(&peer->su, buf1,
8210 SU_ADDRSTRLEN));
8211 } else {
8212 if (peer->conf_if)
8213 vty_out(vty, " %s", peer->conf_if);
8214 else
8215 vty_out(vty, " %s",
8216 sockunion2str(&peer->su, buf1,
8217 SU_ADDRSTRLEN));
8218 }
8219 }
784d3a42
PG
8220}
8221
dcc68b5e
MS
8222static void route_vty_out_tx_ids(struct vty *vty,
8223 struct bgp_addpath_info_data *d)
8224{
8225 int i;
8226
8227 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8228 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8229 d->addpath_tx_id[i],
8230 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8231 }
8232}
8233
0dc8ee70
DS
8234static const char *bgp_path_selection_reason2str(
8235 enum bgp_path_selection_reason reason)
8236{
8237 switch (reason) {
8238 case bgp_path_selection_none:
8239 return "Nothing to Select";
8240 break;
8241 case bgp_path_selection_first:
8242 return "First path received";
8243 break;
8244 case bgp_path_selection_evpn_sticky_mac:
8245 return "EVPN Sticky Mac";
8246 break;
8247 case bgp_path_selection_evpn_seq:
8248 return "EVPN sequence number";
8249 break;
8250 case bgp_path_selection_evpn_lower_ip:
8251 return "EVPN lower IP";
8252 break;
8253 case bgp_path_selection_weight:
8254 return "Weight";
8255 break;
8256 case bgp_path_selection_local_pref:
8257 return "Local Pref";
8258 break;
8259 case bgp_path_selection_local_route:
8260 return "Local Route";
8261 break;
8262 case bgp_path_selection_confed_as_path:
8263 return "Confederation based AS Path";
8264 break;
8265 case bgp_path_selection_as_path:
8266 return "AS Path";
8267 break;
8268 case bgp_path_selection_origin:
8269 return "Origin";
8270 break;
8271 case bgp_path_selection_med:
8272 return "MED";
8273 break;
8274 case bgp_path_selection_peer:
8275 return "Peer Type";
8276 break;
8277 case bgp_path_selection_confed:
8278 return "Confed Peer Type";
8279 break;
8280 case bgp_path_selection_igp_metric:
8281 return "IGP Metric";
8282 break;
8283 case bgp_path_selection_older:
8284 return "Older Path";
8285 break;
8286 case bgp_path_selection_router_id:
8287 return "Router ID";
8288 break;
8289 case bgp_path_selection_cluster_length:
8290 return "Cluser length";
8291 break;
8292 case bgp_path_selection_stale:
8293 return "Path Staleness";
8294 break;
8295 case bgp_path_selection_local_configured:
8296 return "Locally configured route";
8297 break;
8298 case bgp_path_selection_neighbor_ip:
8299 return "Neighbor IP";
8300 break;
8301 case bgp_path_selection_default:
8302 return "Nothing left to compare";
8303 break;
8304 }
a74879b2 8305 return "Invalid (internal error)";
0dc8ee70
DS
8306}
8307
f08b5ca0
DS
8308void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8309 struct bgp_node *bn, struct bgp_path_info *path,
8310 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8311{
8312 char buf[INET6_ADDRSTRLEN];
8313 char buf1[BUFSIZ];
d62a17ae 8314 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8315 struct attr *attr = path->attr;
d62a17ae 8316 int sockunion_vty_out(struct vty *, union sockunion *);
8317 time_t tbuf;
8318 json_object *json_bestpath = NULL;
8319 json_object *json_cluster_list = NULL;
8320 json_object *json_cluster_list_list = NULL;
8321 json_object *json_ext_community = NULL;
8322 json_object *json_last_update = NULL;
7fd077aa 8323 json_object *json_pmsi = NULL;
d62a17ae 8324 json_object *json_nexthop_global = NULL;
8325 json_object *json_nexthop_ll = NULL;
8326 json_object *json_nexthops = NULL;
8327 json_object *json_path = NULL;
8328 json_object *json_peer = NULL;
8329 json_object *json_string = NULL;
8330 json_object *json_adv_to = NULL;
8331 int first = 0;
8332 struct listnode *node, *nnode;
8333 struct peer *peer;
8334 int addpath_capable;
8335 int has_adj;
8336 unsigned int first_as;
1defdda8 8337 bool nexthop_self =
9b6d8fcf 8338 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8339 int i;
515c2602 8340 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 8341
8342 if (json_paths) {
8343 json_path = json_object_new_object();
8344 json_peer = json_object_new_object();
8345 json_nexthop_global = json_object_new_object();
8346 }
8347
44c69747 8348 if (path->extra) {
b57ba6d2 8349 char tag_buf[30];
d62a17ae 8350
d7325ee7 8351 buf2[0] = '\0';
d62a17ae 8352 tag_buf[0] = '\0';
9b6d8fcf
DS
8353 if (path->extra && path->extra->num_labels) {
8354 bgp_evpn_label2str(path->extra->label,
8355 path->extra->num_labels, tag_buf,
a4d82a8a 8356 sizeof(tag_buf));
d62a17ae 8357 }
d7325ee7 8358 if (safi == SAFI_EVPN) {
44c69747
LK
8359 if (!json_paths) {
8360 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8361 buf2, sizeof(buf2));
8362 vty_out(vty, " Route %s", buf2);
8363 if (tag_buf[0] != '\0')
8364 vty_out(vty, " VNI %s", tag_buf);
8365 vty_out(vty, "\n");
8366 } else {
8367 if (tag_buf[0])
8368 json_object_string_add(json_path, "VNI",
8369 tag_buf);
8370 }
d7325ee7
DD
8371 }
8372
44c69747 8373 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8374 struct bgp_path_info *parent_ri;
d62a17ae 8375 struct bgp_node *rn, *prn;
8376
9b6d8fcf 8377 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8378 rn = parent_ri->net;
8379 if (rn && rn->prn) {
8380 prn = rn->prn;
d7325ee7
DD
8381 prefix_rd2str((struct prefix_rd *)&prn->p,
8382 buf1, sizeof(buf1));
8383 if (is_pi_family_evpn(parent_ri)) {
8384 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8385 buf2, sizeof(buf2));
8386 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8387 } else
8388 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8389 }
8390 }
8391 }
d62a17ae 8392
05864da7
DS
8393 /* Line1 display AS-path, Aggregator */
8394 if (attr->aspath) {
8395 if (json_paths) {
8396 if (!attr->aspath->json)
8397 aspath_str_update(attr->aspath, true);
8398 json_object_lock(attr->aspath->json);
8399 json_object_object_add(json_path, "aspath",
8400 attr->aspath->json);
8401 } else {
8402 if (attr->aspath->segments)
8403 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8404 else
05864da7 8405 vty_out(vty, " Local");
d62a17ae 8406 }
05864da7 8407 }
d62a17ae 8408
05864da7
DS
8409 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8410 if (json_paths)
8411 json_object_boolean_true_add(json_path, "removed");
8412 else
8413 vty_out(vty, ", (removed)");
8414 }
d62a17ae 8415
05864da7
DS
8416 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8417 if (json_paths)
8418 json_object_boolean_true_add(json_path, "stale");
8419 else
8420 vty_out(vty, ", (stale)");
8421 }
d62a17ae 8422
05864da7
DS
8423 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8424 if (json_paths) {
8425 json_object_int_add(json_path, "aggregatorAs",
8426 attr->aggregator_as);
8427 json_object_string_add(
8428 json_path, "aggregatorId",
8429 inet_ntoa(attr->aggregator_addr));
8430 } else {
8431 vty_out(vty, ", (aggregated by %u %s)",
8432 attr->aggregator_as,
8433 inet_ntoa(attr->aggregator_addr));
d62a17ae 8434 }
05864da7 8435 }
d62a17ae 8436
05864da7
DS
8437 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8438 PEER_FLAG_REFLECTOR_CLIENT)) {
8439 if (json_paths)
8440 json_object_boolean_true_add(json_path,
8441 "rxedFromRrClient");
8442 else
8443 vty_out(vty, ", (Received from a RR-client)");
8444 }
d62a17ae 8445
05864da7
DS
8446 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8447 PEER_FLAG_RSERVER_CLIENT)) {
8448 if (json_paths)
8449 json_object_boolean_true_add(json_path,
8450 "rxedFromRsClient");
8451 else
8452 vty_out(vty, ", (Received from a RS-client)");
8453 }
d62a17ae 8454
05864da7
DS
8455 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8456 if (json_paths)
8457 json_object_boolean_true_add(json_path,
8458 "dampeningHistoryEntry");
8459 else
8460 vty_out(vty, ", (history entry)");
8461 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8462 if (json_paths)
8463 json_object_boolean_true_add(json_path,
8464 "dampeningSuppressed");
8465 else
8466 vty_out(vty, ", (suppressed due to dampening)");
8467 }
d62a17ae 8468
05864da7
DS
8469 if (!json_paths)
8470 vty_out(vty, "\n");
d62a17ae 8471
05864da7
DS
8472 /* Line2 display Next-hop, Neighbor, Router-id */
8473 /* Display the nexthop */
8474 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8475 || bn->p.family == AF_EVPN)
8476 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8477 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8478 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8479 || safi == SAFI_EVPN) {
515c2602 8480 if (json_paths) {
d62a17ae 8481 json_object_string_add(
515c2602
DA
8482 json_nexthop_global, "ip",
8483 inet_ntoa(attr->mp_nexthop_global_in));
8484
8485 if (nexthop_hostname)
8486 json_object_string_add(
8487 json_nexthop_global, "hostname",
8488 nexthop_hostname);
8489 } else
d62a17ae 8490 vty_out(vty, " %s",
515c2602
DA
8491 nexthop_hostname
8492 ? nexthop_hostname
05864da7 8493 : inet_ntoa(
515c2602 8494 attr->mp_nexthop_global_in));
d62a17ae 8495 } else {
515c2602 8496 if (json_paths) {
05864da7 8497 json_object_string_add(
515c2602
DA
8498 json_nexthop_global, "ip",
8499 inet_ntoa(attr->nexthop));
8500
8501 if (nexthop_hostname)
8502 json_object_string_add(
8503 json_nexthop_global, "hostname",
8504 nexthop_hostname);
8505 } else
05864da7 8506 vty_out(vty, " %s",
515c2602
DA
8507 nexthop_hostname
8508 ? nexthop_hostname
05864da7 8509 : inet_ntoa(attr->nexthop));
d62a17ae 8510 }
8511
05864da7
DS
8512 if (json_paths)
8513 json_object_string_add(json_nexthop_global, "afi",
8514 "ipv4");
8515 } else {
8516 if (json_paths) {
8517 json_object_string_add(
515c2602
DA
8518 json_nexthop_global, "ip",
8519 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8520 buf, INET6_ADDRSTRLEN));
8521
8522 if (nexthop_hostname)
8523 json_object_string_add(json_nexthop_global,
8524 "hostname",
8525 nexthop_hostname);
8526
05864da7
DS
8527 json_object_string_add(json_nexthop_global, "afi",
8528 "ipv6");
8529 json_object_string_add(json_nexthop_global, "scope",
8530 "global");
8531 } else {
8532 vty_out(vty, " %s",
515c2602
DA
8533 nexthop_hostname
8534 ? nexthop_hostname
05864da7
DS
8535 : inet_ntop(AF_INET6,
8536 &attr->mp_nexthop_global,
8537 buf, INET6_ADDRSTRLEN));
d62a17ae 8538 }
05864da7 8539 }
d62a17ae 8540
05864da7
DS
8541 /* Display the IGP cost or 'inaccessible' */
8542 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8543 if (json_paths)
8544 json_object_boolean_false_add(json_nexthop_global,
8545 "accessible");
8546 else
8547 vty_out(vty, " (inaccessible)");
8548 } else {
8549 if (path->extra && path->extra->igpmetric) {
d62a17ae 8550 if (json_paths)
05864da7
DS
8551 json_object_int_add(json_nexthop_global,
8552 "metric",
8553 path->extra->igpmetric);
d62a17ae 8554 else
05864da7
DS
8555 vty_out(vty, " (metric %u)",
8556 path->extra->igpmetric);
d62a17ae 8557 }
8558
05864da7 8559 /* IGP cost is 0, display this only for json */
d62a17ae 8560 else {
d62a17ae 8561 if (json_paths)
05864da7
DS
8562 json_object_int_add(json_nexthop_global,
8563 "metric", 0);
d62a17ae 8564 }
d62a17ae 8565
05864da7
DS
8566 if (json_paths)
8567 json_object_boolean_true_add(json_nexthop_global,
8568 "accessible");
8569 }
d62a17ae 8570
05864da7
DS
8571 /* Display peer "from" output */
8572 /* This path was originated locally */
8573 if (path->peer == bgp->peer_self) {
d62a17ae 8574
05864da7
DS
8575 if (safi == SAFI_EVPN
8576 || (bn->p.family == AF_INET
8577 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8578 if (json_paths)
05864da7
DS
8579 json_object_string_add(json_peer, "peerId",
8580 "0.0.0.0");
d62a17ae 8581 else
05864da7
DS
8582 vty_out(vty, " from 0.0.0.0 ");
8583 } else {
d62a17ae 8584 if (json_paths)
05864da7
DS
8585 json_object_string_add(json_peer, "peerId",
8586 "::");
d62a17ae 8587 else
05864da7 8588 vty_out(vty, " from :: ");
d62a17ae 8589 }
d62a17ae 8590
05864da7
DS
8591 if (json_paths)
8592 json_object_string_add(json_peer, "routerId",
8593 inet_ntoa(bgp->router_id));
8594 else
8595 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8596 }
d62a17ae 8597
05864da7
DS
8598 /* We RXed this path from one of our peers */
8599 else {
8600
8601 if (json_paths) {
8602 json_object_string_add(json_peer, "peerId",
8603 sockunion2str(&path->peer->su,
8604 buf,
8605 SU_ADDRSTRLEN));
8606 json_object_string_add(json_peer, "routerId",
8607 inet_ntop(AF_INET,
8608 &path->peer->remote_id,
8609 buf1, sizeof(buf1)));
8610
8611 if (path->peer->hostname)
8612 json_object_string_add(json_peer, "hostname",
8613 path->peer->hostname);
8614
8615 if (path->peer->domainname)
8616 json_object_string_add(json_peer, "domainname",
8617 path->peer->domainname);
8618
8619 if (path->peer->conf_if)
8620 json_object_string_add(json_peer, "interface",
8621 path->peer->conf_if);
8622 } else {
8623 if (path->peer->conf_if) {
8624 if (path->peer->hostname
8625 && bgp_flag_check(path->peer->bgp,
8626 BGP_FLAG_SHOW_HOSTNAME))
8627 vty_out(vty, " from %s(%s)",
8628 path->peer->hostname,
8629 path->peer->conf_if);
d62a17ae 8630 else
05864da7 8631 vty_out(vty, " from %s",
9b6d8fcf 8632 path->peer->conf_if);
d62a17ae 8633 } else {
05864da7
DS
8634 if (path->peer->hostname
8635 && bgp_flag_check(path->peer->bgp,
8636 BGP_FLAG_SHOW_HOSTNAME))
8637 vty_out(vty, " from %s(%s)",
8638 path->peer->hostname,
8639 path->peer->host);
d62a17ae 8640 else
05864da7
DS
8641 vty_out(vty, " from %s",
8642 sockunion2str(&path->peer->su,
8643 buf,
8644 SU_ADDRSTRLEN));
d62a17ae 8645 }
d62a17ae 8646
05864da7
DS
8647 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8648 vty_out(vty, " (%s)",
8649 inet_ntoa(attr->originator_id));
8650 else
8651 vty_out(vty, " (%s)",
8652 inet_ntop(AF_INET,
8653 &path->peer->remote_id, buf1,
8654 sizeof(buf1)));
d62a17ae 8655 }
05864da7 8656 }
9df8b37c 8657
05864da7
DS
8658 /*
8659 * Note when vrfid of nexthop is different from that of prefix
8660 */
8661 if (path->extra && path->extra->bgp_orig) {
8662 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8663
05864da7
DS
8664 if (json_paths) {
8665 const char *vn;
9df8b37c 8666
05864da7
DS
8667 if (path->extra->bgp_orig->inst_type
8668 == BGP_INSTANCE_TYPE_DEFAULT)
8669 vn = VRF_DEFAULT_NAME;
8670 else
8671 vn = path->extra->bgp_orig->name;
9df8b37c 8672
05864da7 8673 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8674
05864da7
DS
8675 if (nexthop_vrfid == VRF_UNKNOWN) {
8676 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8677 } else {
05864da7
DS
8678 json_object_int_add(json_path, "nhVrfId",
8679 (int)nexthop_vrfid);
9df8b37c 8680 }
05864da7
DS
8681 } else {
8682 if (nexthop_vrfid == VRF_UNKNOWN)
8683 vty_out(vty, " vrf ?");
d62a17ae 8684 else
05864da7 8685 vty_out(vty, " vrf %u", nexthop_vrfid);
9df8b37c 8686 }
05864da7 8687 }
9df8b37c 8688
05864da7
DS
8689 if (nexthop_self) {
8690 if (json_paths) {
8691 json_object_boolean_true_add(json_path,
8692 "announceNexthopSelf");
8693 } else {
8694 vty_out(vty, " announce-nh-self");
9df8b37c 8695 }
05864da7 8696 }
9df8b37c 8697
05864da7
DS
8698 if (!json_paths)
8699 vty_out(vty, "\n");
d62a17ae 8700
05864da7
DS
8701 /* display the link-local nexthop */
8702 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8703 if (json_paths) {
8704 json_nexthop_ll = json_object_new_object();
8705 json_object_string_add(
515c2602
DA
8706 json_nexthop_ll, "ip",
8707 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8708 buf, INET6_ADDRSTRLEN));
8709
8710 if (nexthop_hostname)
8711 json_object_string_add(json_nexthop_ll,
8712 "hostname",
8713 nexthop_hostname);
8714
05864da7
DS
8715 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8716 json_object_string_add(json_nexthop_ll, "scope",
8717 "link-local");
d62a17ae 8718
05864da7
DS
8719 json_object_boolean_true_add(json_nexthop_ll,
8720 "accessible");
d62a17ae 8721
05864da7 8722 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8723 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8724 "used");
8725 else
8726 json_object_boolean_true_add(
8727 json_nexthop_global, "used");
8728 } else {
8729 vty_out(vty, " (%s) %s\n",
8730 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8731 buf, INET6_ADDRSTRLEN),
8732 attr->mp_nexthop_prefer_global
8733 ? "(prefer-global)"
8734 : "(used)");
d62a17ae 8735 }
05864da7
DS
8736 }
8737 /* If we do not have a link-local nexthop then we must flag the
8738 global as "used" */
8739 else {
8740 if (json_paths)
8741 json_object_boolean_true_add(json_nexthop_global,
8742 "used");
8743 }
d62a17ae 8744
05864da7
DS
8745 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8746 * Int/Ext/Local, Atomic, best */
8747 if (json_paths)
8748 json_object_string_add(json_path, "origin",
8749 bgp_origin_long_str[attr->origin]);
8750 else
8751 vty_out(vty, " Origin %s",
8752 bgp_origin_long_str[attr->origin]);
9df8b37c 8753
05864da7
DS
8754 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
8755 if (json_paths) {
8756 /*
8757 * Adding "metric" field to match with
8758 * corresponding CLI. "med" will be
8759 * deprecated in future.
8760 */
8761 json_object_int_add(json_path, "med", attr->med);
8762 json_object_int_add(json_path, "metric", attr->med);
8763 } else
8764 vty_out(vty, ", metric %u", attr->med);
8765 }
9df8b37c 8766
05864da7
DS
8767 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8768 if (json_paths)
8769 json_object_int_add(json_path, "localpref",
8770 attr->local_pref);
8771 else
8772 vty_out(vty, ", localpref %u", attr->local_pref);
8773 }
9df8b37c 8774
05864da7
DS
8775 if (attr->weight != 0) {
8776 if (json_paths)
8777 json_object_int_add(json_path, "weight", attr->weight);
8778 else
8779 vty_out(vty, ", weight %u", attr->weight);
8780 }
9df8b37c 8781
05864da7
DS
8782 if (attr->tag != 0) {
8783 if (json_paths)
8784 json_object_int_add(json_path, "tag", attr->tag);
8785 else
8786 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
8787 }
9df8b37c 8788
05864da7
DS
8789 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8790 if (json_paths)
8791 json_object_boolean_false_add(json_path, "valid");
8792 else
8793 vty_out(vty, ", invalid");
8794 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8795 if (json_paths)
8796 json_object_boolean_true_add(json_path, "valid");
8797 else
8798 vty_out(vty, ", valid");
8799 }
9df8b37c 8800
05864da7
DS
8801 if (path->peer != bgp->peer_self) {
8802 if (path->peer->as == path->peer->local_as) {
8803 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
8804 if (json_paths)
8805 json_object_string_add(
8806 json_peer, "type",
8807 "confed-internal");
d62a17ae 8808 else
05864da7 8809 vty_out(vty, ", confed-internal");
d62a17ae 8810 } else {
05864da7
DS
8811 if (json_paths)
8812 json_object_string_add(
8813 json_peer, "type", "internal");
8814 else
8815 vty_out(vty, ", internal");
9df8b37c 8816 }
05864da7
DS
8817 } else {
8818 if (bgp_confederation_peers_check(bgp,
8819 path->peer->as)) {
8820 if (json_paths)
8821 json_object_string_add(
8822 json_peer, "type",
8823 "confed-external");
d62a17ae 8824 else
05864da7 8825 vty_out(vty, ", confed-external");
d62a17ae 8826 } else {
05864da7
DS
8827 if (json_paths)
8828 json_object_string_add(
8829 json_peer, "type", "external");
8830 else
8831 vty_out(vty, ", external");
d62a17ae 8832 }
8833 }
05864da7
DS
8834 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
8835 if (json_paths) {
8836 json_object_boolean_true_add(json_path, "aggregated");
8837 json_object_boolean_true_add(json_path, "local");
8838 } else {
8839 vty_out(vty, ", aggregated, local");
8840 }
8841 } else if (path->type != ZEBRA_ROUTE_BGP) {
8842 if (json_paths)
8843 json_object_boolean_true_add(json_path, "sourced");
8844 else
8845 vty_out(vty, ", sourced");
8846 } else {
8847 if (json_paths) {
8848 json_object_boolean_true_add(json_path, "sourced");
8849 json_object_boolean_true_add(json_path, "local");
8850 } else {
8851 vty_out(vty, ", sourced, local");
d62a17ae 8852 }
05864da7 8853 }
718e3744 8854
05864da7 8855 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 8856 if (json_paths)
05864da7
DS
8857 json_object_boolean_true_add(json_path,
8858 "atomicAggregate");
d62a17ae 8859 else
05864da7
DS
8860 vty_out(vty, ", atomic-aggregate");
8861 }
d62a17ae 8862
05864da7
DS
8863 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8864 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8865 && bgp_path_info_mpath_count(path))) {
8866 if (json_paths)
8867 json_object_boolean_true_add(json_path, "multipath");
8868 else
8869 vty_out(vty, ", multipath");
8870 }
50e05855 8871
05864da7
DS
8872 // Mark the bestpath(s)
8873 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
8874 first_as = aspath_get_first_as(attr->aspath);
718e3744 8875
05864da7
DS
8876 if (json_paths) {
8877 if (!json_bestpath)
8878 json_bestpath = json_object_new_object();
8879 json_object_int_add(json_bestpath, "bestpathFromAs",
8880 first_as);
8881 } else {
8882 if (first_as)
8883 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 8884 else
05864da7 8885 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 8886 }
05864da7 8887 }
718e3744 8888
05864da7
DS
8889 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8890 if (json_paths) {
8891 if (!json_bestpath)
8892 json_bestpath = json_object_new_object();
8893 json_object_boolean_true_add(json_bestpath, "overall");
8894 json_object_string_add(
8895 json_bestpath, "selectionReason",
8896 bgp_path_selection_reason2str(bn->reason));
8897 } else {
8898 vty_out(vty, ", best");
8899 vty_out(vty, " (%s)",
8900 bgp_path_selection_reason2str(bn->reason));
d62a17ae 8901 }
05864da7 8902 }
718e3744 8903
05864da7
DS
8904 if (json_bestpath)
8905 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 8906
05864da7
DS
8907 if (!json_paths)
8908 vty_out(vty, "\n");
8909
8910 /* Line 4 display Community */
8911 if (attr->community) {
8912 if (json_paths) {
8913 if (!attr->community->json)
8914 community_str(attr->community, true);
8915 json_object_lock(attr->community->json);
8916 json_object_object_add(json_path, "community",
8917 attr->community->json);
8918 } else {
8919 vty_out(vty, " Community: %s\n",
8920 attr->community->str);
d62a17ae 8921 }
05864da7 8922 }
718e3744 8923
05864da7
DS
8924 /* Line 5 display Extended-community */
8925 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8926 if (json_paths) {
8927 json_ext_community = json_object_new_object();
8928 json_object_string_add(json_ext_community, "string",
8929 attr->ecommunity->str);
8930 json_object_object_add(json_path, "extendedCommunity",
8931 json_ext_community);
d62a17ae 8932 } else {
05864da7
DS
8933 vty_out(vty, " Extended Community: %s\n",
8934 attr->ecommunity->str);
d62a17ae 8935 }
05864da7 8936 }
718e3744 8937
05864da7
DS
8938 /* Line 6 display Large community */
8939 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8940 if (json_paths) {
8941 if (!attr->lcommunity->json)
8942 lcommunity_str(attr->lcommunity, true);
8943 json_object_lock(attr->lcommunity->json);
8944 json_object_object_add(json_path, "largeCommunity",
8945 attr->lcommunity->json);
8946 } else {
8947 vty_out(vty, " Large Community: %s\n",
8948 attr->lcommunity->str);
d62a17ae 8949 }
05864da7 8950 }
718e3744 8951
05864da7
DS
8952 /* Line 7 display Originator, Cluster-id */
8953 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8954 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8955 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 8956 if (json_paths)
05864da7
DS
8957 json_object_string_add(
8958 json_path, "originatorId",
8959 inet_ntoa(attr->originator_id));
d62a17ae 8960 else
05864da7
DS
8961 vty_out(vty, " Originator: %s",
8962 inet_ntoa(attr->originator_id));
d62a17ae 8963 }
856ca177 8964
05864da7
DS
8965 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8966 int i;
d62a17ae 8967
8968 if (json_paths) {
05864da7
DS
8969 json_cluster_list = json_object_new_object();
8970 json_cluster_list_list =
8971 json_object_new_array();
8972
8973 for (i = 0; i < attr->cluster->length / 4;
8974 i++) {
8975 json_string = json_object_new_string(
8976 inet_ntoa(attr->cluster
8977 ->list[i]));
8978 json_object_array_add(
8979 json_cluster_list_list,
8980 json_string);
8981 }
718e3744 8982
05864da7
DS
8983 /*
8984 * struct cluster_list does not have
8985 * "str" variable like aspath and community
8986 * do. Add this someday if someone asks
8987 * for it.
8988 * json_object_string_add(json_cluster_list,
8989 * "string", attr->cluster->str);
8990 */
8991 json_object_object_add(json_cluster_list,
8992 "list",
8993 json_cluster_list_list);
8994 json_object_object_add(json_path, "clusterList",
8995 json_cluster_list);
0dc8ee70 8996 } else {
05864da7
DS
8997 vty_out(vty, ", Cluster list: ");
8998
8999 for (i = 0; i < attr->cluster->length / 4;
9000 i++) {
9001 vty_out(vty, "%s ",
9002 inet_ntoa(attr->cluster
9003 ->list[i]));
9004 }
0dc8ee70 9005 }
d62a17ae 9006 }
718e3744 9007
d62a17ae 9008 if (!json_paths)
9009 vty_out(vty, "\n");
05864da7 9010 }
d62a17ae 9011
05864da7 9012 if (path->extra && path->extra->damp_info)
a935f597 9013 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9014
05864da7
DS
9015 /* Remote Label */
9016 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9017 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9018 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9019
05864da7
DS
9020 if (json_paths)
9021 json_object_int_add(json_path, "remoteLabel", label);
9022 else
9023 vty_out(vty, " Remote label: %d\n", label);
9024 }
d62a17ae 9025
e496b420
HS
9026 /* Remote SID */
9027 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9028 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9029 if (json_paths)
9030 json_object_string_add(json_path, "remoteSid", buf);
9031 else
9032 vty_out(vty, " Remote SID: %s\n", buf);
9033 }
9034
05864da7
DS
9035 /* Label Index */
9036 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9037 if (json_paths)
9038 json_object_int_add(json_path, "labelIndex",
9039 attr->label_index);
9040 else
9041 vty_out(vty, " Label Index: %d\n",
9042 attr->label_index);
9043 }
d62a17ae 9044
05864da7
DS
9045 /* Line 8 display Addpath IDs */
9046 if (path->addpath_rx_id
9047 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9048 if (json_paths) {
9049 json_object_int_add(json_path, "addpathRxId",
9050 path->addpath_rx_id);
d62a17ae 9051
05864da7
DS
9052 /* Keep backwards compatibility with the old API
9053 * by putting TX All's ID in the old field
9054 */
9055 json_object_int_add(
9056 json_path, "addpathTxId",
9057 path->tx_addpath
9058 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9059
05864da7
DS
9060 /* ... but create a specific field for each
9061 * strategy
9062 */
9063 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9064 json_object_int_add(
9065 json_path,
9066 bgp_addpath_names(i)->id_json_name,
9067 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9068 }
05864da7
DS
9069 } else {
9070 vty_out(vty, " AddPath ID: RX %u, ",
9071 path->addpath_rx_id);
d62a17ae 9072
05864da7 9073 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9074 }
05864da7 9075 }
520d5d76 9076
05864da7
DS
9077 /* If we used addpath to TX a non-bestpath we need to display
9078 * "Advertised to" on a path-by-path basis
9079 */
9080 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9081 first = 1;
dcc68b5e 9082
05864da7
DS
9083 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9084 addpath_capable =
9085 bgp_addpath_encode_tx(peer, afi, safi);
9086 has_adj = bgp_adj_out_lookup(
9087 peer, path->net,
9088 bgp_addpath_id_for_peer(peer, afi, safi,
9089 &path->tx_addpath));
9090
9091 if ((addpath_capable && has_adj)
9092 || (!addpath_capable && has_adj
9093 && CHECK_FLAG(path->flags,
9094 BGP_PATH_SELECTED))) {
9095 if (json_path && !json_adv_to)
9096 json_adv_to = json_object_new_object();
dcc68b5e 9097
05864da7
DS
9098 route_vty_out_advertised_to(
9099 vty, peer, &first,
9100 " Advertised to:", json_adv_to);
d62a17ae 9101 }
9102 }
718e3744 9103
05864da7
DS
9104 if (json_path) {
9105 if (json_adv_to) {
9106 json_object_object_add(
9107 json_path, "advertisedTo", json_adv_to);
d62a17ae 9108 }
05864da7
DS
9109 } else {
9110 if (!first) {
9111 vty_out(vty, "\n");
d62a17ae 9112 }
9113 }
05864da7 9114 }
b05a1c8b 9115
05864da7
DS
9116 /* Line 9 display Uptime */
9117 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9118 if (json_paths) {
9119 json_last_update = json_object_new_object();
9120 json_object_int_add(json_last_update, "epoch", tbuf);
9121 json_object_string_add(json_last_update, "string",
9122 ctime(&tbuf));
9123 json_object_object_add(json_path, "lastUpdate",
9124 json_last_update);
9125 } else
9126 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9127
05864da7
DS
9128 /* Line 10 display PMSI tunnel attribute, if present */
9129 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9130 const char *str =
9131 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9132 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9133
05864da7
DS
9134 if (json_paths) {
9135 json_pmsi = json_object_new_object();
9136 json_object_string_add(json_pmsi, "tunnelType", str);
9137 json_object_int_add(json_pmsi, "label",
9138 label2vni(&attr->label));
9139 json_object_object_add(json_path, "pmsi", json_pmsi);
9140 } else
9141 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9142 str, label2vni(&attr->label));
d62a17ae 9143 }
f1aa5d8a 9144
d62a17ae 9145 /* We've constructed the json object for this path, add it to the json
9146 * array of paths
9147 */
9148 if (json_paths) {
9149 if (json_nexthop_global || json_nexthop_ll) {
9150 json_nexthops = json_object_new_array();
f1aa5d8a 9151
d62a17ae 9152 if (json_nexthop_global)
9153 json_object_array_add(json_nexthops,
9154 json_nexthop_global);
f1aa5d8a 9155
d62a17ae 9156 if (json_nexthop_ll)
9157 json_object_array_add(json_nexthops,
9158 json_nexthop_ll);
f1aa5d8a 9159
d62a17ae 9160 json_object_object_add(json_path, "nexthops",
9161 json_nexthops);
9162 }
9163
9164 json_object_object_add(json_path, "peer", json_peer);
9165 json_object_array_add(json_paths, json_path);
05864da7 9166 }
b366b518
BB
9167}
9168
96ade3ed 9169#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9170#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9171#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9172
d62a17ae 9173static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9174 const char *prefix_list_str, afi_t afi,
9175 safi_t safi, enum bgp_show_type type);
9176static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9177 const char *filter, afi_t afi, safi_t safi,
9178 enum bgp_show_type type);
9179static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9180 const char *rmap_str, afi_t afi, safi_t safi,
9181 enum bgp_show_type type);
9182static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9183 const char *com, int exact, afi_t afi,
9184 safi_t safi);
9185static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9186 const char *prefix, afi_t afi, safi_t safi,
9187 enum bgp_show_type type);
a4d82a8a 9188static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9189 afi_t afi, safi_t safi, enum bgp_show_type type,
9190 bool use_json);
7f323236
DW
9191static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9192 const char *comstr, int exact, afi_t afi,
9f049418 9193 safi_t safi, bool use_json);
d62a17ae 9194
1ae44dfc
LB
9195
9196static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9197 struct bgp_table *table, enum bgp_show_type type,
9f049418 9198 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9199 int is_last, unsigned long *output_cum,
9200 unsigned long *total_cum,
9386b588 9201 unsigned long *json_header_depth)
d62a17ae 9202{
40381db7 9203 struct bgp_path_info *pi;
d62a17ae 9204 struct bgp_node *rn;
9205 int header = 1;
9206 int display;
1ae44dfc
LB
9207 unsigned long output_count = 0;
9208 unsigned long total_count = 0;
d62a17ae 9209 struct prefix *p;
d62a17ae 9210 char buf2[BUFSIZ];
9211 json_object *json_paths = NULL;
9212 int first = 1;
9213
1ae44dfc
LB
9214 if (output_cum && *output_cum != 0)
9215 header = 0;
9216
9386b588 9217 if (use_json && !*json_header_depth) {
d62a17ae 9218 vty_out(vty,
66f80d74 9219 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9220 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9221 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9222 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9223 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9224 ? VRF_DEFAULT_NAME
9225 : bgp->name,
01eced22
AD
9226 table->version, inet_ntoa(bgp->router_id),
9227 bgp->default_local_pref, bgp->as);
9386b588
PZ
9228 *json_header_depth = 2;
9229 if (rd) {
445c2480 9230 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9231 ++*json_header_depth;
9232 }
d62a17ae 9233 }
718e3744 9234
445c2480
DS
9235 if (use_json && rd) {
9236 vty_out(vty, " \"%s\" : { ", rd);
9237 }
9238
d62a17ae 9239 /* Start processing of routes. */
98ce9a06 9240 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9241 pi = bgp_node_get_bgp_path_info(rn);
9242 if (pi == NULL)
98ce9a06 9243 continue;
d62a17ae 9244
98ce9a06 9245 display = 0;
98ce9a06
DS
9246 if (use_json)
9247 json_paths = json_object_new_array();
9248 else
9249 json_paths = NULL;
d62a17ae 9250
6f94b685 9251 for (; pi; pi = pi->next) {
98ce9a06
DS
9252 total_count++;
9253 if (type == bgp_show_type_flap_statistics
9254 || type == bgp_show_type_flap_neighbor
9255 || type == bgp_show_type_dampend_paths
9256 || type == bgp_show_type_damp_neighbor) {
40381db7 9257 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9258 continue;
9259 }
9260 if (type == bgp_show_type_regexp) {
9261 regex_t *regex = output_arg;
d62a17ae 9262
40381db7 9263 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9264 == REG_NOMATCH)
9265 continue;
9266 }
9267 if (type == bgp_show_type_prefix_list) {
9268 struct prefix_list *plist = output_arg;
d62a17ae 9269
98ce9a06
DS
9270 if (prefix_list_apply(plist, &rn->p)
9271 != PREFIX_PERMIT)
9272 continue;
9273 }
9274 if (type == bgp_show_type_filter_list) {
9275 struct as_list *as_list = output_arg;
d62a17ae 9276
40381db7 9277 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9278 != AS_FILTER_PERMIT)
9279 continue;
9280 }
9281 if (type == bgp_show_type_route_map) {
9282 struct route_map *rmap = output_arg;
9b6d8fcf 9283 struct bgp_path_info path;
98ce9a06 9284 struct attr dummy_attr;
b68885f9 9285 route_map_result_t ret;
d62a17ae 9286
6f4f49b2 9287 dummy_attr = *pi->attr;
d62a17ae 9288
40381db7 9289 path.peer = pi->peer;
9b6d8fcf 9290 path.attr = &dummy_attr;
d62a17ae 9291
a4d82a8a 9292 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9293 &path);
98ce9a06
DS
9294 if (ret == RMAP_DENYMATCH)
9295 continue;
9296 }
9297 if (type == bgp_show_type_neighbor
9298 || type == bgp_show_type_flap_neighbor
9299 || type == bgp_show_type_damp_neighbor) {
9300 union sockunion *su = output_arg;
9301
40381db7
DS
9302 if (pi->peer == NULL
9303 || pi->peer->su_remote == NULL
9304 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9305 continue;
9306 }
9307 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9308 uint32_t destination;
d62a17ae 9309
98ce9a06
DS
9310 destination = ntohl(rn->p.u.prefix4.s_addr);
9311 if (IN_CLASSC(destination)
9312 && rn->p.prefixlen == 24)
9313 continue;
9314 if (IN_CLASSB(destination)
9315 && rn->p.prefixlen == 16)
9316 continue;
9317 if (IN_CLASSA(destination)
9318 && rn->p.prefixlen == 8)
9319 continue;
9320 }
9321 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9322 p = output_arg;
98ce9a06
DS
9323 if (!prefix_match(p, &rn->p))
9324 continue;
9325 }
9326 if (type == bgp_show_type_community_all) {
40381db7 9327 if (!pi->attr->community)
98ce9a06
DS
9328 continue;
9329 }
9330 if (type == bgp_show_type_community) {
9331 struct community *com = output_arg;
d62a17ae 9332
40381db7
DS
9333 if (!pi->attr->community
9334 || !community_match(pi->attr->community,
98ce9a06
DS
9335 com))
9336 continue;
9337 }
9338 if (type == bgp_show_type_community_exact) {
9339 struct community *com = output_arg;
d62a17ae 9340
40381db7
DS
9341 if (!pi->attr->community
9342 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9343 continue;
9344 }
9345 if (type == bgp_show_type_community_list) {
9346 struct community_list *list = output_arg;
d62a17ae 9347
40381db7 9348 if (!community_list_match(pi->attr->community,
a4d82a8a 9349 list))
98ce9a06
DS
9350 continue;
9351 }
a4d82a8a 9352 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9353 struct community_list *list = output_arg;
d62a17ae 9354
98ce9a06 9355 if (!community_list_exact_match(
40381db7 9356 pi->attr->community, list))
98ce9a06
DS
9357 continue;
9358 }
9359 if (type == bgp_show_type_lcommunity) {
9360 struct lcommunity *lcom = output_arg;
d62a17ae 9361
40381db7
DS
9362 if (!pi->attr->lcommunity
9363 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9364 lcom))
9365 continue;
9366 }
36a206db 9367
9368 if (type == bgp_show_type_lcommunity_exact) {
9369 struct lcommunity *lcom = output_arg;
9370
9371 if (!pi->attr->lcommunity
9372 || !lcommunity_cmp(pi->attr->lcommunity,
9373 lcom))
9374 continue;
9375 }
98ce9a06
DS
9376 if (type == bgp_show_type_lcommunity_list) {
9377 struct community_list *list = output_arg;
d62a17ae 9378
40381db7 9379 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9380 list))
98ce9a06
DS
9381 continue;
9382 }
36a206db 9383 if (type
9384 == bgp_show_type_lcommunity_list_exact) {
9385 struct community_list *list = output_arg;
9386
9387 if (!lcommunity_list_exact_match(
9388 pi->attr->lcommunity, list))
9389 continue;
9390 }
98ce9a06 9391 if (type == bgp_show_type_lcommunity_all) {
40381db7 9392 if (!pi->attr->lcommunity)
98ce9a06
DS
9393 continue;
9394 }
9395 if (type == bgp_show_type_dampend_paths
9396 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9397 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9398 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9399 continue;
9400 }
9401
9402 if (!use_json && header) {
996c9314 9403 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9404 ", local router ID is %s, vrf id ",
98ce9a06
DS
9405 table->version,
9406 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9407 if (bgp->vrf_id == VRF_UNKNOWN)
9408 vty_out(vty, "%s", VRFID_NONE_STR);
9409 else
9410 vty_out(vty, "%u", bgp->vrf_id);
9411 vty_out(vty, "\n");
01eced22
AD
9412 vty_out(vty, "Default local pref %u, ",
9413 bgp->default_local_pref);
9414 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9415 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9416 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9417 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9418 if (type == bgp_show_type_dampend_paths
9419 || type == bgp_show_type_damp_neighbor)
98ce9a06 9420 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9421 else if (type == bgp_show_type_flap_statistics
9422 || type == bgp_show_type_flap_neighbor)
98ce9a06 9423 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9424 else
98ce9a06
DS
9425 vty_out(vty, BGP_SHOW_HEADER);
9426 header = 0;
d62a17ae 9427 }
98ce9a06
DS
9428 if (rd != NULL && !display && !output_count) {
9429 if (!use_json)
9430 vty_out(vty,
9431 "Route Distinguisher: %s\n",
9432 rd);
d62a17ae 9433 }
98ce9a06
DS
9434 if (type == bgp_show_type_dampend_paths
9435 || type == bgp_show_type_damp_neighbor)
a935f597 9436 damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9437 safi, use_json, json_paths);
98ce9a06
DS
9438 else if (type == bgp_show_type_flap_statistics
9439 || type == bgp_show_type_flap_neighbor)
a935f597 9440 flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9441 safi, use_json, json_paths);
98ce9a06 9442 else
40381db7 9443 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9444 json_paths);
98ce9a06 9445 display++;
d62a17ae 9446 }
9447
98ce9a06
DS
9448 if (display) {
9449 output_count++;
9450 if (!use_json)
9451 continue;
9452
9453 p = &rn->p;
625d2931
PG
9454 /* encode prefix */
9455 if (p->family == AF_FLOWSPEC) {
9456 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9457
9458 bgp_fs_nlri_get_string((unsigned char *)
9459 p->u.prefix_flowspec.ptr,
9460 p->u.prefix_flowspec
9461 .prefixlen,
9462 retstr,
9463 NLRI_STRING_FORMAT_MIN,
9464 NULL);
9465 if (first)
9466 vty_out(vty, "\"%s/%d\": ",
9467 retstr,
9468 p->u.prefix_flowspec.prefixlen);
9469 else
9470 vty_out(vty, ",\"%s/%d\": ",
9471 retstr,
9472 p->u.prefix_flowspec.prefixlen);
9473 } else {
9474 prefix2str(p, buf2, sizeof(buf2));
9475 if (first)
9476 vty_out(vty, "\"%s\": ", buf2);
9477 else
9478 vty_out(vty, ",\"%s\": ", buf2);
9479 }
98ce9a06 9480 vty_out(vty, "%s",
f4ec52f7
DA
9481 json_object_to_json_string_ext(
9482 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9483 json_object_free(json_paths);
449feb8e 9484 json_paths = NULL;
98ce9a06 9485 first = 0;
1f83ed02
DS
9486 } else
9487 json_object_free(json_paths);
98ce9a06
DS
9488 }
9489
1ae44dfc
LB
9490 if (output_cum) {
9491 output_count += *output_cum;
9492 *output_cum = output_count;
9493 }
9494 if (total_cum) {
9495 total_count += *total_cum;
9496 *total_cum = total_count;
9497 }
d62a17ae 9498 if (use_json) {
9386b588 9499 if (rd) {
a4d82a8a 9500 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9501 }
9502 if (is_last) {
a4d82a8a
PZ
9503 unsigned long i;
9504 for (i = 0; i < *json_header_depth; ++i)
9505 vty_out(vty, " } ");
faf6559a 9506 vty_out(vty, "\n");
9386b588 9507 }
d62a17ae 9508 } else {
1ae44dfc
LB
9509 if (is_last) {
9510 /* No route is displayed */
9511 if (output_count == 0) {
9512 if (type == bgp_show_type_normal)
9513 vty_out(vty,
9514 "No BGP prefixes displayed, %ld exist\n",
9515 total_count);
9516 } else
d62a17ae 9517 vty_out(vty,
1ae44dfc
LB
9518 "\nDisplayed %ld routes and %ld total paths\n",
9519 output_count, total_count);
9520 }
d62a17ae 9521 }
718e3744 9522
d62a17ae 9523 return CMD_SUCCESS;
718e3744 9524}
9525
1ae44dfc
LB
9526int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9527 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9528 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9529{
9530 struct bgp_node *rn, *next;
9531 unsigned long output_cum = 0;
9532 unsigned long total_cum = 0;
9386b588 9533 unsigned long json_header_depth = 0;
67009e22 9534 struct bgp_table *itable;
0136788c
LB
9535 bool show_msg;
9536
9537 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9538
9539 for (rn = bgp_table_top(table); rn; rn = next) {
9540 next = bgp_route_next(rn);
9541 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9542 continue;
67009e22
DS
9543
9544 itable = bgp_node_get_bgp_table_info(rn);
9545 if (itable != NULL) {
1ae44dfc 9546 struct prefix_rd prd;
06b9f471 9547 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9548
9549 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9550 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9551 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9552 use_json, rd, next == NULL, &output_cum,
9553 &total_cum, &json_header_depth);
0136788c
LB
9554 if (next == NULL)
9555 show_msg = false;
1ae44dfc
LB
9556 }
9557 }
0136788c
LB
9558 if (show_msg) {
9559 if (output_cum == 0)
9560 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9561 total_cum);
9562 else
9563 vty_out(vty,
9564 "\nDisplayed %ld routes and %ld total paths\n",
9565 output_cum, total_cum);
9566 }
1ae44dfc
LB
9567 return CMD_SUCCESS;
9568}
d62a17ae 9569static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9570 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9571{
d62a17ae 9572 struct bgp_table *table;
9386b588 9573 unsigned long json_header_depth = 0;
fee0f4c6 9574
d62a17ae 9575 if (bgp == NULL) {
9576 bgp = bgp_get_default();
9577 }
fee0f4c6 9578
d62a17ae 9579 if (bgp == NULL) {
9580 if (!use_json)
9581 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9582 else
9583 vty_out(vty, "{}\n");
d62a17ae 9584 return CMD_WARNING;
9585 }
4dd6177e 9586
1ae44dfc 9587 table = bgp->rib[afi][safi];
d62a17ae 9588 /* use MPLS and ENCAP specific shows until they are merged */
9589 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9590 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9591 output_arg, use_json);
d62a17ae 9592 }
dba3c1d3
PG
9593
9594 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9595 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9596 output_arg, use_json,
9597 1, NULL, NULL);
9598 }
d62a17ae 9599 /* labeled-unicast routes live in the unicast table */
9600 else if (safi == SAFI_LABELED_UNICAST)
9601 safi = SAFI_UNICAST;
fee0f4c6 9602
1ae44dfc 9603 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9604 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9605}
9606
d62a17ae 9607static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9608 safi_t safi, bool use_json)
f186de26 9609{
d62a17ae 9610 struct listnode *node, *nnode;
9611 struct bgp *bgp;
9612 int is_first = 1;
9f049418 9613 bool route_output = false;
f186de26 9614
d62a17ae 9615 if (use_json)
9616 vty_out(vty, "{\n");
9f689658 9617
d62a17ae 9618 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9619 route_output = true;
d62a17ae 9620 if (use_json) {
9621 if (!is_first)
9622 vty_out(vty, ",\n");
9623 else
9624 is_first = 0;
9625
9626 vty_out(vty, "\"%s\":",
9627 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9628 ? VRF_DEFAULT_NAME
d62a17ae 9629 : bgp->name);
9630 } else {
9631 vty_out(vty, "\nInstance %s:\n",
9632 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9633 ? VRF_DEFAULT_NAME
d62a17ae 9634 : bgp->name);
9635 }
9636 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9637 use_json);
9638 }
9f689658 9639
d62a17ae 9640 if (use_json)
9641 vty_out(vty, "}\n");
9f049418
DS
9642 else if (!route_output)
9643 vty_out(vty, "%% BGP instance not found\n");
f186de26 9644}
9645
718e3744 9646/* Header of detailed BGP route information */
d62a17ae 9647void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9648 struct bgp_node *rn, struct prefix_rd *prd,
9649 afi_t afi, safi_t safi, json_object *json)
9650{
40381db7 9651 struct bgp_path_info *pi;
d62a17ae 9652 struct prefix *p;
9653 struct peer *peer;
9654 struct listnode *node, *nnode;
06b9f471 9655 char buf1[RD_ADDRSTRLEN];
d62a17ae 9656 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9657 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9658 char prefix_str[BUFSIZ];
d62a17ae 9659 int count = 0;
9660 int best = 0;
9661 int suppress = 0;
c5f1e1b2
C
9662 int accept_own = 0;
9663 int route_filter_translated_v4 = 0;
9664 int route_filter_v4 = 0;
9665 int route_filter_translated_v6 = 0;
9666 int route_filter_v6 = 0;
9667 int llgr_stale = 0;
9668 int no_llgr = 0;
9669 int accept_own_nexthop = 0;
9670 int blackhole = 0;
d62a17ae 9671 int no_export = 0;
9672 int no_advertise = 0;
9673 int local_as = 0;
c5f1e1b2 9674 int no_peer = 0;
d62a17ae 9675 int first = 1;
9676 int has_valid_label = 0;
9677 mpls_label_t label = 0;
9678 json_object *json_adv_to = NULL;
9bedbb1e 9679
d62a17ae 9680 p = &rn->p;
9681 has_valid_label = bgp_is_valid_label(&rn->local_label);
9682
9683 if (has_valid_label)
9684 label = label_pton(&rn->local_label);
9685
44c69747 9686 if (safi == SAFI_EVPN) {
d62a17ae 9687
44c69747 9688 if (!json) {
d62a17ae 9689 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9690 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9691 : "", prd ? ":" : "",
d62a17ae 9692 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9693 buf3, sizeof(buf3)));
9694 } else {
9695 json_object_string_add(json, "rd",
9696 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9697 "");
9698 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9699 }
9700 } else {
9701 if (!json) {
d62a17ae 9702 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9703 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9704 ? prefix_rd2str(prd, buf1,
9705 sizeof(buf1))
9706 : ""),
d62a17ae 9707 safi == SAFI_MPLS_VPN ? ":" : "",
9708 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9709 INET6_ADDRSTRLEN),
d62a17ae 9710 p->prefixlen);
cd1964ff 9711
44c69747
LK
9712 } else
9713 json_object_string_add(json, "prefix",
9714 prefix2str(p, prefix_str, sizeof(prefix_str)));
9715 }
9716
9717 if (has_valid_label) {
9718 if (json)
9719 json_object_int_add(json, "localLabel", label);
9720 else
d62a17ae 9721 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9722 }
9723
9724 if (!json)
d62a17ae 9725 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9726 vty_out(vty, "not allocated\n");
718e3744 9727
6f94b685 9728 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9729 count++;
40381db7 9730 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9731 best = count;
40381db7 9732 if (pi->extra && pi->extra->suppress)
d62a17ae 9733 suppress = 1;
cee9c031 9734
40381db7 9735 if (pi->attr->community == NULL)
cee9c031
QY
9736 continue;
9737
9738 no_advertise += community_include(
40381db7
DS
9739 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9740 no_export += community_include(pi->attr->community,
cee9c031 9741 COMMUNITY_NO_EXPORT);
40381db7 9742 local_as += community_include(pi->attr->community,
cee9c031 9743 COMMUNITY_LOCAL_AS);
40381db7 9744 accept_own += community_include(pi->attr->community,
cee9c031
QY
9745 COMMUNITY_ACCEPT_OWN);
9746 route_filter_translated_v4 += community_include(
40381db7 9747 pi->attr->community,
cee9c031
QY
9748 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9749 route_filter_translated_v6 += community_include(
40381db7 9750 pi->attr->community,
cee9c031
QY
9751 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9752 route_filter_v4 += community_include(
40381db7 9753 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9754 route_filter_v6 += community_include(
40381db7
DS
9755 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9756 llgr_stale += community_include(pi->attr->community,
cee9c031 9757 COMMUNITY_LLGR_STALE);
40381db7 9758 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9759 COMMUNITY_NO_LLGR);
9760 accept_own_nexthop +=
40381db7 9761 community_include(pi->attr->community,
cee9c031 9762 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9763 blackhole += community_include(pi->attr->community,
cee9c031 9764 COMMUNITY_BLACKHOLE);
40381db7 9765 no_peer += community_include(pi->attr->community,
cee9c031 9766 COMMUNITY_NO_PEER);
d62a17ae 9767 }
718e3744 9768 }
718e3744 9769
d62a17ae 9770 if (!json) {
9771 vty_out(vty, "Paths: (%d available", count);
9772 if (best) {
9773 vty_out(vty, ", best #%d", best);
b84060bb
PG
9774 if (safi == SAFI_UNICAST) {
9775 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9776 vty_out(vty, ", table %s",
9777 VRF_DEFAULT_NAME);
9778 else
9779 vty_out(vty, ", vrf %s",
9780 bgp->name);
9781 }
d62a17ae 9782 } else
9783 vty_out(vty, ", no best path");
9784
c5f1e1b2
C
9785 if (accept_own)
9786 vty_out(vty,
9787 ", accept own local route exported and imported in different VRF");
9788 else if (route_filter_translated_v4)
9789 vty_out(vty,
9790 ", mark translated RTs for VPNv4 route filtering");
9791 else if (route_filter_v4)
9792 vty_out(vty,
9793 ", attach RT as-is for VPNv4 route filtering");
9794 else if (route_filter_translated_v6)
9795 vty_out(vty,
9796 ", mark translated RTs for VPNv6 route filtering");
9797 else if (route_filter_v6)
9798 vty_out(vty,
9799 ", attach RT as-is for VPNv6 route filtering");
9800 else if (llgr_stale)
9801 vty_out(vty,
9802 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9803 else if (no_llgr)
9804 vty_out(vty,
9805 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9806 else if (accept_own_nexthop)
9807 vty_out(vty,
9808 ", accept local nexthop");
9809 else if (blackhole)
9810 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9811 else if (no_export)
9812 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9813 else if (no_advertise)
9814 vty_out(vty, ", not advertised to any peer");
d62a17ae 9815 else if (local_as)
9816 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9817 else if (no_peer)
9818 vty_out(vty,
9819 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9820
9821 if (suppress)
9822 vty_out(vty,
9823 ", Advertisements suppressed by an aggregate.");
9824 vty_out(vty, ")\n");
9825 }
718e3744 9826
d62a17ae 9827 /* If we are not using addpath then we can display Advertised to and
9828 * that will
9829 * show what peers we advertised the bestpath to. If we are using
9830 * addpath
9831 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9832 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9833 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9834 if (bgp_adj_out_lookup(peer, rn, 0)) {
9835 if (json && !json_adv_to)
9836 json_adv_to = json_object_new_object();
9837
9838 route_vty_out_advertised_to(
9839 vty, peer, &first,
9840 " Advertised to non peer-group peers:\n ",
9841 json_adv_to);
9842 }
9843 }
9844
9845 if (json) {
9846 if (json_adv_to) {
9847 json_object_object_add(json, "advertisedTo",
9848 json_adv_to);
9849 }
9850 } else {
9851 if (first)
9852 vty_out(vty, " Not advertised to any peer");
9853 vty_out(vty, "\n");
9854 }
9855 }
718e3744 9856}
9857
44c69747
LK
9858static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9859 struct bgp_node *bgp_node, struct vty *vty,
9860 struct bgp *bgp, afi_t afi,
9861 safi_t safi, json_object *json,
9862 enum bgp_path_type pathtype, int *display)
9863{
9864 struct bgp_path_info *pi;
9865 int header = 1;
9866 char rdbuf[RD_ADDRSTRLEN];
9867 json_object *json_header = NULL;
9868 json_object *json_paths = NULL;
9869
9870 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
9871 pi = pi->next) {
9872
9873 if (json && !json_paths) {
9874 /* Instantiate json_paths only if path is valid */
9875 json_paths = json_object_new_array();
9876 if (pfx_rd) {
9877 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
9878 json_header = json_object_new_object();
9879 } else
9880 json_header = json;
9881 }
9882
9883 if (header) {
9884 route_vty_out_detail_header(
9885 vty, bgp, bgp_node, pfx_rd,
9886 AFI_IP, safi, json_header);
9887 header = 0;
9888 }
9889 (*display)++;
9890
9891 if (pathtype == BGP_PATH_SHOW_ALL
9892 || (pathtype == BGP_PATH_SHOW_BESTPATH
9893 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
9894 || (pathtype == BGP_PATH_SHOW_MULTIPATH
9895 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
9896 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
9897 route_vty_out_detail(vty, bgp, bgp_node,
9898 pi, AFI_IP, safi,
9899 json_paths);
9900 }
9901
9902 if (json && json_paths) {
9903 json_object_object_add(json_header, "paths", json_paths);
9904
9905 if (pfx_rd)
9906 json_object_object_add(json, rdbuf, json_header);
9907 }
9908}
9909
718e3744 9910/* Display specified route of BGP table. */
d62a17ae 9911static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9912 struct bgp_table *rib, const char *ip_str,
9913 afi_t afi, safi_t safi,
9914 struct prefix_rd *prd, int prefix_check,
9f049418 9915 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9916{
9917 int ret;
d62a17ae 9918 int display = 0;
9919 struct prefix match;
9920 struct bgp_node *rn;
9921 struct bgp_node *rm;
d62a17ae 9922 struct bgp_table *table;
9923 json_object *json = NULL;
9924 json_object *json_paths = NULL;
9925
9926 /* Check IP address argument. */
9927 ret = str2prefix(ip_str, &match);
9928 if (!ret) {
9929 vty_out(vty, "address is malformed\n");
9930 return CMD_WARNING;
9931 }
718e3744 9932
d62a17ae 9933 match.family = afi2family(afi);
b05a1c8b 9934
44c69747 9935 if (use_json)
d62a17ae 9936 json = json_object_new_object();
718e3744 9937
44c69747 9938 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 9939 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9940 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9941 continue;
67009e22
DS
9942 table = bgp_node_get_bgp_table_info(rn);
9943 if (!table)
ea47320b 9944 continue;
d62a17ae 9945
ea47320b
DL
9946 if ((rm = bgp_node_match(table, &match)) == NULL)
9947 continue;
d62a17ae 9948
ea47320b
DL
9949 if (prefix_check
9950 && rm->p.prefixlen != match.prefixlen) {
9951 bgp_unlock_node(rm);
9952 continue;
9953 }
d62a17ae 9954
44c69747
LK
9955 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9956 vty, bgp, afi, safi, json,
9957 pathtype, &display);
9958
9959 bgp_unlock_node(rm);
9960 }
9961 } else if (safi == SAFI_EVPN) {
9962 struct bgp_node *longest_pfx;
9963 bool is_exact_pfxlen_match = FALSE;
9964
9965 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9966 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9967 continue;
9968 table = bgp_node_get_bgp_table_info(rn);
9969 if (!table)
9970 continue;
9971
9972 longest_pfx = NULL;
9973 is_exact_pfxlen_match = FALSE;
9974 /*
9975 * Search through all the prefixes for a match. The
9976 * pfx's are enumerated in ascending order of pfxlens.
9977 * So, the last pfx match is the longest match. Set
9978 * is_exact_pfxlen_match when we get exact pfxlen match
9979 */
9980 for (rm = bgp_table_top(table); rm;
9981 rm = bgp_route_next(rm)) {
9982 /*
9983 * Get prefixlen of the ip-prefix within type5
9984 * evpn route
9985 */
9986 if (evpn_type5_prefix_match(&rm->p,
9987 &match) && rm->info) {
9988 longest_pfx = rm;
9989 int type5_pfxlen =
9990 bgp_evpn_get_type5_prefixlen(&rm->p);
9991 if (type5_pfxlen == match.prefixlen) {
9992 is_exact_pfxlen_match = TRUE;
9993 bgp_unlock_node(rm);
9994 break;
9995 }
d62a17ae 9996 }
9997 }
ea47320b 9998
44c69747
LK
9999 if (!longest_pfx)
10000 continue;
10001
10002 if (prefix_check && !is_exact_pfxlen_match)
10003 continue;
10004
10005 rm = longest_pfx;
10006 bgp_lock_node(rm);
10007
10008 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10009 vty, bgp, afi, safi, json,
10010 pathtype, &display);
10011
ea47320b 10012 bgp_unlock_node(rm);
d62a17ae 10013 }
98a9dbc7 10014 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10015 if (use_json)
10016 json_paths = json_object_new_array();
10017
63a0b7a9
PG
10018 display = bgp_flowspec_display_match_per_ip(afi, rib,
10019 &match, prefix_check,
10020 vty,
10021 use_json,
10022 json_paths);
44c69747
LK
10023 if (use_json && display)
10024 json_object_object_add(json, "paths", json_paths);
d62a17ae 10025 } else {
d62a17ae 10026 if ((rn = bgp_node_match(rib, &match)) != NULL) {
10027 if (!prefix_check
10028 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
10029 bgp_show_path_info(NULL, rn, vty, bgp, afi,
10030 safi, json,
10031 pathtype, &display);
d62a17ae 10032 }
10033
10034 bgp_unlock_node(rn);
10035 }
10036 }
e5eee9af 10037
d62a17ae 10038 if (use_json) {
996c9314 10039 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10040 json, JSON_C_TO_STRING_PRETTY |
10041 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10042 json_object_free(json);
10043 } else {
10044 if (!display) {
10045 vty_out(vty, "%% Network not in table\n");
10046 return CMD_WARNING;
10047 }
10048 }
b05a1c8b 10049
d62a17ae 10050 return CMD_SUCCESS;
718e3744 10051}
10052
fee0f4c6 10053/* Display specified route of Main RIB */
d62a17ae 10054static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10055 afi_t afi, safi_t safi, struct prefix_rd *prd,
10056 int prefix_check, enum bgp_path_type pathtype,
9f049418 10057 bool use_json)
d62a17ae 10058{
9b86009a 10059 if (!bgp) {
d62a17ae 10060 bgp = bgp_get_default();
9b86009a
RW
10061 if (!bgp) {
10062 if (!use_json)
10063 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10064 else
10065 vty_out(vty, "{}\n");
9b86009a
RW
10066 return CMD_WARNING;
10067 }
10068 }
d62a17ae 10069
10070 /* labeled-unicast routes live in the unicast table */
10071 if (safi == SAFI_LABELED_UNICAST)
10072 safi = SAFI_UNICAST;
10073
10074 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10075 afi, safi, prd, prefix_check, pathtype,
10076 use_json);
10077}
10078
10079static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10080 struct cmd_token **argv, bool exact, afi_t afi,
10081 safi_t safi, bool uj)
d62a17ae 10082{
10083 struct lcommunity *lcom;
10084 struct buffer *b;
10085 int i;
10086 char *str;
10087 int first = 0;
10088
10089 b = buffer_new(1024);
10090 for (i = 0; i < argc; i++) {
10091 if (first)
10092 buffer_putc(b, ' ');
10093 else {
10094 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10095 first = 1;
10096 buffer_putstr(b, argv[i]->arg);
10097 }
10098 }
10099 }
10100 buffer_putc(b, '\0');
57d187bc 10101
d62a17ae 10102 str = buffer_getstr(b);
10103 buffer_free(b);
57d187bc 10104
d62a17ae 10105 lcom = lcommunity_str2com(str);
10106 XFREE(MTYPE_TMP, str);
10107 if (!lcom) {
10108 vty_out(vty, "%% Large-community malformed\n");
10109 return CMD_WARNING;
10110 }
57d187bc 10111
36a206db 10112 return bgp_show(vty, bgp, afi, safi,
10113 (exact ? bgp_show_type_lcommunity_exact
10114 : bgp_show_type_lcommunity),
10115 lcom, uj);
57d187bc
JS
10116}
10117
d62a17ae 10118static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10119 const char *lcom, bool exact, afi_t afi,
10120 safi_t safi, bool uj)
57d187bc 10121{
d62a17ae 10122 struct community_list *list;
57d187bc 10123
e237b0d2 10124 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10125 LARGE_COMMUNITY_LIST_MASTER);
10126 if (list == NULL) {
10127 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10128 lcom);
10129 return CMD_WARNING;
10130 }
57d187bc 10131
36a206db 10132 return bgp_show(vty, bgp, afi, safi,
10133 (exact ? bgp_show_type_lcommunity_list_exact
10134 : bgp_show_type_lcommunity_list),
d62a17ae 10135 list, uj);
fee0f4c6 10136}
10137
52951b63
DS
10138DEFUN (show_ip_bgp_large_community_list,
10139 show_ip_bgp_large_community_list_cmd,
36a206db 10140 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
10141 SHOW_STR
10142 IP_STR
10143 BGP_STR
10144 BGP_INSTANCE_HELP_STR
9bedbb1e 10145 BGP_AFI_HELP_STR
4dd6177e 10146 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10147 "Display routes matching the large-community-list\n"
10148 "large-community-list number\n"
10149 "large-community-list name\n"
36a206db 10150 "Exact match of the large-communities\n"
52951b63
DS
10151 JSON_STR)
10152{
d62a17ae 10153 char *vrf = NULL;
10154 afi_t afi = AFI_IP6;
10155 safi_t safi = SAFI_UNICAST;
10156 int idx = 0;
36a206db 10157 bool exact_match = 0;
d62a17ae 10158
10159 if (argv_find(argv, argc, "ip", &idx))
10160 afi = AFI_IP;
10161 if (argv_find(argv, argc, "view", &idx)
10162 || argv_find(argv, argc, "vrf", &idx))
10163 vrf = argv[++idx]->arg;
10164 if (argv_find(argv, argc, "ipv4", &idx)
10165 || argv_find(argv, argc, "ipv6", &idx)) {
10166 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10167 if (argv_find(argv, argc, "unicast", &idx)
10168 || argv_find(argv, argc, "multicast", &idx))
10169 safi = bgp_vty_safi_from_str(argv[idx]->text);
10170 }
10171
9f049418 10172 bool uj = use_json(argc, argv);
d62a17ae 10173
10174 struct bgp *bgp = bgp_lookup_by_name(vrf);
10175 if (bgp == NULL) {
10176 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10177 return CMD_WARNING;
10178 }
10179
10180 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10181
10182 const char *clist_number_or_name = argv[++idx]->arg;
10183
10184 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10185 exact_match = 1;
10186
10187 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10188 exact_match, afi, safi, uj);
52951b63
DS
10189}
10190DEFUN (show_ip_bgp_large_community,
10191 show_ip_bgp_large_community_cmd,
36a206db 10192 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
52951b63
DS
10193 SHOW_STR
10194 IP_STR
10195 BGP_STR
10196 BGP_INSTANCE_HELP_STR
9bedbb1e 10197 BGP_AFI_HELP_STR
4dd6177e 10198 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10199 "Display routes matching the large-communities\n"
10200 "List of large-community numbers\n"
36a206db 10201 "Exact match of the large-communities\n"
52951b63
DS
10202 JSON_STR)
10203{
d62a17ae 10204 char *vrf = NULL;
10205 afi_t afi = AFI_IP6;
10206 safi_t safi = SAFI_UNICAST;
10207 int idx = 0;
36a206db 10208 bool exact_match = 0;
d62a17ae 10209
10210 if (argv_find(argv, argc, "ip", &idx))
10211 afi = AFI_IP;
10212 if (argv_find(argv, argc, "view", &idx)
10213 || argv_find(argv, argc, "vrf", &idx))
10214 vrf = argv[++idx]->arg;
10215 if (argv_find(argv, argc, "ipv4", &idx)
10216 || argv_find(argv, argc, "ipv6", &idx)) {
10217 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10218 if (argv_find(argv, argc, "unicast", &idx)
10219 || argv_find(argv, argc, "multicast", &idx))
10220 safi = bgp_vty_safi_from_str(argv[idx]->text);
10221 }
10222
9f049418 10223 bool uj = use_json(argc, argv);
d62a17ae 10224
10225 struct bgp *bgp = bgp_lookup_by_name(vrf);
10226 if (bgp == NULL) {
10227 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10228 return CMD_WARNING;
10229 }
10230
36a206db 10231 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10232 if (argv_find(argv, argc, "exact-match", &idx))
10233 exact_match = 1;
10234 return bgp_show_lcommunity(vty, bgp, argc, argv,
10235 exact_match, afi, safi, uj);
10236 } else
d62a17ae 10237 return bgp_show(vty, bgp, afi, safi,
10238 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10239}
10240
d62a17ae 10241static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10242 safi_t safi);
e01ca200 10243
7b2ff250
DW
10244
10245/* BGP route print out function without JSON */
af462945
DS
10246DEFUN (show_ip_bgp,
10247 show_ip_bgp_cmd,
4dd6177e 10248 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10249 <dampening <parameters>\
10250 |route-map WORD\
10251 |prefix-list WORD\
10252 |filter-list WORD\
10253 |statistics\
7b2ff250
DW
10254 |community-list <(1-500)|WORD> [exact-match]\
10255 |A.B.C.D/M longer-prefixes\
10256 |X:X::X:X/M longer-prefixes\
10257 >",
718e3744 10258 SHOW_STR
10259 IP_STR
10260 BGP_STR
a636c635 10261 BGP_INSTANCE_HELP_STR
4f280b15 10262 BGP_AFI_HELP_STR
4dd6177e 10263 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10264 "Display detailed information about dampening\n"
af462945 10265 "Display detail of configured dampening parameters\n"
a636c635
DW
10266 "Display routes matching the route-map\n"
10267 "A route-map to match on\n"
10268 "Display routes conforming to the prefix-list\n"
8c3deaae 10269 "Prefix-list name\n"
a636c635
DW
10270 "Display routes conforming to the filter-list\n"
10271 "Regular expression access list name\n"
e01ca200 10272 "BGP RIB advertisement statistics\n"
a636c635
DW
10273 "Display routes matching the community-list\n"
10274 "community-list number\n"
10275 "community-list name\n"
10276 "Exact match of the communities\n"
0c7b1b01 10277 "IPv4 prefix\n"
8c3deaae 10278 "Display route and more specific routes\n"
0c7b1b01 10279 "IPv6 prefix\n"
7b2ff250 10280 "Display route and more specific routes\n")
718e3744 10281{
d62a17ae 10282 afi_t afi = AFI_IP6;
10283 safi_t safi = SAFI_UNICAST;
10284 int exact_match = 0;
d62a17ae 10285 struct bgp *bgp = NULL;
10286 int idx = 0;
10287
10288 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10289 &bgp, false);
d62a17ae 10290 if (!idx)
10291 return CMD_WARNING;
10292
d62a17ae 10293 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10294 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10295 return bgp_show_dampening_parameters(vty, afi, safi);
10296 }
c016b6c7 10297
d62a17ae 10298 if (argv_find(argv, argc, "prefix-list", &idx))
10299 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10300 safi, bgp_show_type_prefix_list);
10301
10302 if (argv_find(argv, argc, "filter-list", &idx))
10303 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10304 safi, bgp_show_type_filter_list);
10305
10306 if (argv_find(argv, argc, "statistics", &idx))
10307 return bgp_table_stats(vty, bgp, afi, safi);
10308
10309 if (argv_find(argv, argc, "route-map", &idx))
10310 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10311 safi, bgp_show_type_route_map);
10312
d62a17ae 10313 if (argv_find(argv, argc, "community-list", &idx)) {
10314 const char *clist_number_or_name = argv[++idx]->arg;
10315 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10316 exact_match = 1;
10317 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10318 exact_match, afi, safi);
10319 }
10320 /* prefix-longer */
10321 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10322 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10323 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10324 safi,
10325 bgp_show_type_prefix_longer);
10326
7b2ff250
DW
10327 return CMD_WARNING;
10328}
10329
10330/* BGP route print out function with JSON */
10331DEFUN (show_ip_bgp_json,
10332 show_ip_bgp_json_cmd,
10333 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10334 [cidr-only\
10335 |dampening <flap-statistics|dampened-paths>\
10336 |community [AA:NN|local-AS|no-advertise|no-export\
10337 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10338 |accept-own|accept-own-nexthop|route-filter-v6\
10339 |route-filter-v4|route-filter-translated-v6\
10340 |route-filter-translated-v4] [exact-match]\
10341 ] [json]",
7b2ff250
DW
10342 SHOW_STR
10343 IP_STR
10344 BGP_STR
10345 BGP_INSTANCE_HELP_STR
10346 BGP_AFI_HELP_STR
10347 BGP_SAFI_WITH_LABEL_HELP_STR
10348 "Display only routes with non-natural netmasks\n"
10349 "Display detailed information about dampening\n"
10350 "Display flap statistics of routes\n"
10351 "Display paths suppressed due to dampening\n"
10352 "Display routes matching the communities\n"
d0086e8e
AD
10353 COMMUNITY_AANN_STR
10354 "Do not send outside local AS (well-known community)\n"
10355 "Do not advertise to any peer (well-known community)\n"
10356 "Do not export to next AS (well-known community)\n"
10357 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10358 "Do not export to any peer (well-known community)\n"
10359 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10360 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10361 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10362 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10363 "Should accept VPN route with local nexthop (well-known community)\n"
10364 "RT VPNv6 route filtering (well-known community)\n"
10365 "RT VPNv4 route filtering (well-known community)\n"
10366 "RT translated VPNv6 route filtering (well-known community)\n"
10367 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10368 "Exact match of the communities\n"
7b2ff250
DW
10369 JSON_STR)
10370{
10371 afi_t afi = AFI_IP6;
10372 safi_t safi = SAFI_UNICAST;
10373 enum bgp_show_type sh_type = bgp_show_type_normal;
10374 struct bgp *bgp = NULL;
10375 int idx = 0;
d0086e8e 10376 int exact_match = 0;
9f049418
DS
10377 bool uj = use_json(argc, argv);
10378
10379 if (uj)
10380 argc--;
7b2ff250
DW
10381
10382 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10383 &bgp, uj);
7b2ff250
DW
10384 if (!idx)
10385 return CMD_WARNING;
10386
7b2ff250
DW
10387 if (argv_find(argv, argc, "cidr-only", &idx))
10388 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10389 NULL, uj);
10390
10391 if (argv_find(argv, argc, "dampening", &idx)) {
10392 if (argv_find(argv, argc, "dampened-paths", &idx))
10393 return bgp_show(vty, bgp, afi, safi,
10394 bgp_show_type_dampend_paths, NULL, uj);
10395 else if (argv_find(argv, argc, "flap-statistics", &idx))
10396 return bgp_show(vty, bgp, afi, safi,
10397 bgp_show_type_flap_statistics, NULL,
10398 uj);
10399 }
10400
10401 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10402 char *maybecomm = NULL;
cf4898bc 10403 char *community = NULL;
d0086e8e 10404
79bc257a
RW
10405 if (idx + 1 < argc) {
10406 if (argv[idx + 1]->type == VARIABLE_TKN)
10407 maybecomm = argv[idx + 1]->arg;
10408 else
10409 maybecomm = argv[idx + 1]->text;
10410 }
10411
cf4898bc
QY
10412 if (maybecomm && !strmatch(maybecomm, "json")
10413 && !strmatch(maybecomm, "exact-match"))
10414 community = maybecomm;
d0086e8e 10415
cf4898bc
QY
10416 if (argv_find(argv, argc, "exact-match", &idx))
10417 exact_match = 1;
d0086e8e 10418
cf4898bc
QY
10419 if (community)
10420 return bgp_show_community(vty, bgp, community,
10421 exact_match, afi, safi, uj);
10422 else
d0086e8e 10423 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10424 bgp_show_type_community_all, NULL,
10425 uj));
7b2ff250 10426 }
d0086e8e 10427
1ae44dfc 10428 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10429}
47fc97cc 10430
718e3744 10431DEFUN (show_ip_bgp_route,
10432 show_ip_bgp_route_cmd,
4dd6177e 10433 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10434 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10435 SHOW_STR
10436 IP_STR
10437 BGP_STR
a636c635 10438 BGP_INSTANCE_HELP_STR
4f280b15 10439 BGP_AFI_HELP_STR
4dd6177e 10440 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10441 "Network in the BGP routing table to display\n"
0c7b1b01 10442 "IPv4 prefix\n"
8c3deaae 10443 "Network in the BGP routing table to display\n"
0c7b1b01 10444 "IPv6 prefix\n"
4092b06c 10445 "Display only the bestpath\n"
b05a1c8b 10446 "Display only multipaths\n"
9973d184 10447 JSON_STR)
4092b06c 10448{
d62a17ae 10449 int prefix_check = 0;
ae19d7dd 10450
d62a17ae 10451 afi_t afi = AFI_IP6;
10452 safi_t safi = SAFI_UNICAST;
10453 char *prefix = NULL;
10454 struct bgp *bgp = NULL;
10455 enum bgp_path_type path_type;
9f049418 10456 bool uj = use_json(argc, argv);
b05a1c8b 10457
d62a17ae 10458 int idx = 0;
ae19d7dd 10459
d62a17ae 10460 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10461 &bgp, uj);
d62a17ae 10462 if (!idx)
10463 return CMD_WARNING;
c41247f5 10464
d62a17ae 10465 if (!bgp) {
10466 vty_out(vty,
10467 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10468 return CMD_WARNING;
10469 }
a636c635 10470
d62a17ae 10471 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10472 if (argv_find(argv, argc, "A.B.C.D", &idx)
10473 || argv_find(argv, argc, "X:X::X:X", &idx))
10474 prefix_check = 0;
10475 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10476 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10477 prefix_check = 1;
10478
10479 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10480 && afi != AFI_IP6) {
10481 vty_out(vty,
10482 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10483 return CMD_WARNING;
10484 }
10485 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10486 && afi != AFI_IP) {
10487 vty_out(vty,
10488 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10489 return CMD_WARNING;
10490 }
10491
10492 prefix = argv[idx]->arg;
10493
10494 /* [<bestpath|multipath>] */
10495 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10496 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10497 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10498 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10499 else
360660c6 10500 path_type = BGP_PATH_SHOW_ALL;
a636c635 10501
d62a17ae 10502 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10503 path_type, uj);
4092b06c
DS
10504}
10505
8c3deaae
QY
10506DEFUN (show_ip_bgp_regexp,
10507 show_ip_bgp_regexp_cmd,
3e5b31b3 10508 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
10509 SHOW_STR
10510 IP_STR
10511 BGP_STR
b00b230a 10512 BGP_INSTANCE_HELP_STR
4f280b15 10513 BGP_AFI_HELP_STR
4dd6177e 10514 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10515 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
10516 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10517 JSON_STR)
8c3deaae 10518{
d62a17ae 10519 afi_t afi = AFI_IP6;
10520 safi_t safi = SAFI_UNICAST;
10521 struct bgp *bgp = NULL;
3e5b31b3
DA
10522 bool uj = use_json(argc, argv);
10523 char *regstr = NULL;
8c3deaae 10524
d62a17ae 10525 int idx = 0;
10526 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10527 &bgp, false);
d62a17ae 10528 if (!idx)
10529 return CMD_WARNING;
8c3deaae 10530
d62a17ae 10531 // get index of regex
3e5b31b3
DA
10532 if (argv_find(argv, argc, "REGEX", &idx))
10533 regstr = argv[idx]->arg;
8c3deaae 10534
3e5b31b3
DA
10535 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
10536 bgp_show_type_regexp, uj);
8c3deaae
QY
10537}
10538
a636c635
DW
10539DEFUN (show_ip_bgp_instance_all,
10540 show_ip_bgp_instance_all_cmd,
4dd6177e 10541 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10542 SHOW_STR
a636c635 10543 IP_STR
4092b06c 10544 BGP_STR
a636c635 10545 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10546 BGP_AFI_HELP_STR
4dd6177e 10547 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10548 JSON_STR)
4092b06c 10549{
d62a17ae 10550 afi_t afi = AFI_IP;
10551 safi_t safi = SAFI_UNICAST;
10552 struct bgp *bgp = NULL;
d62a17ae 10553 int idx = 0;
9f049418 10554 bool uj = use_json(argc, argv);
ae19d7dd 10555
d62a17ae 10556 if (uj)
10557 argc--;
e3e29b32 10558
9f049418
DS
10559 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10560 &bgp, uj);
10561 if (!idx)
10562 return CMD_WARNING;
10563
d62a17ae 10564 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10565 return CMD_SUCCESS;
e3e29b32
LB
10566}
10567
a4d82a8a 10568static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10569 afi_t afi, safi_t safi, enum bgp_show_type type,
10570 bool use_json)
718e3744 10571{
d62a17ae 10572 regex_t *regex;
10573 int rc;
e3e29b32 10574
c3900853 10575 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 10576 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
10577 regstr);
10578 return CMD_WARNING_CONFIG_FAILED;
10579 }
10580
d62a17ae 10581 regex = bgp_regcomp(regstr);
10582 if (!regex) {
10583 vty_out(vty, "Can't compile regexp %s\n", regstr);
10584 return CMD_WARNING;
10585 }
a636c635 10586
3e5b31b3 10587 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 10588 bgp_regex_free(regex);
10589 return rc;
e3e29b32
LB
10590}
10591
d62a17ae 10592static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10593 const char *prefix_list_str, afi_t afi,
10594 safi_t safi, enum bgp_show_type type)
e3e29b32 10595{
d62a17ae 10596 struct prefix_list *plist;
718e3744 10597
d62a17ae 10598 plist = prefix_list_lookup(afi, prefix_list_str);
10599 if (plist == NULL) {
10600 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10601 prefix_list_str);
10602 return CMD_WARNING;
10603 }
718e3744 10604
d62a17ae 10605 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10606}
10607
d62a17ae 10608static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10609 const char *filter, afi_t afi, safi_t safi,
10610 enum bgp_show_type type)
4092b06c 10611{
d62a17ae 10612 struct as_list *as_list;
718e3744 10613
d62a17ae 10614 as_list = as_list_lookup(filter);
10615 if (as_list == NULL) {
10616 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10617 filter);
10618 return CMD_WARNING;
10619 }
a636c635 10620
d62a17ae 10621 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10622}
10623
d62a17ae 10624static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10625 const char *rmap_str, afi_t afi, safi_t safi,
10626 enum bgp_show_type type)
718e3744 10627{
d62a17ae 10628 struct route_map *rmap;
bb46e94f 10629
d62a17ae 10630 rmap = route_map_lookup_by_name(rmap_str);
10631 if (!rmap) {
10632 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10633 return CMD_WARNING;
10634 }
10635
10636 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10637}
10638
7f323236
DW
10639static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10640 const char *comstr, int exact, afi_t afi,
9f049418 10641 safi_t safi, bool use_json)
d62a17ae 10642{
10643 struct community *com;
d62a17ae 10644 int ret = 0;
10645
7f323236 10646 com = community_str2com(comstr);
d62a17ae 10647 if (!com) {
7f323236 10648 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10649 return CMD_WARNING;
10650 }
10651
10652 ret = bgp_show(vty, bgp, afi, safi,
10653 (exact ? bgp_show_type_community_exact
10654 : bgp_show_type_community),
d0086e8e 10655 com, use_json);
3c1f53de 10656 community_free(&com);
46c3ce83 10657
d62a17ae 10658 return ret;
718e3744 10659}
10660
d62a17ae 10661static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10662 const char *com, int exact, afi_t afi,
10663 safi_t safi)
50ef26d4 10664{
d62a17ae 10665 struct community_list *list;
50ef26d4 10666
e237b0d2 10667 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10668 if (list == NULL) {
10669 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10670 return CMD_WARNING;
10671 }
718e3744 10672
d62a17ae 10673 return bgp_show(vty, bgp, afi, safi,
10674 (exact ? bgp_show_type_community_list_exact
10675 : bgp_show_type_community_list),
10676 list, 0);
50ef26d4 10677}
10678
d62a17ae 10679static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10680 const char *prefix, afi_t afi, safi_t safi,
10681 enum bgp_show_type type)
718e3744 10682{
d62a17ae 10683 int ret;
10684 struct prefix *p;
47fc97cc 10685
d62a17ae 10686 p = prefix_new();
95cbbd2a 10687
d62a17ae 10688 ret = str2prefix(prefix, p);
10689 if (!ret) {
10690 vty_out(vty, "%% Malformed Prefix\n");
10691 return CMD_WARNING;
10692 }
47e9b292 10693
d62a17ae 10694 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 10695 prefix_free(&p);
d62a17ae 10696 return ret;
10697}
10698
d62a17ae 10699enum bgp_stats {
10700 BGP_STATS_MAXBITLEN = 0,
10701 BGP_STATS_RIB,
10702 BGP_STATS_PREFIXES,
10703 BGP_STATS_TOTPLEN,
10704 BGP_STATS_UNAGGREGATEABLE,
10705 BGP_STATS_MAX_AGGREGATEABLE,
10706 BGP_STATS_AGGREGATES,
10707 BGP_STATS_SPACE,
10708 BGP_STATS_ASPATH_COUNT,
10709 BGP_STATS_ASPATH_MAXHOPS,
10710 BGP_STATS_ASPATH_TOTHOPS,
10711 BGP_STATS_ASPATH_MAXSIZE,
10712 BGP_STATS_ASPATH_TOTSIZE,
10713 BGP_STATS_ASN_HIGHEST,
10714 BGP_STATS_MAX,
a636c635 10715};
2815e61f 10716
2b64873d 10717static const char *const table_stats_strs[] = {
9d303b37
DL
10718 [BGP_STATS_PREFIXES] = "Total Prefixes",
10719 [BGP_STATS_TOTPLEN] = "Average prefix length",
10720 [BGP_STATS_RIB] = "Total Advertisements",
10721 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10722 [BGP_STATS_MAX_AGGREGATEABLE] =
10723 "Maximum aggregateable prefixes",
10724 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10725 [BGP_STATS_SPACE] = "Address space advertised",
10726 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10727 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10728 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10729 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10730 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10731 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10732 [BGP_STATS_MAX] = NULL,
a636c635 10733};
2815e61f 10734
d62a17ae 10735struct bgp_table_stats {
10736 struct bgp_table *table;
10737 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10738 double total_space;
ff7924f6
PJ
10739};
10740
a636c635
DW
10741#if 0
10742#define TALLY_SIGFIG 100000
10743static unsigned long
10744ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10745{
a636c635
DW
10746 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10747 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10748 unsigned long ret = newtot / count;
07d0c4ed 10749
a636c635
DW
10750 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10751 return ret + 1;
10752 else
10753 return ret;
10754}
10755#endif
ff7924f6 10756
9c14ec72
RW
10757static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10758 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10759{
9c14ec72
RW
10760 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10761 struct bgp_path_info *pi;
d62a17ae 10762
9c14ec72
RW
10763 if (rn == top)
10764 return;
d62a17ae 10765
9c14ec72
RW
10766 if (!bgp_node_has_bgp_path_info_data(rn))
10767 return;
d62a17ae 10768
9c14ec72
RW
10769 ts->counts[BGP_STATS_PREFIXES]++;
10770 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10771
a636c635
DW
10772#if 0
10773 ts->counts[BGP_STATS_AVGPLEN]
10774 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10775 ts->counts[BGP_STATS_AVGPLEN],
10776 rn->p.prefixlen);
10777#endif
d62a17ae 10778
9c14ec72
RW
10779 /* check if the prefix is included by any other announcements */
10780 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10781 prn = bgp_node_parent_nolock(prn);
d62a17ae 10782
9c14ec72
RW
10783 if (prn == NULL || prn == top) {
10784 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
10785 /* announced address space */
10786 if (space)
10787 ts->total_space += pow(2.0, space - rn->p.prefixlen);
10788 } else if (bgp_node_has_bgp_path_info_data(prn))
10789 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 10790
9c14ec72
RW
10791
10792 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10793 ts->counts[BGP_STATS_RIB]++;
10794
05864da7
DS
10795 if (CHECK_FLAG(pi->attr->flag,
10796 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
10797 ts->counts[BGP_STATS_AGGREGATES]++;
10798
10799 /* as-path stats */
05864da7 10800 if (pi->attr->aspath) {
9c14ec72
RW
10801 unsigned int hops = aspath_count_hops(pi->attr->aspath);
10802 unsigned int size = aspath_size(pi->attr->aspath);
10803 as_t highest = aspath_highest(pi->attr->aspath);
10804
10805 ts->counts[BGP_STATS_ASPATH_COUNT]++;
10806
10807 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10808 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
10809
10810 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10811 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
10812
10813 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10814 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10815#if 0
07d0c4ed 10816 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10817 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10818 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10819 hops);
10820 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10821 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10822 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10823 size);
10824#endif
9c14ec72
RW
10825 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10826 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
10827 }
10828 }
10829}
10830
10831static int bgp_table_stats_walker(struct thread *t)
10832{
10833 struct bgp_node *rn, *nrn;
10834 struct bgp_node *top;
10835 struct bgp_table_stats *ts = THREAD_ARG(t);
10836 unsigned int space = 0;
10837
10838 if (!(top = bgp_table_top(ts->table)))
10839 return 0;
10840
10841 switch (ts->table->afi) {
10842 case AFI_IP:
10843 space = IPV4_MAX_BITLEN;
10844 break;
10845 case AFI_IP6:
10846 space = IPV6_MAX_BITLEN;
10847 break;
10848 default:
10849 return 0;
10850 }
10851
10852 ts->counts[BGP_STATS_MAXBITLEN] = space;
10853
10854 for (rn = top; rn; rn = bgp_route_next(rn)) {
10855 if (ts->table->safi == SAFI_MPLS_VPN) {
10856 struct bgp_table *table;
10857
10858 table = bgp_node_get_bgp_table_info(rn);
10859 if (!table)
10860 continue;
10861
10862 top = bgp_table_top(table);
10863 for (nrn = bgp_table_top(table); nrn;
10864 nrn = bgp_route_next(nrn))
10865 bgp_table_stats_rn(nrn, top, ts, space);
10866 } else {
10867 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 10868 }
10869 }
9c14ec72 10870
d62a17ae 10871 return 0;
2815e61f 10872}
ff7924f6 10873
d62a17ae 10874static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10875 safi_t safi)
2815e61f 10876{
d62a17ae 10877 struct bgp_table_stats ts;
10878 unsigned int i;
019386c2 10879
d62a17ae 10880 if (!bgp->rib[afi][safi]) {
10881 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10882 afi, safi);
10883 return CMD_WARNING;
10884 }
019386c2 10885
5cb5f4d0 10886 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 10887
d62a17ae 10888 /* labeled-unicast routes live in the unicast table */
10889 if (safi == SAFI_LABELED_UNICAST)
10890 safi = SAFI_UNICAST;
019386c2 10891
d62a17ae 10892 memset(&ts, 0, sizeof(ts));
10893 ts.table = bgp->rib[afi][safi];
10894 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10895
d62a17ae 10896 for (i = 0; i < BGP_STATS_MAX; i++) {
10897 if (!table_stats_strs[i])
10898 continue;
10899
10900 switch (i) {
a636c635
DW
10901#if 0
10902 case BGP_STATS_ASPATH_AVGHOPS:
10903 case BGP_STATS_ASPATH_AVGSIZE:
10904 case BGP_STATS_AVGPLEN:
10905 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10906 vty_out (vty, "%12.2f",
10907 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10908 break;
10909#endif
d62a17ae 10910 case BGP_STATS_ASPATH_TOTHOPS:
10911 case BGP_STATS_ASPATH_TOTSIZE:
10912 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10913 vty_out(vty, "%12.2f",
10914 ts.counts[i]
10915 ? (float)ts.counts[i]
10916 / (float)ts.counts
10917 [BGP_STATS_ASPATH_COUNT]
10918 : 0);
10919 break;
10920 case BGP_STATS_TOTPLEN:
10921 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10922 vty_out(vty, "%12.2f",
10923 ts.counts[i]
10924 ? (float)ts.counts[i]
10925 / (float)ts.counts
10926 [BGP_STATS_PREFIXES]
10927 : 0);
10928 break;
10929 case BGP_STATS_SPACE:
10930 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10931 vty_out(vty, "%12g\n", ts.total_space);
10932
10933 if (afi == AFI_IP6) {
10934 vty_out(vty, "%30s: ", "/32 equivalent ");
10935 vty_out(vty, "%12g\n",
a4d82a8a 10936 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10937 vty_out(vty, "%30s: ", "/48 equivalent ");
10938 vty_out(vty, "%12g\n",
a4d82a8a 10939 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10940 } else {
10941 vty_out(vty, "%30s: ", "% announced ");
10942 vty_out(vty, "%12.2f\n",
10943 ts.total_space * 100. * pow(2.0, -32));
10944 vty_out(vty, "%30s: ", "/8 equivalent ");
10945 vty_out(vty, "%12.2f\n",
a4d82a8a 10946 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10947 vty_out(vty, "%30s: ", "/24 equivalent ");
10948 vty_out(vty, "%12.2f\n",
a4d82a8a 10949 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10950 }
d62a17ae 10951 break;
10952 default:
10953 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10954 vty_out(vty, "%12llu", ts.counts[i]);
10955 }
ff7924f6 10956
d62a17ae 10957 vty_out(vty, "\n");
10958 }
10959 return CMD_SUCCESS;
10960}
10961
10962enum bgp_pcounts {
10963 PCOUNT_ADJ_IN = 0,
10964 PCOUNT_DAMPED,
10965 PCOUNT_REMOVED,
10966 PCOUNT_HISTORY,
10967 PCOUNT_STALE,
10968 PCOUNT_VALID,
10969 PCOUNT_ALL,
10970 PCOUNT_COUNTED,
10971 PCOUNT_PFCNT, /* the figure we display to users */
10972 PCOUNT_MAX,
a636c635 10973};
718e3744 10974
2b64873d 10975static const char *const pcount_strs[] = {
9d303b37
DL
10976 [PCOUNT_ADJ_IN] = "Adj-in",
10977 [PCOUNT_DAMPED] = "Damped",
10978 [PCOUNT_REMOVED] = "Removed",
10979 [PCOUNT_HISTORY] = "History",
10980 [PCOUNT_STALE] = "Stale",
10981 [PCOUNT_VALID] = "Valid",
10982 [PCOUNT_ALL] = "All RIB",
10983 [PCOUNT_COUNTED] = "PfxCt counted",
10984 [PCOUNT_PFCNT] = "Useable",
10985 [PCOUNT_MAX] = NULL,
a636c635 10986};
718e3744 10987
d62a17ae 10988struct peer_pcounts {
10989 unsigned int count[PCOUNT_MAX];
10990 const struct peer *peer;
10991 const struct bgp_table *table;
54317cba 10992 safi_t safi;
a636c635 10993};
47fc97cc 10994
54317cba
JW
10995static void bgp_peer_count_proc(struct bgp_node *rn,
10996 struct peer_pcounts *pc)
d62a17ae 10997{
54317cba
JW
10998 const struct bgp_adj_in *ain;
10999 const struct bgp_path_info *pi;
d62a17ae 11000 const struct peer *peer = pc->peer;
11001
54317cba
JW
11002 for (ain = rn->adj_in; ain; ain = ain->next)
11003 if (ain->peer == peer)
11004 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11005
54317cba 11006 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11007
54317cba
JW
11008 if (pi->peer != peer)
11009 continue;
d62a17ae 11010
54317cba 11011 pc->count[PCOUNT_ALL]++;
d62a17ae 11012
54317cba
JW
11013 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11014 pc->count[PCOUNT_DAMPED]++;
11015 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11016 pc->count[PCOUNT_HISTORY]++;
11017 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11018 pc->count[PCOUNT_REMOVED]++;
11019 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11020 pc->count[PCOUNT_STALE]++;
11021 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11022 pc->count[PCOUNT_VALID]++;
11023 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11024 pc->count[PCOUNT_PFCNT]++;
11025
11026 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11027 pc->count[PCOUNT_COUNTED]++;
11028 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11029 flog_err(
11030 EC_LIB_DEVELOPMENT,
11031 "Attempting to count but flags say it is unusable");
11032 } else {
40381db7 11033 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11034 flog_err(
11035 EC_LIB_DEVELOPMENT,
11036 "Not counted but flags say we should");
d62a17ae 11037 }
11038 }
54317cba
JW
11039}
11040
11041static int bgp_peer_count_walker(struct thread *t)
11042{
11043 struct bgp_node *rn, *rm;
11044 const struct bgp_table *table;
11045 struct peer_pcounts *pc = THREAD_ARG(t);
11046
11047 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11048 || pc->safi == SAFI_EVPN) {
11049 /* Special handling for 2-level routing tables. */
11050 for (rn = bgp_table_top(pc->table); rn;
11051 rn = bgp_route_next(rn)) {
11052 table = bgp_node_get_bgp_table_info(rn);
11053 if (table != NULL)
11054 for (rm = bgp_table_top(table); rm;
11055 rm = bgp_route_next(rm))
11056 bgp_peer_count_proc(rm, pc);
11057 }
11058 } else
11059 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11060 bgp_peer_count_proc(rn, pc);
11061
d62a17ae 11062 return 0;
718e3744 11063}
11064
d62a17ae 11065static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11066 safi_t safi, bool use_json)
856ca177 11067{
d62a17ae 11068 struct peer_pcounts pcounts = {.peer = peer};
11069 unsigned int i;
11070 json_object *json = NULL;
11071 json_object *json_loop = NULL;
856ca177 11072
d62a17ae 11073 if (use_json) {
11074 json = json_object_new_object();
11075 json_loop = json_object_new_object();
11076 }
718e3744 11077
d62a17ae 11078 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11079 || !peer->bgp->rib[afi][safi]) {
11080 if (use_json) {
11081 json_object_string_add(
11082 json, "warning",
11083 "No such neighbor or address family");
11084 vty_out(vty, "%s\n", json_object_to_json_string(json));
11085 json_object_free(json);
11086 } else
11087 vty_out(vty, "%% No such neighbor or address family\n");
11088
11089 return CMD_WARNING;
11090 }
2a71e9ce 11091
d62a17ae 11092 memset(&pcounts, 0, sizeof(pcounts));
11093 pcounts.peer = peer;
11094 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11095 pcounts.safi = safi;
d62a17ae 11096
11097 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11098 * stats for the thread-walk (i.e. ensure this can't be blamed on
11099 * on just vty_read()).
11100 */
d62a17ae 11101 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11102
11103 if (use_json) {
11104 json_object_string_add(json, "prefixCountsFor", peer->host);
11105 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11106 get_afi_safi_str(afi, safi, true));
d62a17ae 11107 json_object_int_add(json, "pfxCounter",
11108 peer->pcount[afi][safi]);
11109
11110 for (i = 0; i < PCOUNT_MAX; i++)
11111 json_object_int_add(json_loop, pcount_strs[i],
11112 pcounts.count[i]);
11113
11114 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11115
11116 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11117 json_object_string_add(json, "pfxctDriftFor",
11118 peer->host);
11119 json_object_string_add(
11120 json, "recommended",
11121 "Please report this bug, with the above command output");
11122 }
996c9314
LB
11123 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11124 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11125 json_object_free(json);
11126 } else {
11127
11128 if (peer->hostname
11129 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
11130 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11131 peer->hostname, peer->host,
5cb5f4d0 11132 get_afi_safi_str(afi, safi, false));
d62a17ae 11133 } else {
11134 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11135 get_afi_safi_str(afi, safi, false));
d62a17ae 11136 }
11137
a0a87037 11138 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11139 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11140
11141 for (i = 0; i < PCOUNT_MAX; i++)
11142 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11143 pcounts.count[i]);
11144
11145 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11146 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11147 vty_out(vty,
11148 "Please report this bug, with the above command output\n");
11149 }
11150 }
11151
11152 return CMD_SUCCESS;
718e3744 11153}
11154
a636c635
DW
11155DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11156 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11157 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11158 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11159 SHOW_STR
11160 IP_STR
11161 BGP_STR
8386ac43 11162 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11163 BGP_AFI_HELP_STR
11164 BGP_SAFI_HELP_STR
0b16f239
DS
11165 "Detailed information on TCP and BGP neighbor connections\n"
11166 "Neighbor to display information about\n"
11167 "Neighbor to display information about\n"
91d37724 11168 "Neighbor on BGP configured interface\n"
a636c635 11169 "Display detailed prefix count information\n"
9973d184 11170 JSON_STR)
0b16f239 11171{
d62a17ae 11172 afi_t afi = AFI_IP6;
11173 safi_t safi = SAFI_UNICAST;
11174 struct peer *peer;
11175 int idx = 0;
11176 struct bgp *bgp = NULL;
9f049418
DS
11177 bool uj = use_json(argc, argv);
11178
11179 if (uj)
11180 argc--;
856ca177 11181
d62a17ae 11182 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11183 &bgp, uj);
d62a17ae 11184 if (!idx)
11185 return CMD_WARNING;
0b16f239 11186
d62a17ae 11187 argv_find(argv, argc, "neighbors", &idx);
11188 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11189 if (!peer)
11190 return CMD_WARNING;
bb46e94f 11191
29c8d9da 11192 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11193}
0b16f239 11194
d6902373
PG
11195#ifdef KEEP_OLD_VPN_COMMANDS
11196DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11197 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11198 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11199 SHOW_STR
11200 IP_STR
11201 BGP_STR
d6902373 11202 BGP_VPNVX_HELP_STR
91d37724 11203 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11204 "Detailed information on TCP and BGP neighbor connections\n"
11205 "Neighbor to display information about\n"
11206 "Neighbor to display information about\n"
91d37724 11207 "Neighbor on BGP configured interface\n"
a636c635 11208 "Display detailed prefix count information\n"
9973d184 11209 JSON_STR)
a636c635 11210{
d62a17ae 11211 int idx_peer = 6;
11212 struct peer *peer;
9f049418 11213 bool uj = use_json(argc, argv);
a636c635 11214
d62a17ae 11215 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11216 if (!peer)
11217 return CMD_WARNING;
11218
11219 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11220}
11221
d6902373
PG
11222DEFUN (show_ip_bgp_vpn_all_route_prefix,
11223 show_ip_bgp_vpn_all_route_prefix_cmd,
11224 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11225 SHOW_STR
11226 IP_STR
11227 BGP_STR
d6902373 11228 BGP_VPNVX_HELP_STR
91d37724
QY
11229 "Display information about all VPNv4 NLRIs\n"
11230 "Network in the BGP routing table to display\n"
3a2d747c 11231 "Network in the BGP routing table to display\n"
9973d184 11232 JSON_STR)
91d37724 11233{
d62a17ae 11234 int idx = 0;
11235 char *network = NULL;
11236 struct bgp *bgp = bgp_get_default();
11237 if (!bgp) {
11238 vty_out(vty, "Can't find default instance\n");
11239 return CMD_WARNING;
11240 }
87e34b58 11241
d62a17ae 11242 if (argv_find(argv, argc, "A.B.C.D", &idx))
11243 network = argv[idx]->arg;
11244 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11245 network = argv[idx]->arg;
11246 else {
11247 vty_out(vty, "Unable to figure out Network\n");
11248 return CMD_WARNING;
11249 }
87e34b58 11250
d62a17ae 11251 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11252 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11253}
d6902373 11254#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11255
44c69747
LK
11256DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11257 show_bgp_l2vpn_evpn_route_prefix_cmd,
11258 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11259 SHOW_STR
4c63a661
PG
11260 BGP_STR
11261 L2VPN_HELP_STR
11262 EVPN_HELP_STR
44c69747
LK
11263 "Network in the BGP routing table to display\n"
11264 "Network in the BGP routing table to display\n"
4c63a661
PG
11265 "Network in the BGP routing table to display\n"
11266 "Network in the BGP routing table to display\n"
11267 JSON_STR)
11268{
d62a17ae 11269 int idx = 0;
11270 char *network = NULL;
44c69747 11271 int prefix_check = 0;
a636c635 11272
44c69747
LK
11273 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11274 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11275 network = argv[idx]->arg;
44c69747 11276 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11277 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11278 network = argv[idx]->arg;
44c69747
LK
11279 prefix_check = 1;
11280 } else {
d62a17ae 11281 vty_out(vty, "Unable to figure out Network\n");
11282 return CMD_WARNING;
11283 }
44c69747
LK
11284 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11285 prefix_check, BGP_PATH_SHOW_ALL,
11286 use_json(argc, argv));
d62a17ae 11287}
11288
11289static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11290 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11291 const char *rmap_name, bool use_json,
6392aaa6 11292 json_object *json)
d62a17ae 11293{
11294 struct bgp_table *table;
11295 struct bgp_adj_in *ain;
11296 struct bgp_adj_out *adj;
11297 unsigned long output_count;
11298 unsigned long filtered_count;
11299 struct bgp_node *rn;
11300 int header1 = 1;
11301 struct bgp *bgp;
11302 int header2 = 1;
11303 struct attr attr;
11304 int ret;
11305 struct update_subgroup *subgrp;
11306 json_object *json_scode = NULL;
11307 json_object *json_ocode = NULL;
11308 json_object *json_ar = NULL;
11309 struct peer_af *paf;
f99def61 11310 bool route_filtered;
d62a17ae 11311
11312 if (use_json) {
11313 json_scode = json_object_new_object();
11314 json_ocode = json_object_new_object();
11315 json_ar = json_object_new_object();
11316
11317 json_object_string_add(json_scode, "suppressed", "s");
11318 json_object_string_add(json_scode, "damped", "d");
11319 json_object_string_add(json_scode, "history", "h");
11320 json_object_string_add(json_scode, "valid", "*");
11321 json_object_string_add(json_scode, "best", ">");
11322 json_object_string_add(json_scode, "multipath", "=");
11323 json_object_string_add(json_scode, "internal", "i");
11324 json_object_string_add(json_scode, "ribFailure", "r");
11325 json_object_string_add(json_scode, "stale", "S");
11326 json_object_string_add(json_scode, "removed", "R");
11327
11328 json_object_string_add(json_ocode, "igp", "i");
11329 json_object_string_add(json_ocode, "egp", "e");
11330 json_object_string_add(json_ocode, "incomplete", "?");
11331 }
a636c635 11332
d62a17ae 11333 bgp = peer->bgp;
a636c635 11334
d62a17ae 11335 if (!bgp) {
11336 if (use_json) {
11337 json_object_string_add(json, "alert", "no BGP");
11338 vty_out(vty, "%s\n", json_object_to_json_string(json));
11339 json_object_free(json);
11340 } else
11341 vty_out(vty, "%% No bgp\n");
11342 return;
11343 }
a636c635 11344
c512a642
EDP
11345 /* labeled-unicast routes live in the unicast table */
11346 if (safi == SAFI_LABELED_UNICAST)
11347 table = bgp->rib[afi][SAFI_UNICAST];
11348 else
11349 table = bgp->rib[afi][safi];
d62a17ae 11350
11351 output_count = filtered_count = 0;
11352 subgrp = peer_subgroup(peer, afi, safi);
11353
6392aaa6 11354 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11355 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11356 if (use_json) {
11357 json_object_int_add(json, "bgpTableVersion",
11358 table->version);
11359 json_object_string_add(json, "bgpLocalRouterId",
11360 inet_ntoa(bgp->router_id));
01eced22
AD
11361 json_object_int_add(json, "defaultLocPrf",
11362 bgp->default_local_pref);
11363 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11364 json_object_object_add(json, "bgpStatusCodes",
11365 json_scode);
11366 json_object_object_add(json, "bgpOriginCodes",
11367 json_ocode);
07d0c4ed
DA
11368 json_object_string_add(
11369 json, "bgpOriginatingDefaultNetwork",
11370 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11371 } else {
996c9314 11372 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11373 ", local router ID is %s, vrf id ",
d62a17ae 11374 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11375 if (bgp->vrf_id == VRF_UNKNOWN)
11376 vty_out(vty, "%s", VRFID_NONE_STR);
11377 else
11378 vty_out(vty, "%u", bgp->vrf_id);
11379 vty_out(vty, "\n");
01eced22
AD
11380 vty_out(vty, "Default local pref %u, ",
11381 bgp->default_local_pref);
11382 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11383 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11384 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11385 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11386
07d0c4ed
DA
11387 vty_out(vty, "Originating default network %s\n\n",
11388 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11389 }
11390 header1 = 0;
11391 }
a636c635 11392
d62a17ae 11393 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11394 if (type == bgp_show_adj_route_received
11395 || type == bgp_show_adj_route_filtered) {
d62a17ae 11396 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11397 if (ain->peer != peer)
ea47320b 11398 continue;
6392aaa6 11399
ea47320b
DL
11400 if (header1) {
11401 if (use_json) {
11402 json_object_int_add(
60466a63 11403 json, "bgpTableVersion",
ea47320b
DL
11404 0);
11405 json_object_string_add(
11406 json,
11407 "bgpLocalRouterId",
11408 inet_ntoa(
11409 bgp->router_id));
01eced22
AD
11410 json_object_int_add(json,
11411 "defaultLocPrf",
11412 bgp->default_local_pref);
11413 json_object_int_add(json,
11414 "localAS", bgp->as);
ea47320b 11415 json_object_object_add(
60466a63 11416 json, "bgpStatusCodes",
ea47320b
DL
11417 json_scode);
11418 json_object_object_add(
60466a63 11419 json, "bgpOriginCodes",
ea47320b
DL
11420 json_ocode);
11421 } else {
11422 vty_out(vty,
9df8b37c 11423 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11424 inet_ntoa(
9df8b37c
PZ
11425 bgp->router_id));
11426 if (bgp->vrf_id == VRF_UNKNOWN)
11427 vty_out(vty, "%s",
11428 VRFID_NONE_STR);
11429 else
11430 vty_out(vty, "%u",
11431 bgp->vrf_id);
11432 vty_out(vty, "\n");
01eced22
AD
11433 vty_out(vty,
11434 "Default local pref %u, ",
11435 bgp->default_local_pref);
11436 vty_out(vty, "local AS %u\n",
11437 bgp->as);
ea47320b
DL
11438 vty_out(vty,
11439 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11440 vty_out(vty,
11441 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11442 vty_out(vty,
11443 BGP_SHOW_OCODE_HEADER);
d62a17ae 11444 }
ea47320b
DL
11445 header1 = 0;
11446 }
11447 if (header2) {
11448 if (!use_json)
11449 vty_out(vty, BGP_SHOW_HEADER);
11450 header2 = 0;
11451 }
6392aaa6 11452
6f4f49b2 11453 attr = *ain->attr;
f99def61
AD
11454 route_filtered = false;
11455
11456 /* Filter prefix using distribute list,
11457 * filter list or prefix list
11458 */
11459 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11460 safi)) == FILTER_DENY)
11461 route_filtered = true;
11462
11463 /* Filter prefix using route-map */
6392aaa6 11464 ret = bgp_input_modifier(peer, &rn->p, &attr,
196c6b09
LK
11465 afi, safi, rmap_name, NULL, 0,
11466 NULL);
6392aaa6 11467
13c8e163
AD
11468 if (type == bgp_show_adj_route_filtered &&
11469 !route_filtered && ret != RMAP_DENY) {
b755861b 11470 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11471 continue;
d62a17ae 11472 }
6392aaa6 11473
13c8e163
AD
11474 if (type == bgp_show_adj_route_received &&
11475 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11476 filtered_count++;
11477
11478 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11479 use_json, json_ar);
b755861b 11480 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11481 output_count++;
d62a17ae 11482 }
6392aaa6 11483 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11484 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11485 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11486 if (paf->peer != peer || !adj->attr)
924c3f6a 11487 continue;
d62a17ae 11488
924c3f6a
DS
11489 if (header1) {
11490 if (use_json) {
11491 json_object_int_add(
11492 json,
11493 "bgpTableVersion",
11494 table->version);
11495 json_object_string_add(
11496 json,
11497 "bgpLocalRouterId",
11498 inet_ntoa(
11499 bgp->router_id));
01eced22
AD
11500 json_object_int_add(
11501 json, "defaultLocPrf",
11502 bgp->default_local_pref
11503 );
11504 json_object_int_add(
11505 json, "localAS",
11506 bgp->as);
924c3f6a
DS
11507 json_object_object_add(
11508 json,
11509 "bgpStatusCodes",
11510 json_scode);
11511 json_object_object_add(
11512 json,
11513 "bgpOriginCodes",
11514 json_ocode);
11515 } else {
11516 vty_out(vty,
11517 "BGP table version is %" PRIu64
9df8b37c 11518 ", local router ID is %s, vrf id ",
924c3f6a
DS
11519 table->version,
11520 inet_ntoa(
11521 bgp->router_id));
9df8b37c
PZ
11522 if (bgp->vrf_id ==
11523 VRF_UNKNOWN)
11524 vty_out(vty,
11525 "%s",
11526 VRFID_NONE_STR);
11527 else
11528 vty_out(vty,
11529 "%u",
11530 bgp->vrf_id);
11531 vty_out(vty, "\n");
01eced22
AD
11532 vty_out(vty,
11533 "Default local pref %u, ",
11534 bgp->default_local_pref
11535 );
11536 vty_out(vty,
11537 "local AS %u\n",
11538 bgp->as);
924c3f6a
DS
11539 vty_out(vty,
11540 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11541 vty_out(vty,
11542 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11543 vty_out(vty,
11544 BGP_SHOW_OCODE_HEADER);
a2addae8 11545 }
924c3f6a
DS
11546 header1 = 0;
11547 }
924c3f6a
DS
11548 if (header2) {
11549 if (!use_json)
11550 vty_out(vty,
11551 BGP_SHOW_HEADER);
11552 header2 = 0;
11553 }
d62a17ae 11554
6f4f49b2 11555 attr = *adj->attr;
b755861b
PM
11556 ret = bgp_output_modifier(
11557 peer, &rn->p, &attr, afi, safi,
11558 rmap_name);
f46d8e1e 11559
b755861b
PM
11560 if (ret != RMAP_DENY) {
11561 route_vty_out_tmp(vty, &rn->p,
11562 &attr, safi,
11563 use_json,
11564 json_ar);
11565 output_count++;
11566 } else {
11567 filtered_count++;
a2addae8 11568 }
b755861b
PM
11569
11570 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11571 }
d62a17ae 11572 }
11573 }
d62a17ae 11574
d62a17ae 11575 if (use_json) {
6392aaa6
PM
11576 json_object_object_add(json, "advertisedRoutes", json_ar);
11577 json_object_int_add(json, "totalPrefixCounter", output_count);
11578 json_object_int_add(json, "filteredPrefixCounter",
11579 filtered_count);
11580
996c9314
LB
11581 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11582 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11583 json_object_free(json);
6392aaa6
PM
11584 } else if (output_count > 0) {
11585 if (filtered_count > 0)
11586 vty_out(vty,
11587 "\nTotal number of prefixes %ld (%ld filtered)\n",
11588 output_count, filtered_count);
11589 else
11590 vty_out(vty, "\nTotal number of prefixes %ld\n",
11591 output_count);
d62a17ae 11592 }
a636c635 11593}
2a71e9ce 11594
d62a17ae 11595static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11596 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11597 const char *rmap_name, bool use_json)
0b16f239 11598{
d62a17ae 11599 json_object *json = NULL;
0b16f239 11600
d62a17ae 11601 if (use_json)
11602 json = json_object_new_object();
0b16f239 11603
d62a17ae 11604 if (!peer || !peer->afc[afi][safi]) {
11605 if (use_json) {
11606 json_object_string_add(
11607 json, "warning",
11608 "No such neighbor or address family");
11609 vty_out(vty, "%s\n", json_object_to_json_string(json));
11610 json_object_free(json);
11611 } else
11612 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11613
d62a17ae 11614 return CMD_WARNING;
11615 }
11616
6392aaa6
PM
11617 if ((type == bgp_show_adj_route_received
11618 || type == bgp_show_adj_route_filtered)
d62a17ae 11619 && !CHECK_FLAG(peer->af_flags[afi][safi],
11620 PEER_FLAG_SOFT_RECONFIG)) {
11621 if (use_json) {
11622 json_object_string_add(
11623 json, "warning",
11624 "Inbound soft reconfiguration not enabled");
11625 vty_out(vty, "%s\n", json_object_to_json_string(json));
11626 json_object_free(json);
11627 } else
11628 vty_out(vty,
11629 "%% Inbound soft reconfiguration not enabled\n");
11630
11631 return CMD_WARNING;
11632 }
0b16f239 11633
6392aaa6 11634 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11635
d62a17ae 11636 return CMD_SUCCESS;
a636c635 11637}
50ef26d4 11638
a636c635
DW
11639DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11640 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11641 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11642 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11643 SHOW_STR
11644 IP_STR
11645 BGP_STR
a636c635 11646 BGP_INSTANCE_HELP_STR
7395a2c9 11647 BGP_AFI_HELP_STR
4dd6177e 11648 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11649 "Detailed information on TCP and BGP neighbor connections\n"
11650 "Neighbor to display information about\n"
11651 "Neighbor to display information about\n"
91d37724 11652 "Neighbor on BGP configured interface\n"
a636c635 11653 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11654 "Display the received routes from neighbor\n"
11655 "Display the filtered routes received from neighbor\n"
a636c635
DW
11656 "Route-map to modify the attributes\n"
11657 "Name of the route map\n"
9973d184 11658 JSON_STR)
718e3744 11659{
d62a17ae 11660 afi_t afi = AFI_IP6;
11661 safi_t safi = SAFI_UNICAST;
11662 char *rmap_name = NULL;
11663 char *peerstr = NULL;
d62a17ae 11664 struct bgp *bgp = NULL;
11665 struct peer *peer;
6392aaa6 11666 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11667 int idx = 0;
9f049418 11668 bool uj = use_json(argc, argv);
6392aaa6 11669
d62a17ae 11670 if (uj)
11671 argc--;
30a6a167 11672
9f049418
DS
11673 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11674 &bgp, uj);
11675 if (!idx)
11676 return CMD_WARNING;
11677
d62a17ae 11678 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11679 argv_find(argv, argc, "neighbors", &idx);
11680 peerstr = argv[++idx]->arg;
8c3deaae 11681
d62a17ae 11682 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11683 if (!peer)
11684 return CMD_WARNING;
856ca177 11685
d62a17ae 11686 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11687 type = bgp_show_adj_route_advertised;
11688 else if (argv_find(argv, argc, "received-routes", &idx))
11689 type = bgp_show_adj_route_received;
11690 else if (argv_find(argv, argc, "filtered-routes", &idx))
11691 type = bgp_show_adj_route_filtered;
11692
d62a17ae 11693 if (argv_find(argv, argc, "route-map", &idx))
11694 rmap_name = argv[++idx]->arg;
95cbbd2a 11695
6392aaa6 11696 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11697}
11698
718e3744 11699DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11700 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11701 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11702 SHOW_STR
11703 IP_STR
11704 BGP_STR
8c3deaae
QY
11705 "Address Family\n"
11706 "Address Family\n"
718e3744 11707 "Address Family modifier\n"
11708 "Detailed information on TCP and BGP neighbor connections\n"
11709 "Neighbor to display information about\n"
11710 "Neighbor to display information about\n"
91d37724 11711 "Neighbor on BGP configured interface\n"
718e3744 11712 "Display information received from a BGP neighbor\n"
856ca177 11713 "Display the prefixlist filter\n"
9973d184 11714 JSON_STR)
718e3744 11715{
d62a17ae 11716 afi_t afi = AFI_IP6;
11717 safi_t safi = SAFI_UNICAST;
11718 char *peerstr = NULL;
11719
11720 char name[BUFSIZ];
11721 union sockunion su;
11722 struct peer *peer;
11723 int count, ret;
11724
11725 int idx = 0;
11726
11727 /* show [ip] bgp */
11728 if (argv_find(argv, argc, "ip", &idx))
11729 afi = AFI_IP;
11730 /* [<ipv4|ipv6> [unicast]] */
11731 if (argv_find(argv, argc, "ipv4", &idx))
11732 afi = AFI_IP;
11733 if (argv_find(argv, argc, "ipv6", &idx))
11734 afi = AFI_IP6;
11735 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11736 argv_find(argv, argc, "neighbors", &idx);
11737 peerstr = argv[++idx]->arg;
11738
9f049418 11739 bool uj = use_json(argc, argv);
d62a17ae 11740
11741 ret = str2sockunion(peerstr, &su);
11742 if (ret < 0) {
11743 peer = peer_lookup_by_conf_if(NULL, peerstr);
11744 if (!peer) {
11745 if (uj)
11746 vty_out(vty, "{}\n");
11747 else
11748 vty_out(vty,
11749 "%% Malformed address or name: %s\n",
11750 peerstr);
11751 return CMD_WARNING;
11752 }
11753 } else {
11754 peer = peer_lookup(NULL, &su);
11755 if (!peer) {
11756 if (uj)
11757 vty_out(vty, "{}\n");
11758 else
11759 vty_out(vty, "No peer\n");
11760 return CMD_WARNING;
11761 }
11762 }
718e3744 11763
d62a17ae 11764 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11765 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11766 if (count) {
11767 if (!uj)
11768 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11769 get_afi_safi_str(afi, safi, false));
d62a17ae 11770 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11771 } else {
11772 if (uj)
11773 vty_out(vty, "{}\n");
11774 else
11775 vty_out(vty, "No functional output\n");
11776 }
718e3744 11777
d62a17ae 11778 return CMD_SUCCESS;
11779}
11780
11781static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11782 afi_t afi, safi_t safi,
9f049418 11783 enum bgp_show_type type, bool use_json)
d62a17ae 11784{
8a893163
DW
11785 /* labeled-unicast routes live in the unicast table */
11786 if (safi == SAFI_LABELED_UNICAST)
11787 safi = SAFI_UNICAST;
11788
d62a17ae 11789 if (!peer || !peer->afc[afi][safi]) {
11790 if (use_json) {
11791 json_object *json_no = NULL;
11792 json_no = json_object_new_object();
11793 json_object_string_add(
11794 json_no, "warning",
11795 "No such neighbor or address family");
11796 vty_out(vty, "%s\n",
11797 json_object_to_json_string(json_no));
11798 json_object_free(json_no);
11799 } else
11800 vty_out(vty, "%% No such neighbor or address family\n");
11801 return CMD_WARNING;
11802 }
47fc97cc 11803
d62a17ae 11804 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 11805}
11806
dba3c1d3
PG
11807DEFUN (show_ip_bgp_flowspec_routes_detailed,
11808 show_ip_bgp_flowspec_routes_detailed_cmd,
11809 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
11810 SHOW_STR
11811 IP_STR
11812 BGP_STR
11813 BGP_INSTANCE_HELP_STR
11814 BGP_AFI_HELP_STR
11815 "SAFI Flowspec\n"
11816 "Detailed information on flowspec entries\n"
11817 JSON_STR)
11818{
11819 afi_t afi = AFI_IP;
11820 safi_t safi = SAFI_UNICAST;
11821 struct bgp *bgp = NULL;
11822 int idx = 0;
9f049418
DS
11823 bool uj = use_json(argc, argv);
11824
11825 if (uj)
11826 argc--;
dba3c1d3
PG
11827
11828 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11829 &bgp, uj);
dba3c1d3
PG
11830 if (!idx)
11831 return CMD_WARNING;
11832
9f049418 11833 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
11834}
11835
718e3744 11836DEFUN (show_ip_bgp_neighbor_routes,
11837 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 11838 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 11839 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 11840 SHOW_STR
11841 IP_STR
11842 BGP_STR
8386ac43 11843 BGP_INSTANCE_HELP_STR
4f280b15 11844 BGP_AFI_HELP_STR
4dd6177e 11845 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11846 "Detailed information on TCP and BGP neighbor connections\n"
11847 "Neighbor to display information about\n"
11848 "Neighbor to display information about\n"
91d37724 11849 "Neighbor on BGP configured interface\n"
2525cf39 11850 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
11851 "Display the dampened routes received from neighbor\n"
11852 "Display routes learned from neighbor\n"
9973d184 11853 JSON_STR)
718e3744 11854{
d62a17ae 11855 char *peerstr = NULL;
11856 struct bgp *bgp = NULL;
11857 afi_t afi = AFI_IP6;
11858 safi_t safi = SAFI_UNICAST;
11859 struct peer *peer;
11860 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 11861 int idx = 0;
9f049418
DS
11862 bool uj = use_json(argc, argv);
11863
11864 if (uj)
11865 argc--;
bb46e94f 11866
d62a17ae 11867 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11868 &bgp, uj);
d62a17ae 11869 if (!idx)
11870 return CMD_WARNING;
c493f2d8 11871
d62a17ae 11872 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11873 argv_find(argv, argc, "neighbors", &idx);
11874 peerstr = argv[++idx]->arg;
8c3deaae 11875
d62a17ae 11876 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11877 if (!peer)
d62a17ae 11878 return CMD_WARNING;
bb46e94f 11879
d62a17ae 11880 if (argv_find(argv, argc, "flap-statistics", &idx))
11881 sh_type = bgp_show_type_flap_neighbor;
11882 else if (argv_find(argv, argc, "dampened-routes", &idx))
11883 sh_type = bgp_show_type_damp_neighbor;
11884 else if (argv_find(argv, argc, "routes", &idx))
11885 sh_type = bgp_show_type_neighbor;
2525cf39 11886
d62a17ae 11887 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11888}
6b0655a2 11889
734b349e 11890struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11891
d62a17ae 11892struct bgp_distance {
11893 /* Distance value for the IP source prefix. */
d7c0a89a 11894 uint8_t distance;
718e3744 11895
d62a17ae 11896 /* Name of the access-list to be matched. */
11897 char *access_list;
718e3744 11898};
11899
4f280b15
LB
11900DEFUN (show_bgp_afi_vpn_rd_route,
11901 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11902 "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
11903 SHOW_STR
11904 BGP_STR
11905 BGP_AFI_HELP_STR
11906 "Address Family modifier\n"
11907 "Display information for a route distinguisher\n"
11908 "Route Distinguisher\n"
7395a2c9
DS
11909 "Network in the BGP routing table to display\n"
11910 "Network in the BGP routing table to display\n"
11911 JSON_STR)
4f280b15 11912{
d62a17ae 11913 int ret;
11914 struct prefix_rd prd;
11915 afi_t afi = AFI_MAX;
11916 int idx = 0;
4f280b15 11917
ff6566f3
DS
11918 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11919 vty_out(vty, "%% Malformed Address Family\n");
11920 return CMD_WARNING;
11921 }
11922
d62a17ae 11923 ret = str2prefix_rd(argv[5]->arg, &prd);
11924 if (!ret) {
11925 vty_out(vty, "%% Malformed Route Distinguisher\n");
11926 return CMD_WARNING;
11927 }
ff6566f3 11928
d62a17ae 11929 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11930 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11931}
11932
d62a17ae 11933static struct bgp_distance *bgp_distance_new(void)
718e3744 11934{
d62a17ae 11935 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11936}
11937
d62a17ae 11938static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11939{
d62a17ae 11940 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11941}
11942
d62a17ae 11943static int bgp_distance_set(struct vty *vty, const char *distance_str,
11944 const char *ip_str, const char *access_list_str)
718e3744 11945{
d62a17ae 11946 int ret;
11947 afi_t afi;
11948 safi_t safi;
11949 struct prefix p;
d7c0a89a 11950 uint8_t distance;
d62a17ae 11951 struct bgp_node *rn;
11952 struct bgp_distance *bdistance;
718e3744 11953
d62a17ae 11954 afi = bgp_node_afi(vty);
11955 safi = bgp_node_safi(vty);
734b349e 11956
d62a17ae 11957 ret = str2prefix(ip_str, &p);
11958 if (ret == 0) {
11959 vty_out(vty, "Malformed prefix\n");
11960 return CMD_WARNING_CONFIG_FAILED;
11961 }
718e3744 11962
d62a17ae 11963 distance = atoi(distance_str);
718e3744 11964
d62a17ae 11965 /* Get BGP distance node. */
11966 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11967 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11968 if (bdistance)
d62a17ae 11969 bgp_unlock_node(rn);
ca2e160d 11970 else {
d62a17ae 11971 bdistance = bgp_distance_new();
5b00b40e 11972 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11973 }
718e3744 11974
d62a17ae 11975 /* Set distance value. */
11976 bdistance->distance = distance;
718e3744 11977
d62a17ae 11978 /* Reset access-list configuration. */
11979 if (bdistance->access_list) {
11980 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11981 bdistance->access_list = NULL;
11982 }
11983 if (access_list_str)
11984 bdistance->access_list =
11985 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11986
d62a17ae 11987 return CMD_SUCCESS;
718e3744 11988}
11989
d62a17ae 11990static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11991 const char *ip_str, const char *access_list_str)
718e3744 11992{
d62a17ae 11993 int ret;
11994 afi_t afi;
11995 safi_t safi;
11996 struct prefix p;
11997 int distance;
11998 struct bgp_node *rn;
11999 struct bgp_distance *bdistance;
718e3744 12000
d62a17ae 12001 afi = bgp_node_afi(vty);
12002 safi = bgp_node_safi(vty);
734b349e 12003
d62a17ae 12004 ret = str2prefix(ip_str, &p);
12005 if (ret == 0) {
12006 vty_out(vty, "Malformed prefix\n");
12007 return CMD_WARNING_CONFIG_FAILED;
12008 }
718e3744 12009
d62a17ae 12010 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
12011 (struct prefix *)&p);
12012 if (!rn) {
12013 vty_out(vty, "Can't find specified prefix\n");
12014 return CMD_WARNING_CONFIG_FAILED;
12015 }
718e3744 12016
5b00b40e 12017 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12018 distance = atoi(distance_str);
1f9a9fff 12019
d62a17ae 12020 if (bdistance->distance != distance) {
12021 vty_out(vty, "Distance does not match configured\n");
12022 return CMD_WARNING_CONFIG_FAILED;
12023 }
718e3744 12024
0a22ddfb 12025 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12026 bgp_distance_free(bdistance);
718e3744 12027
6f94b685 12028 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 12029 bgp_unlock_node(rn);
12030 bgp_unlock_node(rn);
718e3744 12031
d62a17ae 12032 return CMD_SUCCESS;
718e3744 12033}
12034
718e3744 12035/* Apply BGP information to distance method. */
40381db7 12036uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12037 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12038{
12039 struct bgp_node *rn;
12040 struct prefix q;
12041 struct peer *peer;
12042 struct bgp_distance *bdistance;
12043 struct access_list *alist;
12044 struct bgp_static *bgp_static;
12045
12046 if (!bgp)
12047 return 0;
12048
40381db7 12049 peer = pinfo->peer;
d62a17ae 12050
7b7d48e5
DS
12051 if (pinfo->attr->distance)
12052 return pinfo->attr->distance;
12053
d62a17ae 12054 /* Check source address. */
12055 sockunion2hostprefix(&peer->su, &q);
12056 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
12057 if (rn) {
5b00b40e 12058 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12059 bgp_unlock_node(rn);
12060
12061 if (bdistance->access_list) {
12062 alist = access_list_lookup(afi, bdistance->access_list);
12063 if (alist
12064 && access_list_apply(alist, p) == FILTER_PERMIT)
12065 return bdistance->distance;
12066 } else
12067 return bdistance->distance;
718e3744 12068 }
718e3744 12069
d62a17ae 12070 /* Backdoor check. */
12071 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12072 if (rn) {
5a8ba9fc 12073 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12074 bgp_unlock_node(rn);
718e3744 12075
d62a17ae 12076 if (bgp_static->backdoor) {
12077 if (bgp->distance_local[afi][safi])
12078 return bgp->distance_local[afi][safi];
12079 else
12080 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12081 }
718e3744 12082 }
718e3744 12083
d62a17ae 12084 if (peer->sort == BGP_PEER_EBGP) {
12085 if (bgp->distance_ebgp[afi][safi])
12086 return bgp->distance_ebgp[afi][safi];
12087 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12088 } else {
12089 if (bgp->distance_ibgp[afi][safi])
12090 return bgp->distance_ibgp[afi][safi];
12091 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12092 }
718e3744 12093}
12094
a612fb77
DA
12095/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12096 * we should tell ZEBRA update the routes for a specific
12097 * AFI/SAFI to reflect changes in RIB.
12098 */
8b54bc30
DA
12099static void bgp_announce_routes_distance_update(struct bgp *bgp,
12100 afi_t update_afi,
12101 safi_t update_safi)
a612fb77
DA
12102{
12103 afi_t afi;
12104 safi_t safi;
12105
12106 FOREACH_AFI_SAFI (afi, safi) {
12107 if (!bgp_fibupd_safi(safi))
12108 continue;
12109
8b54bc30
DA
12110 if (afi != update_afi && safi != update_safi)
12111 continue;
12112
12113 if (BGP_DEBUG(zebra, ZEBRA))
12114 zlog_debug(
12115 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12116 __func__, afi, safi);
12117 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12118 }
12119}
12120
718e3744 12121DEFUN (bgp_distance,
12122 bgp_distance_cmd,
6147e2c6 12123 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12124 "Define an administrative distance\n"
12125 "BGP distance\n"
12126 "Distance for routes external to the AS\n"
12127 "Distance for routes internal to the AS\n"
12128 "Distance for local routes\n")
12129{
d62a17ae 12130 VTY_DECLVAR_CONTEXT(bgp, bgp);
12131 int idx_number = 2;
12132 int idx_number_2 = 3;
12133 int idx_number_3 = 4;
8b54bc30
DA
12134 int distance_ebgp = atoi(argv[idx_number]->arg);
12135 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12136 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12137 afi_t afi;
12138 safi_t safi;
718e3744 12139
d62a17ae 12140 afi = bgp_node_afi(vty);
12141 safi = bgp_node_safi(vty);
718e3744 12142
8b54bc30
DA
12143 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12144 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12145 || bgp->distance_local[afi][safi] != distance_local) {
12146 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12147 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12148 bgp->distance_local[afi][safi] = distance_local;
12149 bgp_announce_routes_distance_update(bgp, afi, safi);
12150 }
d62a17ae 12151 return CMD_SUCCESS;
718e3744 12152}
12153
12154DEFUN (no_bgp_distance,
12155 no_bgp_distance_cmd,
a636c635 12156 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12157 NO_STR
12158 "Define an administrative distance\n"
12159 "BGP distance\n"
12160 "Distance for routes external to the AS\n"
12161 "Distance for routes internal to the AS\n"
12162 "Distance for local routes\n")
12163{
d62a17ae 12164 VTY_DECLVAR_CONTEXT(bgp, bgp);
12165 afi_t afi;
12166 safi_t safi;
718e3744 12167
d62a17ae 12168 afi = bgp_node_afi(vty);
12169 safi = bgp_node_safi(vty);
718e3744 12170
8b54bc30
DA
12171 if (bgp->distance_ebgp[afi][safi] != 0
12172 || bgp->distance_ibgp[afi][safi] != 0
12173 || bgp->distance_local[afi][safi] != 0) {
12174 bgp->distance_ebgp[afi][safi] = 0;
12175 bgp->distance_ibgp[afi][safi] = 0;
12176 bgp->distance_local[afi][safi] = 0;
12177 bgp_announce_routes_distance_update(bgp, afi, safi);
12178 }
d62a17ae 12179 return CMD_SUCCESS;
718e3744 12180}
12181
718e3744 12182
12183DEFUN (bgp_distance_source,
12184 bgp_distance_source_cmd,
6147e2c6 12185 "distance (1-255) A.B.C.D/M",
718e3744 12186 "Define an administrative distance\n"
12187 "Administrative distance\n"
12188 "IP source prefix\n")
12189{
d62a17ae 12190 int idx_number = 1;
12191 int idx_ipv4_prefixlen = 2;
12192 bgp_distance_set(vty, argv[idx_number]->arg,
12193 argv[idx_ipv4_prefixlen]->arg, NULL);
12194 return CMD_SUCCESS;
718e3744 12195}
12196
12197DEFUN (no_bgp_distance_source,
12198 no_bgp_distance_source_cmd,
6147e2c6 12199 "no distance (1-255) A.B.C.D/M",
718e3744 12200 NO_STR
12201 "Define an administrative distance\n"
12202 "Administrative distance\n"
12203 "IP source prefix\n")
12204{
d62a17ae 12205 int idx_number = 2;
12206 int idx_ipv4_prefixlen = 3;
12207 bgp_distance_unset(vty, argv[idx_number]->arg,
12208 argv[idx_ipv4_prefixlen]->arg, NULL);
12209 return CMD_SUCCESS;
718e3744 12210}
12211
12212DEFUN (bgp_distance_source_access_list,
12213 bgp_distance_source_access_list_cmd,
6147e2c6 12214 "distance (1-255) A.B.C.D/M WORD",
718e3744 12215 "Define an administrative distance\n"
12216 "Administrative distance\n"
12217 "IP source prefix\n"
12218 "Access list name\n")
12219{
d62a17ae 12220 int idx_number = 1;
12221 int idx_ipv4_prefixlen = 2;
12222 int idx_word = 3;
12223 bgp_distance_set(vty, argv[idx_number]->arg,
12224 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12225 return CMD_SUCCESS;
718e3744 12226}
12227
12228DEFUN (no_bgp_distance_source_access_list,
12229 no_bgp_distance_source_access_list_cmd,
6147e2c6 12230 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12231 NO_STR
12232 "Define an administrative distance\n"
12233 "Administrative distance\n"
12234 "IP source prefix\n"
12235 "Access list name\n")
12236{
d62a17ae 12237 int idx_number = 2;
12238 int idx_ipv4_prefixlen = 3;
12239 int idx_word = 4;
12240 bgp_distance_unset(vty, argv[idx_number]->arg,
12241 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12242 return CMD_SUCCESS;
718e3744 12243}
6b0655a2 12244
734b349e
MZ
12245DEFUN (ipv6_bgp_distance_source,
12246 ipv6_bgp_distance_source_cmd,
39e92c06 12247 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12248 "Define an administrative distance\n"
12249 "Administrative distance\n"
12250 "IP source prefix\n")
12251{
d62a17ae 12252 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12253 return CMD_SUCCESS;
734b349e
MZ
12254}
12255
12256DEFUN (no_ipv6_bgp_distance_source,
12257 no_ipv6_bgp_distance_source_cmd,
39e92c06 12258 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12259 NO_STR
12260 "Define an administrative distance\n"
12261 "Administrative distance\n"
12262 "IP source prefix\n")
12263{
d62a17ae 12264 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12265 return CMD_SUCCESS;
734b349e
MZ
12266}
12267
12268DEFUN (ipv6_bgp_distance_source_access_list,
12269 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12270 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12271 "Define an administrative distance\n"
12272 "Administrative distance\n"
12273 "IP source prefix\n"
12274 "Access list name\n")
12275{
d62a17ae 12276 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12277 return CMD_SUCCESS;
734b349e
MZ
12278}
12279
12280DEFUN (no_ipv6_bgp_distance_source_access_list,
12281 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12282 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12283 NO_STR
12284 "Define an administrative distance\n"
12285 "Administrative distance\n"
12286 "IP source prefix\n"
12287 "Access list name\n")
12288{
d62a17ae 12289 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12290 return CMD_SUCCESS;
734b349e
MZ
12291}
12292
718e3744 12293DEFUN (bgp_damp_set,
12294 bgp_damp_set_cmd,
31500417 12295 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12296 "BGP Specific commands\n"
12297 "Enable route-flap dampening\n"
12298 "Half-life time for the penalty\n"
12299 "Value to start reusing a route\n"
12300 "Value to start suppressing a route\n"
12301 "Maximum duration to suppress a stable route\n")
12302{
d62a17ae 12303 VTY_DECLVAR_CONTEXT(bgp, bgp);
12304 int idx_half_life = 2;
12305 int idx_reuse = 3;
12306 int idx_suppress = 4;
12307 int idx_max_suppress = 5;
12308 int half = DEFAULT_HALF_LIFE * 60;
12309 int reuse = DEFAULT_REUSE;
12310 int suppress = DEFAULT_SUPPRESS;
12311 int max = 4 * half;
12312
12313 if (argc == 6) {
12314 half = atoi(argv[idx_half_life]->arg) * 60;
12315 reuse = atoi(argv[idx_reuse]->arg);
12316 suppress = atoi(argv[idx_suppress]->arg);
12317 max = atoi(argv[idx_max_suppress]->arg) * 60;
12318 } else if (argc == 3) {
12319 half = atoi(argv[idx_half_life]->arg) * 60;
12320 max = 4 * half;
12321 }
718e3744 12322
6d24b7cc
DS
12323 /*
12324 * These can't be 0 but our SA doesn't understand the
12325 * way our cli is constructed
12326 */
12327 assert(reuse);
12328 assert(half);
d62a17ae 12329 if (suppress < reuse) {
12330 vty_out(vty,
12331 "Suppress value cannot be less than reuse value \n");
12332 return 0;
12333 }
7ebe9748 12334
d62a17ae 12335 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12336 reuse, suppress, max);
718e3744 12337}
12338
718e3744 12339DEFUN (bgp_damp_unset,
12340 bgp_damp_unset_cmd,
d04c479d 12341 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12342 NO_STR
12343 "BGP Specific commands\n"
16cedbb0
QY
12344 "Enable route-flap dampening\n"
12345 "Half-life time for the penalty\n"
12346 "Value to start reusing a route\n"
12347 "Value to start suppressing a route\n"
12348 "Maximum duration to suppress a stable route\n")
718e3744 12349{
d62a17ae 12350 VTY_DECLVAR_CONTEXT(bgp, bgp);
12351 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12352}
12353
718e3744 12354/* Display specified route of BGP table. */
d62a17ae 12355static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12356 const char *ip_str, afi_t afi, safi_t safi,
12357 struct prefix_rd *prd, int prefix_check)
12358{
12359 int ret;
12360 struct prefix match;
12361 struct bgp_node *rn;
12362 struct bgp_node *rm;
40381db7
DS
12363 struct bgp_path_info *pi;
12364 struct bgp_path_info *pi_temp;
d62a17ae 12365 struct bgp *bgp;
12366 struct bgp_table *table;
12367
12368 /* BGP structure lookup. */
12369 if (view_name) {
12370 bgp = bgp_lookup_by_name(view_name);
12371 if (bgp == NULL) {
12372 vty_out(vty, "%% Can't find BGP instance %s\n",
12373 view_name);
12374 return CMD_WARNING;
12375 }
12376 } else {
12377 bgp = bgp_get_default();
12378 if (bgp == NULL) {
12379 vty_out(vty, "%% No BGP process is configured\n");
12380 return CMD_WARNING;
12381 }
718e3744 12382 }
718e3744 12383
d62a17ae 12384 /* Check IP address argument. */
12385 ret = str2prefix(ip_str, &match);
12386 if (!ret) {
12387 vty_out(vty, "%% address is malformed\n");
12388 return CMD_WARNING;
12389 }
718e3744 12390
d62a17ae 12391 match.family = afi2family(afi);
12392
12393 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12394 || (safi == SAFI_EVPN)) {
12395 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12396 rn = bgp_route_next(rn)) {
12397 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12398 continue;
67009e22
DS
12399 table = bgp_node_get_bgp_table_info(rn);
12400 if (!table)
ea47320b
DL
12401 continue;
12402 if ((rm = bgp_node_match(table, &match)) == NULL)
12403 continue;
d62a17ae 12404
ea47320b
DL
12405 if (!prefix_check
12406 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12407 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12408 while (pi) {
12409 if (pi->extra && pi->extra->damp_info) {
12410 pi_temp = pi->next;
ea47320b 12411 bgp_damp_info_free(
40381db7 12412 pi->extra->damp_info,
a935f597 12413 1, afi, safi);
40381db7 12414 pi = pi_temp;
ea47320b 12415 } else
40381db7 12416 pi = pi->next;
d62a17ae 12417 }
ea47320b
DL
12418 }
12419
12420 bgp_unlock_node(rm);
d62a17ae 12421 }
12422 } else {
12423 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12424 != NULL) {
12425 if (!prefix_check
12426 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12427 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12428 while (pi) {
12429 if (pi->extra && pi->extra->damp_info) {
12430 pi_temp = pi->next;
d62a17ae 12431 bgp_damp_info_free(
40381db7 12432 pi->extra->damp_info,
a935f597 12433 1, afi, safi);
40381db7 12434 pi = pi_temp;
d62a17ae 12435 } else
40381db7 12436 pi = pi->next;
d62a17ae 12437 }
12438 }
12439
12440 bgp_unlock_node(rn);
12441 }
12442 }
718e3744 12443
d62a17ae 12444 return CMD_SUCCESS;
718e3744 12445}
12446
12447DEFUN (clear_ip_bgp_dampening,
12448 clear_ip_bgp_dampening_cmd,
12449 "clear ip bgp dampening",
12450 CLEAR_STR
12451 IP_STR
12452 BGP_STR
12453 "Clear route flap dampening information\n")
12454{
a935f597 12455 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12456 return CMD_SUCCESS;
718e3744 12457}
12458
12459DEFUN (clear_ip_bgp_dampening_prefix,
12460 clear_ip_bgp_dampening_prefix_cmd,
12461 "clear ip bgp dampening A.B.C.D/M",
12462 CLEAR_STR
12463 IP_STR
12464 BGP_STR
12465 "Clear route flap dampening information\n"
0c7b1b01 12466 "IPv4 prefix\n")
718e3744 12467{
d62a17ae 12468 int idx_ipv4_prefixlen = 4;
12469 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12470 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12471}
12472
12473DEFUN (clear_ip_bgp_dampening_address,
12474 clear_ip_bgp_dampening_address_cmd,
12475 "clear ip bgp dampening A.B.C.D",
12476 CLEAR_STR
12477 IP_STR
12478 BGP_STR
12479 "Clear route flap dampening information\n"
12480 "Network to clear damping information\n")
12481{
d62a17ae 12482 int idx_ipv4 = 4;
12483 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12484 SAFI_UNICAST, NULL, 0);
718e3744 12485}
12486
12487DEFUN (clear_ip_bgp_dampening_address_mask,
12488 clear_ip_bgp_dampening_address_mask_cmd,
12489 "clear ip bgp dampening A.B.C.D A.B.C.D",
12490 CLEAR_STR
12491 IP_STR
12492 BGP_STR
12493 "Clear route flap dampening information\n"
12494 "Network to clear damping information\n"
12495 "Network mask\n")
12496{
d62a17ae 12497 int idx_ipv4 = 4;
12498 int idx_ipv4_2 = 5;
12499 int ret;
12500 char prefix_str[BUFSIZ];
718e3744 12501
d62a17ae 12502 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12503 prefix_str);
12504 if (!ret) {
12505 vty_out(vty, "%% Inconsistent address and mask\n");
12506 return CMD_WARNING;
12507 }
718e3744 12508
d62a17ae 12509 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12510 NULL, 0);
718e3744 12511}
6b0655a2 12512
e3b78da8 12513static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12514{
12515 struct vty *vty = arg;
e3b78da8 12516 struct peer *peer = bucket->data;
825d9834
DS
12517 char buf[SU_ADDRSTRLEN];
12518
12519 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12520 sockunion2str(&peer->su, buf, sizeof(buf)));
12521}
12522
12523DEFUN (show_bgp_peerhash,
12524 show_bgp_peerhash_cmd,
12525 "show bgp peerhash",
12526 SHOW_STR
12527 BGP_STR
12528 "Display information about the BGP peerhash\n")
12529{
12530 struct list *instances = bm->bgp;
12531 struct listnode *node;
12532 struct bgp *bgp;
12533
12534 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12535 vty_out(vty, "BGP: %s\n", bgp->name);
12536 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12537 vty);
12538 }
12539
12540 return CMD_SUCCESS;
12541}
12542
587ff0fd 12543/* also used for encap safi */
2b791107
DL
12544static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12545 afi_t afi, safi_t safi)
d62a17ae 12546{
12547 struct bgp_node *prn;
12548 struct bgp_node *rn;
12549 struct bgp_table *table;
12550 struct prefix *p;
12551 struct prefix_rd *prd;
12552 struct bgp_static *bgp_static;
12553 mpls_label_t label;
12554 char buf[SU_ADDRSTRLEN];
12555 char rdbuf[RD_ADDRSTRLEN];
12556
12557 /* Network configuration. */
12558 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12559 prn = bgp_route_next(prn)) {
67009e22
DS
12560 table = bgp_node_get_bgp_table_info(prn);
12561 if (!table)
ea47320b 12562 continue;
d62a17ae 12563
60466a63 12564 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12565 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12566 if (bgp_static == NULL)
ea47320b 12567 continue;
d62a17ae 12568
ea47320b
DL
12569 p = &rn->p;
12570 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12571
ea47320b 12572 /* "network" configuration display. */
06b9f471 12573 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12574 label = decode_label(&bgp_static->label);
12575
12576 vty_out(vty, " network %s/%d rd %s",
12577 inet_ntop(p->family, &p->u.prefix, buf,
12578 SU_ADDRSTRLEN),
12579 p->prefixlen, rdbuf);
12580 if (safi == SAFI_MPLS_VPN)
12581 vty_out(vty, " label %u", label);
12582
12583 if (bgp_static->rmap.name)
12584 vty_out(vty, " route-map %s",
12585 bgp_static->rmap.name);
e2a86ad9
DS
12586
12587 if (bgp_static->backdoor)
12588 vty_out(vty, " backdoor");
12589
ea47320b
DL
12590 vty_out(vty, "\n");
12591 }
12592 }
d62a17ae 12593}
12594
2b791107
DL
12595static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12596 afi_t afi, safi_t safi)
d62a17ae 12597{
12598 struct bgp_node *prn;
12599 struct bgp_node *rn;
12600 struct bgp_table *table;
12601 struct prefix *p;
12602 struct prefix_rd *prd;
12603 struct bgp_static *bgp_static;
ff44f570 12604 char buf[PREFIX_STRLEN * 2];
d62a17ae 12605 char buf2[SU_ADDRSTRLEN];
12606 char rdbuf[RD_ADDRSTRLEN];
12607
12608 /* Network configuration. */
12609 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12610 prn = bgp_route_next(prn)) {
67009e22
DS
12611 table = bgp_node_get_bgp_table_info(prn);
12612 if (!table)
ea47320b 12613 continue;
d62a17ae 12614
60466a63 12615 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12616 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12617 if (bgp_static == NULL)
ea47320b 12618 continue;
d62a17ae 12619
ea47320b
DL
12620 char *macrouter = NULL;
12621 char *esi = NULL;
d62a17ae 12622
ea47320b
DL
12623 if (bgp_static->router_mac)
12624 macrouter = prefix_mac2str(
12625 bgp_static->router_mac, NULL, 0);
12626 if (bgp_static->eth_s_id)
12627 esi = esi2str(bgp_static->eth_s_id);
12628 p = &rn->p;
12629 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12630
ea47320b 12631 /* "network" configuration display. */
06b9f471 12632 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12633 if (p->u.prefix_evpn.route_type == 5) {
12634 char local_buf[PREFIX_STRLEN];
3714a385 12635 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12636 struct prefix_evpn *)p)
12637 ? AF_INET
12638 : AF_INET6;
3714a385 12639 inet_ntop(family,
12640 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12641 local_buf, PREFIX_STRLEN);
12642 sprintf(buf, "%s/%u", local_buf,
3714a385 12643 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12644 } else {
12645 prefix2str(p, buf, sizeof(buf));
12646 }
ea47320b 12647
a4d82a8a
PZ
12648 if (bgp_static->gatewayIp.family == AF_INET
12649 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12650 inet_ntop(bgp_static->gatewayIp.family,
12651 &bgp_static->gatewayIp.u.prefix, buf2,
12652 sizeof(buf2));
ea47320b 12653 vty_out(vty,
7bcc8dac 12654 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12655 buf, rdbuf,
12656 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12657 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12658 macrouter);
12659
0a22ddfb
QY
12660 XFREE(MTYPE_TMP, macrouter);
12661 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12662 }
12663 }
3da6fcd5
PG
12664}
12665
718e3744 12666/* Configuration of static route announcement and aggregate
12667 information. */
2b791107
DL
12668void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12669 safi_t safi)
d62a17ae 12670{
12671 struct bgp_node *rn;
12672 struct prefix *p;
12673 struct bgp_static *bgp_static;
12674 struct bgp_aggregate *bgp_aggregate;
12675 char buf[SU_ADDRSTRLEN];
12676
2b791107
DL
12677 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12678 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12679 return;
12680 }
d62a17ae 12681
2b791107
DL
12682 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12683 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12684 return;
12685 }
d62a17ae 12686
12687 /* Network configuration. */
12688 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12689 rn = bgp_route_next(rn)) {
5a8ba9fc 12690 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12691 if (bgp_static == NULL)
ea47320b 12692 continue;
d62a17ae 12693
ea47320b 12694 p = &rn->p;
d62a17ae 12695
d8a9922d
DS
12696 vty_out(vty, " network %s/%d",
12697 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12698 p->prefixlen);
d62a17ae 12699
ea47320b
DL
12700 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12701 vty_out(vty, " label-index %u",
12702 bgp_static->label_index);
d62a17ae 12703
ea47320b
DL
12704 if (bgp_static->rmap.name)
12705 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12706
12707 if (bgp_static->backdoor)
12708 vty_out(vty, " backdoor");
718e3744 12709
ea47320b
DL
12710 vty_out(vty, "\n");
12711 }
12712
d62a17ae 12713 /* Aggregate-address configuration. */
12714 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12715 rn = bgp_route_next(rn)) {
b613a918 12716 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12717 if (bgp_aggregate == NULL)
ea47320b 12718 continue;
d62a17ae 12719
ea47320b 12720 p = &rn->p;
d62a17ae 12721
d8a9922d
DS
12722 vty_out(vty, " aggregate-address %s/%d",
12723 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12724 p->prefixlen);
d62a17ae 12725
ea47320b
DL
12726 if (bgp_aggregate->as_set)
12727 vty_out(vty, " as-set");
d62a17ae 12728
ea47320b
DL
12729 if (bgp_aggregate->summary_only)
12730 vty_out(vty, " summary-only");
718e3744 12731
20894f50
DA
12732 if (bgp_aggregate->rmap.name)
12733 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12734
ea47320b
DL
12735 vty_out(vty, "\n");
12736 }
d62a17ae 12737}
734b349e 12738
2b791107 12739void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12740 safi_t safi)
d62a17ae 12741{
12742 struct bgp_node *rn;
12743 struct bgp_distance *bdistance;
12744
12745 /* Distance configuration. */
12746 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12747 && bgp->distance_local[afi][safi]
12748 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12749 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12750 || bgp->distance_local[afi][safi]
12751 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12752 vty_out(vty, " distance bgp %d %d %d\n",
12753 bgp->distance_ebgp[afi][safi],
12754 bgp->distance_ibgp[afi][safi],
12755 bgp->distance_local[afi][safi]);
12756 }
734b349e 12757
d62a17ae 12758 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12759 rn = bgp_route_next(rn)) {
5b00b40e 12760 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12761 if (bdistance != NULL) {
d62a17ae 12762 char buf[PREFIX_STRLEN];
12763
d62a17ae 12764 vty_out(vty, " distance %d %s %s\n",
12765 bdistance->distance,
12766 prefix2str(&rn->p, buf, sizeof(buf)),
12767 bdistance->access_list ? bdistance->access_list
12768 : "");
12769 }
ca2e160d 12770 }
718e3744 12771}
12772
12773/* Allocate routing table structure and install commands. */
d62a17ae 12774void bgp_route_init(void)
12775{
12776 afi_t afi;
12777 safi_t safi;
12778
12779 /* Init BGP distance table. */
05c7a1cc 12780 FOREACH_AFI_SAFI (afi, safi)
960035b2 12781 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12782
12783 /* IPv4 BGP commands. */
12784 install_element(BGP_NODE, &bgp_table_map_cmd);
12785 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 12786 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 12787
12788 install_element(BGP_NODE, &aggregate_address_cmd);
12789 install_element(BGP_NODE, &aggregate_address_mask_cmd);
12790 install_element(BGP_NODE, &no_aggregate_address_cmd);
12791 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
12792
12793 /* IPv4 unicast configuration. */
12794 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
12795 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 12796 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 12797
12798 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
12799 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
12800 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
12801 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
12802
12803 /* IPv4 multicast configuration. */
12804 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
12805 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 12806 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 12807 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
12808 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
12809 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
12810 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
12811
12812 /* IPv4 labeled-unicast configuration. */
12813 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
12814 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 12815 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 12816 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
12817 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
12818
12819 install_element(VIEW_NODE,
12820 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
12821 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
12822 install_element(VIEW_NODE,
12823 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 12824#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12825 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 12826#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 12827 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
12828 install_element(VIEW_NODE,
44c69747 12829 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 12830
d62a17ae 12831 /* BGP dampening clear commands */
12832 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
12833 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 12834
d62a17ae 12835 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
12836 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
12837
12838 /* prefix count */
12839 install_element(ENABLE_NODE,
12840 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 12841#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12842 install_element(ENABLE_NODE,
12843 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 12844#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 12845
d62a17ae 12846 /* New config IPv6 BGP commands. */
12847 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
12848 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12849 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 12850
12851 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
12852 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
12853
12854 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12855
d62a17ae 12856 install_element(BGP_NODE, &bgp_distance_cmd);
12857 install_element(BGP_NODE, &no_bgp_distance_cmd);
12858 install_element(BGP_NODE, &bgp_distance_source_cmd);
12859 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
12860 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
12861 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
12862 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
12863 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
12864 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
12865 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
12866 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
12867 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
12868 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
12869 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
12870 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
12871 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
12872 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
12873 install_element(BGP_IPV4M_NODE,
12874 &no_bgp_distance_source_access_list_cmd);
12875 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
12876 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
12877 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
12878 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
12879 install_element(BGP_IPV6_NODE,
12880 &ipv6_bgp_distance_source_access_list_cmd);
12881 install_element(BGP_IPV6_NODE,
12882 &no_ipv6_bgp_distance_source_access_list_cmd);
12883 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
12884 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
12885 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
12886 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
12887 install_element(BGP_IPV6M_NODE,
12888 &ipv6_bgp_distance_source_access_list_cmd);
12889 install_element(BGP_IPV6M_NODE,
12890 &no_ipv6_bgp_distance_source_access_list_cmd);
12891
12892 install_element(BGP_NODE, &bgp_damp_set_cmd);
12893 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12894 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12895 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12896
12897 /* IPv4 Multicast Mode */
12898 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12899 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12900
12901 /* Large Communities */
12902 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12903 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12904
12905 /* show bgp ipv4 flowspec detailed */
12906 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12907
825d9834 12908 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12909}
12910
12911void bgp_route_finish(void)
12912{
12913 afi_t afi;
12914 safi_t safi;
12915
05c7a1cc
QY
12916 FOREACH_AFI_SAFI (afi, safi) {
12917 bgp_table_unlock(bgp_distance_table[afi][safi]);
12918 bgp_distance_table[afi][safi] = NULL;
12919 }
228da428 12920}