]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: extended-community and attrs for MAC-IP SYNC route handling
[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"
8c48b3b6 44#include "zclient.h"
718e3744 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"
2a0e69ae 72#include "bgpd/bgp_network.h"
718e3744 73
49e5a4a0 74#ifdef ENABLE_BGP_VNC
f8b6f499
LB
75#include "bgpd/rfapi/rfapi_backend.h"
76#include "bgpd/rfapi/vnc_import_bgp.h"
77#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 78#endif
aee875b5
PG
79#include "bgpd/bgp_encap_types.h"
80#include "bgpd/bgp_encap_tlv.h"
684a7227 81#include "bgpd/bgp_evpn.h"
0a50c248 82#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 83#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 84#include "bgpd/bgp_flowspec.h"
98a9dbc7 85#include "bgpd/bgp_flowspec_util.h"
45918cfb 86#include "bgpd/bgp_pbr.h"
65efcfce 87
e2a86ad9
DS
88#ifndef VTYSH_EXTRACT_PL
89#include "bgpd/bgp_route_clippy.c"
90#endif
aee875b5 91
718e3744 92/* Extern from bgp_dump.c */
dde72586
SH
93extern const char *bgp_origin_str[];
94extern const char *bgp_origin_long_str[];
36235319 95const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 96/* PMSI strings. */
97#define PMSI_TNLTYPE_STR_NO_INFO "No info"
98#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
99static const struct message bgp_pmsi_tnltype_str[] = {
100 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
101 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
102 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
103 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
104 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
105 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
106 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
107 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 108 {0}
109};
b7d08f5a 110
9df8b37c
PZ
111#define VRFID_NONE_STR "-"
112
4a11bf2c 113DEFINE_HOOK(bgp_process,
9bcb3eef
DS
114 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
115 struct peer *peer, bool withdraw),
116 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c
DL
117
118
9bcb3eef 119struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 120 safi_t safi, const struct prefix *p,
d62a17ae 121 struct prefix_rd *prd)
122{
9bcb3eef
DS
123 struct bgp_dest *dest;
124 struct bgp_dest *pdest = NULL;
d62a17ae 125
126 assert(table);
d62a17ae 127
128 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
129 || (safi == SAFI_EVPN)) {
9bcb3eef 130 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 131
9bcb3eef
DS
132 if (!bgp_dest_has_bgp_path_info_data(pdest))
133 bgp_dest_set_bgp_table_info(
134 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 135 else
9bcb3eef
DS
136 bgp_dest_unlock_node(pdest);
137 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 138 }
718e3744 139
9bcb3eef 140 dest = bgp_node_get(table, p);
718e3744 141
d62a17ae 142 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
143 || (safi == SAFI_EVPN))
9bcb3eef 144 dest->pdest = pdest;
718e3744 145
9bcb3eef 146 return dest;
718e3744 147}
6b0655a2 148
9bcb3eef 149struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 150 safi_t safi, const struct prefix *p,
d62a17ae 151 struct prefix_rd *prd)
128ea8ab 152{
9bcb3eef
DS
153 struct bgp_dest *dest;
154 struct bgp_dest *pdest = 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)) {
9bcb3eef
DS
161 pdest = bgp_node_lookup(table, (struct prefix *)prd);
162 if (!pdest)
d62a17ae 163 return NULL;
128ea8ab 164
9bcb3eef
DS
165 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
166 bgp_dest_unlock_node(pdest);
d62a17ae 167 return NULL;
168 }
128ea8ab 169
9bcb3eef 170 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 171 }
128ea8ab 172
9bcb3eef 173 dest = bgp_node_lookup(table, p);
128ea8ab 174
9bcb3eef 175 return dest;
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;
9bcb3eef 220 bgp_dest_unlock_node((struct bgp_dest *)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 236 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
237}
238
18ee8310
DS
239/* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
fb982c25 241 */
40381db7 242struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 243{
40381db7
DS
244 if (!pi->extra)
245 pi->extra = bgp_path_info_extra_new();
246 return pi->extra;
fb982c25
PJ
247}
248
718e3744 249/* Free bgp route information. */
9b6d8fcf 250static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 251{
05864da7 252 bgp_attr_unintern(&path->attr);
fb018d25 253
9b6d8fcf
DS
254 bgp_unlink_nexthop(path);
255 bgp_path_info_extra_free(&path->extra);
256 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
257 if (path->net)
258 bgp_addpath_free_info_data(&path->tx_addpath,
259 &path->net->tx_addpath);
718e3744 260
9b6d8fcf 261 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 262
9b6d8fcf 263 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 264}
265
9b6d8fcf 266struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 267{
9b6d8fcf
DS
268 path->lock++;
269 return path;
200df115 270}
271
9b6d8fcf 272struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 273{
9b6d8fcf
DS
274 assert(path && path->lock > 0);
275 path->lock--;
d62a17ae 276
9b6d8fcf 277 if (path->lock == 0) {
200df115 278#if 0
279 zlog_debug ("%s: unlocked and freeing", __func__);
280 zlog_backtrace (LOG_DEBUG);
281#endif
9b6d8fcf 282 bgp_path_info_free(path);
d62a17ae 283 return NULL;
284 }
200df115 285
286#if 0
9b6d8fcf 287 if (path->lock == 1)
200df115 288 {
289 zlog_debug ("%s: unlocked to 1", __func__);
290 zlog_backtrace (LOG_DEBUG);
291 }
292#endif
d62a17ae 293
9b6d8fcf 294 return path;
200df115 295}
296
f009ff26 297/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 298static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 299{
300 struct peer *peer;
301 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 302 bool set_flag = false;
f009ff26 303 struct bgp *bgp = NULL;
304 struct bgp_table *table = NULL;
305 afi_t afi = 0;
306 safi_t safi = 0;
f009ff26 307
308 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
309 * then the route selection is deferred
310 */
9bcb3eef 311 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 312 return 0;
313
9bcb3eef 314 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 315 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 316 zlog_debug(
b54892e0 317 "Route %pRN is in workqueue and being processed, not deferred.",
9bcb3eef 318 bgp_dest_to_rnode(dest));
b54892e0 319
5f9c1aa2 320 return 0;
321 }
322
9bcb3eef 323 table = bgp_dest_table(dest);
f009ff26 324 if (table) {
325 bgp = table->bgp;
326 afi = table->afi;
327 safi = table->safi;
328 }
329
9bcb3eef 330 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 331 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
332 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
333 continue;
334
335 /* Route selection is deferred if there is a stale path which
336 * which indicates peer is in restart mode
337 */
36235319
QY
338 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
339 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 340 set_flag = true;
f009ff26 341 } else {
342 /* If the peer is graceful restart capable and peer is
343 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
344 */
345 peer = old_pi->peer;
36235319
QY
346 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
347 && BGP_PEER_RESTARTING_MODE(peer)
348 && (old_pi
349 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 350 set_flag = true;
f009ff26 351 }
352 }
353 if (set_flag)
354 break;
355 }
356
357 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
358 * is active
359 */
2ba1fe69 360 if (set_flag && table) {
f009ff26 361 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
9bcb3eef
DS
362 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
363 if (dest->rt_node == NULL)
364 dest->rt_node = listnode_add(
365 bgp->gr_info[afi][safi].route_list,
366 dest);
f009ff26 367 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef
DS
368 zlog_debug("DEFER route %pRN, dest %p, node %p",
369 dest, dest, dest->rt_node);
f009ff26 370 return 0;
371 }
372 }
373 return -1;
374}
375
9bcb3eef 376void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 377{
4b7e6066 378 struct bgp_path_info *top;
718e3744 379
9bcb3eef 380 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 381
6f94b685 382 pi->next = top;
40381db7 383 pi->prev = NULL;
d62a17ae 384 if (top)
40381db7 385 top->prev = pi;
9bcb3eef 386 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 387
40381db7 388 bgp_path_info_lock(pi);
9bcb3eef 389 bgp_dest_lock_node(dest);
40381db7 390 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 391 bgp_dest_set_defer_flag(dest, false);
718e3744 392}
393
d62a17ae 394/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 395 completion callback *only* */
9bcb3eef 396void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 397{
40381db7
DS
398 if (pi->next)
399 pi->next->prev = pi->prev;
400 if (pi->prev)
401 pi->prev->next = pi->next;
d62a17ae 402 else
9bcb3eef 403 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 404
40381db7
DS
405 bgp_path_info_mpath_dequeue(pi);
406 bgp_path_info_unlock(pi);
9bcb3eef 407 bgp_dest_unlock_node(dest);
718e3744 408}
409
9bcb3eef 410void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 411{
9bcb3eef 412 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 413 /* set of previous already took care of pcount */
40381db7 414 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 415}
416
18ee8310 417/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
418 called when a route is deleted and then quickly re-added before the
419 deletion has been processed */
9bcb3eef 420void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 421{
9bcb3eef 422 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 423 /* unset of previous already took care of pcount */
40381db7 424 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
425}
426
d62a17ae 427/* Adjust pcount as required */
9bcb3eef 428static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 429{
d62a17ae 430 struct bgp_table *table;
67174041 431
9bcb3eef 432 assert(dest && bgp_dest_table(dest));
40381db7 433 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 434
9bcb3eef 435 table = bgp_dest_table(dest);
67174041 436
40381db7 437 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 438 return;
439
40381db7
DS
440 if (!BGP_PATH_COUNTABLE(pi)
441 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 442
40381db7 443 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 444
445 /* slight hack, but more robust against errors. */
40381db7
DS
446 if (pi->peer->pcount[table->afi][table->safi])
447 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 448 else
450971aa 449 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 450 "Asked to decrement 0 prefix count for peer");
40381db7
DS
451 } else if (BGP_PATH_COUNTABLE(pi)
452 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
453 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
454 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 455 }
1a392d46
PJ
456}
457
40381db7
DS
458static int bgp_label_index_differs(struct bgp_path_info *pi1,
459 struct bgp_path_info *pi2)
28d58fd7 460{
40381db7 461 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 462}
1a392d46 463
18ee8310 464/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
465 * This is here primarily to keep prefix-count in check.
466 */
9bcb3eef 467void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 468 uint32_t flag)
1a392d46 469{
40381db7 470 SET_FLAG(pi->flags, flag);
d62a17ae 471
472 /* early bath if we know it's not a flag that changes countability state
473 */
474 if (!CHECK_FLAG(flag,
1defdda8 475 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 476 return;
477
9bcb3eef 478 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
479}
480
9bcb3eef 481void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 482 uint32_t flag)
1a392d46 483{
40381db7 484 UNSET_FLAG(pi->flags, flag);
d62a17ae 485
486 /* early bath if we know it's not a flag that changes countability state
487 */
488 if (!CHECK_FLAG(flag,
1defdda8 489 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 490 return;
491
9bcb3eef 492 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
493}
494
718e3744 495/* Get MED value. If MED value is missing and "bgp bestpath
496 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 497static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 498{
499 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
500 return attr->med;
501 else {
892fedb6 502 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 503 return BGP_MED_MAX;
504 else
505 return 0;
506 }
718e3744 507}
508
40381db7 509void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 510{
40381db7
DS
511 if (pi->addpath_rx_id)
512 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
513 pi->addpath_rx_id);
d62a17ae 514 else
40381db7 515 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 516}
9fbdd100 517
d62a17ae 518/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
519 */
18ee8310
DS
520static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
521 struct bgp_path_info *exist, int *paths_eq,
522 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
523 char *pfx_buf, afi_t afi, safi_t safi,
524 enum bgp_path_selection_reason *reason)
d62a17ae 525{
526 struct attr *newattr, *existattr;
527 bgp_peer_sort_t new_sort;
528 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
529 uint32_t new_pref;
530 uint32_t exist_pref;
531 uint32_t new_med;
532 uint32_t exist_med;
533 uint32_t new_weight;
534 uint32_t exist_weight;
d62a17ae 535 uint32_t newm, existm;
536 struct in_addr new_id;
537 struct in_addr exist_id;
538 int new_cluster;
539 int exist_cluster;
540 int internal_as_route;
541 int confed_as_route;
04d14c8b 542 int ret = 0;
d62a17ae 543 char new_buf[PATH_ADDPATH_STR_BUFFER];
544 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
545 uint32_t new_mm_seq;
546 uint32_t exist_mm_seq;
6d8c603a 547 int nh_cmp;
d62a17ae 548
549 *paths_eq = 0;
550
551 /* 0. Null check. */
552 if (new == NULL) {
fdf81fa0 553 *reason = bgp_path_selection_none;
d62a17ae 554 if (debug)
555 zlog_debug("%s: new is NULL", pfx_buf);
556 return 0;
557 }
2ec1e66f 558
d62a17ae 559 if (debug)
18ee8310 560 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 561
d62a17ae 562 if (exist == NULL) {
fdf81fa0 563 *reason = bgp_path_selection_first;
d62a17ae 564 if (debug)
565 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
566 new_buf);
567 return 1;
568 }
2ec1e66f 569
d62a17ae 570 if (debug) {
18ee8310 571 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 572 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
573 pfx_buf, new_buf, new->flags, exist_buf,
574 exist->flags);
575 }
8ff56318 576
d62a17ae 577 newattr = new->attr;
578 existattr = exist->attr;
579
580 /* For EVPN routes, we cannot just go by local vs remote, we have to
581 * look at the MAC mobility sequence number, if present.
582 */
583 if (safi == SAFI_EVPN) {
584 /* This is an error condition described in RFC 7432 Section
585 * 15.2. The RFC
586 * states that in this scenario "the PE MUST alert the operator"
587 * but it
588 * does not state what other action to take. In order to provide
589 * some
590 * consistency in this scenario we are going to prefer the path
591 * with the
592 * sticky flag.
593 */
594 if (newattr->sticky != existattr->sticky) {
595 if (!debug) {
9bcb3eef
DS
596 prefix2str(
597 bgp_dest_get_prefix(new->net), pfx_buf,
598 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
599 bgp_path_info_path_with_addpath_rx_str(new,
600 new_buf);
601 bgp_path_info_path_with_addpath_rx_str(
602 exist, exist_buf);
d62a17ae 603 }
604
605 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 606 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
607 if (debug)
608 zlog_debug(
609 "%s: %s wins over %s due to sticky MAC flag",
610 pfx_buf, new_buf, exist_buf);
d62a17ae 611 return 1;
612 }
613
614 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 615 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
616 if (debug)
617 zlog_debug(
618 "%s: %s loses to %s due to sticky MAC flag",
619 pfx_buf, new_buf, exist_buf);
d62a17ae 620 return 0;
621 }
622 }
128ea8ab 623
d62a17ae 624 new_mm_seq = mac_mobility_seqnum(newattr);
625 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 626
d62a17ae 627 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 628 *reason = bgp_path_selection_evpn_seq;
d62a17ae 629 if (debug)
630 zlog_debug(
631 "%s: %s wins over %s due to MM seq %u > %u",
632 pfx_buf, new_buf, exist_buf, new_mm_seq,
633 exist_mm_seq);
634 return 1;
635 }
8ff56318 636
d62a17ae 637 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 638 *reason = bgp_path_selection_evpn_seq;
d62a17ae 639 if (debug)
640 zlog_debug(
641 "%s: %s loses to %s due to MM seq %u < %u",
642 pfx_buf, new_buf, exist_buf, new_mm_seq,
643 exist_mm_seq);
644 return 0;
645 }
6d8c603a
AK
646
647 /*
648 * if sequence numbers are the same path with the lowest IP
649 * wins
650 */
651 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
652 if (nh_cmp < 0) {
fdf81fa0 653 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
654 if (debug)
655 zlog_debug(
656 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
657 pfx_buf, new_buf, exist_buf, new_mm_seq,
658 inet_ntoa(new->attr->nexthop));
659 return 1;
660 }
661 if (nh_cmp > 0) {
fdf81fa0 662 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
663 if (debug)
664 zlog_debug(
665 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
666 pfx_buf, new_buf, exist_buf, new_mm_seq,
667 inet_ntoa(new->attr->nexthop));
668 return 0;
669 }
d62a17ae 670 }
9fbdd100 671
d62a17ae 672 /* 1. Weight check. */
d62a17ae 673 new_weight = newattr->weight;
674 exist_weight = existattr->weight;
8ff56318 675
d62a17ae 676 if (new_weight > exist_weight) {
fdf81fa0 677 *reason = bgp_path_selection_weight;
d62a17ae 678 if (debug)
679 zlog_debug("%s: %s wins over %s due to weight %d > %d",
680 pfx_buf, new_buf, exist_buf, new_weight,
681 exist_weight);
682 return 1;
683 }
718e3744 684
d62a17ae 685 if (new_weight < exist_weight) {
fdf81fa0 686 *reason = bgp_path_selection_weight;
d62a17ae 687 if (debug)
688 zlog_debug("%s: %s loses to %s due to weight %d < %d",
689 pfx_buf, new_buf, exist_buf, new_weight,
690 exist_weight);
691 return 0;
692 }
9fbdd100 693
d62a17ae 694 /* 2. Local preference check. */
695 new_pref = exist_pref = bgp->default_local_pref;
696
697 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
698 new_pref = newattr->local_pref;
699 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
700 exist_pref = existattr->local_pref;
701
702 if (new_pref > exist_pref) {
fdf81fa0 703 *reason = bgp_path_selection_local_pref;
d62a17ae 704 if (debug)
705 zlog_debug(
706 "%s: %s wins over %s due to localpref %d > %d",
707 pfx_buf, new_buf, exist_buf, new_pref,
708 exist_pref);
709 return 1;
710 }
718e3744 711
d62a17ae 712 if (new_pref < exist_pref) {
fdf81fa0 713 *reason = bgp_path_selection_local_pref;
d62a17ae 714 if (debug)
715 zlog_debug(
716 "%s: %s loses to %s due to localpref %d < %d",
717 pfx_buf, new_buf, exist_buf, new_pref,
718 exist_pref);
719 return 0;
720 }
9fbdd100 721
d62a17ae 722 /* 3. Local route check. We prefer:
723 * - BGP_ROUTE_STATIC
724 * - BGP_ROUTE_AGGREGATE
725 * - BGP_ROUTE_REDISTRIBUTE
726 */
90f4f482 727 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
728 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 729 *reason = bgp_path_selection_local_route;
d62a17ae 730 if (debug)
731 zlog_debug(
732 "%s: %s wins over %s due to preferred BGP_ROUTE type",
733 pfx_buf, new_buf, exist_buf);
734 return 1;
735 }
718e3744 736
90f4f482 737 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 738 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 739 *reason = bgp_path_selection_local_route;
d62a17ae 740 if (debug)
741 zlog_debug(
742 "%s: %s loses to %s due to preferred BGP_ROUTE type",
743 pfx_buf, new_buf, exist_buf);
744 return 0;
6811845b 745 }
718e3744 746
d62a17ae 747 /* 4. AS path length check. */
892fedb6 748 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 749 int exist_hops = aspath_count_hops(existattr->aspath);
750 int exist_confeds = aspath_count_confeds(existattr->aspath);
751
892fedb6 752 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 753 int aspath_hops;
754
755 aspath_hops = aspath_count_hops(newattr->aspath);
756 aspath_hops += aspath_count_confeds(newattr->aspath);
757
758 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 759 *reason = bgp_path_selection_confed_as_path;
d62a17ae 760 if (debug)
761 zlog_debug(
762 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
763 pfx_buf, new_buf, exist_buf,
764 aspath_hops,
765 (exist_hops + exist_confeds));
766 return 1;
767 }
768
769 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 770 *reason = bgp_path_selection_confed_as_path;
d62a17ae 771 if (debug)
772 zlog_debug(
773 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
774 pfx_buf, new_buf, exist_buf,
775 aspath_hops,
776 (exist_hops + exist_confeds));
777 return 0;
778 }
779 } else {
780 int newhops = aspath_count_hops(newattr->aspath);
781
782 if (newhops < exist_hops) {
fdf81fa0 783 *reason = bgp_path_selection_as_path;
d62a17ae 784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s due to aspath hopcount %d < %d",
787 pfx_buf, new_buf, exist_buf,
788 newhops, exist_hops);
789 return 1;
790 }
791
792 if (newhops > exist_hops) {
fdf81fa0 793 *reason = bgp_path_selection_as_path;
d62a17ae 794 if (debug)
795 zlog_debug(
796 "%s: %s loses to %s due to aspath hopcount %d > %d",
797 pfx_buf, new_buf, exist_buf,
798 newhops, exist_hops);
799 return 0;
800 }
801 }
802 }
9fbdd100 803
d62a17ae 804 /* 5. Origin check. */
805 if (newattr->origin < existattr->origin) {
fdf81fa0 806 *reason = bgp_path_selection_origin;
d62a17ae 807 if (debug)
808 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
809 pfx_buf, new_buf, exist_buf,
810 bgp_origin_long_str[newattr->origin],
811 bgp_origin_long_str[existattr->origin]);
812 return 1;
813 }
718e3744 814
d62a17ae 815 if (newattr->origin > existattr->origin) {
fdf81fa0 816 *reason = bgp_path_selection_origin;
d62a17ae 817 if (debug)
818 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
819 pfx_buf, new_buf, exist_buf,
820 bgp_origin_long_str[newattr->origin],
821 bgp_origin_long_str[existattr->origin]);
822 return 0;
823 }
718e3744 824
d62a17ae 825 /* 6. MED check. */
826 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
827 && aspath_count_hops(existattr->aspath) == 0);
828 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
829 && aspath_count_confeds(existattr->aspath) > 0
830 && aspath_count_hops(newattr->aspath) == 0
831 && aspath_count_hops(existattr->aspath) == 0);
832
892fedb6
DA
833 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
834 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 835 || aspath_cmp_left(newattr->aspath, existattr->aspath)
836 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
837 || internal_as_route) {
838 new_med = bgp_med_value(new->attr, bgp);
839 exist_med = bgp_med_value(exist->attr, bgp);
840
841 if (new_med < exist_med) {
fdf81fa0 842 *reason = bgp_path_selection_med;
d62a17ae 843 if (debug)
844 zlog_debug(
845 "%s: %s wins over %s due to MED %d < %d",
846 pfx_buf, new_buf, exist_buf, new_med,
847 exist_med);
848 return 1;
849 }
8ff56318 850
d62a17ae 851 if (new_med > exist_med) {
fdf81fa0 852 *reason = bgp_path_selection_med;
d62a17ae 853 if (debug)
854 zlog_debug(
855 "%s: %s loses to %s due to MED %d > %d",
856 pfx_buf, new_buf, exist_buf, new_med,
857 exist_med);
858 return 0;
859 }
860 }
9fbdd100 861
d62a17ae 862 /* 7. Peer type check. */
863 new_sort = new->peer->sort;
864 exist_sort = exist->peer->sort;
865
866 if (new_sort == BGP_PEER_EBGP
867 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 868 *reason = bgp_path_selection_peer;
d62a17ae 869 if (debug)
870 zlog_debug(
871 "%s: %s wins over %s due to eBGP peer > iBGP peer",
872 pfx_buf, new_buf, exist_buf);
873 return 1;
874 }
718e3744 875
d62a17ae 876 if (exist_sort == BGP_PEER_EBGP
877 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 878 *reason = bgp_path_selection_peer;
d62a17ae 879 if (debug)
880 zlog_debug(
881 "%s: %s loses to %s due to iBGP peer < eBGP peer",
882 pfx_buf, new_buf, exist_buf);
883 return 0;
884 }
8ff56318 885
d62a17ae 886 /* 8. IGP metric check. */
887 newm = existm = 0;
8ff56318 888
d62a17ae 889 if (new->extra)
890 newm = new->extra->igpmetric;
891 if (exist->extra)
892 existm = exist->extra->igpmetric;
9fbdd100 893
d62a17ae 894 if (newm < existm) {
895 if (debug)
896 zlog_debug(
897 "%s: %s wins over %s due to IGP metric %d < %d",
898 pfx_buf, new_buf, exist_buf, newm, existm);
899 ret = 1;
900 }
718e3744 901
d62a17ae 902 if (newm > existm) {
903 if (debug)
904 zlog_debug(
905 "%s: %s loses to %s due to IGP metric %d > %d",
906 pfx_buf, new_buf, exist_buf, newm, existm);
907 ret = 0;
5e242b0d 908 }
5e242b0d 909
d62a17ae 910 /* 9. Same IGP metric. Compare the cluster list length as
911 representative of IGP hops metric. Rewrite the metric value
912 pair (newm, existm) with the cluster list length. Prefer the
913 path with smaller cluster list length. */
914 if (newm == existm) {
bf0d28dc
DS
915 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
916 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 917 && (mpath_cfg == NULL
918 || CHECK_FLAG(
919 mpath_cfg->ibgp_flags,
920 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
921 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
922 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
923
924 if (newm < existm) {
925 if (debug)
926 zlog_debug(
927 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
928 pfx_buf, new_buf, exist_buf,
929 newm, existm);
930 ret = 1;
931 }
932
933 if (newm > existm) {
934 if (debug)
935 zlog_debug(
936 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
937 pfx_buf, new_buf, exist_buf,
938 newm, existm);
939 ret = 0;
940 }
941 }
942 }
31a4638f 943
d62a17ae 944 /* 10. confed-external vs. confed-internal */
945 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
946 if (new_sort == BGP_PEER_CONFED
947 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 948 *reason = bgp_path_selection_confed;
d62a17ae 949 if (debug)
950 zlog_debug(
951 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
952 pfx_buf, new_buf, exist_buf);
953 return 1;
954 }
718e3744 955
d62a17ae 956 if (exist_sort == BGP_PEER_CONFED
957 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 958 *reason = bgp_path_selection_confed;
d62a17ae 959 if (debug)
960 zlog_debug(
961 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
962 pfx_buf, new_buf, exist_buf);
963 return 0;
964 }
965 }
718e3744 966
d62a17ae 967 /* 11. Maximum path check. */
968 if (newm == existm) {
969 /* If one path has a label but the other does not, do not treat
970 * them as equals for multipath
971 */
a4d82a8a 972 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 973 != (exist->extra
b57ba6d2 974 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 975 if (debug)
976 zlog_debug(
977 "%s: %s and %s cannot be multipath, one has a label while the other does not",
978 pfx_buf, new_buf, exist_buf);
892fedb6
DA
979 } else if (CHECK_FLAG(bgp->flags,
980 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 981
982 /*
983 * For the two paths, all comparison steps till IGP
984 * metric
985 * have succeeded - including AS_PATH hop count. Since
986 * 'bgp
987 * bestpath as-path multipath-relax' knob is on, we
988 * don't need
989 * an exact match of AS_PATH. Thus, mark the paths are
990 * equal.
991 * That will trigger both these paths to get into the
992 * multipath
993 * array.
994 */
995 *paths_eq = 1;
996
997 if (debug)
998 zlog_debug(
999 "%s: %s and %s are equal via multipath-relax",
1000 pfx_buf, new_buf, exist_buf);
1001 } else if (new->peer->sort == BGP_PEER_IBGP) {
1002 if (aspath_cmp(new->attr->aspath,
1003 exist->attr->aspath)) {
1004 *paths_eq = 1;
1005
1006 if (debug)
1007 zlog_debug(
1008 "%s: %s and %s are equal via matching aspaths",
1009 pfx_buf, new_buf, exist_buf);
1010 }
1011 } else if (new->peer->as == exist->peer->as) {
1012 *paths_eq = 1;
1013
1014 if (debug)
1015 zlog_debug(
1016 "%s: %s and %s are equal via same remote-as",
1017 pfx_buf, new_buf, exist_buf);
1018 }
1019 } else {
1020 /*
1021 * TODO: If unequal cost ibgp multipath is enabled we can
1022 * mark the paths as equal here instead of returning
1023 */
1024 if (debug) {
1025 if (ret == 1)
1026 zlog_debug(
1027 "%s: %s wins over %s after IGP metric comparison",
1028 pfx_buf, new_buf, exist_buf);
1029 else
1030 zlog_debug(
1031 "%s: %s loses to %s after IGP metric comparison",
1032 pfx_buf, new_buf, exist_buf);
1033 }
fdf81fa0 1034 *reason = bgp_path_selection_igp_metric;
d62a17ae 1035 return ret;
1036 }
718e3744 1037
d62a17ae 1038 /* 12. If both paths are external, prefer the path that was received
1039 first (the oldest one). This step minimizes route-flap, since a
1040 newer path won't displace an older one, even if it was the
1041 preferred route based on the additional decision criteria below. */
892fedb6 1042 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1043 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1044 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1045 *reason = bgp_path_selection_older;
d62a17ae 1046 if (debug)
1047 zlog_debug(
1048 "%s: %s wins over %s due to oldest external",
1049 pfx_buf, new_buf, exist_buf);
1050 return 1;
1051 }
9fbdd100 1052
1defdda8 1053 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1054 *reason = bgp_path_selection_older;
d62a17ae 1055 if (debug)
1056 zlog_debug(
1057 "%s: %s loses to %s due to oldest external",
1058 pfx_buf, new_buf, exist_buf);
1059 return 0;
1060 }
1061 }
718e3744 1062
d62a17ae 1063 /* 13. Router-ID comparision. */
1064 /* If one of the paths is "stale", the corresponding peer router-id will
1065 * be 0 and would always win over the other path. If originator id is
1066 * used for the comparision, it will decide which path is better.
1067 */
1068 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1069 new_id.s_addr = newattr->originator_id.s_addr;
1070 else
1071 new_id.s_addr = new->peer->remote_id.s_addr;
1072 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1073 exist_id.s_addr = existattr->originator_id.s_addr;
1074 else
1075 exist_id.s_addr = exist->peer->remote_id.s_addr;
1076
1077 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1078 *reason = bgp_path_selection_router_id;
d62a17ae 1079 if (debug)
1080 zlog_debug(
1081 "%s: %s wins over %s due to Router-ID comparison",
1082 pfx_buf, new_buf, exist_buf);
1083 return 1;
1084 }
718e3744 1085
d62a17ae 1086 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1087 *reason = bgp_path_selection_router_id;
d62a17ae 1088 if (debug)
1089 zlog_debug(
1090 "%s: %s loses to %s due to Router-ID comparison",
1091 pfx_buf, new_buf, exist_buf);
1092 return 0;
1093 }
9fbdd100 1094
d62a17ae 1095 /* 14. Cluster length comparision. */
1096 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1097 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1098
1099 if (new_cluster < exist_cluster) {
fdf81fa0 1100 *reason = bgp_path_selection_cluster_length;
d62a17ae 1101 if (debug)
1102 zlog_debug(
1103 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1104 pfx_buf, new_buf, exist_buf, new_cluster,
1105 exist_cluster);
1106 return 1;
1107 }
718e3744 1108
d62a17ae 1109 if (new_cluster > exist_cluster) {
fdf81fa0 1110 *reason = bgp_path_selection_cluster_length;
d62a17ae 1111 if (debug)
1112 zlog_debug(
1113 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1114 pfx_buf, new_buf, exist_buf, new_cluster,
1115 exist_cluster);
1116 return 0;
1117 }
9fbdd100 1118
d62a17ae 1119 /* 15. Neighbor address comparision. */
1120 /* Do this only if neither path is "stale" as stale paths do not have
1121 * valid peer information (as the connection may or may not be up).
1122 */
1defdda8 1123 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1124 *reason = bgp_path_selection_stale;
d62a17ae 1125 if (debug)
1126 zlog_debug(
1127 "%s: %s wins over %s due to latter path being STALE",
1128 pfx_buf, new_buf, exist_buf);
1129 return 1;
1130 }
0de5153c 1131
1defdda8 1132 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1133 *reason = bgp_path_selection_stale;
d62a17ae 1134 if (debug)
1135 zlog_debug(
1136 "%s: %s loses to %s due to former path being STALE",
1137 pfx_buf, new_buf, exist_buf);
1138 return 0;
1139 }
718e3744 1140
d62a17ae 1141 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1142 if (new->peer->su_remote == NULL) {
1143 *reason = bgp_path_selection_local_configured;
d62a17ae 1144 return 0;
fdf81fa0
DS
1145 }
1146 if (exist->peer->su_remote == NULL) {
1147 *reason = bgp_path_selection_local_configured;
d62a17ae 1148 return 1;
fdf81fa0 1149 }
9fbdd100 1150
d62a17ae 1151 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1152
1153 if (ret == 1) {
fdf81fa0 1154 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1155 if (debug)
1156 zlog_debug(
1157 "%s: %s loses to %s due to Neighor IP comparison",
1158 pfx_buf, new_buf, exist_buf);
1159 return 0;
1160 }
1161
1162 if (ret == -1) {
fdf81fa0 1163 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1164 if (debug)
1165 zlog_debug(
1166 "%s: %s wins over %s due to Neighor IP comparison",
1167 pfx_buf, new_buf, exist_buf);
1168 return 1;
1169 }
9fbdd100 1170
fdf81fa0 1171 *reason = bgp_path_selection_default;
d62a17ae 1172 if (debug)
1173 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1174 pfx_buf, new_buf, exist_buf);
718e3744 1175
d62a17ae 1176 return 1;
718e3744 1177}
1178
65efcfce
LB
1179/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1180 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1181 * multipath is enabled
65efcfce 1182 * This version is compatible with */
18ee8310
DS
1183int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1184 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1185 afi_t afi, safi_t safi,
1186 enum bgp_path_selection_reason *reason)
d62a17ae 1187{
1188 int paths_eq;
1189 int ret;
18ee8310 1190 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1191 afi, safi, reason);
d62a17ae 1192
1193 if (paths_eq)
1194 ret = 0;
1195 else {
1196 if (ret == 1)
1197 ret = -1;
1198 else
1199 ret = 1;
1200 }
1201 return ret;
65efcfce
LB
1202}
1203
5a1ae2c2
DS
1204static enum filter_type bgp_input_filter(struct peer *peer,
1205 const struct prefix *p,
d62a17ae 1206 struct attr *attr, afi_t afi,
1207 safi_t safi)
718e3744 1208{
d62a17ae 1209 struct bgp_filter *filter;
718e3744 1210
d62a17ae 1211 filter = &peer->filter[afi][safi];
718e3744 1212
d62a17ae 1213#define FILTER_EXIST_WARN(F, f, filter) \
1214 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1215 zlog_debug("%s: Could not find configured input %s-list %s!", \
1216 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1217
1218 if (DISTRIBUTE_IN_NAME(filter)) {
1219 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1220
1221 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1222 return FILTER_DENY;
1223 }
1224
1225 if (PREFIX_LIST_IN_NAME(filter)) {
1226 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1227
1228 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1229 return FILTER_DENY;
1230 }
1231
1232 if (FILTER_LIST_IN_NAME(filter)) {
1233 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1234
1235 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1236 == AS_FILTER_DENY)
1237 return FILTER_DENY;
1238 }
1239
1240 return FILTER_PERMIT;
650f76c2 1241#undef FILTER_EXIST_WARN
718e3744 1242}
1243
b8685f9b
DS
1244static enum filter_type bgp_output_filter(struct peer *peer,
1245 const struct prefix *p,
d62a17ae 1246 struct attr *attr, afi_t afi,
1247 safi_t safi)
718e3744 1248{
d62a17ae 1249 struct bgp_filter *filter;
1250
1251 filter = &peer->filter[afi][safi];
1252
1253#define FILTER_EXIST_WARN(F, f, filter) \
1254 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1255 zlog_debug("%s: Could not find configured output %s-list %s!", \
1256 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1257
d62a17ae 1258 if (DISTRIBUTE_OUT_NAME(filter)) {
1259 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1260
d62a17ae 1261 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1262 return FILTER_DENY;
1263 }
1264
1265 if (PREFIX_LIST_OUT_NAME(filter)) {
1266 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1267
d62a17ae 1268 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1269 == PREFIX_DENY)
1270 return FILTER_DENY;
1271 }
718e3744 1272
d62a17ae 1273 if (FILTER_LIST_OUT_NAME(filter)) {
1274 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1275
d62a17ae 1276 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1277 == AS_FILTER_DENY)
1278 return FILTER_DENY;
1279 }
718e3744 1280
d62a17ae 1281 return FILTER_PERMIT;
650f76c2 1282#undef FILTER_EXIST_WARN
718e3744 1283}
1284
1285/* If community attribute includes no_export then return 1. */
3dc339cd 1286static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1287{
1288 if (attr->community) {
1289 /* NO_ADVERTISE check. */
1290 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1291 return true;
d62a17ae 1292
1293 /* NO_EXPORT check. */
1294 if (peer->sort == BGP_PEER_EBGP
1295 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1296 return true;
d62a17ae 1297
1298 /* NO_EXPORT_SUBCONFED check. */
1299 if (peer->sort == BGP_PEER_EBGP
1300 || peer->sort == BGP_PEER_CONFED)
1301 if (community_include(attr->community,
1302 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1303 return true;
d62a17ae 1304 }
3dc339cd 1305 return false;
718e3744 1306}
1307
1308/* Route reflection loop check. */
3dc339cd 1309static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1310{
d62a17ae 1311 struct in_addr cluster_id;
718e3744 1312
d62a17ae 1313 if (attr->cluster) {
1314 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1315 cluster_id = peer->bgp->cluster_id;
1316 else
1317 cluster_id = peer->bgp->router_id;
1318
1319 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1320 return true;
d62a17ae 1321 }
3dc339cd 1322 return false;
718e3744 1323}
6b0655a2 1324
5a1ae2c2 1325static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1326 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1327 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1328 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1329{
d62a17ae 1330 struct bgp_filter *filter;
82b692c0
LK
1331 struct bgp_path_info rmap_path = { 0 };
1332 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1333 route_map_result_t ret;
1334 struct route_map *rmap = NULL;
718e3744 1335
d62a17ae 1336 filter = &peer->filter[afi][safi];
718e3744 1337
d62a17ae 1338 /* Apply default weight value. */
1339 if (peer->weight[afi][safi])
1340 attr->weight = peer->weight[afi][safi];
718e3744 1341
d62a17ae 1342 if (rmap_name) {
1343 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1344
d62a17ae 1345 if (rmap == NULL)
1346 return RMAP_DENY;
1347 } else {
1348 if (ROUTE_MAP_IN_NAME(filter)) {
1349 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1350
d62a17ae 1351 if (rmap == NULL)
1352 return RMAP_DENY;
1353 }
1354 }
0b16f239 1355
d62a17ae 1356 /* Route map apply. */
1357 if (rmap) {
40381db7 1358 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1359 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1360 rmap_path.peer = peer;
1361 rmap_path.attr = attr;
82b692c0 1362 rmap_path.extra = &extra;
9bcb3eef 1363 rmap_path.net = dest;
196c6b09 1364
82b692c0
LK
1365 extra.num_labels = num_labels;
1366 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1367 memcpy(extra.label, label,
1368 num_labels * sizeof(mpls_label_t));
718e3744 1369
d62a17ae 1370 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1371
d62a17ae 1372 /* Apply BGP route map to the attribute. */
40381db7 1373 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1374
d62a17ae 1375 peer->rmap_type = 0;
0b16f239 1376
1f2263be 1377 if (ret == RMAP_DENYMATCH)
d62a17ae 1378 return RMAP_DENY;
0b16f239 1379 }
d62a17ae 1380 return RMAP_PERMIT;
0b16f239
DS
1381}
1382
5f040085 1383static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1384 struct attr *attr, afi_t afi, safi_t safi,
1385 const char *rmap_name)
0b16f239 1386{
40381db7 1387 struct bgp_path_info rmap_path;
d62a17ae 1388 route_map_result_t ret;
1389 struct route_map *rmap = NULL;
d7c0a89a 1390 uint8_t rmap_type;
0b16f239 1391
b787157a
DS
1392 /*
1393 * So if we get to this point and have no rmap_name
1394 * we want to just show the output as it currently
1395 * exists.
1396 */
1397 if (!rmap_name)
1398 return RMAP_PERMIT;
0b16f239 1399
d62a17ae 1400 /* Apply default weight value. */
1401 if (peer->weight[afi][safi])
1402 attr->weight = peer->weight[afi][safi];
0b16f239 1403
b787157a 1404 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1405
b787157a
DS
1406 /*
1407 * If we have a route map name and we do not find
1408 * the routemap that means we have an implicit
1409 * deny.
1410 */
1411 if (rmap == NULL)
1412 return RMAP_DENY;
0b16f239 1413
40381db7 1414 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1415 /* Route map apply. */
b787157a 1416 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1417 rmap_path.peer = peer;
1418 rmap_path.attr = attr;
0b16f239 1419
0f672529 1420 rmap_type = peer->rmap_type;
b787157a 1421 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1422
b787157a 1423 /* Apply BGP route map to the attribute. */
40381db7 1424 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1425
0f672529 1426 peer->rmap_type = rmap_type;
b787157a
DS
1427
1428 if (ret == RMAP_DENYMATCH)
1429 /*
1430 * caller has multiple error paths with bgp_attr_flush()
1431 */
1432 return RMAP_DENY;
ac41b2a2 1433
d62a17ae 1434 return RMAP_PERMIT;
718e3744 1435}
6b0655a2 1436
5000f21c 1437/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1438static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1439 struct peer *peer, struct attr *attr)
1440{
1441 if (peer->sort == BGP_PEER_EBGP
1442 && (peer_af_flag_check(peer, afi, safi,
1443 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1444 || peer_af_flag_check(peer, afi, safi,
1445 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1446 || peer_af_flag_check(peer, afi, safi,
1447 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1448 || peer_af_flag_check(peer, afi, safi,
1449 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1450 // Take action on the entire aspath
1451 if (peer_af_flag_check(peer, afi, safi,
1452 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1453 || peer_af_flag_check(peer, afi, safi,
1454 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1455 if (peer_af_flag_check(
1456 peer, afi, safi,
1457 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1458 attr->aspath = aspath_replace_private_asns(
bf26b80e 1459 attr->aspath, bgp->as, peer->as);
d62a17ae 1460
1461 // The entire aspath consists of private ASNs so create
1462 // an empty aspath
1463 else if (aspath_private_as_check(attr->aspath))
1464 attr->aspath = aspath_empty_get();
1465
1466 // There are some public and some private ASNs, remove
1467 // the private ASNs
1468 else
1469 attr->aspath = aspath_remove_private_asns(
bf26b80e 1470 attr->aspath, peer->as);
d62a17ae 1471 }
1472
1473 // 'all' was not specified so the entire aspath must be private
1474 // ASNs
1475 // for us to do anything
1476 else if (aspath_private_as_check(attr->aspath)) {
1477 if (peer_af_flag_check(
1478 peer, afi, safi,
1479 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1480 attr->aspath = aspath_replace_private_asns(
bf26b80e 1481 attr->aspath, bgp->as, peer->as);
d62a17ae 1482 else
1483 attr->aspath = aspath_empty_get();
1484 }
1485 }
5000f21c
DS
1486}
1487
c7122e14 1488/* If this is an EBGP peer with as-override */
d62a17ae 1489static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1490 struct peer *peer, struct attr *attr)
1491{
1492 if (peer->sort == BGP_PEER_EBGP
1493 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1494 if (aspath_single_asn_check(attr->aspath, peer->as))
1495 attr->aspath = aspath_replace_specific_asn(
1496 attr->aspath, peer->as, bgp->as);
1497 }
1498}
1499
7f323236
DW
1500void bgp_attr_add_gshut_community(struct attr *attr)
1501{
1502 struct community *old;
1503 struct community *new;
1504 struct community *merge;
1505 struct community *gshut;
1506
1507 old = attr->community;
1508 gshut = community_str2com("graceful-shutdown");
1509
990f4f91 1510 assert(gshut);
1511
7f323236
DW
1512 if (old) {
1513 merge = community_merge(community_dup(old), gshut);
1514
a4d82a8a 1515 if (old->refcnt == 0)
3c1f53de 1516 community_free(&old);
7f323236
DW
1517
1518 new = community_uniq_sort(merge);
3c1f53de 1519 community_free(&merge);
7f323236
DW
1520 } else {
1521 new = community_dup(gshut);
1522 }
1523
3c1f53de 1524 community_free(&gshut);
7f323236
DW
1525 attr->community = new;
1526 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1527
1528 /* When we add the graceful-shutdown community we must also
1529 * lower the local-preference */
1530 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1531 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1532}
1533
1534
d7c0a89a 1535static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1536{
960035b2 1537 if (family == AF_INET) {
975a328e
DA
1538 attr->nexthop.s_addr = INADDR_ANY;
1539 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1540 }
d62a17ae 1541 if (family == AF_INET6)
1542 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1543 if (family == AF_EVPN)
1544 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1545}
1546
9bcb3eef 1547bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b
DS
1548 struct update_subgroup *subgrp,
1549 const struct prefix *p, struct attr *attr)
d62a17ae 1550{
1551 struct bgp_filter *filter;
1552 struct peer *from;
1553 struct peer *peer;
1554 struct peer *onlypeer;
1555 struct bgp *bgp;
40381db7 1556 struct attr *piattr;
d62a17ae 1557 char buf[PREFIX_STRLEN];
b68885f9 1558 route_map_result_t ret;
d62a17ae 1559 int transparent;
1560 int reflect;
1561 afi_t afi;
1562 safi_t safi;
1563 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1564 bool nh_reset = false;
1565 uint64_t cum_bw;
d62a17ae 1566
1567 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1568 return false;
d62a17ae 1569
1570 afi = SUBGRP_AFI(subgrp);
1571 safi = SUBGRP_SAFI(subgrp);
1572 peer = SUBGRP_PEER(subgrp);
1573 onlypeer = NULL;
1574 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1575 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1576
40381db7 1577 from = pi->peer;
d62a17ae 1578 filter = &peer->filter[afi][safi];
1579 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1580 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1581 : pi->attr;
3f9c7369 1582
49e5a4a0 1583#ifdef ENABLE_BGP_VNC
d62a17ae 1584 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1585 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1586 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1587
1588 /*
1589 * direct and direct_ext type routes originate internally even
1590 * though they can have peer pointers that reference other
1591 * systems
1592 */
1593 prefix2str(p, buf, PREFIX_STRLEN);
1594 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1595 __func__, buf);
1596 samepeer_safe = 1;
1597 }
65efcfce
LB
1598#endif
1599
ddb5b488
PZ
1600 if (((afi == AFI_IP) || (afi == AFI_IP6))
1601 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1602 && (pi->type == ZEBRA_ROUTE_BGP)
1603 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1604
1605 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1606
1607 samepeer_safe = 1;
1608 }
1609
d62a17ae 1610 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1611 * pi is valid */
1612 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1613 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1614 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1615 return false;
d62a17ae 1616 }
adbac85e 1617
d62a17ae 1618 /* If this is not the bestpath then check to see if there is an enabled
1619 * addpath
1620 * feature that requires us to advertise it */
40381db7 1621 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1622 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1623 return false;
d62a17ae 1624 }
1625 }
06370dac 1626
d62a17ae 1627 /* Aggregate-address suppress check. */
40381db7 1628 if (pi->extra && pi->extra->suppress)
d62a17ae 1629 if (!UNSUPPRESS_MAP_NAME(filter)) {
3dc339cd 1630 return false;
d62a17ae 1631 }
3f9c7369 1632
13b7e7f0
DS
1633 /*
1634 * If we are doing VRF 2 VRF leaking via the import
1635 * statement, we want to prevent the route going
1636 * off box as that the RT and RD created are localy
1637 * significant and globaly useless.
1638 */
40381db7
DS
1639 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1640 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1641 return false;
13b7e7f0 1642
d62a17ae 1643 /* If it's labeled safi, make sure the route has a valid label. */
1644 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1645 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1646 if (!bgp_is_valid_label(&label)) {
1647 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
6cde4b45 1648 zlog_debug("u%" PRIu64 ":s%" PRIu64" %s/%d is filtered - no label (%p)",
d62a17ae 1649 subgrp->update_group->id, subgrp->id,
1650 inet_ntop(p->family, &p->u.prefix,
1651 buf, SU_ADDRSTRLEN),
1652 p->prefixlen, &label);
3dc339cd 1653 return false;
d62a17ae 1654 }
1655 }
cd1964ff 1656
d62a17ae 1657 /* Do not send back route to sender. */
1658 if (onlypeer && from == onlypeer) {
3dc339cd 1659 return false;
d62a17ae 1660 }
3f9c7369 1661
d62a17ae 1662 /* Do not send the default route in the BGP table if the neighbor is
1663 * configured for default-originate */
1664 if (CHECK_FLAG(peer->af_flags[afi][safi],
1665 PEER_FLAG_DEFAULT_ORIGINATE)) {
1666 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1667 return false;
d62a17ae 1668 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1669 return false;
d62a17ae 1670 }
4125bb67 1671
d62a17ae 1672 /* Transparency check. */
1673 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1674 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1675 transparent = 1;
1676 else
1677 transparent = 0;
1678
1679 /* If community is not disabled check the no-export and local. */
40381db7 1680 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1681 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1682 zlog_debug(
1683 "subgrpannouncecheck: community filter check fail");
3dc339cd 1684 return false;
d62a17ae 1685 }
3f9c7369 1686
d62a17ae 1687 /* If the attribute has originator-id and it is same as remote
1688 peer's id. */
40381db7
DS
1689 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1690 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1691 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1692 zlog_debug(
3efd0893 1693 "%s [Update:SEND] %s originator-id is same as remote router-id",
d62a17ae 1694 onlypeer->host,
1695 prefix2str(p, buf, sizeof(buf)));
3dc339cd 1696 return false;
d62a17ae 1697 }
3f9c7369 1698
d62a17ae 1699 /* ORF prefix-list filter check */
1700 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1701 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1702 || CHECK_FLAG(peer->af_cap[afi][safi],
1703 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1704 if (peer->orf_plist[afi][safi]) {
1705 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1706 == PREFIX_DENY) {
1707 if (bgp_debug_update(NULL, p,
1708 subgrp->update_group, 0))
1709 zlog_debug(
1710 "%s [Update:SEND] %s is filtered via ORF",
1711 peer->host,
1712 prefix2str(p, buf,
1713 sizeof(buf)));
3dc339cd 1714 return false;
d62a17ae 1715 }
1716 }
1717
1718 /* Output filter check. */
40381db7 1719 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1720 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1721 zlog_debug("%s [Update:SEND] %s is filtered",
1722 peer->host, prefix2str(p, buf, sizeof(buf)));
3dc339cd 1723 return false;
d62a17ae 1724 }
3f9c7369 1725
d62a17ae 1726 /* AS path loop check. */
2b31007c
RZ
1727 if (onlypeer && onlypeer->as_path_loop_detection
1728 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1729 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1730 zlog_debug(
3efd0893 1731 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1732 onlypeer->host, onlypeer->as);
3dc339cd 1733 return false;
d62a17ae 1734 }
3f9c7369 1735
d62a17ae 1736 /* If we're a CONFED we need to loop check the CONFED ID too */
1737 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1738 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1739 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1740 zlog_debug(
3efd0893 1741 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1742 peer->host, bgp->confed_id);
3dc339cd 1743 return false;
d62a17ae 1744 }
3f9c7369 1745 }
3f9c7369 1746
d62a17ae 1747 /* Route-Reflect check. */
1748 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1749 reflect = 1;
1750 else
1751 reflect = 0;
1752
1753 /* IBGP reflection check. */
1754 if (reflect && !samepeer_safe) {
1755 /* A route from a Client peer. */
1756 if (CHECK_FLAG(from->af_flags[afi][safi],
1757 PEER_FLAG_REFLECTOR_CLIENT)) {
1758 /* Reflect to all the Non-Client peers and also to the
1759 Client peers other than the originator. Originator
1760 check
1761 is already done. So there is noting to do. */
1762 /* no bgp client-to-client reflection check. */
892fedb6
DA
1763 if (CHECK_FLAG(bgp->flags,
1764 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1765 if (CHECK_FLAG(peer->af_flags[afi][safi],
1766 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1767 return false;
d62a17ae 1768 } else {
1769 /* A route from a Non-client peer. Reflect to all other
1770 clients. */
1771 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1772 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1773 return false;
d62a17ae 1774 }
1775 }
3f9c7369 1776
d62a17ae 1777 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1778 *attr = *piattr;
d62a17ae 1779
1780 /* If local-preference is not set. */
1781 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1782 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1783 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1784 attr->local_pref = bgp->default_local_pref;
3f9c7369 1785 }
3f9c7369 1786
d62a17ae 1787 /* If originator-id is not set and the route is to be reflected,
1788 set the originator id */
1789 if (reflect
1790 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1791 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1792 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1793 }
3f9c7369 1794
d62a17ae 1795 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1796 */
1797 if (peer->sort == BGP_PEER_EBGP
1798 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1799 if (from != bgp->peer_self && !transparent
1800 && !CHECK_FLAG(peer->af_flags[afi][safi],
1801 PEER_FLAG_MED_UNCHANGED))
1802 attr->flag &=
1803 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1804 }
3f9c7369 1805
d62a17ae 1806 /* Since the nexthop attribute can vary per peer, it is not explicitly
1807 * set
1808 * in announce check, only certain flags and length (or number of
1809 * nexthops
1810 * -- for IPv6/MP_REACH) are set here in order to guide the update
1811 * formation
1812 * code in setting the nexthop(s) on a per peer basis in
1813 * reformat_peer().
1814 * Typically, the source nexthop in the attribute is preserved but in
1815 * the
1816 * scenarios where we know it will always be overwritten, we reset the
1817 * nexthop to "0" in an attempt to achieve better Update packing. An
1818 * example of this is when a prefix from each of 2 IBGP peers needs to
1819 * be
1820 * announced to an EBGP peer (and they have the same attributes barring
1821 * their nexthop).
1822 */
1823 if (reflect)
1824 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1825
1826#define NEXTHOP_IS_V6 \
1827 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1828 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1829 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1830 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1831
1832 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1833 * if
1834 * the peer (group) is configured to receive link-local nexthop
1835 * unchanged
c728d027
DA
1836 * and it is available in the prefix OR we're not reflecting the route,
1837 * link-local nexthop address is valid and
d62a17ae 1838 * the peer (group) to whom we're going to announce is on a shared
1839 * network
1840 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1841 * By checking if nexthop LL address is valid we are sure that
1842 * we do not announce LL address as `::`.
d62a17ae 1843 */
1844 if (NEXTHOP_IS_V6) {
1845 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1846 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1847 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1848 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1849 || (!reflect
1850 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1851 && peer->shared_network
d62a17ae 1852 && (from == bgp->peer_self
1853 || peer->sort == BGP_PEER_EBGP))) {
1854 attr->mp_nexthop_len =
1855 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1856 }
3f9c7369 1857
d62a17ae 1858 /* Clear off link-local nexthop in source, whenever it is not
1859 * needed to
1860 * ensure more prefixes share the same attribute for
1861 * announcement.
1862 */
1863 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1864 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1865 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1866 }
3f9c7369 1867
d62a17ae 1868 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1869 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1870
1871 /* Route map & unsuppress-map apply. */
40381db7 1872 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1873 struct bgp_path_info rmap_path = {0};
1874 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1875 struct attr dummy_attr = {0};
d62a17ae 1876
e34291b8 1877 /* Fill temp path_info */
9bcb3eef
DS
1878 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
1879 pi, peer, attr);
16f7ce2b 1880
d62a17ae 1881 /* don't confuse inbound and outbound setting */
1882 RESET_FLAG(attr->rmap_change_flags);
1883
1884 /*
1885 * The route reflector is not allowed to modify the attributes
1886 * of the reflected IBGP routes unless explicitly allowed.
1887 */
1888 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
1889 && !CHECK_FLAG(bgp->flags,
1890 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1891 dummy_attr = *attr;
40381db7 1892 rmap_path.attr = &dummy_attr;
d62a17ae 1893 }
3f9c7369 1894
d62a17ae 1895 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1896
40381db7 1897 if (pi->extra && pi->extra->suppress)
d62a17ae 1898 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1899 RMAP_BGP, &rmap_path);
d62a17ae 1900 else
1901 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1902 RMAP_BGP, &rmap_path);
d62a17ae 1903
1904 peer->rmap_type = 0;
1905
1906 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1907 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1908 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1909 peer->host, prefix2str(p, buf, sizeof(buf)));
1910
d62a17ae 1911 bgp_attr_flush(attr);
3dc339cd 1912 return false;
d62a17ae 1913 }
3f9c7369 1914 }
3f9c7369 1915
9dac9fc8
DA
1916 /* RFC 8212 to prevent route leaks.
1917 * This specification intends to improve this situation by requiring the
1918 * explicit configuration of both BGP Import and Export Policies for any
1919 * External BGP (EBGP) session such as customers, peers, or
1920 * confederation boundaries for all enabled address families. Through
1921 * codification of the aforementioned requirement, operators will
1922 * benefit from consistent behavior across different BGP
1923 * implementations.
1924 */
1d3fdccf 1925 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 1926 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 1927 return false;
9dac9fc8 1928
fb29348a
DA
1929 /* draft-ietf-idr-deprecate-as-set-confed-set
1930 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1931 * Eventually, This document (if approved) updates RFC 4271
1932 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1933 * and obsoletes RFC 6472.
1934 */
7f972cd8 1935 if (peer->bgp->reject_as_sets)
fb29348a 1936 if (aspath_check_as_sets(attr->aspath))
3dc339cd 1937 return false;
fb29348a 1938
33d022bc
DA
1939 /* Codification of AS 0 Processing */
1940 if (aspath_check_as_zero(attr->aspath))
e2369003 1941 return false;
33d022bc 1942
892fedb6 1943 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1944 if (peer->sort == BGP_PEER_IBGP
1945 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1946 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1947 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1948 } else {
1949 bgp_attr_add_gshut_community(attr);
1950 }
1951 }
1952
d62a17ae 1953 /* After route-map has been applied, we check to see if the nexthop to
1954 * be carried in the attribute (that is used for the announcement) can
1955 * be cleared off or not. We do this in all cases where we would be
1956 * setting the nexthop to "ourselves". For IPv6, we only need to
1957 * consider
1958 * the global nexthop here; the link-local nexthop would have been
1959 * cleared
1960 * already, and if not, it is required by the update formation code.
1961 * Also see earlier comments in this function.
1962 */
1963 /*
1964 * If route-map has performed some operation on the nexthop or the peer
1965 * configuration says to pass it unchanged, we cannot reset the nexthop
1966 * here, so only attempt to do it if these aren't true. Note that the
1967 * route-map handler itself might have cleared the nexthop, if for
1968 * example,
1969 * it is configured as 'peer-address'.
1970 */
1971 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1972 piattr->rmap_change_flags)
d62a17ae 1973 && !transparent
1974 && !CHECK_FLAG(peer->af_flags[afi][safi],
1975 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1976 /* We can reset the nexthop, if setting (or forcing) it to
1977 * 'self' */
1978 if (CHECK_FLAG(peer->af_flags[afi][safi],
1979 PEER_FLAG_NEXTHOP_SELF)
1980 || CHECK_FLAG(peer->af_flags[afi][safi],
1981 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1982 if (!reflect
1983 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 1984 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 1985 subgroup_announce_reset_nhop(
1986 (peer_cap_enhe(peer, afi, safi)
1987 ? AF_INET6
1988 : p->family),
1989 attr);
7b651a32 1990 nh_reset = true;
1991 }
d62a17ae 1992 } else if (peer->sort == BGP_PEER_EBGP) {
1993 /* Can also reset the nexthop if announcing to EBGP, but
1994 * only if
1995 * no peer in the subgroup is on a shared subnet.
1996 * Note: 3rd party nexthop currently implemented for
1997 * IPv4 only.
1998 */
737af885
BS
1999 if ((p->family == AF_INET) &&
2000 (!bgp_subgrp_multiaccess_check_v4(
2001 piattr->nexthop,
7b651a32 2002 subgrp, from))) {
d62a17ae 2003 subgroup_announce_reset_nhop(
2004 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2005 ? AF_INET6
2006 : p->family),
737af885 2007 attr);
7b651a32 2008 nh_reset = true;
2009 }
737af885
BS
2010
2011 if ((p->family == AF_INET6) &&
2012 (!bgp_subgrp_multiaccess_check_v6(
2013 piattr->mp_nexthop_global,
7b651a32 2014 subgrp, from))) {
737af885
BS
2015 subgroup_announce_reset_nhop(
2016 (peer_cap_enhe(peer, afi, safi)
2017 ? AF_INET6
2018 : p->family),
2019 attr);
7b651a32 2020 nh_reset = true;
2021 }
737af885
BS
2022
2023
2024
40381db7 2025 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2026 /*
2027 * This flag is used for leaked vpn-vrf routes
2028 */
2029 int family = p->family;
2030
2031 if (peer_cap_enhe(peer, afi, safi))
2032 family = AF_INET6;
2033
2034 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2035 zlog_debug(
1defdda8 2036 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2037 __func__, family2str(family));
2038 subgroup_announce_reset_nhop(family, attr);
7b651a32 2039 nh_reset = true;
d62a17ae 2040 }
63696f1d 2041 }
960035b2 2042
63696f1d 2043 /* If IPv6/MP and nexthop does not have any override and happens
2044 * to
2045 * be a link-local address, reset it so that we don't pass along
2046 * the
2047 * source's link-local IPv6 address to recipients who may not be
2048 * on
2049 * the same interface.
2050 */
2051 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2052 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2053 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2054 nh_reset = true;
2055 }
d62a17ae 2056 }
3f9c7369 2057
7b651a32 2058 /*
2059 * When the next hop is set to ourselves, if all multipaths have
2060 * link-bandwidth announce the cumulative bandwidth as that makes
2061 * the most sense. However, don't modify if the link-bandwidth has
2062 * been explicitly set by user policy.
2063 */
2064 if (nh_reset &&
f7e1c681 2065 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2066 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2067 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2068 attr->ecommunity = ecommunity_replace_linkbw(
2069 bgp->as, attr->ecommunity, cum_bw);
2070
3dc339cd 2071 return true;
3f9c7369
DS
2072}
2073
f009ff26 2074static int bgp_route_select_timer_expire(struct thread *thread)
2075{
2076 struct afi_safi_info *info;
2077 afi_t afi;
2078 safi_t safi;
2079 struct bgp *bgp;
2080
2081 info = THREAD_ARG(thread);
2082 afi = info->afi;
2083 safi = info->safi;
2084 bgp = info->bgp;
2085
2086 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2087 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2088 safi);
f009ff26 2089
2090 bgp->gr_info[afi][safi].t_route_select = NULL;
2091
2092 XFREE(MTYPE_TMP, info);
2093
2094 /* Best path selection */
2095 return bgp_best_path_select_defer(bgp, afi, safi);
2096}
2097
9bcb3eef 2098void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2099 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2100 struct bgp_path_info_pair *result, afi_t afi,
2101 safi_t safi)
2102{
2103 struct bgp_path_info *new_select;
2104 struct bgp_path_info *old_select;
40381db7
DS
2105 struct bgp_path_info *pi;
2106 struct bgp_path_info *pi1;
2107 struct bgp_path_info *pi2;
2108 struct bgp_path_info *nextpi = NULL;
d62a17ae 2109 int paths_eq, do_mpath, debug;
2110 struct list mp_list;
2111 char pfx_buf[PREFIX2STR_BUFFER];
2112 char path_buf[PATH_ADDPATH_STR_BUFFER];
2113
2114 bgp_mp_list_init(&mp_list);
2115 do_mpath =
2116 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2117
9bcb3eef 2118 debug = bgp_debug_bestpath(dest);
d62a17ae 2119
2120 if (debug)
9bcb3eef 2121 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2122
9bcb3eef 2123 dest->reason = bgp_path_selection_none;
d62a17ae 2124 /* bgp deterministic-med */
2125 new_select = NULL;
892fedb6 2126 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2127
1defdda8 2128 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2129 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2130 pi1 = pi1->next)
9bcb3eef 2131 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2132 BGP_PATH_DMED_SELECTED);
d62a17ae 2133
9bcb3eef 2134 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2135 pi1 = pi1->next) {
40381db7 2136 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2137 continue;
40381db7 2138 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2139 continue;
ea8b2282 2140 if (pi1->peer != bgp->peer_self)
40381db7 2141 if (pi1->peer->status != Established)
d62a17ae 2142 continue;
2143
40381db7
DS
2144 new_select = pi1;
2145 if (pi1->next) {
2146 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2147 if (CHECK_FLAG(pi2->flags,
1defdda8 2148 BGP_PATH_DMED_CHECK))
d62a17ae 2149 continue;
40381db7 2150 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2151 continue;
ea8b2282 2152 if (pi2->peer != bgp->peer_self
d62a17ae 2153 && !CHECK_FLAG(
ea8b2282
DS
2154 pi2->peer->sflags,
2155 PEER_STATUS_NSF_WAIT))
40381db7 2156 if (pi2->peer->status
d62a17ae 2157 != Established)
2158 continue;
2159
121e245d
DS
2160 if (!aspath_cmp_left(pi1->attr->aspath,
2161 pi2->attr->aspath)
2162 && !aspath_cmp_left_confed(
40381db7 2163 pi1->attr->aspath,
121e245d
DS
2164 pi2->attr->aspath))
2165 continue;
d62a17ae 2166
121e245d
DS
2167 if (bgp_path_info_cmp(
2168 bgp, pi2, new_select,
2169 &paths_eq, mpath_cfg, debug,
fdf81fa0 2170 pfx_buf, afi, safi,
9bcb3eef 2171 &dest->reason)) {
121e245d 2172 bgp_path_info_unset_flag(
9bcb3eef 2173 dest, new_select,
121e245d
DS
2174 BGP_PATH_DMED_SELECTED);
2175 new_select = pi2;
d62a17ae 2176 }
121e245d
DS
2177
2178 bgp_path_info_set_flag(
9bcb3eef 2179 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2180 }
2181 }
9bcb3eef 2182 bgp_path_info_set_flag(dest, new_select,
18ee8310 2183 BGP_PATH_DMED_CHECK);
9bcb3eef 2184 bgp_path_info_set_flag(dest, new_select,
18ee8310 2185 BGP_PATH_DMED_SELECTED);
d62a17ae 2186
2187 if (debug) {
18ee8310
DS
2188 bgp_path_info_path_with_addpath_rx_str(
2189 new_select, path_buf);
c66faab1 2190 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2191 pfx_buf, path_buf,
2192 aspath_get_first_as(
2193 new_select->attr->aspath));
2194 }
2195 }
2196 }
96450faf 2197
d62a17ae 2198 /* Check old selected route and new selected route. */
2199 old_select = NULL;
2200 new_select = NULL;
9bcb3eef 2201 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2202 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2203 enum bgp_path_selection_reason reason;
2204
40381db7
DS
2205 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2206 old_select = pi;
d62a17ae 2207
40381db7 2208 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2209 /* reap REMOVED routes, if needs be
2210 * selected route must stay for a while longer though
2211 */
40381db7
DS
2212 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2213 && (pi != old_select))
9bcb3eef 2214 bgp_path_info_reap(dest, pi);
d62a17ae 2215
ddb5b488 2216 if (debug)
40381db7
DS
2217 zlog_debug("%s: pi %p in holddown", __func__,
2218 pi);
ddb5b488 2219
d62a17ae 2220 continue;
2221 }
96450faf 2222
40381db7
DS
2223 if (pi->peer && pi->peer != bgp->peer_self
2224 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2225 if (pi->peer->status != Established) {
ddb5b488
PZ
2226
2227 if (debug)
2228 zlog_debug(
40381db7
DS
2229 "%s: pi %p non self peer %s not estab state",
2230 __func__, pi, pi->peer->host);
ddb5b488 2231
d62a17ae 2232 continue;
ddb5b488 2233 }
9fbdd100 2234
892fedb6 2235 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2236 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2237 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2238 if (debug)
40381db7 2239 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2240 continue;
2241 }
9fbdd100 2242
9bcb3eef 2243 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2244
9bcb3eef 2245 reason = dest->reason;
40381db7 2246 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2247 debug, pfx_buf, afi, safi,
2248 &dest->reason)) {
19ea4cec
DS
2249 if (new_select == NULL &&
2250 reason != bgp_path_selection_none)
9bcb3eef 2251 dest->reason = reason;
40381db7 2252 new_select = pi;
d62a17ae 2253 }
2254 }
718e3744 2255
d62a17ae 2256 /* Now that we know which path is the bestpath see if any of the other
2257 * paths
2258 * qualify as multipaths
2259 */
2260 if (debug) {
2261 if (new_select)
18ee8310
DS
2262 bgp_path_info_path_with_addpath_rx_str(new_select,
2263 path_buf);
d62a17ae 2264 else
772270f3 2265 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2266 zlog_debug(
2267 "%s: After path selection, newbest is %s oldbest was %s",
2268 pfx_buf, path_buf,
2269 old_select ? old_select->peer->host : "NONE");
96450faf 2270 }
9fbdd100 2271
d62a17ae 2272 if (do_mpath && new_select) {
9bcb3eef 2273 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2274 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2275
2276 if (debug)
18ee8310 2277 bgp_path_info_path_with_addpath_rx_str(
40381db7 2278 pi, path_buf);
d62a17ae 2279
40381db7 2280 if (pi == new_select) {
d62a17ae 2281 if (debug)
2282 zlog_debug(
2283 "%s: %s is the bestpath, add to the multipath list",
2284 pfx_buf, path_buf);
40381db7 2285 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2286 continue;
2287 }
2288
40381db7 2289 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2290 continue;
2291
40381db7
DS
2292 if (pi->peer && pi->peer != bgp->peer_self
2293 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2294 PEER_STATUS_NSF_WAIT))
40381db7 2295 if (pi->peer->status != Established)
d62a17ae 2296 continue;
2297
40381db7 2298 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2299 if (debug)
2300 zlog_debug(
2301 "%s: %s has the same nexthop as the bestpath, skip it",
2302 pfx_buf, path_buf);
2303 continue;
2304 }
2305
40381db7 2306 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2307 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2308 &dest->reason);
d62a17ae 2309
2310 if (paths_eq) {
2311 if (debug)
2312 zlog_debug(
2313 "%s: %s is equivalent to the bestpath, add to the multipath list",
2314 pfx_buf, path_buf);
40381db7 2315 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2316 }
2317 }
2318 }
fee0f4c6 2319
9bcb3eef 2320 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2321 mpath_cfg);
2322 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2323 bgp_mp_list_clear(&mp_list);
96450faf 2324
9bcb3eef 2325 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2326
d62a17ae 2327 result->old = old_select;
2328 result->new = new_select;
96450faf 2329
d62a17ae 2330 return;
fee0f4c6 2331}
2332
3f9c7369
DS
2333/*
2334 * A new route/change in bestpath of an existing route. Evaluate the path
2335 * for advertisement to the subgroup.
2336 */
3dc339cd
DA
2337void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2338 struct bgp_path_info *selected,
9bcb3eef 2339 struct bgp_dest *dest,
3dc339cd 2340 uint32_t addpath_tx_id)
d62a17ae 2341{
b54892e0 2342 const struct prefix *p;
d62a17ae 2343 struct peer *onlypeer;
2344 struct attr attr;
2345 afi_t afi;
2346 safi_t safi;
adbac85e 2347
9bcb3eef 2348 p = bgp_dest_get_prefix(dest);
d62a17ae 2349 afi = SUBGRP_AFI(subgrp);
2350 safi = SUBGRP_SAFI(subgrp);
2351 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2352 : NULL);
2353
e0207895
PZ
2354 if (BGP_DEBUG(update, UPDATE_OUT)) {
2355 char buf_prefix[PREFIX_STRLEN];
2356 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2357 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2358 selected);
e0207895
PZ
2359 }
2360
d62a17ae 2361 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2362 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2363 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2364 return;
d62a17ae 2365
2366 memset(&attr, 0, sizeof(struct attr));
2367 /* It's initialized in bgp_announce_check() */
2368
2369 /* Announcement to the subgroup. If the route is filtered withdraw it.
2370 */
2371 if (selected) {
9bcb3eef
DS
2372 if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
2373 bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
d62a17ae 2374 else
9bcb3eef 2375 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2376 addpath_tx_id);
d62a17ae 2377 }
2378
2379 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2380 else {
9bcb3eef 2381 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2382 }
200df115 2383}
fee0f4c6 2384
3064bf43 2385/*
e1072051 2386 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2387 * This is called at the end of route processing.
3064bf43 2388 */
9bcb3eef 2389void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2390{
40381db7 2391 struct bgp_path_info *pi;
3064bf43 2392
9bcb3eef 2393 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2394 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2395 continue;
40381db7
DS
2396 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2397 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2398 }
3064bf43 2399}
2400
2401/*
2402 * Has the route changed from the RIB's perspective? This is invoked only
2403 * if the route selection returns the same best route as earlier - to
2404 * determine if we need to update zebra or not.
2405 */
9bcb3eef 2406bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2407{
4b7e6066 2408 struct bgp_path_info *mpinfo;
d62a17ae 2409
2bb9eff4
DS
2410 /* If this is multipath, check all selected paths for any nexthop
2411 * change or attribute change. Some attribute changes (e.g., community)
2412 * aren't of relevance to the RIB, but we'll update zebra to ensure
2413 * we handle the case of BGP nexthop change. This is the behavior
2414 * when the best path has an attribute change anyway.
d62a17ae 2415 */
1defdda8 2416 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2417 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2418 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2419 return true;
d62a17ae 2420
2bb9eff4
DS
2421 /*
2422 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2423 */
18ee8310
DS
2424 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2425 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2426 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2427 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2428 return true;
d62a17ae 2429 }
3064bf43 2430
d62a17ae 2431 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2432 return false;
3064bf43 2433}
2434
d62a17ae 2435struct bgp_process_queue {
2436 struct bgp *bgp;
9bcb3eef 2437 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2438#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2439 unsigned int flags;
2440 unsigned int queued;
200df115 2441};
2442
3b0c17e1 2443static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2444 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2445 struct bgp_path_info *new_select,
2446 struct bgp_path_info *old_select)
2447{
9bcb3eef 2448 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2449
2450 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2451 return;
2452
2453 if (advertise_type5_routes(bgp, afi) && new_select
2454 && is_route_injectable_into_evpn(new_select)) {
2455
2456 /* apply the route-map */
2457 if (bgp->adv_cmd_rmap[afi][safi].map) {
2458 route_map_result_t ret;
2459 struct bgp_path_info rmap_path;
2460 struct bgp_path_info_extra rmap_path_extra;
2461 struct attr dummy_attr;
2462
2463 dummy_attr = *new_select->attr;
2464
2465 /* Fill temp path_info */
9bcb3eef 2466 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2467 new_select, new_select->peer,
2468 &dummy_attr);
2469
2470 RESET_FLAG(dummy_attr.rmap_change_flags);
2471
2472 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2473 p, RMAP_BGP, &rmap_path);
2474
2475 if (ret == RMAP_DENYMATCH) {
2476 bgp_attr_flush(&dummy_attr);
2477 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2478 safi);
2479 } else
2480 bgp_evpn_advertise_type5_route(
2481 bgp, p, &dummy_attr, afi, safi);
2482 } else {
2483 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2484 afi, safi);
2485 }
2486 } else if (advertise_type5_routes(bgp, afi) && old_select
2487 && is_route_injectable_into_evpn(old_select))
2488 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2489}
2490
3103e8d2
DS
2491/*
2492 * old_select = The old best path
2493 * new_select = the new best path
2494 *
2495 * if (!old_select && new_select)
2496 * We are sending new information on.
2497 *
2498 * if (old_select && new_select) {
2499 * if (new_select != old_select)
2500 * We have a new best path send a change
2501 * else
2502 * We've received a update with new attributes that needs
2503 * to be passed on.
2504 * }
2505 *
2506 * if (old_select && !new_select)
2507 * We have no eligible route that we can announce or the rn
2508 * is being removed.
2509 */
9bcb3eef 2510static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2511 afi_t afi, safi_t safi)
d62a17ae 2512{
4b7e6066
DS
2513 struct bgp_path_info *new_select;
2514 struct bgp_path_info *old_select;
2515 struct bgp_path_info_pair old_and_new;
ddb5b488 2516 int debug = 0;
d62a17ae 2517
892fedb6 2518 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2519 if (dest)
2520 debug = bgp_debug_bestpath(dest);
b54892e0 2521 if (debug)
f4c713ae 2522 zlog_debug(
b54892e0 2523 "%s: bgp delete in progress, ignoring event, p=%pRN",
9bcb3eef 2524 __func__, dest);
f4c713ae
LB
2525 return;
2526 }
d62a17ae 2527 /* Is it end of initial update? (after startup) */
9bcb3eef 2528 if (!dest) {
d62a17ae 2529 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2530 sizeof(bgp->update_delay_zebra_resume_time));
2531
2532 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2533 FOREACH_AFI_SAFI (afi, safi) {
2534 if (bgp_fibupd_safi(safi))
2535 bgp_zebra_announce_table(bgp, afi, safi);
2536 }
d62a17ae 2537 bgp->main_peers_update_hold = 0;
2538
2539 bgp_start_routeadv(bgp);
aac24838 2540 return;
d62a17ae 2541 }
cb1faec9 2542
9bcb3eef 2543 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2544
9bcb3eef 2545 debug = bgp_debug_bestpath(dest);
b54892e0 2546 if (debug)
9bcb3eef 2547 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, dest,
ddb5b488 2548 afi2str(afi), safi2str(safi));
ddb5b488 2549
f009ff26 2550 /* The best path calculation for the route is deferred if
2551 * BGP_NODE_SELECT_DEFER is set
2552 */
9bcb3eef 2553 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2554 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef 2555 zlog_debug("SELECT_DEFER falg set for route %p", dest);
f009ff26 2556 return;
2557 }
2558
d62a17ae 2559 /* Best path selection. */
9bcb3eef 2560 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2561 afi, safi);
2562 old_select = old_and_new.old;
2563 new_select = old_and_new.new;
2564
2565 /* Do we need to allocate or free labels?
2566 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2567 * necessary to do this upon changes to best path. Exceptions:
2568 * - label index has changed -> recalculate resulting label
2569 * - path_info sub_type changed -> switch to/from implicit-null
2570 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2571 */
318cac96 2572 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2573 if (new_select) {
2574 if (!old_select
2575 || bgp_label_index_differs(new_select, old_select)
57592a53 2576 || new_select->sub_type != old_select->sub_type
9bcb3eef 2577 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2578 /* Enforced penultimate hop popping:
2579 * implicit-null for local routes, aggregate
2580 * and redistributed routes
2581 */
d62a17ae 2582 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2583 || new_select->sub_type
2584 == BGP_ROUTE_AGGREGATE
2585 || new_select->sub_type
2586 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2587 if (CHECK_FLAG(
9bcb3eef 2588 dest->flags,
d62a17ae 2589 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2590 bgp_unregister_for_label(dest);
70e98a7f 2591 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2592 &dest->local_label);
2593 bgp_set_valid_label(&dest->local_label);
d62a17ae 2594 } else
9bcb3eef
DS
2595 bgp_register_for_label(dest,
2596 new_select);
d62a17ae 2597 }
9bcb3eef 2598 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2599 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2600 bgp_unregister_for_label(dest);
318cac96 2601 }
9bcb3eef
DS
2602 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2603 bgp_unregister_for_label(dest);
d62a17ae 2604 }
cd1964ff 2605
b54892e0 2606 if (debug)
ddb5b488 2607 zlog_debug(
b54892e0 2608 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2609 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2610 old_select, new_select);
ddb5b488 2611
d62a17ae 2612 /* If best route remains the same and this is not due to user-initiated
2613 * clear, see exactly what needs to be done.
2614 */
d62a17ae 2615 if (old_select && old_select == new_select
9bcb3eef 2616 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2617 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2618 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2619 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2620#ifdef ENABLE_BGP_VNC
d62a17ae 2621 vnc_import_bgp_add_route(bgp, p, old_select);
2622 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2623#endif
bb744275 2624 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2625 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2626
2627 if (new_select->type == ZEBRA_ROUTE_BGP
2628 && (new_select->sub_type == BGP_ROUTE_NORMAL
2629 || new_select->sub_type
2630 == BGP_ROUTE_IMPORTED))
2631
9bcb3eef 2632 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2633 bgp, afi, safi);
2634 }
d62a17ae 2635 }
d62a17ae 2636
2637 /* If there is a change of interest to peers, reannounce the
2638 * route. */
1defdda8 2639 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2640 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2641 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2642 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2643
2644 /* unicast routes must also be annouced to
2645 * labeled-unicast update-groups */
2646 if (safi == SAFI_UNICAST)
2647 group_announce_route(bgp, afi,
9bcb3eef 2648 SAFI_LABELED_UNICAST, dest,
d62a17ae 2649 new_select);
2650
1defdda8 2651 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2652 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2653 }
fee0f4c6 2654
3b0c17e1 2655 /* advertise/withdraw type-5 routes */
2656 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2657 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2658 bgp_process_evpn_route_injection(
9bcb3eef 2659 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2660
b1875e65 2661 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2662 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2663 bgp_zebra_clear_route_change_flags(dest);
2664 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2665 return;
d62a17ae 2666 }
8ad7271d 2667
d62a17ae 2668 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2669 */
9bcb3eef 2670 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2671
2672 /* bestpath has changed; bump version */
2673 if (old_select || new_select) {
9bcb3eef 2674 bgp_bump_version(dest);
d62a17ae 2675
2676 if (!bgp->t_rmap_def_originate_eval) {
2677 bgp_lock(bgp);
2678 thread_add_timer(
2679 bm->master,
2680 update_group_refresh_default_originate_route_map,
2681 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2682 &bgp->t_rmap_def_originate_eval);
2683 }
2684 }
3f9c7369 2685
d62a17ae 2686 if (old_select)
9bcb3eef 2687 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2688 if (new_select) {
ddb5b488
PZ
2689 if (debug)
2690 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2691 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2692 bgp_path_info_unset_flag(dest, new_select,
2693 BGP_PATH_ATTR_CHANGED);
1defdda8 2694 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2695 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2696 }
338b3424 2697
49e5a4a0 2698#ifdef ENABLE_BGP_VNC
d62a17ae 2699 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2700 if (old_select != new_select) {
2701 if (old_select) {
2702 vnc_import_bgp_exterior_del_route(bgp, p,
2703 old_select);
2704 vnc_import_bgp_del_route(bgp, p, old_select);
2705 }
2706 if (new_select) {
2707 vnc_import_bgp_exterior_add_route(bgp, p,
2708 new_select);
2709 vnc_import_bgp_add_route(bgp, p, new_select);
2710 }
2711 }
2712 }
65efcfce
LB
2713#endif
2714
9bcb3eef 2715 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2716
2717 /* unicast routes must also be annouced to labeled-unicast update-groups
2718 */
2719 if (safi == SAFI_UNICAST)
9bcb3eef 2720 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2721 new_select);
2722
2723 /* FIB update. */
2724 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2725 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2726 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2727 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2728 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2729 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2730
2731 /* if this is an evpn imported type-5 prefix,
2732 * we need to withdraw the route first to clear
2733 * the nh neigh and the RMAC entry.
2734 */
2735 if (old_select &&
2736 is_route_parent_evpn(old_select))
2737 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2738
9bcb3eef 2739 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2740 } else {
d62a17ae 2741 /* Withdraw the route from the kernel. */
2742 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2743 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2744 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2745 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2746
568e10ca 2747 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2748 }
718e3744 2749 }
3064bf43 2750
9bcb3eef 2751 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2752 old_select);
5424b7ba 2753
d62a17ae 2754 /* Clear any route change flags. */
9bcb3eef 2755 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2756
18ee8310 2757 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2758 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2759 bgp_path_info_reap(dest, old_select);
d62a17ae 2760
9bcb3eef 2761 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2762 return;
718e3744 2763}
2764
f009ff26 2765/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2766int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2767{
9bcb3eef 2768 struct bgp_dest *dest;
f009ff26 2769 int cnt = 0;
2770 struct afi_safi_info *thread_info;
2771 struct listnode *node = NULL, *nnode = NULL;
2772
2773 if (bgp->gr_info[afi][safi].t_route_select)
2774 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2775
2776 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2777 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2778 get_afi_safi_str(afi, safi, false),
2779 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2780 }
2781
2782 /* Process the route list */
2783 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2784 while (node) {
9bcb3eef 2785 dest = listgetdata(node);
f009ff26 2786 nnode = node->next;
2787 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
9bcb3eef 2788 dest->rt_node = NULL;
f009ff26 2789
9bcb3eef
DS
2790 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2791 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2792 bgp_process_main_one(bgp, dest, afi, safi);
f009ff26 2793 cnt++;
2794 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2795 break;
2796 }
2797 node = nnode;
2798 }
2799
9e3b51a7 2800 /* Send EOR message when all routes are processed */
2801 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2802 bgp_send_delayed_eor(bgp);
8c48b3b6 2803 /* Send route processing complete message to RIB */
2804 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2805 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2806 return 0;
9e3b51a7 2807 }
f009ff26 2808
2809 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2810
2811 thread_info->afi = afi;
2812 thread_info->safi = safi;
2813 thread_info->bgp = bgp;
2814
2815 /* If there are more routes to be processed, start the
2816 * selection timer
2817 */
2818 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2819 BGP_ROUTE_SELECT_DELAY,
2820 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2821 return 0;
2822}
2823
aac24838 2824static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2825{
aac24838
JB
2826 struct bgp_process_queue *pqnode = data;
2827 struct bgp *bgp = pqnode->bgp;
d62a17ae 2828 struct bgp_table *table;
9bcb3eef 2829 struct bgp_dest *dest;
aac24838
JB
2830
2831 /* eoiu marker */
2832 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2833 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2834 /* should always have dedicated wq call */
2835 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2836 return WQ_SUCCESS;
2837 }
2838
ac021f40 2839 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 2840 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 2841 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
2842 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
2843 table = bgp_dest_table(dest);
2844 /* note, new DESTs may be added as part of processing */
2845 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 2846
9bcb3eef 2847 bgp_dest_unlock_node(dest);
d62a17ae 2848 bgp_table_unlock(table);
2849 }
aac24838
JB
2850
2851 return WQ_SUCCESS;
2852}
2853
2854static void bgp_processq_del(struct work_queue *wq, void *data)
2855{
2856 struct bgp_process_queue *pqnode = data;
2857
2858 bgp_unlock(pqnode->bgp);
2859
2860 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2861}
2862
d62a17ae 2863void bgp_process_queue_init(void)
200df115 2864{
0ce1ca80 2865 if (!bm->process_main_queue)
d62a17ae 2866 bm->process_main_queue =
2867 work_queue_new(bm->master, "process_main_queue");
2868
aac24838 2869 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2870 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2871 bm->process_main_queue->spec.max_retries = 0;
2872 bm->process_main_queue->spec.hold = 50;
2873 /* Use a higher yield value of 50ms for main queue processing */
2874 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2875}
2876
cfe8d15a 2877static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2878{
2879 struct bgp_process_queue *pqnode;
2880
a4d82a8a
PZ
2881 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2882 sizeof(struct bgp_process_queue));
aac24838
JB
2883
2884 /* unlocked in bgp_processq_del */
2885 pqnode->bgp = bgp_lock(bgp);
2886 STAILQ_INIT(&pqnode->pqueue);
2887
aac24838
JB
2888 return pqnode;
2889}
2890
9bcb3eef 2891void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 2892{
aac24838
JB
2893#define ARBITRARY_PROCESS_QLEN 10000
2894 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2895 struct bgp_process_queue *pqnode;
cfe8d15a 2896 int pqnode_reuse = 0;
495f0b13 2897
d62a17ae 2898 /* already scheduled for processing? */
9bcb3eef 2899 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 2900 return;
2e02b9b2 2901
f009ff26 2902 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2903 * the workqueue
2904 */
9bcb3eef 2905 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2906 if (BGP_DEBUG(update, UPDATE_OUT))
2907 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 2908 dest);
f009ff26 2909 return;
2910 }
2911
aac24838 2912 if (wq == NULL)
d62a17ae 2913 return;
2914
aac24838 2915 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2916 limit only if is from the same BGP view and it's not an EOIU marker
2917 */
aac24838
JB
2918 if (work_queue_item_count(wq)) {
2919 struct work_queue_item *item = work_queue_last_item(wq);
2920 pqnode = item->data;
228da428 2921
a4d82a8a
PZ
2922 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2923 || pqnode->bgp != bgp
2924 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2925 pqnode = bgp_processq_alloc(bgp);
2926 else
2927 pqnode_reuse = 1;
aac24838 2928 } else
cfe8d15a 2929 pqnode = bgp_processq_alloc(bgp);
aac24838 2930 /* all unlocked in bgp_process_wq */
9bcb3eef 2931 bgp_table_lock(bgp_dest_table(dest));
aac24838 2932
9bcb3eef
DS
2933 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2934 bgp_dest_lock_node(dest);
aac24838 2935
60466a63 2936 /* can't be enqueued twice */
9bcb3eef
DS
2937 assert(STAILQ_NEXT(dest, pq) == NULL);
2938 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
2939 pqnode->queued++;
2940
cfe8d15a
LB
2941 if (!pqnode_reuse)
2942 work_queue_add(wq, pqnode);
2943
d62a17ae 2944 return;
fee0f4c6 2945}
0a486e5f 2946
d62a17ae 2947void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2948{
d62a17ae 2949 struct bgp_process_queue *pqnode;
cb1faec9 2950
d62a17ae 2951 if (bm->process_main_queue == NULL)
2952 return;
2e02b9b2 2953
cfe8d15a 2954 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2955
aac24838 2956 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2957 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2958}
2959
d62a17ae 2960static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2961{
d62a17ae 2962 struct peer *peer;
0a486e5f 2963
d62a17ae 2964 peer = THREAD_ARG(thread);
2965 peer->t_pmax_restart = NULL;
0a486e5f 2966
d62a17ae 2967 if (bgp_debug_neighbor_events(peer))
2968 zlog_debug(
2969 "%s Maximum-prefix restart timer expired, restore peering",
2970 peer->host);
0a486e5f 2971
a9bafa95 2972 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 2973 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 2974
d62a17ae 2975 return 0;
0a486e5f 2976}
2977
3dc339cd
DA
2978bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2979 int always)
718e3744 2980{
d62a17ae 2981 iana_afi_t pkt_afi;
5c525538 2982 iana_safi_t pkt_safi;
9cabb64b 2983
d62a17ae 2984 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 2985 return false;
e0701b79 2986
d62a17ae 2987 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2988 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2989 PEER_STATUS_PREFIX_LIMIT)
2990 && !always)
3dc339cd 2991 return false;
e0701b79 2992
d62a17ae 2993 zlog_info(
6cde4b45 2994 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
5cb5f4d0 2995 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2996 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2997 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2998
2999 if (CHECK_FLAG(peer->af_flags[afi][safi],
3000 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3001 return false;
d62a17ae 3002
3003 /* Convert AFI, SAFI to values for packet. */
3004 pkt_afi = afi_int2iana(afi);
3005 pkt_safi = safi_int2iana(safi);
3006 {
d7c0a89a 3007 uint8_t ndata[7];
d62a17ae 3008
3009 ndata[0] = (pkt_afi >> 8);
3010 ndata[1] = pkt_afi;
3011 ndata[2] = pkt_safi;
3012 ndata[3] = (peer->pmax[afi][safi] >> 24);
3013 ndata[4] = (peer->pmax[afi][safi] >> 16);
3014 ndata[5] = (peer->pmax[afi][safi] >> 8);
3015 ndata[6] = (peer->pmax[afi][safi]);
3016
3017 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3018 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3019 BGP_NOTIFY_CEASE_MAX_PREFIX,
3020 ndata, 7);
3021 }
3022
3023 /* Dynamic peers will just close their connection. */
3024 if (peer_dynamic_neighbor(peer))
3dc339cd 3025 return true;
d62a17ae 3026
3027 /* restart timer start */
3028 if (peer->pmax_restart[afi][safi]) {
3029 peer->v_pmax_restart =
3030 peer->pmax_restart[afi][safi] * 60;
3031
3032 if (bgp_debug_neighbor_events(peer))
3033 zlog_debug(
3034 "%s Maximum-prefix restart timer started for %d secs",
3035 peer->host, peer->v_pmax_restart);
3036
3037 BGP_TIMER_ON(peer->t_pmax_restart,
3038 bgp_maximum_prefix_restart_timer,
3039 peer->v_pmax_restart);
3040 }
3041
3dc339cd 3042 return true;
d62a17ae 3043 } else
3044 UNSET_FLAG(peer->af_sflags[afi][safi],
3045 PEER_STATUS_PREFIX_LIMIT);
3046
3047 if (peer->pcount[afi][safi]
3048 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3049 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3050 PEER_STATUS_PREFIX_THRESHOLD)
3051 && !always)
3dc339cd 3052 return false;
d62a17ae 3053
3054 zlog_info(
6cde4b45 3055 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
5cb5f4d0 3056 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3057 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3058 SET_FLAG(peer->af_sflags[afi][safi],
3059 PEER_STATUS_PREFIX_THRESHOLD);
3060 } else
3061 UNSET_FLAG(peer->af_sflags[afi][safi],
3062 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3063 return false;
718e3744 3064}
3065
b40d939b 3066/* Unconditionally remove the route from the RIB, without taking
3067 * damping into consideration (eg, because the session went down)
3068 */
9bcb3eef 3069void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3070 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3071{
f009ff26 3072
3073 struct bgp *bgp = NULL;
3074 bool delete_route = false;
3075
9bcb3eef
DS
3076 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3077 safi);
d62a17ae 3078
f009ff26 3079 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3080 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3081
f009ff26 3082 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3083 * flag
3084 */
3085 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3086 delete_route = true;
9bcb3eef 3087 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3088 delete_route = true;
f009ff26 3089 if (delete_route) {
9bcb3eef
DS
3090 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3091 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3092 bgp = pi->peer->bgp;
9bcb3eef 3093 if ((dest->rt_node)
36235319
QY
3094 && (bgp->gr_info[afi][safi].route_list)) {
3095 list_delete_node(bgp->gr_info[afi][safi]
3096 .route_list,
9bcb3eef
DS
3097 dest->rt_node);
3098 dest->rt_node = NULL;
f009ff26 3099 }
3100 }
3101 }
3102 }
4a11bf2c 3103
9bcb3eef
DS
3104 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3105 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3106}
3107
9bcb3eef 3108static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3109 struct peer *peer, afi_t afi, safi_t safi,
3110 struct prefix_rd *prd)
3111{
9bcb3eef 3112 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3113
d62a17ae 3114 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3115 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3116 */
3117 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3118 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3119 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3120 == BGP_DAMP_SUPPRESSED) {
b54892e0 3121 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3122 safi);
3123 return;
3124 }
3125
49e5a4a0 3126#ifdef ENABLE_BGP_VNC
d62a17ae 3127 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3128 struct bgp_dest *pdest = NULL;
d62a17ae 3129 struct bgp_table *table = NULL;
3130
9bcb3eef
DS
3131 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3132 (struct prefix *)prd);
3133 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3134 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3135
3136 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3137 peer->bgp, prd, table, p, pi);
d62a17ae 3138 }
9bcb3eef 3139 bgp_dest_unlock_node(pdest);
d62a17ae 3140 }
3141 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3142 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3143
b54892e0
DS
3144 vnc_import_bgp_del_route(peer->bgp, p, pi);
3145 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3146 }
65efcfce 3147 }
d62a17ae 3148#endif
128ea8ab 3149
d62a17ae 3150 /* If this is an EVPN route, process for un-import. */
3151 if (safi == SAFI_EVPN)
b54892e0 3152 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3153
9bcb3eef 3154 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3155}
3156
4b7e6066
DS
3157struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3158 struct peer *peer, struct attr *attr,
9bcb3eef 3159 struct bgp_dest *dest)
fb018d25 3160{
4b7e6066 3161 struct bgp_path_info *new;
fb018d25 3162
d62a17ae 3163 /* Make new BGP info. */
4b7e6066 3164 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3165 new->type = type;
3166 new->instance = instance;
3167 new->sub_type = sub_type;
3168 new->peer = peer;
3169 new->attr = attr;
3170 new->uptime = bgp_clock();
9bcb3eef 3171 new->net = dest;
d62a17ae 3172 return new;
fb018d25
DS
3173}
3174
d62a17ae 3175static void overlay_index_update(struct attr *attr,
d62a17ae 3176 union gw_addr *gw_ip)
684a7227 3177{
d62a17ae 3178 if (!attr)
3179 return;
d62a17ae 3180 if (gw_ip == NULL) {
3181 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3182 } else {
3183 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3184 sizeof(union gw_addr));
3185 }
684a7227
PG
3186}
3187
40381db7 3188static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3189 union gw_addr *gw_ip)
3190{
40381db7 3191 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3192 union {
0a50c248 3193 esi_t esi;
11ebf4ed
DS
3194 union gw_addr ip;
3195 } temp;
d62a17ae 3196
3197 if (afi != AFI_L2VPN)
3198 return true;
11ebf4ed 3199
05864da7 3200 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3201
3202 if (gw_ip == NULL) {
3203 memset(&temp, 0, sizeof(temp));
40381db7 3204 path_gw_ip_remote = &temp.ip;
11ebf4ed 3205 } else
40381db7 3206 path_gw_ip_remote = gw_ip;
11ebf4ed 3207
0a50c248 3208 return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3209}
3210
c265ee22 3211/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3212bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3213 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3214 struct bgp_dest *dest)
d62a17ae 3215{
2dbe3fa9 3216 bool ret = false;
b099a5c8
DA
3217 bool is_bgp_static_route =
3218 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3219 : false;
d62a17ae 3220
3221 /* Only validated for unicast and multicast currently. */
3222 /* Also valid for EVPN where the nexthop is an IP address. */
3223 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3dc339cd 3224 return false;
d62a17ae 3225
3226 /* If NEXT_HOP is present, validate it. */
3227 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
b099a5c8 3228 if ((attr->nexthop.s_addr == INADDR_ANY && !is_bgp_static_route)
d62a17ae 3229 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3230 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3231 return true;
d62a17ae 3232 }
c265ee22 3233
d62a17ae 3234 /* If MP_NEXTHOP is present, validate it. */
3235 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3236 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3237 * it is not an IPv6 link-local address.
0355b41d
DA
3238 *
3239 * If we receive an UPDATE with nexthop length set to 32 bytes
3240 * we shouldn't discard an UPDATE if it's set to (::).
3241 * The link-local (2st) is validated along the code path later.
d62a17ae 3242 */
3243 if (attr->mp_nexthop_len) {
3244 switch (attr->mp_nexthop_len) {
3245 case BGP_ATTR_NHLEN_IPV4:
3246 case BGP_ATTR_NHLEN_VPNV4:
b099a5c8
DA
3247 ret = ((attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3248 && !is_bgp_static_route)
975a328e
DA
3249 || IPV4_CLASS_DE(
3250 ntohl(attr->mp_nexthop_global_in.s_addr))
3251 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3252 dest));
d62a17ae 3253 break;
3254
3255 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3256 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
b099a5c8
DA
3257 ret = ((IN6_IS_ADDR_UNSPECIFIED(
3258 &attr->mp_nexthop_global)
3259 && !is_bgp_static_route)
d62a17ae 3260 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3261 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3262 &attr->mp_nexthop_global)
3263 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3264 dest));
d62a17ae 3265 break;
0355b41d
DA
3266 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3267 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3268 || IN6_IS_ADDR_MULTICAST(
3269 &attr->mp_nexthop_global)
3270 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3271 dest));
0355b41d 3272 break;
d62a17ae 3273
3274 default:
3dc339cd 3275 ret = true;
d62a17ae 3276 break;
3277 }
3278 }
c265ee22 3279
d62a17ae 3280 return ret;
3281}
3282
5a1ae2c2 3283int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3284 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3285 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3286 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3287 struct bgp_route_evpn *evpn)
d62a17ae 3288{
3289 int ret;
3290 int aspath_loop_count = 0;
9bcb3eef 3291 struct bgp_dest *dest;
d62a17ae 3292 struct bgp *bgp;
3293 struct attr new_attr;
3294 struct attr *attr_new;
40381db7 3295 struct bgp_path_info *pi;
4b7e6066
DS
3296 struct bgp_path_info *new;
3297 struct bgp_path_info_extra *extra;
d62a17ae 3298 const char *reason;
3299 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3300 int connected = 0;
3301 int do_loop_check = 1;
3302 int has_valid_label = 0;
7c312383 3303 afi_t nh_afi;
949b0f24 3304 uint8_t pi_type = 0;
3305 uint8_t pi_sub_type = 0;
3306
49e5a4a0 3307#ifdef ENABLE_BGP_VNC
d62a17ae 3308 int vnc_implicit_withdraw = 0;
65efcfce 3309#endif
d62a17ae 3310 int same_attr = 0;
718e3744 3311
d62a17ae 3312 memset(&new_attr, 0, sizeof(struct attr));
3313 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3314 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3315
d62a17ae 3316 bgp = peer->bgp;
9bcb3eef 3317 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3318 /* TODO: Check to see if we can get rid of "is_valid_label" */
3319 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3320 has_valid_label = (num_labels > 0) ? 1 : 0;
3321 else
3322 has_valid_label = bgp_is_valid_label(label);
718e3744 3323
d62a17ae 3324 /* When peer's soft reconfiguration enabled. Record input packet in
3325 Adj-RIBs-In. */
3326 if (!soft_reconfig
3327 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3328 && peer != bgp->peer_self)
9bcb3eef 3329 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3330
3331 /* Check previously received route. */
9bcb3eef 3332 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3333 if (pi->peer == peer && pi->type == type
3334 && pi->sub_type == sub_type
3335 && pi->addpath_rx_id == addpath_id)
d62a17ae 3336 break;
3337
3338 /* AS path local-as loop check. */
3339 if (peer->change_local_as) {
c4368918
DW
3340 if (peer->allowas_in[afi][safi])
3341 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3342 else if (!CHECK_FLAG(peer->flags,
3343 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3344 aspath_loop_count = 1;
3345
3346 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3347 > aspath_loop_count) {
b4d46cc9 3348 peer->stat_pfx_aspath_loop++;
9bcb3eef 3349 reason = "as-path contains our own AS A;";
d62a17ae 3350 goto filtered;
3351 }
718e3744 3352 }
718e3744 3353
d62a17ae 3354 /* If the peer is configured for "allowas-in origin" and the last ASN in
3355 * the
3356 * as-path is our ASN then we do not need to call aspath_loop_check
3357 */
3358 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3359 if (aspath_get_last_as(attr->aspath) == bgp->as)
3360 do_loop_check = 0;
3361
3362 /* AS path loop check. */
3363 if (do_loop_check) {
3364 if (aspath_loop_check(attr->aspath, bgp->as)
3365 > peer->allowas_in[afi][safi]
3366 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3367 && aspath_loop_check(attr->aspath, bgp->confed_id)
3368 > peer->allowas_in[afi][safi])) {
b4d46cc9 3369 peer->stat_pfx_aspath_loop++;
d62a17ae 3370 reason = "as-path contains our own AS;";
3371 goto filtered;
3372 }
3373 }
aac9ef6c 3374
d62a17ae 3375 /* Route reflector originator ID check. */
3376 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3377 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3378 peer->stat_pfx_originator_loop++;
d62a17ae 3379 reason = "originator is us;";
3380 goto filtered;
3381 }
718e3744 3382
d62a17ae 3383 /* Route reflector cluster ID check. */
3384 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3385 peer->stat_pfx_cluster_loop++;
d62a17ae 3386 reason = "reflected from the same cluster;";
3387 goto filtered;
3388 }
718e3744 3389
d62a17ae 3390 /* Apply incoming filter. */
3391 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3392 peer->stat_pfx_filter++;
d62a17ae 3393 reason = "filter;";
3394 goto filtered;
3395 }
718e3744 3396
a8b72dc6
DA
3397 /* RFC 8212 to prevent route leaks.
3398 * This specification intends to improve this situation by requiring the
3399 * explicit configuration of both BGP Import and Export Policies for any
3400 * External BGP (EBGP) session such as customers, peers, or
3401 * confederation boundaries for all enabled address families. Through
3402 * codification of the aforementioned requirement, operators will
3403 * benefit from consistent behavior across different BGP
3404 * implementations.
3405 */
1d3fdccf 3406 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3407 if (!bgp_inbound_policy_exists(peer,
3408 &peer->filter[afi][safi])) {
3409 reason = "inbound policy missing";
3410 goto filtered;
3411 }
3412
fb29348a
DA
3413 /* draft-ietf-idr-deprecate-as-set-confed-set
3414 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3415 * Eventually, This document (if approved) updates RFC 4271
3416 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3417 * and obsoletes RFC 6472.
3418 */
7f972cd8 3419 if (peer->bgp->reject_as_sets)
fb29348a
DA
3420 if (aspath_check_as_sets(attr->aspath)) {
3421 reason =
3422 "as-path contains AS_SET or AS_CONFED_SET type;";
3423 goto filtered;
3424 }
3425
6f4f49b2 3426 new_attr = *attr;
d62a17ae 3427
3428 /* Apply incoming route-map.
3429 * NB: new_attr may now contain newly allocated values from route-map
3430 * "set"
3431 * commands, so we need bgp_attr_flush in the error paths, until we
3432 * intern
3433 * the attr (which takes over the memory references) */
9bcb3eef
DS
3434 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3435 num_labels, dest)
3436 == RMAP_DENY) {
b4d46cc9 3437 peer->stat_pfx_filter++;
d62a17ae 3438 reason = "route-map;";
3439 bgp_attr_flush(&new_attr);
3440 goto filtered;
3441 }
718e3744 3442
05864da7 3443 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3444 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3445 /* remove from RIB previous entry */
3446 bgp_zebra_withdraw(p, pi, bgp, safi);
3447 }
3448
7f323236
DW
3449 if (peer->sort == BGP_PEER_EBGP) {
3450
a4d82a8a
PZ
3451 /* If we receive the graceful-shutdown community from an eBGP
3452 * peer we must lower local-preference */
3453 if (new_attr.community
3454 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3455 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3456 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3457
a4d82a8a
PZ
3458 /* If graceful-shutdown is configured then add the GSHUT
3459 * community to all paths received from eBGP peers */
892fedb6
DA
3460 } else if (CHECK_FLAG(peer->bgp->flags,
3461 BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236 3462 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3463 }
3464
949b0f24 3465 if (pi) {
3466 pi_type = pi->type;
3467 pi_sub_type = pi->sub_type;
3468 }
3469
d62a17ae 3470 /* next hop check. */
a4d82a8a 3471 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3472 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3473 &new_attr, dest)) {
b4d46cc9 3474 peer->stat_pfx_nh_invalid++;
d62a17ae 3475 reason = "martian or self next-hop;";
3476 bgp_attr_flush(&new_attr);
3477 goto filtered;
3478 }
718e3744 3479
5c14a191 3480 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3481 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3482 reason = "self mac;";
3483 goto filtered;
3484 }
3485
d62a17ae 3486 attr_new = bgp_attr_intern(&new_attr);
3487
3488 /* If the update is implicit withdraw. */
40381db7
DS
3489 if (pi) {
3490 pi->uptime = bgp_clock();
3491 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3492
9bcb3eef 3493 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3494
d62a17ae 3495 /* Same attribute comes in. */
40381db7
DS
3496 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3497 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3498 && (!has_valid_label
40381db7 3499 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3500 num_labels * sizeof(mpls_label_t))
d62a17ae 3501 == 0)
3502 && (overlay_index_equal(
0a50c248 3503 afi, pi,
d62a17ae 3504 evpn == NULL ? NULL : &evpn->gw_ip))) {
3505 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3506 BGP_CONFIG_DAMPENING)
3507 && peer->sort == BGP_PEER_EBGP
40381db7 3508 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3509 if (bgp_debug_update(peer, p, NULL, 1)) {
3510 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3511 afi, safi, prd, p, label,
3512 num_labels, addpath_id ? 1 : 0,
3513 addpath_id, pfx_buf,
3514 sizeof(pfx_buf));
d62a17ae 3515 zlog_debug("%s rcvd %s", peer->host,
3516 pfx_buf);
3517 }
3518
9bcb3eef 3519 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3520 != BGP_DAMP_SUPPRESSED) {
40381db7 3521 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3522 safi);
9bcb3eef 3523 bgp_process(bgp, dest, afi, safi);
d62a17ae 3524 }
3525 } else /* Duplicate - odd */
3526 {
3527 if (bgp_debug_update(peer, p, NULL, 1)) {
3528 if (!peer->rcvd_attr_printed) {
3529 zlog_debug(
3530 "%s rcvd UPDATE w/ attr: %s",
3531 peer->host,
3532 peer->rcvd_attr_str);
3533 peer->rcvd_attr_printed = 1;
3534 }
3535
3536 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3537 afi, safi, prd, p, label,
3538 num_labels, addpath_id ? 1 : 0,
3539 addpath_id, pfx_buf,
3540 sizeof(pfx_buf));
d62a17ae 3541 zlog_debug(
3542 "%s rcvd %s...duplicate ignored",
3543 peer->host, pfx_buf);
3544 }
3545
3546 /* graceful restart STALE flag unset. */
40381db7 3547 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3548 bgp_path_info_unset_flag(
9bcb3eef
DS
3549 dest, pi, BGP_PATH_STALE);
3550 bgp_dest_set_defer_flag(dest, false);
3551 bgp_process(bgp, dest, afi, safi);
d62a17ae 3552 }
3553 }
3554
9bcb3eef 3555 bgp_dest_unlock_node(dest);
d62a17ae 3556 bgp_attr_unintern(&attr_new);
3557
3558 return 0;
3559 }
718e3744 3560
d62a17ae 3561 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3562 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3563 if (bgp_debug_update(peer, p, NULL, 1)) {
3564 bgp_debug_rdpfxpath2str(
a4d82a8a 3565 afi, safi, prd, p, label, num_labels,
d62a17ae 3566 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3567 sizeof(pfx_buf));
3568 zlog_debug(
3569 "%s rcvd %s, flapped quicker than processing",
3570 peer->host, pfx_buf);
3571 }
3572
9bcb3eef 3573 bgp_path_info_restore(dest, pi);
d62a17ae 3574 }
718e3744 3575
d62a17ae 3576 /* Received Logging. */
3577 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3578 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3579 num_labels, addpath_id ? 1 : 0,
3580 addpath_id, pfx_buf,
3581 sizeof(pfx_buf));
d62a17ae 3582 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3583 }
718e3744 3584
d62a17ae 3585 /* graceful restart STALE flag unset. */
f009ff26 3586 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3587 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3588 bgp_dest_set_defer_flag(dest, false);
f009ff26 3589 }
d62a17ae 3590
3591 /* The attribute is changed. */
9bcb3eef 3592 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3593
3594 /* implicit withdraw, decrement aggregate and pcount here.
3595 * only if update is accepted, they'll increment below.
3596 */
40381db7 3597 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3598
3599 /* Update bgp route dampening information. */
3600 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3601 && peer->sort == BGP_PEER_EBGP) {
3602 /* This is implicit withdraw so we should update
3603 dampening
3604 information. */
40381db7 3605 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3606 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3607 }
49e5a4a0 3608#ifdef ENABLE_BGP_VNC
d62a17ae 3609 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3610 struct bgp_dest *pdest = NULL;
d62a17ae 3611 struct bgp_table *table = NULL;
3612
9bcb3eef
DS
3613 pdest = bgp_node_get(bgp->rib[afi][safi],
3614 (struct prefix *)prd);
3615 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3616 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3617
3618 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3619 bgp, prd, table, p, pi);
d62a17ae 3620 }
9bcb3eef 3621 bgp_dest_unlock_node(pdest);
d62a17ae 3622 }
3623 if ((afi == AFI_IP || afi == AFI_IP6)
3624 && (safi == SAFI_UNICAST)) {
40381db7 3625 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3626 /*
3627 * Implicit withdraw case.
3628 */
3629 ++vnc_implicit_withdraw;
40381db7
DS
3630 vnc_import_bgp_del_route(bgp, p, pi);
3631 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3632 }
3633 }
65efcfce 3634#endif
128ea8ab 3635
d62a17ae 3636 /* Special handling for EVPN update of an existing route. If the
3637 * extended community attribute has changed, we need to
3638 * un-import
3639 * the route using its existing extended community. It will be
3640 * subsequently processed for import with the new extended
3641 * community.
3642 */
6f8c9c11
PR
3643 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3644 && !same_attr) {
40381db7 3645 if ((pi->attr->flag
d62a17ae 3646 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3647 && (attr_new->flag
3648 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3649 int cmp;
3650
40381db7 3651 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3652 attr_new->ecommunity);
3653 if (!cmp) {
3654 if (bgp_debug_update(peer, p, NULL, 1))
3655 zlog_debug(
3656 "Change in EXT-COMM, existing %s new %s",
3657 ecommunity_str(
40381db7 3658 pi->attr->ecommunity),
d62a17ae 3659 ecommunity_str(
3660 attr_new->ecommunity));
6f8c9c11
PR
3661 if (safi == SAFI_EVPN)
3662 bgp_evpn_unimport_route(
3663 bgp, afi, safi, p, pi);
3664 else /* SAFI_MPLS_VPN */
3665 vpn_leak_to_vrf_withdraw(bgp,
3666 pi);
d62a17ae 3667 }
3668 }
3669 }
718e3744 3670
d62a17ae 3671 /* Update to new attribute. */
40381db7
DS
3672 bgp_attr_unintern(&pi->attr);
3673 pi->attr = attr_new;
d62a17ae 3674
3675 /* Update MPLS label */
3676 if (has_valid_label) {
40381db7 3677 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3678 if (extra->label != label) {
3679 memcpy(&extra->label, label,
dbd587da 3680 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3681 extra->num_labels = num_labels;
3682 }
b57ba6d2
MK
3683 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3684 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3685 }
718e3744 3686
e496b420
HS
3687 /* Update SRv6 SID */
3688 if (attr->srv6_l3vpn) {
3689 extra = bgp_path_info_extra_get(pi);
3690 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3691 sid_copy(&extra->sid[0],
3692 &attr->srv6_l3vpn->sid);
3693 extra->num_sids = 1;
3694 }
3695 } else if (attr->srv6_vpn) {
3696 extra = bgp_path_info_extra_get(pi);
3697 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3698 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3699 extra->num_sids = 1;
3700 }
3701 }
3702
49e5a4a0 3703#ifdef ENABLE_BGP_VNC
d62a17ae 3704 if ((afi == AFI_IP || afi == AFI_IP6)
3705 && (safi == SAFI_UNICAST)) {
3706 if (vnc_implicit_withdraw) {
3707 /*
3708 * Add back the route with its new attributes
3709 * (e.g., nexthop).
3710 * The route is still selected, until the route
3711 * selection
3712 * queued by bgp_process actually runs. We have
3713 * to make this
3714 * update to the VNC side immediately to avoid
3715 * racing against
3716 * configuration changes (e.g., route-map
3717 * changes) which
3718 * trigger re-importation of the entire RIB.
3719 */
40381db7
DS
3720 vnc_import_bgp_add_route(bgp, p, pi);
3721 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3722 }
3723 }
65efcfce 3724#endif
d62a17ae 3725 /* Update Overlay Index */
3726 if (afi == AFI_L2VPN) {
3727 overlay_index_update(
0a50c248 3728 pi->attr,
d62a17ae 3729 evpn == NULL ? NULL : &evpn->gw_ip);
3730 }
65efcfce 3731
d62a17ae 3732 /* Update bgp route dampening information. */
3733 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3734 && peer->sort == BGP_PEER_EBGP) {
3735 /* Now we do normal update dampening. */
9bcb3eef 3736 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3737 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3738 bgp_dest_unlock_node(dest);
d62a17ae 3739 return 0;
3740 }
3741 }
128ea8ab 3742
d62a17ae 3743 /* Nexthop reachability check - for unicast and
3744 * labeled-unicast.. */
7c312383
AD
3745 if (((afi == AFI_IP || afi == AFI_IP6)
3746 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3747 || (safi == SAFI_EVPN &&
3748 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3749 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3750 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3751 && !CHECK_FLAG(peer->flags,
3752 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3753 && !CHECK_FLAG(bgp->flags,
3754 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3755 connected = 1;
3756 else
3757 connected = 0;
3758
960035b2
PZ
3759 struct bgp *bgp_nexthop = bgp;
3760
40381db7
DS
3761 if (pi->extra && pi->extra->bgp_orig)
3762 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3763
7c312383
AD
3764 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3765
3766 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3767 pi, NULL, connected)
a4d82a8a 3768 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
3769 bgp_path_info_set_flag(dest, pi,
3770 BGP_PATH_VALID);
d62a17ae 3771 else {
3772 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
3773 zlog_debug("%s(%pI4): NH unresolved",
3774 __func__,
3775 (in_addr_t *)&attr_new->nexthop);
d62a17ae 3776 }
9bcb3eef 3777 bgp_path_info_unset_flag(dest, pi,
18ee8310 3778 BGP_PATH_VALID);
d62a17ae 3779 }
3780 } else
9bcb3eef 3781 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 3782
49e5a4a0 3783#ifdef ENABLE_BGP_VNC
d62a17ae 3784 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3785 struct bgp_dest *pdest = NULL;
d62a17ae 3786 struct bgp_table *table = NULL;
3787
9bcb3eef
DS
3788 pdest = bgp_node_get(bgp->rib[afi][safi],
3789 (struct prefix *)prd);
3790 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3791 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3792
3793 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3794 bgp, prd, table, p, pi);
d62a17ae 3795 }
9bcb3eef 3796 bgp_dest_unlock_node(pdest);
d62a17ae 3797 }
3798#endif
718e3744 3799
d62a17ae 3800 /* If this is an EVPN route and some attribute has changed,
3801 * process
3802 * route for import. If the extended community has changed, we
3803 * would
3804 * have done the un-import earlier and the import would result
3805 * in the
3806 * route getting injected into appropriate L2 VNIs. If it is
3807 * just
3808 * some other attribute change, the import will result in
3809 * updating
3810 * the attributes for the route in the VNI(s).
3811 */
7c312383
AD
3812 if (safi == SAFI_EVPN && !same_attr &&
3813 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3814 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3815
3816 /* Process change. */
40381db7 3817 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3818
9bcb3eef
DS
3819 bgp_process(bgp, dest, afi, safi);
3820 bgp_dest_unlock_node(dest);
558d1fec 3821
ddb5b488
PZ
3822 if (SAFI_UNICAST == safi
3823 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3824 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3825
40381db7 3826 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3827 }
3828 if ((SAFI_MPLS_VPN == safi)
3829 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3830
40381db7 3831 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3832 }
3833
49e5a4a0 3834#ifdef ENABLE_BGP_VNC
d62a17ae 3835 if (SAFI_MPLS_VPN == safi) {
3836 mpls_label_t label_decoded = decode_label(label);
28070ee3 3837
d62a17ae 3838 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3839 type, sub_type, &label_decoded);
3840 }
3841 if (SAFI_ENCAP == safi) {
3842 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3843 type, sub_type, NULL);
3844 }
28070ee3
PZ
3845#endif
3846
d62a17ae 3847 return 0;
3848 } // End of implicit withdraw
718e3744 3849
d62a17ae 3850 /* Received Logging. */
3851 if (bgp_debug_update(peer, p, NULL, 1)) {
3852 if (!peer->rcvd_attr_printed) {
3853 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3854 peer->rcvd_attr_str);
3855 peer->rcvd_attr_printed = 1;
3856 }
718e3744 3857
a4d82a8a 3858 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3859 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3860 sizeof(pfx_buf));
3861 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3862 }
718e3744 3863
d62a17ae 3864 /* Make new BGP info. */
9bcb3eef 3865 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 3866
d62a17ae 3867 /* Update MPLS label */
3868 if (has_valid_label) {
18ee8310 3869 extra = bgp_path_info_extra_get(new);
8ba71050 3870 if (extra->label != label) {
dbd587da
QY
3871 memcpy(&extra->label, label,
3872 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3873 extra->num_labels = num_labels;
3874 }
b57ba6d2
MK
3875 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3876 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3877 }
718e3744 3878
e496b420
HS
3879 /* Update SRv6 SID */
3880 if (safi == SAFI_MPLS_VPN) {
3881 extra = bgp_path_info_extra_get(new);
3882 if (attr->srv6_l3vpn) {
3883 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3884 extra->num_sids = 1;
3885 } else if (attr->srv6_vpn) {
3886 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3887 extra->num_sids = 1;
3888 }
3889 }
3890
d62a17ae 3891 /* Update Overlay Index */
3892 if (afi == AFI_L2VPN) {
3893 overlay_index_update(new->attr,
d62a17ae 3894 evpn == NULL ? NULL : &evpn->gw_ip);
3895 }
3896 /* Nexthop reachability check. */
7c312383
AD
3897 if (((afi == AFI_IP || afi == AFI_IP6)
3898 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3899 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3900 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3901 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3902 && !CHECK_FLAG(peer->flags,
3903 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3904 && !CHECK_FLAG(bgp->flags,
3905 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3906 connected = 1;
3907 else
3908 connected = 0;
3909
7c312383
AD
3910 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3911
3912 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3913 connected)
a4d82a8a 3914 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 3915 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 3916 else {
3917 if (BGP_DEBUG(nht, NHT)) {
3918 char buf1[INET6_ADDRSTRLEN];
3919 inet_ntop(AF_INET,
3920 (const void *)&attr_new->nexthop,
3921 buf1, INET6_ADDRSTRLEN);
15569c58
DA
3922 zlog_debug("%s(%s): NH unresolved", __func__,
3923 buf1);
d62a17ae 3924 }
9bcb3eef 3925 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 3926 }
3927 } else
9bcb3eef 3928 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 3929
d62a17ae 3930 /* Addpath ID */
3931 new->addpath_rx_id = addpath_id;
3932
3933 /* Increment prefix */
3934 bgp_aggregate_increment(bgp, p, new, afi, safi);
3935
3936 /* Register new BGP information. */
9bcb3eef 3937 bgp_path_info_add(dest, new);
d62a17ae 3938
3939 /* route_node_get lock */
9bcb3eef 3940 bgp_dest_unlock_node(dest);
558d1fec 3941
49e5a4a0 3942#ifdef ENABLE_BGP_VNC
d62a17ae 3943 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3944 struct bgp_dest *pdest = NULL;
d62a17ae 3945 struct bgp_table *table = NULL;
3946
9bcb3eef
DS
3947 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
3948 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3949 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3950
3951 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3952 bgp, prd, table, p, new);
3953 }
9bcb3eef 3954 bgp_dest_unlock_node(pdest);
d62a17ae 3955 }
65efcfce
LB
3956#endif
3957
d62a17ae 3958 /* If maximum prefix count is configured and current prefix
3959 count exeed it. */
3960 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3961 return -1;
718e3744 3962
d62a17ae 3963 /* If this is an EVPN route, process for import. */
7c312383 3964 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3965 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3966
9bcb3eef 3967 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 3968
d62a17ae 3969 /* Process change. */
9bcb3eef 3970 bgp_process(bgp, dest, afi, safi);
718e3744 3971
ddb5b488
PZ
3972 if (SAFI_UNICAST == safi
3973 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3974 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3975 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3976 }
3977 if ((SAFI_MPLS_VPN == safi)
3978 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3979
3980 vpn_leak_to_vrf_update(bgp, new);
3981 }
49e5a4a0 3982#ifdef ENABLE_BGP_VNC
d62a17ae 3983 if (SAFI_MPLS_VPN == safi) {
3984 mpls_label_t label_decoded = decode_label(label);
28070ee3 3985
d62a17ae 3986 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3987 sub_type, &label_decoded);
3988 }
3989 if (SAFI_ENCAP == safi) {
3990 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3991 sub_type, NULL);
3992 }
28070ee3
PZ
3993#endif
3994
d62a17ae 3995 return 0;
718e3744 3996
d62a17ae 3997/* This BGP update is filtered. Log the reason then update BGP
3998 entry. */
3999filtered:
9bcb3eef 4000 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4001
d62a17ae 4002 if (bgp_debug_update(peer, p, NULL, 1)) {
4003 if (!peer->rcvd_attr_printed) {
4004 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4005 peer->rcvd_attr_str);
4006 peer->rcvd_attr_printed = 1;
4007 }
718e3744 4008
a4d82a8a 4009 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4010 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4011 sizeof(pfx_buf));
4012 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4013 peer->host, pfx_buf, reason);
4014 }
128ea8ab 4015
40381db7 4016 if (pi) {
d62a17ae 4017 /* If this is an EVPN route, un-import it as it is now filtered.
4018 */
4019 if (safi == SAFI_EVPN)
40381db7 4020 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4021
ddb5b488
PZ
4022 if (SAFI_UNICAST == safi
4023 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4024 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4025
40381db7 4026 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4027 }
4028 if ((SAFI_MPLS_VPN == safi)
4029 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4030
40381db7 4031 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4032 }
4033
9bcb3eef 4034 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4035 }
4036
9bcb3eef 4037 bgp_dest_unlock_node(dest);
558d1fec 4038
49e5a4a0 4039#ifdef ENABLE_BGP_VNC
d62a17ae 4040 /*
4041 * Filtered update is treated as an implicit withdrawal (see
4042 * bgp_rib_remove()
4043 * a few lines above)
4044 */
4045 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4046 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4047 0);
4048 }
97736e32
PZ
4049#endif
4050
d62a17ae 4051 return 0;
718e3744 4052}
4053
26a3ffd6 4054int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4055 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4056 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4057 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4058{
d62a17ae 4059 struct bgp *bgp;
4060 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4061 struct bgp_dest *dest;
40381db7 4062 struct bgp_path_info *pi;
718e3744 4063
49e5a4a0 4064#ifdef ENABLE_BGP_VNC
d62a17ae 4065 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4066 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4067 0);
4068 }
28070ee3
PZ
4069#endif
4070
d62a17ae 4071 bgp = peer->bgp;
4072
4073 /* Lookup node. */
9bcb3eef 4074 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4075
4076 /* If peer is soft reconfiguration enabled. Record input packet for
4077 * further calculation.
4078 *
4079 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4080 * routes that are filtered. This tanks out Quagga RS pretty badly due
4081 * to
4082 * the iteration over all RS clients.
4083 * Since we need to remove the entry from adj_in anyway, do that first
4084 * and
4085 * if there was no entry, we don't need to do anything more.
4086 */
4087 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4088 && peer != bgp->peer_self)
9bcb3eef 4089 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4090 peer->stat_pfx_dup_withdraw++;
4091
d62a17ae 4092 if (bgp_debug_update(peer, p, NULL, 1)) {
4093 bgp_debug_rdpfxpath2str(
a4d82a8a 4094 afi, safi, prd, p, label, num_labels,
d62a17ae 4095 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4096 sizeof(pfx_buf));
4097 zlog_debug(
4098 "%s withdrawing route %s not in adj-in",
4099 peer->host, pfx_buf);
4100 }
9bcb3eef 4101 bgp_dest_unlock_node(dest);
d62a17ae 4102 return 0;
4103 }
cd808e74 4104
d62a17ae 4105 /* Lookup withdrawn route. */
9bcb3eef 4106 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4107 if (pi->peer == peer && pi->type == type
4108 && pi->sub_type == sub_type
4109 && pi->addpath_rx_id == addpath_id)
d62a17ae 4110 break;
4111
4112 /* Logging. */
4113 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4114 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4115 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4116 sizeof(pfx_buf));
4117 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4118 pfx_buf);
4119 }
718e3744 4120
d62a17ae 4121 /* Withdraw specified route from routing table. */
40381db7 4122 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4123 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4124 if (SAFI_UNICAST == safi
4125 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4126 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4127 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4128 }
4129 if ((SAFI_MPLS_VPN == safi)
4130 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4131
40381db7 4132 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4133 }
4134 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4135 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4136 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4137 sizeof(pfx_buf));
4138 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4139 }
718e3744 4140
d62a17ae 4141 /* Unlock bgp_node_get() lock. */
9bcb3eef 4142 bgp_dest_unlock_node(dest);
d62a17ae 4143
4144 return 0;
718e3744 4145}
6b0655a2 4146
d62a17ae 4147void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4148 int withdraw)
718e3744 4149{
d62a17ae 4150 struct update_subgroup *subgrp;
4151 subgrp = peer_subgroup(peer, afi, safi);
4152 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4153}
6182d65b 4154
718e3744 4155
3f9c7369
DS
4156/*
4157 * bgp_stop_announce_route_timer
4158 */
d62a17ae 4159void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4160{
d62a17ae 4161 if (!paf->t_announce_route)
4162 return;
4163
4164 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4165}
6b0655a2 4166
3f9c7369
DS
4167/*
4168 * bgp_announce_route_timer_expired
4169 *
4170 * Callback that is invoked when the route announcement timer for a
4171 * peer_af expires.
4172 */
d62a17ae 4173static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4174{
d62a17ae 4175 struct peer_af *paf;
4176 struct peer *peer;
558d1fec 4177
d62a17ae 4178 paf = THREAD_ARG(t);
4179 peer = paf->peer;
718e3744 4180
d62a17ae 4181 if (peer->status != Established)
4182 return 0;
3f9c7369 4183
d62a17ae 4184 if (!peer->afc_nego[paf->afi][paf->safi])
4185 return 0;
3f9c7369 4186
d62a17ae 4187 peer_af_announce_route(paf, 1);
4188 return 0;
718e3744 4189}
4190
3f9c7369
DS
4191/*
4192 * bgp_announce_route
4193 *
4194 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4195 */
d62a17ae 4196void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4197{
4198 struct peer_af *paf;
4199 struct update_subgroup *subgrp;
4200
4201 paf = peer_af_find(peer, afi, safi);
4202 if (!paf)
4203 return;
4204 subgrp = PAF_SUBGRP(paf);
4205
4206 /*
4207 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4208 * or a refresh has already been triggered.
4209 */
4210 if (!subgrp || paf->t_announce_route)
4211 return;
4212
4213 /*
4214 * Start a timer to stagger/delay the announce. This serves
4215 * two purposes - announcement can potentially be combined for
4216 * multiple peers and the announcement doesn't happen in the
4217 * vty context.
4218 */
4219 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4220 (subgrp->peer_count == 1)
4221 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4222 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4223 &paf->t_announce_route);
3f9c7369
DS
4224}
4225
4226/*
4227 * Announce routes from all AF tables to a peer.
4228 *
4229 * This should ONLY be called when there is a need to refresh the
4230 * routes to the peer based on a policy change for this peer alone
4231 * or a route refresh request received from the peer.
4232 * The operation will result in splitting the peer from its existing
4233 * subgroups and putting it in new subgroups.
4234 */
d62a17ae 4235void bgp_announce_route_all(struct peer *peer)
718e3744 4236{
d62a17ae 4237 afi_t afi;
4238 safi_t safi;
4239
05c7a1cc
QY
4240 FOREACH_AFI_SAFI (afi, safi)
4241 bgp_announce_route(peer, afi, safi);
718e3744 4242}
6b0655a2 4243
d62a17ae 4244static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4245 struct bgp_table *table,
4246 struct prefix_rd *prd)
718e3744 4247{
d62a17ae 4248 int ret;
9bcb3eef 4249 struct bgp_dest *dest;
d62a17ae 4250 struct bgp_adj_in *ain;
718e3744 4251
d62a17ae 4252 if (!table)
4253 table = peer->bgp->rib[afi][safi];
718e3744 4254
9bcb3eef
DS
4255 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4256 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4257 if (ain->peer != peer)
4258 continue;
8692c506 4259
d7d15889 4260 struct bgp_path_info *pi;
d7c0a89a 4261 uint32_t num_labels = 0;
b57ba6d2 4262 mpls_label_t *label_pnt = NULL;
8cb687c2 4263 struct bgp_route_evpn evpn;
b57ba6d2 4264
9bcb3eef 4265 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4266 pi = pi->next)
4267 if (pi->peer == peer)
4268 break;
4269
40381db7
DS
4270 if (pi && pi->extra)
4271 num_labels = pi->extra->num_labels;
b57ba6d2 4272 if (num_labels)
40381db7 4273 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4274 if (pi)
4275 memcpy(&evpn, &pi->attr->evpn_overlay,
4276 sizeof(evpn));
4277 else
4278 memset(&evpn, 0, sizeof(evpn));
8692c506 4279
9bcb3eef
DS
4280 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4281 ain->addpath_rx_id, ain->attr, afi,
4282 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4283 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4284 num_labels, 1, &evpn);
ea47320b
DL
4285
4286 if (ret < 0) {
9bcb3eef 4287 bgp_dest_unlock_node(dest);
ea47320b 4288 return;
d62a17ae 4289 }
4290 }
718e3744 4291}
4292
d62a17ae 4293void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4294{
9bcb3eef 4295 struct bgp_dest *dest;
d62a17ae 4296 struct bgp_table *table;
718e3744 4297
d62a17ae 4298 if (peer->status != Established)
4299 return;
718e3744 4300
d62a17ae 4301 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4302 && (safi != SAFI_EVPN))
4303 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4304 else
9bcb3eef
DS
4305 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4306 dest = bgp_route_next(dest)) {
4307 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4308
b54892e0
DS
4309 if (table == NULL)
4310 continue;
8692c506 4311
9bcb3eef 4312 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4313 struct prefix_rd prd;
4314
4315 prd.family = AF_UNSPEC;
4316 prd.prefixlen = 64;
4317 memcpy(&prd.val, p->u.val, 8);
4318
4319 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4320 }
718e3744 4321}
6b0655a2 4322
228da428 4323
d62a17ae 4324struct bgp_clear_node_queue {
9bcb3eef 4325 struct bgp_dest *dest;
228da428
CC
4326};
4327
d62a17ae 4328static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4329{
d62a17ae 4330 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4331 struct bgp_dest *dest = cnq->dest;
d62a17ae 4332 struct peer *peer = wq->spec.data;
40381db7 4333 struct bgp_path_info *pi;
3103e8d2 4334 struct bgp *bgp;
9bcb3eef
DS
4335 afi_t afi = bgp_dest_table(dest)->afi;
4336 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4337
9bcb3eef 4338 assert(dest && peer);
3103e8d2 4339 bgp = peer->bgp;
d62a17ae 4340
4341 /* It is possible that we have multiple paths for a prefix from a peer
4342 * if that peer is using AddPath.
4343 */
9bcb3eef 4344 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4345 if (pi->peer != peer)
ea47320b
DL
4346 continue;
4347
4348 /* graceful restart STALE flag set. */
4349 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4350 && peer->nsf[afi][safi]
40381db7
DS
4351 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4352 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4353 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4354 else {
4355 /* If this is an EVPN route, process for
4356 * un-import. */
4357 if (safi == SAFI_EVPN)
9bcb3eef
DS
4358 bgp_evpn_unimport_route(
4359 bgp, afi, safi,
4360 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4361 /* Handle withdraw for VRF route-leaking and L3VPN */
4362 if (SAFI_UNICAST == safi
4363 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4364 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4365 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4366 bgp, pi);
960035b2 4367 }
3103e8d2 4368 if (SAFI_MPLS_VPN == safi &&
960035b2 4369 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4370 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4371 }
3103e8d2 4372
9bcb3eef 4373 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4374 }
ea47320b 4375 }
d62a17ae 4376 return WQ_SUCCESS;
200df115 4377}
4378
d62a17ae 4379static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4380{
d62a17ae 4381 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4382 struct bgp_dest *dest = cnq->dest;
4383 struct bgp_table *table = bgp_dest_table(dest);
228da428 4384
9bcb3eef 4385 bgp_dest_unlock_node(dest);
d62a17ae 4386 bgp_table_unlock(table);
4387 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4388}
4389
d62a17ae 4390static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4391{
d62a17ae 4392 struct peer *peer = wq->spec.data;
64e580a7 4393
d62a17ae 4394 /* Tickle FSM to start moving again */
4395 BGP_EVENT_ADD(peer, Clearing_Completed);
4396
4397 peer_unlock(peer); /* bgp_clear_route */
200df115 4398}
718e3744 4399
d62a17ae 4400static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4401{
d62a17ae 4402 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4403
4404 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4405#undef CLEAR_QUEUE_NAME_LEN
4406
0ce1ca80 4407 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4408 peer->clear_node_queue->spec.hold = 10;
4409 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4410 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4411 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4412 peer->clear_node_queue->spec.max_retries = 0;
4413
4414 /* we only 'lock' this peer reference when the queue is actually active
4415 */
4416 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4417}
4418
d62a17ae 4419static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4420 struct bgp_table *table)
65ca75e0 4421{
9bcb3eef 4422 struct bgp_dest *dest;
d62a17ae 4423 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4424
d62a17ae 4425 if (!table)
4426 table = peer->bgp->rib[afi][safi];
dc83d712 4427
d62a17ae 4428 /* If still no table => afi/safi isn't configured at all or smth. */
4429 if (!table)
4430 return;
dc83d712 4431
9bcb3eef 4432 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4433 struct bgp_path_info *pi, *next;
d62a17ae 4434 struct bgp_adj_in *ain;
4435 struct bgp_adj_in *ain_next;
4436
4437 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4438 * queued for every clearing peer, regardless of whether it is
4439 * relevant to the peer at hand.
4440 *
4441 * Overview: There are 3 different indices which need to be
4442 * scrubbed, potentially, when a peer is removed:
4443 *
4444 * 1 peer's routes visible via the RIB (ie accepted routes)
4445 * 2 peer's routes visible by the (optional) peer's adj-in index
4446 * 3 other routes visible by the peer's adj-out index
4447 *
4448 * 3 there is no hurry in scrubbing, once the struct peer is
4449 * removed from bgp->peer, we could just GC such deleted peer's
4450 * adj-outs at our leisure.
4451 *
4452 * 1 and 2 must be 'scrubbed' in some way, at least made
4453 * invisible via RIB index before peer session is allowed to be
4454 * brought back up. So one needs to know when such a 'search' is
4455 * complete.
4456 *
4457 * Ideally:
4458 *
4459 * - there'd be a single global queue or a single RIB walker
4460 * - rather than tracking which route_nodes still need to be
4461 * examined on a peer basis, we'd track which peers still
4462 * aren't cleared
4463 *
4464 * Given that our per-peer prefix-counts now should be reliable,
4465 * this may actually be achievable. It doesn't seem to be a huge
4466 * problem at this time,
4467 *
4468 * It is possible that we have multiple paths for a prefix from
4469 * a peer
4470 * if that peer is using AddPath.
4471 */
9bcb3eef 4472 ain = dest->adj_in;
d62a17ae 4473 while (ain) {
4474 ain_next = ain->next;
4475
4476 if (ain->peer == peer) {
9bcb3eef
DS
4477 bgp_adj_in_remove(dest, ain);
4478 bgp_dest_unlock_node(dest);
d62a17ae 4479 }
4480
4481 ain = ain_next;
4482 }
4483
9bcb3eef 4484 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4485 next = pi->next;
4486 if (pi->peer != peer)
d62a17ae 4487 continue;
4488
4489 if (force)
9bcb3eef 4490 bgp_path_info_reap(dest, pi);
d62a17ae 4491 else {
4492 struct bgp_clear_node_queue *cnq;
4493
4494 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4495 bgp_table_lock(bgp_dest_table(dest));
4496 bgp_dest_lock_node(dest);
d62a17ae 4497 cnq = XCALLOC(
4498 MTYPE_BGP_CLEAR_NODE_QUEUE,
4499 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4500 cnq->dest = dest;
d62a17ae 4501 work_queue_add(peer->clear_node_queue, cnq);
4502 break;
4503 }
4504 }
4505 }
4506 return;
4507}
4508
4509void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4510{
9bcb3eef 4511 struct bgp_dest *dest;
d62a17ae 4512 struct bgp_table *table;
4513
4514 if (peer->clear_node_queue == NULL)
4515 bgp_clear_node_queue_init(peer);
4516
4517 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4518 * Idle until it receives a Clearing_Completed event. This protects
4519 * against peers which flap faster than we can we clear, which could
4520 * lead to:
4521 *
4522 * a) race with routes from the new session being installed before
4523 * clear_route_node visits the node (to delete the route of that
4524 * peer)
4525 * b) resource exhaustion, clear_route_node likely leads to an entry
4526 * on the process_main queue. Fast-flapping could cause that queue
4527 * to grow and grow.
4528 */
4529
4530 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4531 * the unlock will happen upon work-queue completion; other wise, the
4532 * unlock happens at the end of this function.
4533 */
4534 if (!peer->clear_node_queue->thread)
4535 peer_lock(peer);
4536
4537 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4538 bgp_clear_route_table(peer, afi, safi, NULL);
4539 else
9bcb3eef
DS
4540 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4541 dest = bgp_route_next(dest)) {
4542 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4543 if (!table)
4544 continue;
4545
4546 bgp_clear_route_table(peer, afi, safi, table);
4547 }
d62a17ae 4548
4549 /* unlock if no nodes got added to the clear-node-queue. */
4550 if (!peer->clear_node_queue->thread)
4551 peer_unlock(peer);
718e3744 4552}
d62a17ae 4553
4554void bgp_clear_route_all(struct peer *peer)
718e3744 4555{
d62a17ae 4556 afi_t afi;
4557 safi_t safi;
718e3744 4558
05c7a1cc
QY
4559 FOREACH_AFI_SAFI (afi, safi)
4560 bgp_clear_route(peer, afi, safi);
65efcfce 4561
49e5a4a0 4562#ifdef ENABLE_BGP_VNC
d62a17ae 4563 rfapiProcessPeerDown(peer);
65efcfce 4564#endif
718e3744 4565}
4566
d62a17ae 4567void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4568{
d62a17ae 4569 struct bgp_table *table;
9bcb3eef 4570 struct bgp_dest *dest;
d62a17ae 4571 struct bgp_adj_in *ain;
4572 struct bgp_adj_in *ain_next;
718e3744 4573
d62a17ae 4574 table = peer->bgp->rib[afi][safi];
718e3744 4575
d62a17ae 4576 /* It is possible that we have multiple paths for a prefix from a peer
4577 * if that peer is using AddPath.
4578 */
9bcb3eef
DS
4579 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4580 ain = dest->adj_in;
43143c8f 4581
d62a17ae 4582 while (ain) {
4583 ain_next = ain->next;
43143c8f 4584
d62a17ae 4585 if (ain->peer == peer) {
9bcb3eef
DS
4586 bgp_adj_in_remove(dest, ain);
4587 bgp_dest_unlock_node(dest);
d62a17ae 4588 }
43143c8f 4589
d62a17ae 4590 ain = ain_next;
4591 }
4592 }
718e3744 4593}
93406d87 4594
d62a17ae 4595void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4596{
9bcb3eef 4597 struct bgp_dest *dest;
40381db7 4598 struct bgp_path_info *pi;
d62a17ae 4599 struct bgp_table *table;
4600
4601 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4602 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4603 dest = bgp_route_next(dest)) {
4604 struct bgp_dest *rm;
d62a17ae 4605
4606 /* look for neighbor in tables */
9bcb3eef 4607 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4608 if (!table)
ea47320b
DL
4609 continue;
4610
4611 for (rm = bgp_table_top(table); rm;
4612 rm = bgp_route_next(rm))
9bcb3eef 4613 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4614 pi = pi->next) {
40381db7 4615 if (pi->peer != peer)
ea47320b 4616 continue;
40381db7 4617 if (!CHECK_FLAG(pi->flags,
1defdda8 4618 BGP_PATH_STALE))
ea47320b
DL
4619 break;
4620
40381db7 4621 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4622 break;
4623 }
d62a17ae 4624 }
4625 } else {
9bcb3eef
DS
4626 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4627 dest = bgp_route_next(dest))
4628 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4629 pi = pi->next) {
40381db7 4630 if (pi->peer != peer)
ea47320b 4631 continue;
40381db7 4632 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4633 break;
9bcb3eef 4634 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4635 break;
4636 }
d62a17ae 4637 }
93406d87 4638}
6b0655a2 4639
3dc339cd 4640bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4641{
e0df4c04 4642 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4643 return true;
e0df4c04 4644
9dac9fc8
DA
4645 if (peer->sort == BGP_PEER_EBGP
4646 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4647 || FILTER_LIST_OUT_NAME(filter)
4648 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4649 return true;
4650 return false;
9dac9fc8
DA
4651}
4652
3dc339cd 4653bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4654{
e0df4c04 4655 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4656 return true;
e0df4c04 4657
9dac9fc8
DA
4658 if (peer->sort == BGP_PEER_EBGP
4659 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4660 || FILTER_LIST_IN_NAME(filter)
4661 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4662 return true;
4663 return false;
9dac9fc8
DA
4664}
4665
568e10ca 4666static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4667 safi_t safi)
bb86c601 4668{
9bcb3eef 4669 struct bgp_dest *dest;
40381db7 4670 struct bgp_path_info *pi;
4b7e6066 4671 struct bgp_path_info *next;
bb86c601 4672
9bcb3eef
DS
4673 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4674 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4675 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4676
40381db7 4677 next = pi->next;
1b7bb747
CS
4678
4679 /* Unimport EVPN routes from VRFs */
4680 if (safi == SAFI_EVPN)
4681 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4682 SAFI_EVPN, p, pi);
1b7bb747 4683
40381db7
DS
4684 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4685 && pi->type == ZEBRA_ROUTE_BGP
4686 && (pi->sub_type == BGP_ROUTE_NORMAL
4687 || pi->sub_type == BGP_ROUTE_AGGREGATE
4688 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4689
d62a17ae 4690 if (bgp_fibupd_safi(safi))
b54892e0 4691 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4692 }
9514b37d 4693
9bcb3eef 4694 bgp_path_info_reap(dest, pi);
d62a17ae 4695 }
bb86c601
LB
4696}
4697
718e3744 4698/* Delete all kernel routes. */
d62a17ae 4699void bgp_cleanup_routes(struct bgp *bgp)
4700{
4701 afi_t afi;
9bcb3eef 4702 struct bgp_dest *dest;
67009e22 4703 struct bgp_table *table;
d62a17ae 4704
4705 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4706 if (afi == AFI_L2VPN)
4707 continue;
568e10ca 4708 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4709 SAFI_UNICAST);
d62a17ae 4710 /*
4711 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4712 */
4713 if (afi != AFI_L2VPN) {
4714 safi_t safi;
4715 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4716 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4717 dest = bgp_route_next(dest)) {
4718 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4719 if (table != NULL) {
4720 bgp_cleanup_table(bgp, table, safi);
4721 bgp_table_finish(&table);
9bcb3eef
DS
4722 bgp_dest_set_bgp_table_info(dest, NULL);
4723 bgp_dest_unlock_node(dest);
d62a17ae 4724 }
4725 }
4726 safi = SAFI_ENCAP;
9bcb3eef
DS
4727 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4728 dest = bgp_route_next(dest)) {
4729 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4730 if (table != NULL) {
4731 bgp_cleanup_table(bgp, table, safi);
4732 bgp_table_finish(&table);
9bcb3eef
DS
4733 bgp_dest_set_bgp_table_info(dest, NULL);
4734 bgp_dest_unlock_node(dest);
d62a17ae 4735 }
4736 }
4737 }
4738 }
9bcb3eef
DS
4739 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4740 dest = bgp_route_next(dest)) {
4741 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4742 if (table != NULL) {
4743 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4744 bgp_table_finish(&table);
9bcb3eef
DS
4745 bgp_dest_set_bgp_table_info(dest, NULL);
4746 bgp_dest_unlock_node(dest);
d62a17ae 4747 }
bb86c601 4748 }
718e3744 4749}
4750
d62a17ae 4751void bgp_reset(void)
718e3744 4752{
d62a17ae 4753 vty_reset();
4754 bgp_zclient_reset();
4755 access_list_reset();
4756 prefix_list_reset();
718e3744 4757}
6b0655a2 4758
d62a17ae 4759static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4760{
d62a17ae 4761 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4762 && CHECK_FLAG(peer->af_cap[afi][safi],
4763 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4764}
4765
718e3744 4766/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4767 value. */
d62a17ae 4768int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4769 struct bgp_nlri *packet)
4770{
d7c0a89a
QY
4771 uint8_t *pnt;
4772 uint8_t *lim;
d62a17ae 4773 struct prefix p;
4774 int psize;
4775 int ret;
4776 afi_t afi;
4777 safi_t safi;
4778 int addpath_encoded;
d7c0a89a 4779 uint32_t addpath_id;
d62a17ae 4780
d62a17ae 4781 pnt = packet->nlri;
4782 lim = pnt + packet->length;
4783 afi = packet->afi;
4784 safi = packet->safi;
4785 addpath_id = 0;
4786 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4787
4788 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4789 syntactic validity. If the field is syntactically incorrect,
4790 then the Error Subcode is set to Invalid Network Field. */
4791 for (; pnt < lim; pnt += psize) {
4792 /* Clear prefix structure. */
4793 memset(&p, 0, sizeof(struct prefix));
4794
4795 if (addpath_encoded) {
4796
4797 /* When packet overflow occurs return immediately. */
761ed665 4798 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4799 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4800
a3a850a1 4801 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4802 addpath_id = ntohl(addpath_id);
d62a17ae 4803 pnt += BGP_ADDPATH_ID_LEN;
4804 }
718e3744 4805
d62a17ae 4806 /* Fetch prefix length. */
4807 p.prefixlen = *pnt++;
4808 /* afi/safi validity already verified by caller,
4809 * bgp_update_receive */
4810 p.family = afi2family(afi);
4811
4812 /* Prefix length check. */
4813 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4814 flog_err(
e50f7cfd 4815 EC_BGP_UPDATE_RCV,
14454c9f 4816 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4817 peer->host, p.prefixlen, packet->afi);
513386b5 4818 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4819 }
6b0655a2 4820
d62a17ae 4821 /* Packet size overflow check. */
4822 psize = PSIZE(p.prefixlen);
4823
4824 /* When packet overflow occur return immediately. */
4825 if (pnt + psize > lim) {
af4c2728 4826 flog_err(
e50f7cfd 4827 EC_BGP_UPDATE_RCV,
d62a17ae 4828 "%s [Error] Update packet error (prefix length %d overflows packet)",
4829 peer->host, p.prefixlen);
513386b5 4830 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4831 }
4832
4833 /* Defensive coding, double-check the psize fits in a struct
4834 * prefix */
4835 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4836 flog_err(
e50f7cfd 4837 EC_BGP_UPDATE_RCV,
d62a17ae 4838 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4839 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4840 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4841 }
4842
4843 /* Fetch prefix from NLRI packet. */
a85297a7 4844 memcpy(p.u.val, pnt, psize);
d62a17ae 4845
4846 /* Check address. */
4847 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4848 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4849 /* From RFC4271 Section 6.3:
4850 *
4851 * If a prefix in the NLRI field is semantically
4852 * incorrect
4853 * (e.g., an unexpected multicast IP address),
4854 * an error SHOULD
4855 * be logged locally, and the prefix SHOULD be
4856 * ignored.
a4d82a8a 4857 */
af4c2728 4858 flog_err(
e50f7cfd 4859 EC_BGP_UPDATE_RCV,
d62a17ae 4860 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4861 peer->host, inet_ntoa(p.u.prefix4));
4862 continue;
4863 }
4864 }
4865
4866 /* Check address. */
4867 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4868 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4869 char buf[BUFSIZ];
4870
af4c2728 4871 flog_err(
e50f7cfd 4872 EC_BGP_UPDATE_RCV,
d62a17ae 4873 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4874 peer->host,
4875 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4876 BUFSIZ));
4877
4878 continue;
4879 }
4880 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4881 char buf[BUFSIZ];
4882
af4c2728 4883 flog_err(
e50f7cfd 4884 EC_BGP_UPDATE_RCV,
d62a17ae 4885 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4886 peer->host,
4887 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4888 BUFSIZ));
4889
4890 continue;
4891 }
4892 }
4893
4894 /* Normal process. */
4895 if (attr)
4896 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4897 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4898 NULL, NULL, 0, 0, NULL);
d62a17ae 4899 else
4900 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4901 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4902 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4903 NULL);
d62a17ae 4904
513386b5
DA
4905 /* Do not send BGP notification twice when maximum-prefix count
4906 * overflow. */
4907 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4908 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4909
4910 /* Address family configuration mismatch. */
d62a17ae 4911 if (ret < 0)
513386b5 4912 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4913 }
4914
4915 /* Packet length consistency check. */
4916 if (pnt != lim) {
af4c2728 4917 flog_err(
e50f7cfd 4918 EC_BGP_UPDATE_RCV,
d62a17ae 4919 "%s [Error] Update packet error (prefix length mismatch with total length)",
4920 peer->host);
513386b5 4921 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4922 }
6b0655a2 4923
513386b5 4924 return BGP_NLRI_PARSE_OK;
718e3744 4925}
4926
d62a17ae 4927static struct bgp_static *bgp_static_new(void)
718e3744 4928{
d62a17ae 4929 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4930}
4931
d62a17ae 4932static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4933{
0a22ddfb 4934 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4935 route_map_counter_decrement(bgp_static->rmap.map);
4936
0a22ddfb 4937 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4938 XFREE(MTYPE_BGP_STATIC, bgp_static);
4939}
4940
5f040085 4941void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 4942 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4943{
9bcb3eef 4944 struct bgp_dest *dest;
40381db7 4945 struct bgp_path_info *pi;
4b7e6066 4946 struct bgp_path_info *new;
40381db7 4947 struct bgp_path_info rmap_path;
d62a17ae 4948 struct attr attr;
4949 struct attr *attr_new;
b68885f9 4950 route_map_result_t ret;
49e5a4a0 4951#ifdef ENABLE_BGP_VNC
d62a17ae 4952 int vnc_implicit_withdraw = 0;
65efcfce 4953#endif
fee0f4c6 4954
d62a17ae 4955 assert(bgp_static);
dd8103a9 4956
9bcb3eef 4957 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4958
d62a17ae 4959 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4960
d62a17ae 4961 attr.nexthop = bgp_static->igpnexthop;
4962 attr.med = bgp_static->igpmetric;
4963 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4964
d62a17ae 4965 if (bgp_static->atomic)
4966 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4967
d62a17ae 4968 /* Store label index, if required. */
4969 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4970 attr.label_index = bgp_static->label_index;
4971 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4972 }
718e3744 4973
d62a17ae 4974 /* Apply route-map. */
4975 if (bgp_static->rmap.name) {
4976 struct attr attr_tmp = attr;
80ced710 4977
40381db7
DS
4978 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4979 rmap_path.peer = bgp->peer_self;
4980 rmap_path.attr = &attr_tmp;
fee0f4c6 4981
d62a17ae 4982 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4983
40381db7
DS
4984 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4985 &rmap_path);
fee0f4c6 4986
d62a17ae 4987 bgp->peer_self->rmap_type = 0;
718e3744 4988
d62a17ae 4989 if (ret == RMAP_DENYMATCH) {
4990 /* Free uninterned attribute. */
4991 bgp_attr_flush(&attr_tmp);
718e3744 4992
d62a17ae 4993 /* Unintern original. */
4994 aspath_unintern(&attr.aspath);
4995 bgp_static_withdraw(bgp, p, afi, safi);
4996 return;
4997 }
7f323236 4998
892fedb6 4999 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5000 bgp_attr_add_gshut_community(&attr_tmp);
5001
d62a17ae 5002 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5003 } else {
5004
892fedb6 5005 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5006 bgp_attr_add_gshut_community(&attr);
5007
d62a17ae 5008 attr_new = bgp_attr_intern(&attr);
7f323236 5009 }
718e3744 5010
9bcb3eef 5011 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5012 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5013 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5014 break;
5015
40381db7
DS
5016 if (pi) {
5017 if (attrhash_cmp(pi->attr, attr_new)
5018 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5019 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5020 bgp_dest_unlock_node(dest);
d62a17ae 5021 bgp_attr_unintern(&attr_new);
5022 aspath_unintern(&attr.aspath);
5023 return;
5024 } else {
5025 /* The attribute is changed. */
9bcb3eef 5026 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5027
5028 /* Rewrite BGP route information. */
40381db7 5029 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5030 bgp_path_info_restore(dest, pi);
d62a17ae 5031 else
40381db7 5032 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5033#ifdef ENABLE_BGP_VNC
d62a17ae 5034 if ((afi == AFI_IP || afi == AFI_IP6)
5035 && (safi == SAFI_UNICAST)) {
40381db7 5036 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5037 /*
5038 * Implicit withdraw case.
40381db7 5039 * We have to do this before pi is
d62a17ae 5040 * changed
5041 */
5042 ++vnc_implicit_withdraw;
40381db7 5043 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5044 vnc_import_bgp_exterior_del_route(
40381db7 5045 bgp, p, pi);
d62a17ae 5046 }
5047 }
65efcfce 5048#endif
40381db7
DS
5049 bgp_attr_unintern(&pi->attr);
5050 pi->attr = attr_new;
5051 pi->uptime = bgp_clock();
49e5a4a0 5052#ifdef ENABLE_BGP_VNC
d62a17ae 5053 if ((afi == AFI_IP || afi == AFI_IP6)
5054 && (safi == SAFI_UNICAST)) {
5055 if (vnc_implicit_withdraw) {
40381db7 5056 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5057 vnc_import_bgp_exterior_add_route(
40381db7 5058 bgp, p, pi);
d62a17ae 5059 }
5060 }
65efcfce 5061#endif
718e3744 5062
d62a17ae 5063 /* Nexthop reachability check. */
892fedb6 5064 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5065 && (safi == SAFI_UNICAST
5066 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5067
5068 struct bgp *bgp_nexthop = bgp;
5069
40381db7
DS
5070 if (pi->extra && pi->extra->bgp_orig)
5071 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5072
5073 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5074 afi, pi, NULL, 0))
9bcb3eef 5075 bgp_path_info_set_flag(dest, pi,
18ee8310 5076 BGP_PATH_VALID);
d62a17ae 5077 else {
5078 if (BGP_DEBUG(nht, NHT)) {
5079 char buf1[INET6_ADDRSTRLEN];
5080 inet_ntop(p->family,
5081 &p->u.prefix, buf1,
5082 INET6_ADDRSTRLEN);
5083 zlog_debug(
5084 "%s(%s): Route not in table, not advertising",
15569c58 5085 __func__, buf1);
d62a17ae 5086 }
18ee8310 5087 bgp_path_info_unset_flag(
9bcb3eef 5088 dest, pi, BGP_PATH_VALID);
d62a17ae 5089 }
5090 } else {
5091 /* Delete the NHT structure if any, if we're
5092 * toggling between
5093 * enabling/disabling import check. We
5094 * deregister the route
5095 * from NHT to avoid overloading NHT and the
5096 * process interaction
5097 */
40381db7 5098 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5099 bgp_path_info_set_flag(dest, pi,
5100 BGP_PATH_VALID);
d62a17ae 5101 }
5102 /* Process change. */
40381db7 5103 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5104 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5105
5106 if (SAFI_UNICAST == safi
5107 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5108 || bgp->inst_type
5109 == BGP_INSTANCE_TYPE_DEFAULT)) {
5110 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5111 pi);
ddb5b488
PZ
5112 }
5113
9bcb3eef 5114 bgp_dest_unlock_node(dest);
d62a17ae 5115 aspath_unintern(&attr.aspath);
5116 return;
5117 }
718e3744 5118 }
718e3744 5119
d62a17ae 5120 /* Make new BGP info. */
5121 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5122 attr_new, dest);
d62a17ae 5123 /* Nexthop reachability check. */
892fedb6 5124 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5125 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5126 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5127 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5128 else {
5129 if (BGP_DEBUG(nht, NHT)) {
5130 char buf1[INET6_ADDRSTRLEN];
5131 inet_ntop(p->family, &p->u.prefix, buf1,
5132 INET6_ADDRSTRLEN);
5133 zlog_debug(
5134 "%s(%s): Route not in table, not advertising",
15569c58 5135 __func__, buf1);
d62a17ae 5136 }
9bcb3eef 5137 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5138 }
5139 } else {
5140 /* Delete the NHT structure if any, if we're toggling between
5141 * enabling/disabling import check. We deregister the route
5142 * from NHT to avoid overloading NHT and the process interaction
5143 */
5144 bgp_unlink_nexthop(new);
5145
9bcb3eef 5146 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5147 }
078430f6 5148
d62a17ae 5149 /* Aggregate address increment. */
5150 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5151
d62a17ae 5152 /* Register new BGP information. */
9bcb3eef 5153 bgp_path_info_add(dest, new);
718e3744 5154
d62a17ae 5155 /* route_node_get lock */
9bcb3eef 5156 bgp_dest_unlock_node(dest);
d62a17ae 5157
5158 /* Process change. */
9bcb3eef 5159 bgp_process(bgp, dest, afi, safi);
d62a17ae 5160
ddb5b488
PZ
5161 if (SAFI_UNICAST == safi
5162 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5163 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5164 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5165 }
5166
d62a17ae 5167 /* Unintern original. */
5168 aspath_unintern(&attr.aspath);
718e3744 5169}
5170
5f040085 5171void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5172 safi_t safi)
718e3744 5173{
9bcb3eef 5174 struct bgp_dest *dest;
40381db7 5175 struct bgp_path_info *pi;
718e3744 5176
9bcb3eef 5177 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5178
d62a17ae 5179 /* Check selected route and self inserted route. */
9bcb3eef 5180 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5181 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5182 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5183 break;
5184
5185 /* Withdraw static BGP route from routing table. */
40381db7 5186 if (pi) {
ddb5b488
PZ
5187 if (SAFI_UNICAST == safi
5188 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5189 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5190 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5191 }
40381db7
DS
5192 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5193 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5194 bgp_path_info_delete(dest, pi);
5195 bgp_process(bgp, dest, afi, safi);
d62a17ae 5196 }
718e3744 5197
d62a17ae 5198 /* Unlock bgp_node_lookup. */
9bcb3eef 5199 bgp_dest_unlock_node(dest);
718e3744 5200}
5201
137446f9
LB
5202/*
5203 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5204 */
5f040085 5205static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5206 afi_t afi, safi_t safi,
5207 struct prefix_rd *prd)
718e3744 5208{
9bcb3eef 5209 struct bgp_dest *dest;
40381db7 5210 struct bgp_path_info *pi;
718e3744 5211
9bcb3eef 5212 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5213
d62a17ae 5214 /* Check selected route and self inserted route. */
9bcb3eef 5215 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5216 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5217 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5218 break;
718e3744 5219
d62a17ae 5220 /* Withdraw static BGP route from routing table. */
40381db7 5221 if (pi) {
49e5a4a0 5222#ifdef ENABLE_BGP_VNC
d62a17ae 5223 rfapiProcessWithdraw(
40381db7 5224 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5225 1); /* Kill, since it is an administrative change */
65efcfce 5226#endif
ddb5b488
PZ
5227 if (SAFI_MPLS_VPN == safi
5228 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5229 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5230 }
40381db7 5231 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5232 bgp_path_info_delete(dest, pi);
5233 bgp_process(bgp, dest, afi, safi);
d62a17ae 5234 }
718e3744 5235
d62a17ae 5236 /* Unlock bgp_node_lookup. */
9bcb3eef 5237 bgp_dest_unlock_node(dest);
718e3744 5238}
5239
5f040085 5240static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5241 struct bgp_static *bgp_static, afi_t afi,
5242 safi_t safi)
137446f9 5243{
9bcb3eef 5244 struct bgp_dest *dest;
4b7e6066 5245 struct bgp_path_info *new;
d62a17ae 5246 struct attr *attr_new;
5247 struct attr attr = {0};
40381db7 5248 struct bgp_path_info *pi;
49e5a4a0 5249#ifdef ENABLE_BGP_VNC
d62a17ae 5250 mpls_label_t label = 0;
65efcfce 5251#endif
d7c0a89a 5252 uint32_t num_labels = 0;
d62a17ae 5253 union gw_addr add;
137446f9 5254
d62a17ae 5255 assert(bgp_static);
137446f9 5256
b57ba6d2
MK
5257 if (bgp_static->label != MPLS_INVALID_LABEL)
5258 num_labels = 1;
9bcb3eef
DS
5259 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5260 &bgp_static->prd);
137446f9 5261
d62a17ae 5262 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5263
d62a17ae 5264 attr.nexthop = bgp_static->igpnexthop;
5265 attr.med = bgp_static->igpmetric;
5266 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5267
d62a17ae 5268 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5269 || (safi == SAFI_ENCAP)) {
5270 if (afi == AFI_IP) {
5271 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5272 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5273 }
5274 }
5275 if (afi == AFI_L2VPN) {
5276 if (bgp_static->gatewayIp.family == AF_INET)
5277 add.ipv4.s_addr =
5278 bgp_static->gatewayIp.u.prefix4.s_addr;
5279 else if (bgp_static->gatewayIp.family == AF_INET6)
5280 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5281 sizeof(struct in6_addr));
0a50c248 5282 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5283 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5284 struct bgp_encap_type_vxlan bet;
5285 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5286 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5287 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5288 }
5289 if (bgp_static->router_mac) {
5290 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5291 }
5292 }
5293 /* Apply route-map. */
5294 if (bgp_static->rmap.name) {
5295 struct attr attr_tmp = attr;
40381db7 5296 struct bgp_path_info rmap_path;
b68885f9 5297 route_map_result_t ret;
137446f9 5298
40381db7
DS
5299 rmap_path.peer = bgp->peer_self;
5300 rmap_path.attr = &attr_tmp;
137446f9 5301
d62a17ae 5302 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5303
40381db7
DS
5304 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5305 &rmap_path);
137446f9 5306
d62a17ae 5307 bgp->peer_self->rmap_type = 0;
137446f9 5308
d62a17ae 5309 if (ret == RMAP_DENYMATCH) {
5310 /* Free uninterned attribute. */
5311 bgp_attr_flush(&attr_tmp);
137446f9 5312
d62a17ae 5313 /* Unintern original. */
5314 aspath_unintern(&attr.aspath);
5315 bgp_static_withdraw_safi(bgp, p, afi, safi,
5316 &bgp_static->prd);
5317 return;
5318 }
137446f9 5319
d62a17ae 5320 attr_new = bgp_attr_intern(&attr_tmp);
5321 } else {
5322 attr_new = bgp_attr_intern(&attr);
5323 }
137446f9 5324
9bcb3eef 5325 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5326 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5327 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5328 break;
5329
40381db7 5330 if (pi) {
d62a17ae 5331 memset(&add, 0, sizeof(union gw_addr));
40381db7 5332 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5333 && overlay_index_equal(afi, pi, &add)
40381db7 5334 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5335 bgp_dest_unlock_node(dest);
d62a17ae 5336 bgp_attr_unintern(&attr_new);
5337 aspath_unintern(&attr.aspath);
5338 return;
5339 } else {
5340 /* The attribute is changed. */
9bcb3eef 5341 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5342
5343 /* Rewrite BGP route information. */
40381db7 5344 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5345 bgp_path_info_restore(dest, pi);
d62a17ae 5346 else
40381db7
DS
5347 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5348 bgp_attr_unintern(&pi->attr);
5349 pi->attr = attr_new;
5350 pi->uptime = bgp_clock();
49e5a4a0 5351#ifdef ENABLE_BGP_VNC
40381db7
DS
5352 if (pi->extra)
5353 label = decode_label(&pi->extra->label[0]);
65efcfce 5354#endif
137446f9 5355
d62a17ae 5356 /* Process change. */
40381db7 5357 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5358 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5359
5360 if (SAFI_MPLS_VPN == safi
5361 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5362 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5363 }
49e5a4a0 5364#ifdef ENABLE_BGP_VNC
40381db7
DS
5365 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5366 pi->attr, afi, safi, pi->type,
5367 pi->sub_type, &label);
65efcfce 5368#endif
9bcb3eef 5369 bgp_dest_unlock_node(dest);
d62a17ae 5370 aspath_unintern(&attr.aspath);
5371 return;
5372 }
5373 }
137446f9
LB
5374
5375
d62a17ae 5376 /* Make new BGP info. */
5377 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5378 attr_new, dest);
1defdda8 5379 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5380 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5381 if (num_labels) {
5382 new->extra->label[0] = bgp_static->label;
5383 new->extra->num_labels = num_labels;
5384 }
49e5a4a0 5385#ifdef ENABLE_BGP_VNC
d62a17ae 5386 label = decode_label(&bgp_static->label);
65efcfce 5387#endif
137446f9 5388
d62a17ae 5389 /* Aggregate address increment. */
5390 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5391
d62a17ae 5392 /* Register new BGP information. */
9bcb3eef 5393 bgp_path_info_add(dest, new);
d62a17ae 5394 /* route_node_get lock */
9bcb3eef 5395 bgp_dest_unlock_node(dest);
137446f9 5396
d62a17ae 5397 /* Process change. */
9bcb3eef 5398 bgp_process(bgp, dest, afi, safi);
137446f9 5399
ddb5b488
PZ
5400 if (SAFI_MPLS_VPN == safi
5401 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5402 vpn_leak_to_vrf_update(bgp, new);
5403 }
49e5a4a0 5404#ifdef ENABLE_BGP_VNC
d62a17ae 5405 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5406 safi, new->type, new->sub_type, &label);
65efcfce
LB
5407#endif
5408
d62a17ae 5409 /* Unintern original. */
5410 aspath_unintern(&attr.aspath);
137446f9
LB
5411}
5412
718e3744 5413/* Configure static BGP network. When user don't run zebra, static
5414 route should be installed as valid. */
e2a86ad9
DS
5415static int bgp_static_set(struct vty *vty, const char *negate,
5416 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5417 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5418{
5419 VTY_DECLVAR_CONTEXT(bgp, bgp);
5420 int ret;
5421 struct prefix p;
5422 struct bgp_static *bgp_static;
9bcb3eef 5423 struct bgp_dest *dest;
d7c0a89a 5424 uint8_t need_update = 0;
d62a17ae 5425
5426 /* Convert IP prefix string to struct prefix. */
5427 ret = str2prefix(ip_str, &p);
5428 if (!ret) {
5429 vty_out(vty, "%% Malformed prefix\n");
5430 return CMD_WARNING_CONFIG_FAILED;
5431 }
5432 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5433 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5434 return CMD_WARNING_CONFIG_FAILED;
5435 }
718e3744 5436
d62a17ae 5437 apply_mask(&p);
718e3744 5438
e2a86ad9 5439 if (negate) {
718e3744 5440
e2a86ad9 5441 /* Set BGP static route configuration. */
9bcb3eef 5442 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5443
9bcb3eef 5444 if (!dest) {
a4d82a8a 5445 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5446 return CMD_WARNING_CONFIG_FAILED;
5447 }
5448
9bcb3eef 5449 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5450
e2a86ad9
DS
5451 if ((label_index != BGP_INVALID_LABEL_INDEX)
5452 && (label_index != bgp_static->label_index)) {
5453 vty_out(vty,
5454 "%% label-index doesn't match static route\n");
5455 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5456 }
d62a17ae 5457
e2a86ad9
DS
5458 if ((rmap && bgp_static->rmap.name)
5459 && strcmp(rmap, bgp_static->rmap.name)) {
5460 vty_out(vty,
5461 "%% route-map name doesn't match static route\n");
5462 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5463 }
718e3744 5464
e2a86ad9
DS
5465 /* Update BGP RIB. */
5466 if (!bgp_static->backdoor)
5467 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5468
e2a86ad9
DS
5469 /* Clear configuration. */
5470 bgp_static_free(bgp_static);
9bcb3eef
DS
5471 bgp_dest_set_bgp_static_info(dest, NULL);
5472 bgp_dest_unlock_node(dest);
5473 bgp_dest_unlock_node(dest);
e2a86ad9 5474 } else {
718e3744 5475
e2a86ad9 5476 /* Set BGP static route configuration. */
9bcb3eef
DS
5477 dest = bgp_node_get(bgp->route[afi][safi], &p);
5478 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5479 if (bgp_static) {
e2a86ad9 5480 /* Configuration change. */
e2a86ad9
DS
5481 /* Label index cannot be changed. */
5482 if (bgp_static->label_index != label_index) {
5483 vty_out(vty, "%% cannot change label-index\n");
5484 return CMD_WARNING_CONFIG_FAILED;
5485 }
d62a17ae 5486
e2a86ad9 5487 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5488 if (bgp_static->valid
5489 && bgp_static->backdoor != backdoor)
e2a86ad9 5490 need_update = 1;
718e3744 5491
e2a86ad9 5492 bgp_static->backdoor = backdoor;
718e3744 5493
e2a86ad9 5494 if (rmap) {
0a22ddfb
QY
5495 XFREE(MTYPE_ROUTE_MAP_NAME,
5496 bgp_static->rmap.name);
b4897fa5 5497 route_map_counter_decrement(
5498 bgp_static->rmap.map);
e2a86ad9
DS
5499 bgp_static->rmap.name =
5500 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5501 bgp_static->rmap.map =
5502 route_map_lookup_by_name(rmap);
b4897fa5 5503 route_map_counter_increment(
5504 bgp_static->rmap.map);
e2a86ad9 5505 } else {
0a22ddfb
QY
5506 XFREE(MTYPE_ROUTE_MAP_NAME,
5507 bgp_static->rmap.name);
b4897fa5 5508 route_map_counter_decrement(
5509 bgp_static->rmap.map);
e2a86ad9
DS
5510 bgp_static->rmap.map = NULL;
5511 bgp_static->valid = 0;
5512 }
9bcb3eef 5513 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5514 } else {
5515 /* New configuration. */
5516 bgp_static = bgp_static_new();
5517 bgp_static->backdoor = backdoor;
5518 bgp_static->valid = 0;
5519 bgp_static->igpmetric = 0;
975a328e 5520 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5521 bgp_static->label_index = label_index;
718e3744 5522
e2a86ad9 5523 if (rmap) {
0a22ddfb
QY
5524 XFREE(MTYPE_ROUTE_MAP_NAME,
5525 bgp_static->rmap.name);
b4897fa5 5526 route_map_counter_decrement(
5527 bgp_static->rmap.map);
e2a86ad9
DS
5528 bgp_static->rmap.name =
5529 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5530 bgp_static->rmap.map =
5531 route_map_lookup_by_name(rmap);
b4897fa5 5532 route_map_counter_increment(
5533 bgp_static->rmap.map);
e2a86ad9 5534 }
9bcb3eef 5535 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5536 }
d62a17ae 5537
e2a86ad9
DS
5538 bgp_static->valid = 1;
5539 if (need_update)
5540 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5541
e2a86ad9
DS
5542 if (!bgp_static->backdoor)
5543 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5544 }
d62a17ae 5545
5546 return CMD_SUCCESS;
5547}
5548
5549void bgp_static_add(struct bgp *bgp)
5550{
5551 afi_t afi;
5552 safi_t safi;
9bcb3eef
DS
5553 struct bgp_dest *dest;
5554 struct bgp_dest *rm;
d62a17ae 5555 struct bgp_table *table;
5556 struct bgp_static *bgp_static;
5557
05c7a1cc 5558 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5559 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5560 dest = bgp_route_next(dest)) {
5561 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5562 continue;
ea47320b 5563
05c7a1cc
QY
5564 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5565 || (safi == SAFI_EVPN)) {
9bcb3eef 5566 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5567
5568 for (rm = bgp_table_top(table); rm;
5569 rm = bgp_route_next(rm)) {
a78beeb5 5570 bgp_static =
9bcb3eef 5571 bgp_dest_get_bgp_static_info(
5a8ba9fc 5572 rm);
9bcb3eef
DS
5573 bgp_static_update_safi(
5574 bgp, bgp_dest_get_prefix(rm),
5575 bgp_static, afi, safi);
d62a17ae 5576 }
05c7a1cc 5577 } else {
5a8ba9fc 5578 bgp_static_update(
9bcb3eef
DS
5579 bgp, bgp_dest_get_prefix(dest),
5580 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5581 safi);
ea47320b 5582 }
05c7a1cc 5583 }
6aeb9e78
DS
5584}
5585
718e3744 5586/* Called from bgp_delete(). Delete all static routes from the BGP
5587 instance. */
d62a17ae 5588void bgp_static_delete(struct bgp *bgp)
5589{
5590 afi_t afi;
5591 safi_t safi;
9bcb3eef
DS
5592 struct bgp_dest *dest;
5593 struct bgp_dest *rm;
d62a17ae 5594 struct bgp_table *table;
5595 struct bgp_static *bgp_static;
5596
05c7a1cc 5597 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5598 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5599 dest = bgp_route_next(dest)) {
5600 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5601 continue;
ea47320b 5602
05c7a1cc
QY
5603 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5604 || (safi == SAFI_EVPN)) {
9bcb3eef 5605 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5606
5607 for (rm = bgp_table_top(table); rm;
5608 rm = bgp_route_next(rm)) {
a78beeb5 5609 bgp_static =
9bcb3eef 5610 bgp_dest_get_bgp_static_info(
5a8ba9fc 5611 rm);
c7d14ba6
PG
5612 if (!bgp_static)
5613 continue;
5614
05c7a1cc 5615 bgp_static_withdraw_safi(
9bcb3eef 5616 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5617 AFI_IP, safi,
5618 (struct prefix_rd *)
9bcb3eef
DS
5619 bgp_dest_get_prefix(
5620 dest));
ea47320b 5621 bgp_static_free(bgp_static);
9bcb3eef
DS
5622 bgp_dest_set_bgp_static_info(dest,
5623 NULL);
5624 bgp_dest_unlock_node(dest);
d62a17ae 5625 }
05c7a1cc 5626 } else {
9bcb3eef 5627 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5628 bgp_static_withdraw(bgp,
9bcb3eef 5629 bgp_dest_get_prefix(dest),
b54892e0 5630 afi, safi);
05c7a1cc 5631 bgp_static_free(bgp_static);
9bcb3eef
DS
5632 bgp_dest_set_bgp_static_info(dest, NULL);
5633 bgp_dest_unlock_node(dest);
ea47320b 5634 }
05c7a1cc 5635 }
d62a17ae 5636}
5637
5638void bgp_static_redo_import_check(struct bgp *bgp)
5639{
5640 afi_t afi;
5641 safi_t safi;
9bcb3eef
DS
5642 struct bgp_dest *dest;
5643 struct bgp_dest *rm;
d62a17ae 5644 struct bgp_table *table;
5645 struct bgp_static *bgp_static;
5646
5647 /* Use this flag to force reprocessing of the route */
892fedb6 5648 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5649 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5650 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5651 dest = bgp_route_next(dest)) {
5652 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5653 continue;
ea47320b 5654
05c7a1cc
QY
5655 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5656 || (safi == SAFI_EVPN)) {
9bcb3eef 5657 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5658
5659 for (rm = bgp_table_top(table); rm;
5660 rm = bgp_route_next(rm)) {
a78beeb5 5661 bgp_static =
9bcb3eef 5662 bgp_dest_get_bgp_static_info(
5a8ba9fc 5663 rm);
9bcb3eef
DS
5664 bgp_static_update_safi(
5665 bgp, bgp_dest_get_prefix(rm),
5666 bgp_static, afi, safi);
d62a17ae 5667 }
05c7a1cc 5668 } else {
9bcb3eef
DS
5669 bgp_static = bgp_dest_get_bgp_static_info(dest);
5670 bgp_static_update(bgp,
5671 bgp_dest_get_prefix(dest),
5672 bgp_static, afi, safi);
ea47320b 5673 }
05c7a1cc
QY
5674 }
5675 }
892fedb6 5676 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5677}
5678
5679static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5680 safi_t safi)
5681{
5682 struct bgp_table *table;
9bcb3eef 5683 struct bgp_dest *dest;
40381db7 5684 struct bgp_path_info *pi;
d62a17ae 5685
dfb6fd1d
NT
5686 /* Do not install the aggregate route if BGP is in the
5687 * process of termination.
5688 */
892fedb6
DA
5689 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5690 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5691 return;
5692
d62a17ae 5693 table = bgp->rib[afi][safi];
9bcb3eef
DS
5694 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5695 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5696 if (pi->peer == bgp->peer_self
5697 && ((pi->type == ZEBRA_ROUTE_BGP
5698 && pi->sub_type == BGP_ROUTE_STATIC)
5699 || (pi->type != ZEBRA_ROUTE_BGP
5700 && pi->sub_type
d62a17ae 5701 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5702 bgp_aggregate_decrement(
5703 bgp, bgp_dest_get_prefix(dest), pi, afi,
5704 safi);
40381db7 5705 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5706 bgp_path_info_delete(dest, pi);
5707 bgp_process(bgp, dest, afi, safi);
d62a17ae 5708 }
5709 }
5710 }
ad4cbda1 5711}
5712
5713/*
5714 * Purge all networks and redistributed routes from routing table.
5715 * Invoked upon the instance going down.
5716 */
d62a17ae 5717void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5718{
d62a17ae 5719 afi_t afi;
5720 safi_t safi;
ad4cbda1 5721
05c7a1cc
QY
5722 FOREACH_AFI_SAFI (afi, safi)
5723 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5724}
5725
137446f9
LB
5726/*
5727 * gpz 110624
5728 * Currently this is used to set static routes for VPN and ENCAP.
5729 * I think it can probably be factored with bgp_static_set.
5730 */
d62a17ae 5731int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5732 const char *ip_str, const char *rd_str,
5733 const char *label_str, const char *rmap_str,
5734 int evpn_type, const char *esi, const char *gwip,
5735 const char *ethtag, const char *routermac)
5736{
5737 VTY_DECLVAR_CONTEXT(bgp, bgp);
5738 int ret;
5739 struct prefix p;
5740 struct prefix_rd prd;
9bcb3eef
DS
5741 struct bgp_dest *pdest;
5742 struct bgp_dest *dest;
d62a17ae 5743 struct bgp_table *table;
5744 struct bgp_static *bgp_static;
5745 mpls_label_t label = MPLS_INVALID_LABEL;
5746 struct prefix gw_ip;
5747
5748 /* validate ip prefix */
5749 ret = str2prefix(ip_str, &p);
5750 if (!ret) {
5751 vty_out(vty, "%% Malformed prefix\n");
5752 return CMD_WARNING_CONFIG_FAILED;
5753 }
5754 apply_mask(&p);
5755 if ((afi == AFI_L2VPN)
5756 && (bgp_build_evpn_prefix(evpn_type,
5757 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5758 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5759 return CMD_WARNING_CONFIG_FAILED;
5760 }
718e3744 5761
d62a17ae 5762 ret = str2prefix_rd(rd_str, &prd);
5763 if (!ret) {
5764 vty_out(vty, "%% Malformed rd\n");
5765 return CMD_WARNING_CONFIG_FAILED;
5766 }
718e3744 5767
d62a17ae 5768 if (label_str) {
5769 unsigned long label_val;
5770 label_val = strtoul(label_str, NULL, 10);
5771 encode_label(label_val, &label);
5772 }
9bedbb1e 5773
d62a17ae 5774 if (safi == SAFI_EVPN) {
5775 if (esi && str2esi(esi, NULL) == 0) {
5776 vty_out(vty, "%% Malformed ESI\n");
5777 return CMD_WARNING_CONFIG_FAILED;
5778 }
5779 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5780 vty_out(vty, "%% Malformed Router MAC\n");
5781 return CMD_WARNING_CONFIG_FAILED;
5782 }
5783 if (gwip) {
5784 memset(&gw_ip, 0, sizeof(struct prefix));
5785 ret = str2prefix(gwip, &gw_ip);
5786 if (!ret) {
5787 vty_out(vty, "%% Malformed GatewayIp\n");
5788 return CMD_WARNING_CONFIG_FAILED;
5789 }
5790 if ((gw_ip.family == AF_INET
3714a385 5791 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5792 (struct prefix_evpn *)&p))
5793 || (gw_ip.family == AF_INET6
3714a385 5794 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5795 (struct prefix_evpn *)&p))) {
5796 vty_out(vty,
5797 "%% GatewayIp family differs with IP prefix\n");
5798 return CMD_WARNING_CONFIG_FAILED;
5799 }
5800 }
5801 }
9bcb3eef
DS
5802 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5803 if (!bgp_dest_has_bgp_path_info_data(pdest))
5804 bgp_dest_set_bgp_table_info(pdest,
67009e22 5805 bgp_table_init(bgp, afi, safi));
9bcb3eef 5806 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 5807
9bcb3eef 5808 dest = bgp_node_get(table, &p);
d62a17ae 5809
9bcb3eef 5810 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 5811 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 5812 bgp_dest_unlock_node(dest);
d62a17ae 5813 } else {
5814 /* New configuration. */
5815 bgp_static = bgp_static_new();
5816 bgp_static->backdoor = 0;
5817 bgp_static->valid = 0;
5818 bgp_static->igpmetric = 0;
975a328e 5819 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5820 bgp_static->label = label;
5821 bgp_static->prd = prd;
5822
5823 if (rmap_str) {
0a22ddfb 5824 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5825 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5826 bgp_static->rmap.name =
5827 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5828 bgp_static->rmap.map =
5829 route_map_lookup_by_name(rmap_str);
b4897fa5 5830 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5831 }
718e3744 5832
d62a17ae 5833 if (safi == SAFI_EVPN) {
5834 if (esi) {
5835 bgp_static->eth_s_id =
5836 XCALLOC(MTYPE_ATTR,
0a50c248 5837 sizeof(esi_t));
d62a17ae 5838 str2esi(esi, bgp_static->eth_s_id);
5839 }
5840 if (routermac) {
5841 bgp_static->router_mac =
28328ea9 5842 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5843 (void)prefix_str2mac(routermac,
5844 bgp_static->router_mac);
d62a17ae 5845 }
5846 if (gwip)
5847 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5848 }
9bcb3eef 5849 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 5850
d62a17ae 5851 bgp_static->valid = 1;
5852 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5853 }
718e3744 5854
d62a17ae 5855 return CMD_SUCCESS;
718e3744 5856}
5857
5858/* Configure static BGP network. */
d62a17ae 5859int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5860 const char *ip_str, const char *rd_str,
5861 const char *label_str, int evpn_type, const char *esi,
5862 const char *gwip, const char *ethtag)
5863{
5864 VTY_DECLVAR_CONTEXT(bgp, bgp);
5865 int ret;
5866 struct prefix p;
5867 struct prefix_rd prd;
9bcb3eef
DS
5868 struct bgp_dest *pdest;
5869 struct bgp_dest *dest;
d62a17ae 5870 struct bgp_table *table;
5871 struct bgp_static *bgp_static;
5872 mpls_label_t label = MPLS_INVALID_LABEL;
5873
5874 /* Convert IP prefix string to struct prefix. */
5875 ret = str2prefix(ip_str, &p);
5876 if (!ret) {
5877 vty_out(vty, "%% Malformed prefix\n");
5878 return CMD_WARNING_CONFIG_FAILED;
5879 }
5880 apply_mask(&p);
5881 if ((afi == AFI_L2VPN)
5882 && (bgp_build_evpn_prefix(evpn_type,
5883 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5884 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5885 return CMD_WARNING_CONFIG_FAILED;
5886 }
5887 ret = str2prefix_rd(rd_str, &prd);
5888 if (!ret) {
5889 vty_out(vty, "%% Malformed rd\n");
5890 return CMD_WARNING_CONFIG_FAILED;
5891 }
718e3744 5892
d62a17ae 5893 if (label_str) {
5894 unsigned long label_val;
5895 label_val = strtoul(label_str, NULL, 10);
5896 encode_label(label_val, &label);
5897 }
718e3744 5898
9bcb3eef
DS
5899 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5900 if (!bgp_dest_has_bgp_path_info_data(pdest))
5901 bgp_dest_set_bgp_table_info(pdest,
67009e22 5902 bgp_table_init(bgp, afi, safi));
d62a17ae 5903 else
9bcb3eef
DS
5904 bgp_dest_unlock_node(pdest);
5905 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 5906
9bcb3eef 5907 dest = bgp_node_lookup(table, &p);
6b0655a2 5908
9bcb3eef 5909 if (dest) {
d62a17ae 5910 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5911
9bcb3eef 5912 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5913 bgp_static_free(bgp_static);
9bcb3eef
DS
5914 bgp_dest_set_bgp_static_info(dest, NULL);
5915 bgp_dest_unlock_node(dest);
5916 bgp_dest_unlock_node(dest);
d62a17ae 5917 } else
5918 vty_out(vty, "%% Can't find the route\n");
5919
5920 return CMD_SUCCESS;
5921}
5922
5923static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5924 const char *rmap_name)
5925{
5926 VTY_DECLVAR_CONTEXT(bgp, bgp);
5927 struct bgp_rmap *rmap;
5928
5929 rmap = &bgp->table_map[afi][safi];
5930 if (rmap_name) {
0a22ddfb 5931 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5932 route_map_counter_decrement(rmap->map);
d62a17ae 5933 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5934 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5935 route_map_counter_increment(rmap->map);
d62a17ae 5936 } else {
0a22ddfb 5937 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5938 route_map_counter_decrement(rmap->map);
d62a17ae 5939 rmap->map = NULL;
5940 }
73ac8160 5941
d62a17ae 5942 if (bgp_fibupd_safi(safi))
5943 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5944
d62a17ae 5945 return CMD_SUCCESS;
73ac8160
DS
5946}
5947
d62a17ae 5948static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5949 const char *rmap_name)
73ac8160 5950{
d62a17ae 5951 VTY_DECLVAR_CONTEXT(bgp, bgp);
5952 struct bgp_rmap *rmap;
73ac8160 5953
d62a17ae 5954 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5955 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5956 route_map_counter_decrement(rmap->map);
d62a17ae 5957 rmap->map = NULL;
73ac8160 5958
d62a17ae 5959 if (bgp_fibupd_safi(safi))
5960 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5961
d62a17ae 5962 return CMD_SUCCESS;
73ac8160
DS
5963}
5964
2b791107 5965void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5966 safi_t safi)
73ac8160 5967{
d62a17ae 5968 if (bgp->table_map[afi][safi].name) {
d62a17ae 5969 vty_out(vty, " table-map %s\n",
5970 bgp->table_map[afi][safi].name);
5971 }
73ac8160
DS
5972}
5973
73ac8160
DS
5974DEFUN (bgp_table_map,
5975 bgp_table_map_cmd,
5976 "table-map WORD",
5977 "BGP table to RIB route download filter\n"
5978 "Name of the route map\n")
5979{
d62a17ae 5980 int idx_word = 1;
5981 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5982 argv[idx_word]->arg);
73ac8160
DS
5983}
5984DEFUN (no_bgp_table_map,
5985 no_bgp_table_map_cmd,
5986 "no table-map WORD",
3a2d747c 5987 NO_STR
73ac8160
DS
5988 "BGP table to RIB route download filter\n"
5989 "Name of the route map\n")
5990{
d62a17ae 5991 int idx_word = 2;
5992 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5993 argv[idx_word]->arg);
73ac8160
DS
5994}
5995
e2a86ad9
DS
5996DEFPY(bgp_network,
5997 bgp_network_cmd,
5998 "[no] network \
5999 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6000 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6001 backdoor$backdoor}]",
6002 NO_STR
6003 "Specify a network to announce via BGP\n"
6004 "IPv4 prefix\n"
6005 "Network number\n"
6006 "Network mask\n"
6007 "Network mask\n"
6008 "Route-map to modify the attributes\n"
6009 "Name of the route map\n"
6010 "Label index to associate with the prefix\n"
6011 "Label index value\n"
6012 "Specify a BGP backdoor route\n")
6013{
6014 char addr_prefix_str[BUFSIZ];
6015
6016 if (address_str) {
6017 int ret;
718e3744 6018
e2a86ad9
DS
6019 ret = netmask_str2prefix_str(address_str, netmask_str,
6020 addr_prefix_str);
6021 if (!ret) {
6022 vty_out(vty, "%% Inconsistent address and mask\n");
6023 return CMD_WARNING_CONFIG_FAILED;
6024 }
d62a17ae 6025 }
718e3744 6026
a4d82a8a
PZ
6027 return bgp_static_set(
6028 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6029 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6030 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6031}
6032
e2a86ad9
DS
6033DEFPY(ipv6_bgp_network,
6034 ipv6_bgp_network_cmd,
6035 "[no] network X:X::X:X/M$prefix \
6036 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6037 NO_STR
6038 "Specify a network to announce via BGP\n"
6039 "IPv6 prefix\n"
6040 "Route-map to modify the attributes\n"
6041 "Name of the route map\n"
6042 "Label index to associate with the prefix\n"
6043 "Label index value\n")
718e3744 6044{
a4d82a8a
PZ
6045 return bgp_static_set(
6046 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6047 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6048}
6049
d62a17ae 6050static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6051{
d62a17ae 6052 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6053}
6054
d62a17ae 6055static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6056{
20894f50
DA
6057 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6058 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6059 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6060}
718e3744 6061
3dc339cd
DA
6062static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6063 struct aspath *aspath,
6064 struct community *comm,
6065 struct ecommunity *ecomm,
6066 struct lcommunity *lcomm)
eaaf8adb
DS
6067{
6068 static struct aspath *ae = NULL;
6069
6070 if (!ae)
6071 ae = aspath_empty();
6072
40381db7 6073 if (!pi)
3dc339cd 6074 return false;
eaaf8adb 6075
40381db7 6076 if (origin != pi->attr->origin)
3dc339cd 6077 return false;
eaaf8adb 6078
40381db7 6079 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6080 return false;
29f7d023 6081
40381db7 6082 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6083 return false;
eaaf8adb 6084
3da2cc32 6085 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6086 return false;
eaaf8adb 6087
dd18c5a9 6088 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6089 return false;
dd18c5a9 6090
40381db7 6091 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6092 return false;
7ce8a8e0 6093
3dc339cd 6094 return true;
eaaf8adb
DS
6095}
6096
5f040085
DS
6097static void bgp_aggregate_install(
6098 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6099 uint8_t origin, struct aspath *aspath, struct community *community,
6100 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6101 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6102{
9bcb3eef 6103 struct bgp_dest *dest;
c701010e 6104 struct bgp_table *table;
6f94b685 6105 struct bgp_path_info *pi, *orig, *new;
20894f50 6106 struct attr *attr;
c701010e
DS
6107
6108 table = bgp->rib[afi][safi];
6109
9bcb3eef 6110 dest = bgp_node_get(table, p);
eaaf8adb 6111
9bcb3eef 6112 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6113 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6114 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6115 break;
6116
c701010e 6117 if (aggregate->count > 0) {
eaaf8adb
DS
6118 /*
6119 * If the aggregate information has not changed
6120 * no need to re-install it again.
6121 */
6f94b685 6122 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6123 ecommunity, lcommunity)) {
9bcb3eef 6124 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6125
6126 if (aspath)
6127 aspath_free(aspath);
6128 if (community)
3c1f53de 6129 community_free(&community);
3da2cc32
DS
6130 if (ecommunity)
6131 ecommunity_free(&ecommunity);
dd18c5a9
DS
6132 if (lcommunity)
6133 lcommunity_free(&lcommunity);
eaaf8adb
DS
6134
6135 return;
6136 }
6137
6138 /*
6139 * Mark the old as unusable
6140 */
40381db7 6141 if (pi)
9bcb3eef 6142 bgp_path_info_delete(dest, pi);
eaaf8adb 6143
20894f50
DA
6144 attr = bgp_attr_aggregate_intern(
6145 bgp, origin, aspath, community, ecommunity, lcommunity,
6146 aggregate, atomic_aggregate, p);
6147
6148 if (!attr) {
6149 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6150 return;
6151 }
6152
3da2cc32 6153 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6154 bgp->peer_self, attr, dest);
20894f50 6155
1defdda8 6156 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6157
9bcb3eef
DS
6158 bgp_path_info_add(dest, new);
6159 bgp_process(bgp, dest, afi, safi);
c701010e 6160 } else {
6f94b685 6161 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6162 if (pi->peer == bgp->peer_self
6163 && pi->type == ZEBRA_ROUTE_BGP
6164 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6165 break;
6166
6167 /* Withdraw static BGP route from routing table. */
40381db7 6168 if (pi) {
9bcb3eef
DS
6169 bgp_path_info_delete(dest, pi);
6170 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6171 }
6172 }
6173
9bcb3eef 6174 bgp_dest_unlock_node(dest);
c701010e
DS
6175}
6176
b5d58c32 6177/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6178void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6179 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6180{
6181 struct bgp_table *table;
9bcb3eef
DS
6182 struct bgp_dest *top;
6183 struct bgp_dest *dest;
d7c0a89a 6184 uint8_t origin;
d62a17ae 6185 struct aspath *aspath = NULL;
d62a17ae 6186 struct community *community = NULL;
3da2cc32 6187 struct ecommunity *ecommunity = NULL;
dd18c5a9 6188 struct lcommunity *lcommunity = NULL;
40381db7 6189 struct bgp_path_info *pi;
d62a17ae 6190 unsigned long match = 0;
d7c0a89a 6191 uint8_t atomic_aggregate = 0;
d62a17ae 6192
9f822fa2
S
6193 /* If the bgp instance is being deleted or self peer is deleted
6194 * then do not create aggregate route
6195 */
892fedb6
DA
6196 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6197 || (bgp->peer_self == NULL))
9f822fa2
S
6198 return;
6199
d62a17ae 6200 /* ORIGIN attribute: If at least one route among routes that are
6201 aggregated has ORIGIN with the value INCOMPLETE, then the
6202 aggregated route must have the ORIGIN attribute with the value
6203 INCOMPLETE. Otherwise, if at least one route among routes that
6204 are aggregated has ORIGIN with the value EGP, then the aggregated
6205 route must have the origin attribute with the value EGP. In all
6206 other case the value of the ORIGIN attribute of the aggregated
6207 route is INTERNAL. */
6208 origin = BGP_ORIGIN_IGP;
718e3744 6209
d62a17ae 6210 table = bgp->rib[afi][safi];
718e3744 6211
d62a17ae 6212 top = bgp_node_get(table, p);
9bcb3eef
DS
6213 for (dest = bgp_node_get(table, p); dest;
6214 dest = bgp_route_next_until(dest, top)) {
6215 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6216
9bcb3eef 6217 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6218 continue;
d62a17ae 6219
c2ff8b3e 6220 match = 0;
d62a17ae 6221
9bcb3eef 6222 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6223 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6224 continue;
718e3744 6225
40381db7 6226 if (pi->attr->flag
c2ff8b3e
DS
6227 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6228 atomic_aggregate = 1;
d62a17ae 6229
40381db7 6230 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6231 continue;
d62a17ae 6232
f273fef1
DS
6233 /*
6234 * summary-only aggregate route suppress
6235 * aggregated route announcements.
6236 */
c2ff8b3e 6237 if (aggregate->summary_only) {
40381db7 6238 (bgp_path_info_extra_get(pi))->suppress++;
9bcb3eef 6239 bgp_path_info_set_flag(dest, pi,
18ee8310 6240 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6241 match++;
d62a17ae 6242 }
c2ff8b3e
DS
6243
6244 aggregate->count++;
6245
f273fef1
DS
6246 /*
6247 * If at least one route among routes that are
6248 * aggregated has ORIGIN with the value INCOMPLETE,
6249 * then the aggregated route MUST have the ORIGIN
6250 * attribute with the value INCOMPLETE. Otherwise, if
6251 * at least one route among routes that are aggregated
6252 * has ORIGIN with the value EGP, then the aggregated
6253 * route MUST have the ORIGIN attribute with the value
6254 * EGP.
6255 */
fc968841
NT
6256 switch (pi->attr->origin) {
6257 case BGP_ORIGIN_INCOMPLETE:
6258 aggregate->incomplete_origin_count++;
6259 break;
6260 case BGP_ORIGIN_EGP:
6261 aggregate->egp_origin_count++;
6262 break;
6263 default:
6264 /*Do nothing.
6265 */
6266 break;
6267 }
c2ff8b3e
DS
6268
6269 if (!aggregate->as_set)
6270 continue;
6271
f273fef1
DS
6272 /*
6273 * as-set aggregate route generate origin, as path,
6274 * and community aggregation.
6275 */
fc968841
NT
6276 /* Compute aggregate route's as-path.
6277 */
ef51a7d8 6278 bgp_compute_aggregate_aspath_hash(aggregate,
6279 pi->attr->aspath);
c2ff8b3e 6280
fc968841
NT
6281 /* Compute aggregate route's community.
6282 */
6283 if (pi->attr->community)
21fec674 6284 bgp_compute_aggregate_community_hash(
fc968841
NT
6285 aggregate,
6286 pi->attr->community);
dd18c5a9 6287
fc968841
NT
6288 /* Compute aggregate route's extended community.
6289 */
6290 if (pi->attr->ecommunity)
4edd83f9 6291 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6292 aggregate,
6293 pi->attr->ecommunity);
6294
6295 /* Compute aggregate route's large community.
6296 */
6297 if (pi->attr->lcommunity)
f1eb1f05 6298 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6299 aggregate,
6300 pi->attr->lcommunity);
d62a17ae 6301 }
c2ff8b3e 6302 if (match)
9bcb3eef 6303 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6304 }
21fec674 6305 if (aggregate->as_set) {
ef51a7d8 6306 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6307 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6308 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6309 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6310 }
6311
f1eb1f05 6312
9bcb3eef 6313 bgp_dest_unlock_node(top);
718e3744 6314
718e3744 6315
fc968841
NT
6316 if (aggregate->incomplete_origin_count > 0)
6317 origin = BGP_ORIGIN_INCOMPLETE;
6318 else if (aggregate->egp_origin_count > 0)
6319 origin = BGP_ORIGIN_EGP;
d62a17ae 6320
229757f1
DA
6321 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6322 origin = aggregate->origin;
6323
fc968841
NT
6324 if (aggregate->as_set) {
6325 if (aggregate->aspath)
6326 /* Retrieve aggregate route's as-path.
6327 */
6328 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6329
fc968841
NT
6330 if (aggregate->community)
6331 /* Retrieve aggregate route's community.
6332 */
6333 community = community_dup(aggregate->community);
3da2cc32 6334
fc968841
NT
6335 if (aggregate->ecommunity)
6336 /* Retrieve aggregate route's ecommunity.
6337 */
6338 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6339
fc968841
NT
6340 if (aggregate->lcommunity)
6341 /* Retrieve aggregate route's lcommunity.
6342 */
6343 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6344 }
718e3744 6345
c701010e 6346 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6347 ecommunity, lcommunity, atomic_aggregate,
6348 aggregate);
718e3744 6349}
6350
5f040085
DS
6351void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6352 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6353{
6354 struct bgp_table *table;
9bcb3eef
DS
6355 struct bgp_dest *top;
6356 struct bgp_dest *dest;
40381db7 6357 struct bgp_path_info *pi;
3b7db173
DS
6358 unsigned long match;
6359
6360 table = bgp->rib[afi][safi];
6361
6362 /* If routes exists below this node, generate aggregate routes. */
6363 top = bgp_node_get(table, p);
9bcb3eef
DS
6364 for (dest = bgp_node_get(table, p); dest;
6365 dest = bgp_route_next_until(dest, top)) {
6366 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6367
9bcb3eef 6368 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
6369 continue;
6370 match = 0;
6371
9bcb3eef 6372 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6373 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6374 continue;
6375
40381db7 6376 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6377 continue;
6378
40381db7
DS
6379 if (aggregate->summary_only && pi->extra) {
6380 pi->extra->suppress--;
3b7db173 6381
40381db7 6382 if (pi->extra->suppress == 0) {
18ee8310 6383 bgp_path_info_set_flag(
9bcb3eef
DS
6384 dest, pi,
6385 BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6386 match++;
6387 }
6388 }
6389 aggregate->count--;
fc968841
NT
6390
6391 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6392 aggregate->incomplete_origin_count--;
6393 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6394 aggregate->egp_origin_count--;
6395
6396 if (aggregate->as_set) {
6397 /* Remove as-path from aggregate.
6398 */
ef51a7d8 6399 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6400 aggregate,
6401 pi->attr->aspath);
6402
6403 if (pi->attr->community)
6404 /* Remove community from aggregate.
6405 */
21fec674 6406 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6407 aggregate,
6408 pi->attr->community);
6409
6410 if (pi->attr->ecommunity)
6411 /* Remove ecommunity from aggregate.
6412 */
4edd83f9 6413 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6414 aggregate,
6415 pi->attr->ecommunity);
6416
6417 if (pi->attr->lcommunity)
6418 /* Remove lcommunity from aggregate.
6419 */
f1eb1f05 6420 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6421 aggregate,
6422 pi->attr->lcommunity);
6423 }
3b7db173
DS
6424 }
6425
6426 /* If this node was suppressed, process the change. */
6427 if (match)
9bcb3eef 6428 bgp_process(bgp, dest, afi, safi);
3b7db173 6429 }
f1eb1f05 6430 if (aggregate->as_set) {
ef51a7d8 6431 aspath_free(aggregate->aspath);
6432 aggregate->aspath = NULL;
21fec674 6433 if (aggregate->community)
6434 community_free(&aggregate->community);
4edd83f9 6435 if (aggregate->ecommunity)
6436 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6437 if (aggregate->lcommunity)
6438 lcommunity_free(&aggregate->lcommunity);
6439 }
6440
9bcb3eef 6441 bgp_dest_unlock_node(top);
3b7db173 6442}
718e3744 6443
5f040085
DS
6444static void bgp_add_route_to_aggregate(struct bgp *bgp,
6445 const struct prefix *aggr_p,
fc968841
NT
6446 struct bgp_path_info *pinew, afi_t afi,
6447 safi_t safi,
6448 struct bgp_aggregate *aggregate)
6449{
6450 uint8_t origin;
6451 struct aspath *aspath = NULL;
6452 uint8_t atomic_aggregate = 0;
6453 struct community *community = NULL;
6454 struct ecommunity *ecommunity = NULL;
6455 struct lcommunity *lcommunity = NULL;
6456
6457 /* ORIGIN attribute: If at least one route among routes that are
6458 * aggregated has ORIGIN with the value INCOMPLETE, then the
6459 * aggregated route must have the ORIGIN attribute with the value
6460 * INCOMPLETE. Otherwise, if at least one route among routes that
6461 * are aggregated has ORIGIN with the value EGP, then the aggregated
6462 * route must have the origin attribute with the value EGP. In all
6463 * other case the value of the ORIGIN attribute of the aggregated
6464 * route is INTERNAL.
6465 */
6466 origin = BGP_ORIGIN_IGP;
6467
6468 aggregate->count++;
6469
6470 if (aggregate->summary_only)
6471 (bgp_path_info_extra_get(pinew))->suppress++;
6472
6473 switch (pinew->attr->origin) {
6474 case BGP_ORIGIN_INCOMPLETE:
6475 aggregate->incomplete_origin_count++;
6476 break;
6477 case BGP_ORIGIN_EGP:
6478 aggregate->egp_origin_count++;
6479 break;
6480 default:
6481 /* Do nothing.
6482 */
6483 break;
6484 }
6485
6486 if (aggregate->incomplete_origin_count > 0)
6487 origin = BGP_ORIGIN_INCOMPLETE;
6488 else if (aggregate->egp_origin_count > 0)
6489 origin = BGP_ORIGIN_EGP;
6490
229757f1
DA
6491 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6492 origin = aggregate->origin;
6493
fc968841
NT
6494 if (aggregate->as_set) {
6495 /* Compute aggregate route's as-path.
6496 */
6497 bgp_compute_aggregate_aspath(aggregate,
6498 pinew->attr->aspath);
6499
6500 /* Compute aggregate route's community.
6501 */
6502 if (pinew->attr->community)
6503 bgp_compute_aggregate_community(
6504 aggregate,
6505 pinew->attr->community);
6506
6507 /* Compute aggregate route's extended community.
6508 */
6509 if (pinew->attr->ecommunity)
6510 bgp_compute_aggregate_ecommunity(
6511 aggregate,
6512 pinew->attr->ecommunity);
6513
6514 /* Compute aggregate route's large community.
6515 */
6516 if (pinew->attr->lcommunity)
6517 bgp_compute_aggregate_lcommunity(
6518 aggregate,
6519 pinew->attr->lcommunity);
6520
6521 /* Retrieve aggregate route's as-path.
6522 */
6523 if (aggregate->aspath)
6524 aspath = aspath_dup(aggregate->aspath);
6525
6526 /* Retrieve aggregate route's community.
6527 */
6528 if (aggregate->community)
6529 community = community_dup(aggregate->community);
6530
6531 /* Retrieve aggregate route's ecommunity.
6532 */
6533 if (aggregate->ecommunity)
6534 ecommunity = ecommunity_dup(aggregate->ecommunity);
6535
6536 /* Retrieve aggregate route's lcommunity.
6537 */
6538 if (aggregate->lcommunity)
6539 lcommunity = lcommunity_dup(aggregate->lcommunity);
6540 }
6541
6542 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6543 aspath, community, ecommunity,
6544 lcommunity, atomic_aggregate, aggregate);
6545}
6546
6547static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6548 safi_t safi,
6549 struct bgp_path_info *pi,
6550 struct bgp_aggregate *aggregate,
5f040085 6551 const struct prefix *aggr_p)
fc968841
NT
6552{
6553 uint8_t origin;
6554 struct aspath *aspath = NULL;
6555 uint8_t atomic_aggregate = 0;
6556 struct community *community = NULL;
6557 struct ecommunity *ecommunity = NULL;
6558 struct lcommunity *lcommunity = NULL;
6559 unsigned long match = 0;
6560
6561 if (BGP_PATH_HOLDDOWN(pi))
6562 return;
6563
6564 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6565 return;
6566
6567 if (aggregate->summary_only
6568 && pi->extra
6569 && pi->extra->suppress > 0) {
6570 pi->extra->suppress--;
6571
6572 if (pi->extra->suppress == 0) {
6573 bgp_path_info_set_flag(pi->net, pi,
6574 BGP_PATH_ATTR_CHANGED);
6575 match++;
6576 }
6577 }
6578
6579 if (aggregate->count > 0)
6580 aggregate->count--;
6581
6582 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6583 aggregate->incomplete_origin_count--;
6584 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6585 aggregate->egp_origin_count--;
6586
6587 if (aggregate->as_set) {
6588 /* Remove as-path from aggregate.
6589 */
6590 bgp_remove_aspath_from_aggregate(aggregate,
6591 pi->attr->aspath);
6592
6593 if (pi->attr->community)
6594 /* Remove community from aggregate.
6595 */
6596 bgp_remove_community_from_aggregate(
6597 aggregate,
6598 pi->attr->community);
6599
6600 if (pi->attr->ecommunity)
6601 /* Remove ecommunity from aggregate.
6602 */
6603 bgp_remove_ecommunity_from_aggregate(
6604 aggregate,
6605 pi->attr->ecommunity);
6606
6607 if (pi->attr->lcommunity)
6608 /* Remove lcommunity from aggregate.
6609 */
6610 bgp_remove_lcommunity_from_aggregate(
6611 aggregate,
6612 pi->attr->lcommunity);
6613 }
6614
6615 /* If this node was suppressed, process the change. */
6616 if (match)
6617 bgp_process(bgp, pi->net, afi, safi);
6618
6619 origin = BGP_ORIGIN_IGP;
6620 if (aggregate->incomplete_origin_count > 0)
6621 origin = BGP_ORIGIN_INCOMPLETE;
6622 else if (aggregate->egp_origin_count > 0)
6623 origin = BGP_ORIGIN_EGP;
6624
229757f1
DA
6625 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6626 origin = aggregate->origin;
6627
fc968841
NT
6628 if (aggregate->as_set) {
6629 /* Retrieve aggregate route's as-path.
6630 */
6631 if (aggregate->aspath)
6632 aspath = aspath_dup(aggregate->aspath);
6633
6634 /* Retrieve aggregate route's community.
6635 */
6636 if (aggregate->community)
6637 community = community_dup(aggregate->community);
6638
6639 /* Retrieve aggregate route's ecommunity.
6640 */
6641 if (aggregate->ecommunity)
6642 ecommunity = ecommunity_dup(aggregate->ecommunity);
6643
6644 /* Retrieve aggregate route's lcommunity.
6645 */
6646 if (aggregate->lcommunity)
6647 lcommunity = lcommunity_dup(aggregate->lcommunity);
6648 }
6649
6650 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6651 aspath, community, ecommunity,
6652 lcommunity, atomic_aggregate, aggregate);
6653}
6654
5a1ae2c2 6655void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 6656 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6657{
9bcb3eef
DS
6658 struct bgp_dest *child;
6659 struct bgp_dest *dest;
d62a17ae 6660 struct bgp_aggregate *aggregate;
6661 struct bgp_table *table;
718e3744 6662
d62a17ae 6663 table = bgp->aggregate[afi][safi];
f018db83 6664
d62a17ae 6665 /* No aggregates configured. */
6666 if (bgp_table_top_nolock(table) == NULL)
6667 return;
f018db83 6668
d62a17ae 6669 if (p->prefixlen == 0)
6670 return;
718e3744 6671
40381db7 6672 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6673 return;
718e3744 6674
d62a17ae 6675 child = bgp_node_get(table, p);
718e3744 6676
d62a17ae 6677 /* Aggregate address configuration check. */
9bcb3eef
DS
6678 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
6679 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6680
9bcb3eef
DS
6681 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
6682 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
6683 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 6684 aggregate);
d62a17ae 6685 }
b1e62edd 6686 }
9bcb3eef 6687 bgp_dest_unlock_node(child);
718e3744 6688}
6689
5a1ae2c2 6690void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 6691 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6692{
9bcb3eef
DS
6693 struct bgp_dest *child;
6694 struct bgp_dest *dest;
d62a17ae 6695 struct bgp_aggregate *aggregate;
6696 struct bgp_table *table;
718e3744 6697
d62a17ae 6698 table = bgp->aggregate[afi][safi];
718e3744 6699
d62a17ae 6700 /* No aggregates configured. */
6701 if (bgp_table_top_nolock(table) == NULL)
6702 return;
718e3744 6703
d62a17ae 6704 if (p->prefixlen == 0)
6705 return;
718e3744 6706
d62a17ae 6707 child = bgp_node_get(table, p);
718e3744 6708
d62a17ae 6709 /* Aggregate address configuration check. */
9bcb3eef
DS
6710 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
6711 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6712
9bcb3eef
DS
6713 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
6714 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 6715 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 6716 aggregate, dest_p);
d62a17ae 6717 }
b1e62edd 6718 }
9bcb3eef 6719 bgp_dest_unlock_node(child);
d62a17ae 6720}
718e3744 6721
718e3744 6722/* Aggregate route attribute. */
6723#define AGGREGATE_SUMMARY_ONLY 1
6724#define AGGREGATE_AS_SET 1
fb29348a 6725#define AGGREGATE_AS_UNSET 0
718e3744 6726
229757f1
DA
6727static const char *bgp_origin2str(uint8_t origin)
6728{
6729 switch (origin) {
6730 case BGP_ORIGIN_IGP:
6731 return "igp";
6732 case BGP_ORIGIN_EGP:
6733 return "egp";
6734 case BGP_ORIGIN_INCOMPLETE:
6735 return "incomplete";
6736 }
6737 return "n/a";
6738}
6739
d62a17ae 6740static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6741 afi_t afi, safi_t safi)
718e3744 6742{
d62a17ae 6743 VTY_DECLVAR_CONTEXT(bgp, bgp);
6744 int ret;
6745 struct prefix p;
9bcb3eef 6746 struct bgp_dest *dest;
d62a17ae 6747 struct bgp_aggregate *aggregate;
718e3744 6748
d62a17ae 6749 /* Convert string to prefix structure. */
6750 ret = str2prefix(prefix_str, &p);
6751 if (!ret) {
6752 vty_out(vty, "Malformed prefix\n");
6753 return CMD_WARNING_CONFIG_FAILED;
6754 }
6755 apply_mask(&p);
6756
6757 /* Old configuration check. */
9bcb3eef
DS
6758 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6759 if (!dest) {
d62a17ae 6760 vty_out(vty,
6761 "%% There is no aggregate-address configuration.\n");
6762 return CMD_WARNING_CONFIG_FAILED;
6763 }
f6269b4f 6764
9bcb3eef 6765 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
09990cdd 6766 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6767 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6768 NULL, NULL, 0, aggregate);
d62a17ae 6769
6770 /* Unlock aggregate address configuration. */
9bcb3eef 6771 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
6772
6773 if (aggregate->community)
6774 community_free(&aggregate->community);
6775
6776 if (aggregate->community_hash) {
6777 /* Delete all communities in the hash.
6778 */
6779 hash_clean(aggregate->community_hash,
6780 bgp_aggr_community_remove);
6781 /* Free up the community_hash.
6782 */
6783 hash_free(aggregate->community_hash);
6784 }
6785
6786 if (aggregate->ecommunity)
6787 ecommunity_free(&aggregate->ecommunity);
6788
6789 if (aggregate->ecommunity_hash) {
6790 /* Delete all ecommunities in the hash.
6791 */
6792 hash_clean(aggregate->ecommunity_hash,
6793 bgp_aggr_ecommunity_remove);
6794 /* Free up the ecommunity_hash.
6795 */
6796 hash_free(aggregate->ecommunity_hash);
6797 }
6798
6799 if (aggregate->lcommunity)
6800 lcommunity_free(&aggregate->lcommunity);
6801
6802 if (aggregate->lcommunity_hash) {
6803 /* Delete all lcommunities in the hash.
6804 */
6805 hash_clean(aggregate->lcommunity_hash,
6806 bgp_aggr_lcommunity_remove);
6807 /* Free up the lcommunity_hash.
6808 */
6809 hash_free(aggregate->lcommunity_hash);
6810 }
6811
6812 if (aggregate->aspath)
6813 aspath_free(aggregate->aspath);
6814
6815 if (aggregate->aspath_hash) {
6816 /* Delete all as-paths in the hash.
6817 */
6818 hash_clean(aggregate->aspath_hash,
6819 bgp_aggr_aspath_remove);
6820 /* Free up the aspath_hash.
6821 */
6822 hash_free(aggregate->aspath_hash);
6823 }
6824
d62a17ae 6825 bgp_aggregate_free(aggregate);
9bcb3eef
DS
6826 bgp_dest_unlock_node(dest);
6827 bgp_dest_unlock_node(dest);
d62a17ae 6828
6829 return CMD_SUCCESS;
6830}
6831
6832static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
6833 safi_t safi, const char *rmap,
6834 uint8_t summary_only, uint8_t as_set,
6835 uint8_t origin)
d62a17ae 6836{
6837 VTY_DECLVAR_CONTEXT(bgp, bgp);
6838 int ret;
6839 struct prefix p;
9bcb3eef 6840 struct bgp_dest *dest;
d62a17ae 6841 struct bgp_aggregate *aggregate;
fb29348a 6842 uint8_t as_set_new = as_set;
d62a17ae 6843
6844 /* Convert string to prefix structure. */
6845 ret = str2prefix(prefix_str, &p);
6846 if (!ret) {
6847 vty_out(vty, "Malformed prefix\n");
6848 return CMD_WARNING_CONFIG_FAILED;
6849 }
6850 apply_mask(&p);
6851
3624ac81
DS
6852 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6853 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6854 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6855 prefix_str);
6856 return CMD_WARNING_CONFIG_FAILED;
6857 }
6858
d62a17ae 6859 /* Old configuration check. */
9bcb3eef
DS
6860 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
6861 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 6862
20894f50 6863 if (aggregate) {
d62a17ae 6864 vty_out(vty, "There is already same aggregate network.\n");
6865 /* try to remove the old entry */
6866 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6867 if (ret) {
6868 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 6869 bgp_dest_unlock_node(dest);
d62a17ae 6870 return CMD_WARNING_CONFIG_FAILED;
6871 }
6872 }
718e3744 6873
d62a17ae 6874 /* Make aggregate address structure. */
6875 aggregate = bgp_aggregate_new();
6876 aggregate->summary_only = summary_only;
fb29348a
DA
6877
6878 /* Network operators MUST NOT locally generate any new
6879 * announcements containing AS_SET or AS_CONFED_SET. If they have
6880 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6881 * SHOULD withdraw those routes and re-announce routes for the
6882 * aggregate or component prefixes (i.e., the more-specific routes
6883 * subsumed by the previously aggregated route) without AS_SET
6884 * or AS_CONFED_SET in the updates.
6885 */
7f972cd8 6886 if (bgp->reject_as_sets) {
fb29348a
DA
6887 if (as_set == AGGREGATE_AS_SET) {
6888 as_set_new = AGGREGATE_AS_UNSET;
6889 zlog_warn(
63efca0e 6890 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a
DA
6891 __func__);
6892 vty_out(vty,
6893 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6894 }
6895 }
6896
6897 aggregate->as_set = as_set_new;
d62a17ae 6898 aggregate->safi = safi;
229757f1
DA
6899 /* Override ORIGIN attribute if defined.
6900 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6901 * to IGP which is not what rfc4271 says.
6902 * This enables the same behavior, optionally.
6903 */
6904 aggregate->origin = origin;
20894f50
DA
6905
6906 if (rmap) {
6907 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6908 route_map_counter_decrement(aggregate->rmap.map);
6909 aggregate->rmap.name =
6910 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6911 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6912 route_map_counter_increment(aggregate->rmap.map);
6913 }
9bcb3eef 6914 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 6915
d62a17ae 6916 /* Aggregate address insert into BGP routing table. */
fc968841 6917 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6918
d62a17ae 6919 return CMD_SUCCESS;
718e3744 6920}
6921
6922DEFUN (aggregate_address,
6923 aggregate_address_cmd,
229757f1 6924 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6925 "Configure BGP aggregate entries\n"
6926 "Aggregate prefix\n"
6927 "Generate AS set path information\n"
a636c635
DW
6928 "Filter more specific routes from updates\n"
6929 "Filter more specific routes from updates\n"
20894f50
DA
6930 "Generate AS set path information\n"
6931 "Apply route map to aggregate network\n"
229757f1
DA
6932 "Name of route map\n"
6933 "BGP origin code\n"
6934 "Remote EGP\n"
6935 "Local IGP\n"
6936 "Unknown heritage\n")
718e3744 6937{
d62a17ae 6938 int idx = 0;
6939 argv_find(argv, argc, "A.B.C.D/M", &idx);
6940 char *prefix = argv[idx]->arg;
20894f50 6941 char *rmap = NULL;
229757f1 6942 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6943 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6944 : AGGREGATE_AS_UNSET;
d62a17ae 6945 idx = 0;
6946 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6947 ? AGGREGATE_SUMMARY_ONLY
6948 : 0;
e3e6107d 6949
20894f50
DA
6950 idx = 0;
6951 argv_find(argv, argc, "WORD", &idx);
6952 if (idx)
6953 rmap = argv[idx]->arg;
6954
229757f1
DA
6955 idx = 0;
6956 if (argv_find(argv, argc, "origin", &idx)) {
6957 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6958 origin = BGP_ORIGIN_IGP;
6959 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6960 origin = BGP_ORIGIN_EGP;
6961 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6962 origin = BGP_ORIGIN_INCOMPLETE;
6963 }
6964
6965 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
6966 summary_only, as_set, origin);
718e3744 6967}
6968
e3e6107d
QY
6969DEFUN (aggregate_address_mask,
6970 aggregate_address_mask_cmd,
229757f1 6971 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6972 "Configure BGP aggregate entries\n"
6973 "Aggregate address\n"
6974 "Aggregate mask\n"
6975 "Generate AS set path information\n"
a636c635
DW
6976 "Filter more specific routes from updates\n"
6977 "Filter more specific routes from updates\n"
20894f50
DA
6978 "Generate AS set path information\n"
6979 "Apply route map to aggregate network\n"
229757f1
DA
6980 "Name of route map\n"
6981 "BGP origin code\n"
6982 "Remote EGP\n"
6983 "Local IGP\n"
6984 "Unknown heritage\n")
718e3744 6985{
d62a17ae 6986 int idx = 0;
6987 argv_find(argv, argc, "A.B.C.D", &idx);
6988 char *prefix = argv[idx]->arg;
6989 char *mask = argv[idx + 1]->arg;
cf40d052 6990 bool rmap_found;
20894f50 6991 char *rmap = NULL;
229757f1 6992 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6993 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6994 : AGGREGATE_AS_UNSET;
d62a17ae 6995 idx = 0;
6996 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6997 ? AGGREGATE_SUMMARY_ONLY
6998 : 0;
6999
cf40d052
DS
7000 rmap_found = argv_find(argv, argc, "WORD", &idx);
7001 if (rmap_found)
20894f50
DA
7002 rmap = argv[idx]->arg;
7003
d62a17ae 7004 char prefix_str[BUFSIZ];
7005 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
7006
7007 if (!ret) {
7008 vty_out(vty, "%% Inconsistent address and mask\n");
7009 return CMD_WARNING_CONFIG_FAILED;
7010 }
718e3744 7011
229757f1
DA
7012 idx = 0;
7013 if (argv_find(argv, argc, "origin", &idx)) {
7014 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7015 origin = BGP_ORIGIN_IGP;
7016 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7017 origin = BGP_ORIGIN_EGP;
7018 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7019 origin = BGP_ORIGIN_INCOMPLETE;
7020 }
7021
d62a17ae 7022 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
229757f1 7023 rmap, summary_only, as_set, origin);
718e3744 7024}
7025
718e3744 7026DEFUN (no_aggregate_address,
7027 no_aggregate_address_cmd,
229757f1 7028 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7029 NO_STR
7030 "Configure BGP aggregate entries\n"
a636c635
DW
7031 "Aggregate prefix\n"
7032 "Generate AS set path information\n"
e3e6107d
QY
7033 "Filter more specific routes from updates\n"
7034 "Filter more specific routes from updates\n"
b84da0db
DA
7035 "Generate AS set path information\n"
7036 "Apply route map to aggregate network\n"
229757f1
DA
7037 "Name of route map\n"
7038 "BGP origin code\n"
7039 "Remote EGP\n"
7040 "Local IGP\n"
7041 "Unknown heritage\n")
718e3744 7042{
d62a17ae 7043 int idx = 0;
7044 argv_find(argv, argc, "A.B.C.D/M", &idx);
7045 char *prefix = argv[idx]->arg;
7046 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 7047}
7048
718e3744 7049DEFUN (no_aggregate_address_mask,
7050 no_aggregate_address_mask_cmd,
229757f1 7051 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7052 NO_STR
7053 "Configure BGP aggregate entries\n"
7054 "Aggregate address\n"
a636c635
DW
7055 "Aggregate mask\n"
7056 "Generate AS set path information\n"
e3e6107d
QY
7057 "Filter more specific routes from updates\n"
7058 "Filter more specific routes from updates\n"
b84da0db
DA
7059 "Generate AS set path information\n"
7060 "Apply route map to aggregate network\n"
229757f1
DA
7061 "Name of route map\n"
7062 "BGP origin code\n"
7063 "Remote EGP\n"
7064 "Local IGP\n"
7065 "Unknown heritage\n")
718e3744 7066{
d62a17ae 7067 int idx = 0;
7068 argv_find(argv, argc, "A.B.C.D", &idx);
7069 char *prefix = argv[idx]->arg;
7070 char *mask = argv[idx + 1]->arg;
718e3744 7071
d62a17ae 7072 char prefix_str[BUFSIZ];
7073 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 7074
d62a17ae 7075 if (!ret) {
7076 vty_out(vty, "%% Inconsistent address and mask\n");
7077 return CMD_WARNING_CONFIG_FAILED;
7078 }
718e3744 7079
d62a17ae 7080 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 7081}
7082
718e3744 7083DEFUN (ipv6_aggregate_address,
7084 ipv6_aggregate_address_cmd,
229757f1 7085 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7086 "Configure BGP aggregate entries\n"
7087 "Aggregate prefix\n"
5101fece 7088 "Generate AS set path information\n"
7089 "Filter more specific routes from updates\n"
7090 "Filter more specific routes from updates\n"
20894f50
DA
7091 "Generate AS set path information\n"
7092 "Apply route map to aggregate network\n"
229757f1
DA
7093 "Name of route map\n"
7094 "BGP origin code\n"
7095 "Remote EGP\n"
7096 "Local IGP\n"
7097 "Unknown heritage\n")
718e3744 7098{
d62a17ae 7099 int idx = 0;
7100 argv_find(argv, argc, "X:X::X:X/M", &idx);
7101 char *prefix = argv[idx]->arg;
20894f50 7102 char *rmap = NULL;
273fae13 7103 bool rmap_found;
229757f1 7104 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7105 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7106 : AGGREGATE_AS_UNSET;
5101fece 7107
7108 idx = 0;
d62a17ae 7109 int sum_only = argv_find(argv, argc, "summary-only", &idx)
7110 ? AGGREGATE_SUMMARY_ONLY
7111 : 0;
20894f50 7112
273fae13
DA
7113 rmap_found = argv_find(argv, argc, "WORD", &idx);
7114 if (rmap_found)
20894f50
DA
7115 rmap = argv[idx]->arg;
7116
229757f1
DA
7117 idx = 0;
7118 if (argv_find(argv, argc, "origin", &idx)) {
7119 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7120 origin = BGP_ORIGIN_IGP;
7121 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7122 origin = BGP_ORIGIN_EGP;
7123 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7124 origin = BGP_ORIGIN_INCOMPLETE;
7125 }
7126
20894f50 7127 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
229757f1 7128 sum_only, as_set, origin);
718e3744 7129}
7130
7131DEFUN (no_ipv6_aggregate_address,
7132 no_ipv6_aggregate_address_cmd,
229757f1 7133 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7134 NO_STR
7135 "Configure BGP aggregate entries\n"
16cedbb0 7136 "Aggregate prefix\n"
5101fece 7137 "Generate AS set path information\n"
7138 "Filter more specific routes from updates\n"
7139 "Filter more specific routes from updates\n"
b84da0db
DA
7140 "Generate AS set path information\n"
7141 "Apply route map to aggregate network\n"
229757f1
DA
7142 "Name of route map\n"
7143 "BGP origin code\n"
7144 "Remote EGP\n"
7145 "Local IGP\n"
7146 "Unknown heritage\n")
718e3744 7147{
d62a17ae 7148 int idx = 0;
7149 argv_find(argv, argc, "X:X::X:X/M", &idx);
7150 char *prefix = argv[idx]->arg;
7151 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7152}
7153
718e3744 7154/* Redistribute route treatment. */
d62a17ae 7155void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7156 const union g_addr *nexthop, ifindex_t ifindex,
7157 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7158 uint8_t type, unsigned short instance,
7159 route_tag_t tag)
d62a17ae 7160{
4b7e6066 7161 struct bgp_path_info *new;
40381db7
DS
7162 struct bgp_path_info *bpi;
7163 struct bgp_path_info rmap_path;
9bcb3eef 7164 struct bgp_dest *bn;
d62a17ae 7165 struct attr attr;
7166 struct attr *new_attr;
7167 afi_t afi;
b68885f9 7168 route_map_result_t ret;
d62a17ae 7169 struct bgp_redist *red;
7170
7171 /* Make default attribute. */
7172 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7173 /*
7174 * This must not be NULL to satisfy Coverity SA
7175 */
7176 assert(attr.aspath);
9de1f7ff 7177
a4d82a8a 7178 switch (nhtype) {
9de1f7ff
DS
7179 case NEXTHOP_TYPE_IFINDEX:
7180 break;
7181 case NEXTHOP_TYPE_IPV4:
7182 case NEXTHOP_TYPE_IPV4_IFINDEX:
7183 attr.nexthop = nexthop->ipv4;
7184 break;
7185 case NEXTHOP_TYPE_IPV6:
7186 case NEXTHOP_TYPE_IPV6_IFINDEX:
7187 attr.mp_nexthop_global = nexthop->ipv6;
7188 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7189 break;
7190 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7191 switch (p->family) {
7192 case AF_INET:
9de1f7ff 7193 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7194 break;
7195 case AF_INET6:
9de1f7ff
DS
7196 memset(&attr.mp_nexthop_global, 0,
7197 sizeof(attr.mp_nexthop_global));
74489921 7198 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7199 break;
74489921 7200 }
9de1f7ff 7201 break;
d62a17ae 7202 }
74489921 7203 attr.nh_ifindex = ifindex;
f04a80a5 7204
d62a17ae 7205 attr.med = metric;
7206 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7207 attr.tag = tag;
718e3744 7208
d62a17ae 7209 afi = family2afi(p->family);
6aeb9e78 7210
d62a17ae 7211 red = bgp_redist_lookup(bgp, afi, type, instance);
7212 if (red) {
7213 struct attr attr_new;
718e3744 7214
d62a17ae 7215 /* Copy attribute for modification. */
6f4f49b2 7216 attr_new = attr;
718e3744 7217
d62a17ae 7218 if (red->redist_metric_flag)
7219 attr_new.med = red->redist_metric;
718e3744 7220
d62a17ae 7221 /* Apply route-map. */
7222 if (red->rmap.name) {
40381db7
DS
7223 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7224 rmap_path.peer = bgp->peer_self;
7225 rmap_path.attr = &attr_new;
718e3744 7226
d62a17ae 7227 SET_FLAG(bgp->peer_self->rmap_type,
7228 PEER_RMAP_TYPE_REDISTRIBUTE);
7229
7230 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7231 &rmap_path);
d62a17ae 7232
7233 bgp->peer_self->rmap_type = 0;
7234
7235 if (ret == RMAP_DENYMATCH) {
7236 /* Free uninterned attribute. */
7237 bgp_attr_flush(&attr_new);
7238
7239 /* Unintern original. */
7240 aspath_unintern(&attr.aspath);
7241 bgp_redistribute_delete(bgp, p, type, instance);
7242 return;
7243 }
7244 }
7245
892fedb6 7246 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
7247 bgp_attr_add_gshut_community(&attr_new);
7248
d62a17ae 7249 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7250 SAFI_UNICAST, p, NULL);
7251
7252 new_attr = bgp_attr_intern(&attr_new);
7253
9bcb3eef 7254 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7255 if (bpi->peer == bgp->peer_self
7256 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7257 break;
7258
40381db7 7259 if (bpi) {
d62a17ae 7260 /* Ensure the (source route) type is updated. */
40381db7
DS
7261 bpi->type = type;
7262 if (attrhash_cmp(bpi->attr, new_attr)
7263 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7264 bgp_attr_unintern(&new_attr);
7265 aspath_unintern(&attr.aspath);
9bcb3eef 7266 bgp_dest_unlock_node(bn);
d62a17ae 7267 return;
7268 } else {
7269 /* The attribute is changed. */
40381db7 7270 bgp_path_info_set_flag(bn, bpi,
18ee8310 7271 BGP_PATH_ATTR_CHANGED);
d62a17ae 7272
7273 /* Rewrite BGP route information. */
40381db7
DS
7274 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7275 bgp_path_info_restore(bn, bpi);
d62a17ae 7276 else
40381db7
DS
7277 bgp_aggregate_decrement(
7278 bgp, p, bpi, afi, SAFI_UNICAST);
7279 bgp_attr_unintern(&bpi->attr);
7280 bpi->attr = new_attr;
7281 bpi->uptime = bgp_clock();
d62a17ae 7282
7283 /* Process change. */
40381db7 7284 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7285 SAFI_UNICAST);
7286 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7287 bgp_dest_unlock_node(bn);
d62a17ae 7288 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7289
7290 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7291 || (bgp->inst_type
7292 == BGP_INSTANCE_TYPE_DEFAULT)) {
7293
7294 vpn_leak_from_vrf_update(
40381db7 7295 bgp_get_default(), bgp, bpi);
ddb5b488 7296 }
d62a17ae 7297 return;
7298 }
7299 }
7300
7301 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7302 bgp->peer_self, new_attr, bn);
1defdda8 7303 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7304
7305 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7306 bgp_path_info_add(bn, new);
9bcb3eef 7307 bgp_dest_unlock_node(bn);
d62a17ae 7308 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7309
7310 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7311 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7312
7313 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7314 }
d62a17ae 7315 }
7316
7317 /* Unintern original. */
7318 aspath_unintern(&attr.aspath);
718e3744 7319}
7320
d7c0a89a
QY
7321void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7322 unsigned short instance)
718e3744 7323{
d62a17ae 7324 afi_t afi;
9bcb3eef 7325 struct bgp_dest *dest;
40381db7 7326 struct bgp_path_info *pi;
d62a17ae 7327 struct bgp_redist *red;
718e3744 7328
d62a17ae 7329 afi = family2afi(p->family);
718e3744 7330
d62a17ae 7331 red = bgp_redist_lookup(bgp, afi, type, instance);
7332 if (red) {
9bcb3eef
DS
7333 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7334 SAFI_UNICAST, p, NULL);
d62a17ae 7335
9bcb3eef 7336 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7337 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7338 break;
7339
40381db7 7340 if (pi) {
ddb5b488
PZ
7341 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7342 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7343
7344 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7345 bgp, pi);
ddb5b488 7346 }
40381db7 7347 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7348 bgp_path_info_delete(dest, pi);
7349 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7350 }
9bcb3eef 7351 bgp_dest_unlock_node(dest);
d62a17ae 7352 }
7353}
7354
7355/* Withdraw specified route type's route. */
7356void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7357 unsigned short instance)
d62a17ae 7358{
9bcb3eef 7359 struct bgp_dest *dest;
40381db7 7360 struct bgp_path_info *pi;
d62a17ae 7361 struct bgp_table *table;
7362
7363 table = bgp->rib[afi][SAFI_UNICAST];
7364
9bcb3eef
DS
7365 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7366 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7367 if (pi->peer == bgp->peer_self && pi->type == type
7368 && pi->instance == instance)
d62a17ae 7369 break;
7370
40381db7 7371 if (pi) {
ddb5b488
PZ
7372 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7373 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7374
7375 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7376 bgp, pi);
ddb5b488 7377 }
9bcb3eef 7378 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 7379 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7380 bgp_path_info_delete(dest, pi);
7381 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7382 }
718e3744 7383 }
718e3744 7384}
6b0655a2 7385
718e3744 7386/* Static function to display route. */
bd494ec5 7387static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 7388 json_object *json, bool wide)
718e3744 7389{
be054588 7390 int len = 0;
d62a17ae 7391 char buf[BUFSIZ];
50e05855 7392 char buf2[BUFSIZ];
718e3744 7393
d62a17ae 7394 if (p->family == AF_INET) {
c6462ff4 7395 if (!json) {
89e5e9f0
PM
7396 len = vty_out(
7397 vty, "%s/%d",
7398 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7399 p->prefixlen);
c6462ff4
MK
7400 } else {
7401 json_object_string_add(json, "prefix",
7402 inet_ntop(p->family,
7403 &p->u.prefix, buf,
7404 BUFSIZ));
7405 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7406 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7407 json_object_string_add(json, "network", buf2);
c6462ff4 7408 }
d62a17ae 7409 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7410 prefix2str(p, buf, PREFIX_STRLEN);
7411 len = vty_out(vty, "%s", buf);
7412 } else if (p->family == AF_EVPN) {
57f7feb6 7413 if (!json)
60466a63
QY
7414 len = vty_out(
7415 vty, "%s",
7416 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7417 BUFSIZ));
57f7feb6 7418 else
60466a63 7419 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7420 } else if (p->family == AF_FLOWSPEC) {
7421 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7422 json ?
7423 NLRI_STRING_FORMAT_JSON_SIMPLE :
7424 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7425 } else {
c6462ff4 7426 if (!json)
60466a63
QY
7427 len = vty_out(
7428 vty, "%s/%d",
7429 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7430 p->prefixlen);
50e05855
AD
7431 else {
7432 json_object_string_add(json, "prefix",
7433 inet_ntop(p->family,
7434 &p->u.prefix, buf,
7435 BUFSIZ));
7436 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7437 prefix2str(p, buf2, PREFIX_STRLEN);
7438 json_object_string_add(json, "network", buf2);
7439 }
9c92b5f7 7440 }
d62a17ae 7441
9c92b5f7 7442 if (!json) {
ae248832 7443 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
7444 if (len < 1)
7445 vty_out(vty, "\n%*s", 20, " ");
7446 else
7447 vty_out(vty, "%*s", len, " ");
7448 }
718e3744 7449}
7450
d62a17ae 7451enum bgp_display_type {
7452 normal_list,
718e3744 7453};
7454
18ee8310 7455/* Print the short form route status for a bgp_path_info */
4b7e6066 7456static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7457 struct bgp_path_info *path,
d62a17ae 7458 json_object *json_path)
718e3744 7459{
d62a17ae 7460 if (json_path) {
b05a1c8b 7461
d62a17ae 7462 /* Route status display. */
9b6d8fcf 7463 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7464 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7465
9b6d8fcf 7466 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7467 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7468
9b6d8fcf 7469 if (path->extra && path->extra->suppress)
d62a17ae 7470 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7471
9b6d8fcf
DS
7472 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7473 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7474 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7475
d62a17ae 7476 /* Selected */
9b6d8fcf 7477 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7478 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7479
9b6d8fcf 7480 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7481 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7482
9b6d8fcf 7483 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7484 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7485
9b6d8fcf 7486 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7487 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7488
d62a17ae 7489 /* Internal route. */
9b6d8fcf
DS
7490 if ((path->peer->as)
7491 && (path->peer->as == path->peer->local_as))
d62a17ae 7492 json_object_string_add(json_path, "pathFrom",
7493 "internal");
7494 else
7495 json_object_string_add(json_path, "pathFrom",
7496 "external");
b05a1c8b 7497
d62a17ae 7498 return;
7499 }
b05a1c8b 7500
d62a17ae 7501 /* Route status display. */
9b6d8fcf 7502 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7503 vty_out(vty, "R");
9b6d8fcf 7504 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7505 vty_out(vty, "S");
9b6d8fcf 7506 else if (path->extra && path->extra->suppress)
d62a17ae 7507 vty_out(vty, "s");
9b6d8fcf
DS
7508 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7509 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7510 vty_out(vty, "*");
7511 else
7512 vty_out(vty, " ");
7513
7514 /* Selected */
9b6d8fcf 7515 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7516 vty_out(vty, "h");
9b6d8fcf 7517 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7518 vty_out(vty, "d");
9b6d8fcf 7519 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7520 vty_out(vty, ">");
9b6d8fcf 7521 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7522 vty_out(vty, "=");
7523 else
7524 vty_out(vty, " ");
718e3744 7525
d62a17ae 7526 /* Internal route. */
9b6d8fcf
DS
7527 if (path->peer && (path->peer->as)
7528 && (path->peer->as == path->peer->local_as))
d62a17ae 7529 vty_out(vty, "i");
7530 else
7531 vty_out(vty, " ");
b40d939b 7532}
7533
2ba93fd6
DA
7534static char *bgp_nexthop_hostname(struct peer *peer,
7535 struct bgp_nexthop_cache *bnc)
25b5da8d 7536{
892fedb6 7537 if (peer->hostname
aef999a2 7538 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
7539 return peer->hostname;
7540 return NULL;
7541}
7542
b40d939b 7543/* called from terminal list command */
bd494ec5 7544void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 7545 struct bgp_path_info *path, int display, safi_t safi,
ae248832 7546 json_object *json_paths, bool wide)
d62a17ae 7547{
aef999a2 7548 int len;
515c2602 7549 struct attr *attr = path->attr;
d62a17ae 7550 json_object *json_path = NULL;
7551 json_object *json_nexthops = NULL;
7552 json_object *json_nexthop_global = NULL;
7553 json_object *json_nexthop_ll = NULL;
6f214dd3 7554 json_object *json_ext_community = NULL;
9df8b37c 7555 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7556 bool nexthop_self =
9b6d8fcf 7557 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7558 bool nexthop_othervrf = false;
43089216 7559 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7560 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
7561 char *nexthop_hostname =
7562 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 7563 char esi_buf[ESI_STR_LEN];
d62a17ae 7564
7565 if (json_paths)
7566 json_path = json_object_new_object();
7567
7568 /* short status lead text */
9b6d8fcf 7569 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7570
7571 if (!json_paths) {
7572 /* print prefix and mask */
7573 if (!display)
ae248832 7574 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 7575 else
ae248832 7576 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 7577 } else {
ae248832 7578 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 7579 }
47fc97cc 7580
9df8b37c
PZ
7581 /*
7582 * If vrf id of nexthop is different from that of prefix,
7583 * set up printable string to append
7584 */
9b6d8fcf 7585 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7586 const char *self = "";
7587
7588 if (nexthop_self)
7589 self = "<";
7590
7591 nexthop_othervrf = true;
9b6d8fcf 7592 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7593
9b6d8fcf 7594 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7595 snprintf(vrf_id_str, sizeof(vrf_id_str),
7596 "@%s%s", VRFID_NONE_STR, self);
7597 else
7598 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7599 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7600
9b6d8fcf
DS
7601 if (path->extra->bgp_orig->inst_type
7602 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7603
9b6d8fcf 7604 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7605 } else {
7606 const char *self = "";
7607
7608 if (nexthop_self)
7609 self = "<";
7610
7611 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7612 }
7613
445c2480
DS
7614 /*
7615 * For ENCAP and EVPN routes, nexthop address family is not
7616 * neccessarily the same as the prefix address family.
7617 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7618 * EVPN routes are also exchanged with a MP nexthop. Currently,
7619 * this
7620 * is only IPv4, the value will be present in either
7621 * attr->nexthop or
7622 * attr->mp_nexthop_global_in
7623 */
7624 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7625 char buf[BUFSIZ];
7626 char nexthop[128];
7627 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7628
7629 switch (af) {
7630 case AF_INET:
772270f3
QY
7631 snprintf(nexthop, sizeof(nexthop), "%s",
7632 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7633 BUFSIZ));
445c2480
DS
7634 break;
7635 case AF_INET6:
772270f3
QY
7636 snprintf(nexthop, sizeof(nexthop), "%s",
7637 inet_ntop(af, &attr->mp_nexthop_global, buf,
7638 BUFSIZ));
445c2480
DS
7639 break;
7640 default:
772270f3 7641 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 7642 break;
d62a17ae 7643 }
d62a17ae 7644
445c2480
DS
7645 if (json_paths) {
7646 json_nexthop_global = json_object_new_object();
7647
515c2602
DA
7648 json_object_string_add(json_nexthop_global, "ip",
7649 nexthop);
7650
939a97f4 7651 if (path->peer->hostname)
515c2602
DA
7652 json_object_string_add(json_nexthop_global,
7653 "hostname",
939a97f4 7654 path->peer->hostname);
515c2602
DA
7655
7656 json_object_string_add(json_nexthop_global, "afi",
7657 (af == AF_INET) ? "ipv4"
7658 : "ipv6");
445c2480
DS
7659 json_object_boolean_true_add(json_nexthop_global,
7660 "used");
aef999a2
DA
7661 } else {
7662 if (nexthop_hostname)
7663 len = vty_out(vty, "%s(%s)%s", nexthop,
7664 nexthop_hostname, vrf_id_str);
7665 else
7666 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
7667
ae248832 7668 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7669 if (len < 1)
7670 vty_out(vty, "\n%*s", 36, " ");
7671 else
7672 vty_out(vty, "%*s", len, " ");
7673 }
445c2480
DS
7674 } else if (safi == SAFI_EVPN) {
7675 if (json_paths) {
7676 json_nexthop_global = json_object_new_object();
7677
515c2602
DA
7678 json_object_string_add(json_nexthop_global, "ip",
7679 inet_ntoa(attr->nexthop));
7680
939a97f4 7681 if (path->peer->hostname)
515c2602
DA
7682 json_object_string_add(json_nexthop_global,
7683 "hostname",
939a97f4 7684 path->peer->hostname);
515c2602 7685
a4d82a8a
PZ
7686 json_object_string_add(json_nexthop_global, "afi",
7687 "ipv4");
445c2480
DS
7688 json_object_boolean_true_add(json_nexthop_global,
7689 "used");
aef999a2
DA
7690 } else {
7691 if (nexthop_hostname)
7692 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7693 nexthop_hostname, vrf_id_str);
7694 else
7695 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7696 vrf_id_str);
7697
ae248832 7698 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7699 if (len < 1)
7700 vty_out(vty, "\n%*s", 36, " ");
7701 else
7702 vty_out(vty, "%*s", len, " ");
7703 }
d33fc23b 7704 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7705 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7706 if (json_paths) {
7707 json_nexthop_global = json_object_new_object();
515c2602 7708
026b914a
PG
7709 json_object_string_add(json_nexthop_global,
7710 "afi", "ipv4");
515c2602
DA
7711 json_object_string_add(
7712 json_nexthop_global, "ip",
7713 inet_ntoa(attr->nexthop));
7714
939a97f4 7715 if (path->peer->hostname)
515c2602
DA
7716 json_object_string_add(
7717 json_nexthop_global, "hostname",
939a97f4 7718 path->peer->hostname);
515c2602 7719
50e05855
AD
7720 json_object_boolean_true_add(
7721 json_nexthop_global,
026b914a
PG
7722 "used");
7723 } else {
aef999a2
DA
7724 if (nexthop_hostname)
7725 len = vty_out(vty, "%pI4(%s)%s",
7726 &attr->nexthop,
7727 nexthop_hostname,
7728 vrf_id_str);
7729 else
7730 len = vty_out(vty, "%pI4%s",
7731 &attr->nexthop,
7732 vrf_id_str);
7733
ae248832 7734 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7735 if (len < 1)
7736 vty_out(vty, "\n%*s", 36, " ");
7737 else
7738 vty_out(vty, "%*s", len, " ");
026b914a
PG
7739 }
7740 }
d33fc23b 7741 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7742 if (json_paths) {
7743 json_nexthop_global = json_object_new_object();
d62a17ae 7744
515c2602
DA
7745 json_object_string_add(json_nexthop_global, "ip",
7746 inet_ntoa(attr->nexthop));
7747
939a97f4 7748 if (path->peer->hostname)
515c2602
DA
7749 json_object_string_add(json_nexthop_global,
7750 "hostname",
939a97f4 7751 path->peer->hostname);
445c2480 7752
a4d82a8a
PZ
7753 json_object_string_add(json_nexthop_global, "afi",
7754 "ipv4");
445c2480
DS
7755 json_object_boolean_true_add(json_nexthop_global,
7756 "used");
7757 } else {
aef999a2
DA
7758 if (nexthop_hostname)
7759 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7760 nexthop_hostname, vrf_id_str);
7761 else
7762 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7763 vrf_id_str);
9df8b37c 7764
ae248832 7765 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7766 if (len < 1)
7767 vty_out(vty, "\n%*s", 36, " ");
7768 else
7769 vty_out(vty, "%*s", len, " ");
d62a17ae 7770 }
445c2480 7771 }
b05a1c8b 7772
445c2480 7773 /* IPv6 Next Hop */
a4d82a8a 7774 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 7775 char buf[BUFSIZ];
d62a17ae 7776
445c2480
DS
7777 if (json_paths) {
7778 json_nexthop_global = json_object_new_object();
a4d82a8a 7779 json_object_string_add(
515c2602
DA
7780 json_nexthop_global, "ip",
7781 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7782 buf, BUFSIZ));
7783
939a97f4 7784 if (path->peer->hostname)
515c2602
DA
7785 json_object_string_add(json_nexthop_global,
7786 "hostname",
939a97f4 7787 path->peer->hostname);
515c2602 7788
a4d82a8a
PZ
7789 json_object_string_add(json_nexthop_global, "afi",
7790 "ipv6");
7791 json_object_string_add(json_nexthop_global, "scope",
7792 "global");
445c2480
DS
7793
7794 /* We display both LL & GL if both have been
7795 * received */
0606039c
DA
7796 if ((attr->mp_nexthop_len
7797 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7798 || (path->peer->conf_if)) {
a4d82a8a 7799 json_nexthop_ll = json_object_new_object();
d62a17ae 7800 json_object_string_add(
515c2602
DA
7801 json_nexthop_ll, "ip",
7802 inet_ntop(AF_INET6,
7803 &attr->mp_nexthop_local, buf,
7804 BUFSIZ));
7805
939a97f4 7806 if (path->peer->hostname)
515c2602
DA
7807 json_object_string_add(
7808 json_nexthop_ll, "hostname",
939a97f4 7809 path->peer->hostname);
515c2602 7810
a4d82a8a
PZ
7811 json_object_string_add(json_nexthop_ll, "afi",
7812 "ipv6");
7813 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7814 "link-local");
d62a17ae 7815
a4d82a8a
PZ
7816 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7817 &attr->mp_nexthop_local)
445c2480
DS
7818 != 0)
7819 && !attr->mp_nexthop_prefer_global)
d62a17ae 7820 json_object_boolean_true_add(
a4d82a8a 7821 json_nexthop_ll, "used");
445c2480
DS
7822 else
7823 json_object_boolean_true_add(
a4d82a8a 7824 json_nexthop_global, "used");
445c2480
DS
7825 } else
7826 json_object_boolean_true_add(
7827 json_nexthop_global, "used");
7828 } else {
7829 /* Display LL if LL/Global both in table unless
7830 * prefer-global is set */
0606039c
DA
7831 if (((attr->mp_nexthop_len
7832 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7833 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7834 || (path->peer->conf_if)) {
7835 if (path->peer->conf_if) {
a4d82a8a 7836 len = vty_out(vty, "%s",
9b6d8fcf 7837 path->peer->conf_if);
ae248832
MK
7838 /* len of IPv6 addr + max len of def
7839 * ifname */
7840 len = wide ? (41 - len) : (16 - len);
445c2480
DS
7841
7842 if (len < 1)
a4d82a8a 7843 vty_out(vty, "\n%*s", 36, " ");
445c2480 7844 else
a4d82a8a 7845 vty_out(vty, "%*s", len, " ");
d62a17ae 7846 } else {
aef999a2
DA
7847 if (nexthop_hostname)
7848 len = vty_out(
7849 vty, "%pI6(%s)%s",
7850 &attr->mp_nexthop_local,
7851 nexthop_hostname,
7852 vrf_id_str);
7853 else
7854 len = vty_out(
7855 vty, "%pI6%s",
7856 &attr->mp_nexthop_local,
7857 vrf_id_str);
7858
ae248832 7859 len = wide ? (41 - len) : (16 - len);
d62a17ae 7860
7861 if (len < 1)
a4d82a8a 7862 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7863 else
a4d82a8a 7864 vty_out(vty, "%*s", len, " ");
d62a17ae 7865 }
445c2480 7866 } else {
aef999a2
DA
7867 if (nexthop_hostname)
7868 len = vty_out(vty, "%pI6(%s)%s",
7869 &attr->mp_nexthop_global,
7870 nexthop_hostname,
7871 vrf_id_str);
7872 else
7873 len = vty_out(vty, "%pI6%s",
7874 &attr->mp_nexthop_global,
7875 vrf_id_str);
7876
ae248832 7877 len = wide ? (41 - len) : (16 - len);
445c2480
DS
7878
7879 if (len < 1)
7880 vty_out(vty, "\n%*s", 36, " ");
7881 else
7882 vty_out(vty, "%*s", len, " ");
d62a17ae 7883 }
7884 }
445c2480 7885 }
718e3744 7886
445c2480
DS
7887 /* MED/Metric */
7888 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 7889 if (json_paths)
50e05855 7890 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
7891 else if (wide)
7892 vty_out(vty, "%7u", attr->med);
0fbac0b4 7893 else
445c2480 7894 vty_out(vty, "%10u", attr->med);
ae248832
MK
7895 else if (!json_paths) {
7896 if (wide)
7897 vty_out(vty, "%*s", 7, " ");
7898 else
7899 vty_out(vty, "%*s", 10, " ");
7900 }
d62a17ae 7901
445c2480
DS
7902 /* Local Pref */
7903 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 7904 if (json_paths)
50e05855 7905 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
7906 attr->local_pref);
7907 else
445c2480
DS
7908 vty_out(vty, "%7u", attr->local_pref);
7909 else if (!json_paths)
7910 vty_out(vty, " ");
d62a17ae 7911
445c2480
DS
7912 if (json_paths)
7913 json_object_int_add(json_path, "weight", attr->weight);
7914 else
7915 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7916
445c2480
DS
7917 if (json_paths) {
7918 char buf[BUFSIZ];
a4d82a8a
PZ
7919 json_object_string_add(
7920 json_path, "peerId",
9b6d8fcf 7921 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7922 }
b05a1c8b 7923
445c2480
DS
7924 /* Print aspath */
7925 if (attr->aspath) {
0fbac0b4 7926 if (json_paths)
50e05855 7927 json_object_string_add(json_path, "path",
0fbac0b4
DA
7928 attr->aspath->str);
7929 else
445c2480 7930 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7931 }
f1aa5d8a 7932
445c2480
DS
7933 /* Print origin */
7934 if (json_paths)
a4d82a8a
PZ
7935 json_object_string_add(json_path, "origin",
7936 bgp_origin_long_str[attr->origin]);
445c2480
DS
7937 else
7938 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7939
9df8b37c 7940 if (json_paths) {
b5e140c8
AK
7941 if (memcmp(&attr->esi, zero_esi, sizeof(esi_t))) {
7942 json_object_string_add(json_path, "esi",
7943 esi_to_str(&attr->esi,
7944 esi_buf, sizeof(esi_buf)));
7945 }
6f214dd3
CS
7946 if (safi == SAFI_EVPN &&
7947 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7948 json_ext_community = json_object_new_object();
7949 json_object_string_add(json_ext_community,
7950 "string",
7951 attr->ecommunity->str);
7952 json_object_object_add(json_path,
7953 "extendedCommunity",
7954 json_ext_community);
7955 }
7956
9df8b37c
PZ
7957 if (nexthop_self)
7958 json_object_boolean_true_add(json_path,
7959 "announceNexthopSelf");
7960 if (nexthop_othervrf) {
7961 json_object_string_add(json_path, "nhVrfName",
7962 nexthop_vrfname);
7963
7964 json_object_int_add(json_path, "nhVrfId",
7965 ((nexthop_vrfid == VRF_UNKNOWN)
7966 ? -1
7967 : (int)nexthop_vrfid));
7968 }
7969 }
7970
d62a17ae 7971 if (json_paths) {
7972 if (json_nexthop_global || json_nexthop_ll) {
7973 json_nexthops = json_object_new_array();
f1aa5d8a 7974
d62a17ae 7975 if (json_nexthop_global)
7976 json_object_array_add(json_nexthops,
7977 json_nexthop_global);
f1aa5d8a 7978
d62a17ae 7979 if (json_nexthop_ll)
7980 json_object_array_add(json_nexthops,
7981 json_nexthop_ll);
f1aa5d8a 7982
d62a17ae 7983 json_object_object_add(json_path, "nexthops",
7984 json_nexthops);
7985 }
7986
7987 json_object_array_add(json_paths, json_path);
7988 } else {
7989 vty_out(vty, "\n");
6f214dd3 7990
b5e140c8
AK
7991 if (safi == SAFI_EVPN) {
7992 if (memcmp(&attr->esi, zero_esi, sizeof(esi_t))) {
7993 vty_out(vty, "%*s", 20, " ");
7994 vty_out(vty, "ESI:%s\n",
7995 esi_to_str(&attr->esi,
7996 esi_buf, sizeof(esi_buf)));
7997 }
7998 if (attr->flag &
7999 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8000 vty_out(vty, "%*s", 20, " ");
8001 vty_out(vty, "%s\n", attr->ecommunity->str);
8002 }
6f214dd3
CS
8003 }
8004
49e5a4a0 8005#ifdef ENABLE_BGP_VNC
d62a17ae 8006 /* prints an additional line, indented, with VNC info, if
8007 * present */
8008 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8009 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8010#endif
d62a17ae 8011 }
8012}
718e3744 8013
8014/* called from terminal list command */
5f040085
DS
8015void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8016 struct attr *attr, safi_t safi, bool use_json,
ae248832 8017 json_object *json_ar, bool wide)
d62a17ae 8018{
8019 json_object *json_status = NULL;
8020 json_object *json_net = NULL;
aef999a2 8021 int len;
d62a17ae 8022 char buff[BUFSIZ];
dc387b0f 8023
d62a17ae 8024 /* Route status display. */
8025 if (use_json) {
8026 json_status = json_object_new_object();
8027 json_net = json_object_new_object();
8028 } else {
8029 vty_out(vty, "*");
8030 vty_out(vty, ">");
8031 vty_out(vty, " ");
8032 }
718e3744 8033
d62a17ae 8034 /* print prefix and mask */
50e05855 8035 if (use_json) {
dc387b0f
LK
8036 if (safi == SAFI_EVPN)
8037 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8038 else if (p->family == AF_INET || p->family == AF_INET6) {
8039 json_object_string_add(
8040 json_net, "addrPrefix",
8041 inet_ntop(p->family, &p->u.prefix, buff,
8042 BUFSIZ));
8043 json_object_int_add(json_net, "prefixLen",
8044 p->prefixlen);
8045 prefix2str(p, buff, PREFIX_STRLEN);
8046 json_object_string_add(json_net, "network", buff);
8047 }
50e05855 8048 } else
ae248832 8049 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8050
8051 /* Print attribute */
8052 if (attr) {
8053 if (use_json) {
8054 if (p->family == AF_INET
8055 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8056 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8057 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8058 json_object_string_add(
8059 json_net, "nextHop",
8060 inet_ntoa(
8061 attr->mp_nexthop_global_in));
8062 else
8063 json_object_string_add(
8064 json_net, "nextHop",
8065 inet_ntoa(attr->nexthop));
8066 } else if (p->family == AF_INET6
8067 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8068 char buf[BUFSIZ];
8069
8070 json_object_string_add(
aa0a10fc 8071 json_net, "nextHopGlobal",
d62a17ae 8072 inet_ntop(AF_INET6,
8073 &attr->mp_nexthop_global, buf,
8074 BUFSIZ));
dc387b0f
LK
8075 } else if (p->family == AF_EVPN &&
8076 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8077 json_object_string_add(json_net,
8078 "nextHop", inet_ntoa(
8079 attr->mp_nexthop_global_in));
d62a17ae 8080
8081 if (attr->flag
8082 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8083 json_object_int_add(json_net, "metric",
8084 attr->med);
8085
0fbac0b4 8086 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8087 json_object_int_add(json_net, "locPrf",
0fbac0b4 8088 attr->local_pref);
d62a17ae 8089
8090 json_object_int_add(json_net, "weight", attr->weight);
8091
8092 /* Print aspath */
0fbac0b4 8093 if (attr->aspath)
50e05855 8094 json_object_string_add(json_net, "path",
0fbac0b4 8095 attr->aspath->str);
d62a17ae 8096
8097 /* Print origin */
8098 json_object_string_add(json_net, "bgpOriginCode",
8099 bgp_origin_str[attr->origin]);
8100 } else {
8101 if (p->family == AF_INET
8102 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8103 || safi == SAFI_EVPN
8104 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8105 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8106 || safi == SAFI_EVPN)
8107 vty_out(vty, "%-16s",
8108 inet_ntoa(
8109 attr->mp_nexthop_global_in));
ae248832
MK
8110 else if (wide)
8111 vty_out(vty, "%-41s",
8112 inet_ntoa(attr->nexthop));
d62a17ae 8113 else
8114 vty_out(vty, "%-16s",
8115 inet_ntoa(attr->nexthop));
8116 } else if (p->family == AF_INET6
8117 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8118 char buf[BUFSIZ];
8119
8120 len = vty_out(
8121 vty, "%s",
8122 inet_ntop(AF_INET6,
8123 &attr->mp_nexthop_global, buf,
8124 BUFSIZ));
ae248832 8125 len = wide ? (41 - len) : (16 - len);
d62a17ae 8126 if (len < 1)
8127 vty_out(vty, "\n%*s", 36, " ");
8128 else
8129 vty_out(vty, "%*s", len, " ");
8130 }
8131 if (attr->flag
8132 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8133 if (wide)
8134 vty_out(vty, "%7u", attr->med);
8135 else
8136 vty_out(vty, "%10u", attr->med);
8137 else if (wide)
8138 vty_out(vty, " ");
d62a17ae 8139 else
8140 vty_out(vty, " ");
718e3744 8141
d62a17ae 8142 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8143 vty_out(vty, "%7u", attr->local_pref);
8144 else
8145 vty_out(vty, " ");
8146
8147 vty_out(vty, "%7u ", attr->weight);
8148
8149 /* Print aspath */
8150 if (attr->aspath)
8151 aspath_print_vty(vty, "%s", attr->aspath, " ");
8152
8153 /* Print origin */
8154 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8155 }
8156 }
8157 if (use_json) {
8158 json_object_boolean_true_add(json_status, "*");
8159 json_object_boolean_true_add(json_status, ">");
8160 json_object_object_add(json_net, "appliedStatusSymbols",
8161 json_status);
1608ff77 8162
dc387b0f
LK
8163 prefix2str(p, buff, PREFIX_STRLEN);
8164 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8165 } else
8166 vty_out(vty, "\n");
8167}
8168
bd494ec5 8169void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8170 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8171 json_object *json)
8172{
8173 json_object *json_out = NULL;
8174 struct attr *attr;
8175 mpls_label_t label = MPLS_INVALID_LABEL;
8176
9b6d8fcf 8177 if (!path->extra)
d62a17ae 8178 return;
8179
8180 if (json)
8181 json_out = json_object_new_object();
8182
8183 /* short status lead text */
9b6d8fcf 8184 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8185
8186 /* print prefix and mask */
8187 if (json == NULL) {
8188 if (!display)
ae248832 8189 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8190 else
8191 vty_out(vty, "%*s", 17, " ");
8192 }
8193
8194 /* Print attribute */
9b6d8fcf 8195 attr = path->attr;
05864da7
DS
8196 if (((p->family == AF_INET)
8197 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8198 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8199 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8200 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8201 || safi == SAFI_EVPN) {
8202 if (json)
8203 json_object_string_add(
8204 json_out, "mpNexthopGlobalIn",
8205 inet_ntoa(attr->mp_nexthop_global_in));
8206 else
8207 vty_out(vty, "%-16s",
8208 inet_ntoa(attr->mp_nexthop_global_in));
8209 } else {
8210 if (json)
8211 json_object_string_add(
8212 json_out, "nexthop",
8213 inet_ntoa(attr->nexthop));
8214 else
8215 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8216 }
8217 } else if (((p->family == AF_INET6)
8218 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8219 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8220 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8221 char buf_a[512];
8222
8223 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8224 if (json)
8225 json_object_string_add(
8226 json_out, "mpNexthopGlobalIn",
8227 inet_ntop(AF_INET6,
8228 &attr->mp_nexthop_global,
8229 buf_a, sizeof(buf_a)));
8230 else
8231 vty_out(vty, "%s",
8232 inet_ntop(AF_INET6,
8233 &attr->mp_nexthop_global,
8234 buf_a, sizeof(buf_a)));
8235 } else if (attr->mp_nexthop_len
8236 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8237 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8238 &attr->mp_nexthop_global,
8239 &attr->mp_nexthop_local);
8240 if (json)
8241 json_object_string_add(json_out,
8242 "mpNexthopGlobalLocal",
8243 buf_a);
8244 else
8245 vty_out(vty, "%s", buf_a);
d62a17ae 8246 }
8247 }
8248
9b6d8fcf 8249 label = decode_label(&path->extra->label[0]);
d62a17ae 8250
8251 if (bgp_is_valid_label(&label)) {
8252 if (json) {
8253 json_object_int_add(json_out, "notag", label);
8254 json_object_array_add(json, json_out);
8255 } else {
8256 vty_out(vty, "notag/%d", label);
8257 vty_out(vty, "\n");
8258 }
8259 }
8260}
718e3744 8261
bd494ec5 8262void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8263 struct bgp_path_info *path, int display,
d62a17ae 8264 json_object *json_paths)
718e3744 8265{
d62a17ae 8266 struct attr *attr;
14f51eba 8267 char buf[BUFSIZ] = {0};
d62a17ae 8268 json_object *json_path = NULL;
14f51eba
LK
8269 json_object *json_nexthop = NULL;
8270 json_object *json_overlay = NULL;
856ca177 8271
9b6d8fcf 8272 if (!path->extra)
d62a17ae 8273 return;
718e3744 8274
14f51eba
LK
8275 if (json_paths) {
8276 json_path = json_object_new_object();
8277 json_overlay = json_object_new_object();
8278 json_nexthop = json_object_new_object();
8279 }
8280
d62a17ae 8281 /* short status lead text */
9b6d8fcf 8282 route_vty_short_status_out(vty, path, json_path);
856ca177 8283
d62a17ae 8284 /* print prefix and mask */
8285 if (!display)
ae248832 8286 route_vty_out_route(p, vty, json_path, false);
d62a17ae 8287 else
8288 vty_out(vty, "%*s", 17, " ");
8289
8290 /* Print attribute */
9b6d8fcf 8291 attr = path->attr;
05864da7
DS
8292 char buf1[BUFSIZ];
8293 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8294
05864da7
DS
8295 switch (af) {
8296 case AF_INET:
8297 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8298 if (!json_path) {
8299 vty_out(vty, "%-16s", buf);
8300 } else {
8301 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8302
05864da7 8303 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8304
05864da7
DS
8305 json_object_object_add(json_path, "nexthop",
8306 json_nexthop);
8307 }
8308 break;
8309 case AF_INET6:
8310 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8311 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8312 if (!json_path) {
8313 vty_out(vty, "%s(%s)", buf, buf1);
8314 } else {
8315 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8316
05864da7
DS
8317 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8318 buf1);
14f51eba 8319
05864da7 8320 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8321
05864da7
DS
8322 json_object_object_add(json_path, "nexthop",
8323 json_nexthop);
8324 }
8325 break;
8326 default:
8327 if (!json_path) {
8328 vty_out(vty, "?");
8329 } else {
8330 json_object_string_add(json_nexthop, "Error",
8331 "Unsupported address-family");
d62a17ae 8332 }
05864da7 8333 }
988258b4 8334
05864da7
DS
8335 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8336 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8337 BUFSIZ);
8338 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8339 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8340 BUFSIZ);
8341 }
14f51eba 8342
05864da7
DS
8343 if (!json_path)
8344 vty_out(vty, "/%s", buf);
8345 else
8346 json_object_string_add(json_overlay, "gw", buf);
8347
8348 if (attr->ecommunity) {
8349 char *mac = NULL;
8350 struct ecommunity_val *routermac = ecommunity_lookup(
8351 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8352 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8353
8354 if (routermac)
8355 mac = ecom_mac2str((char *)routermac->val);
8356 if (mac) {
8357 if (!json_path) {
c4efd0f4 8358 vty_out(vty, "/%s", mac);
05864da7
DS
8359 } else {
8360 json_object_string_add(json_overlay, "rmac",
8361 mac);
988258b4 8362 }
05864da7 8363 XFREE(MTYPE_TMP, mac);
988258b4 8364 }
05864da7 8365 }
718e3744 8366
05864da7
DS
8367 if (!json_path) {
8368 vty_out(vty, "\n");
8369 } else {
8370 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8371
05864da7 8372 json_object_array_add(json_paths, json_path);
14f51eba 8373 }
d62a17ae 8374}
718e3744 8375
d62a17ae 8376/* dampening route */
5f040085
DS
8377static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8378 struct bgp_path_info *path, int display,
8379 afi_t afi, safi_t safi, bool use_json,
8380 json_object *json)
d62a17ae 8381{
8382 struct attr *attr;
8383 int len;
8384 char timebuf[BGP_UPTIME_LEN];
8385
8386 /* short status lead text */
9b6d8fcf 8387 route_vty_short_status_out(vty, path, json);
d62a17ae 8388
8389 /* print prefix and mask */
8390 if (!use_json) {
8391 if (!display)
ae248832 8392 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8393 else
8394 vty_out(vty, "%*s", 17, " ");
8395 }
8396
9b6d8fcf 8397 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8398 len = 17 - len;
8399 if (len < 1) {
8400 if (!use_json)
8401 vty_out(vty, "\n%*s", 34, " ");
8402 } else {
8403 if (use_json)
8404 json_object_int_add(json, "peerHost", len);
8405 else
8406 vty_out(vty, "%*s", len, " ");
8407 }
8408
8409 if (use_json)
a935f597
DA
8410 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8411 safi, use_json, json);
d62a17ae 8412 else
9b6d8fcf
DS
8413 vty_out(vty, "%s ",
8414 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8415 BGP_UPTIME_LEN, afi, safi,
8416 use_json, json));
d62a17ae 8417
8418 /* Print attribute */
9b6d8fcf 8419 attr = path->attr;
d62a17ae 8420
05864da7
DS
8421 /* Print aspath */
8422 if (attr->aspath) {
d62a17ae 8423 if (use_json)
05864da7
DS
8424 json_object_string_add(json, "asPath",
8425 attr->aspath->str);
d62a17ae 8426 else
05864da7 8427 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8428 }
05864da7
DS
8429
8430 /* Print origin */
8431 if (use_json)
8432 json_object_string_add(json, "origin",
8433 bgp_origin_str[attr->origin]);
8434 else
8435 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8436
d62a17ae 8437 if (!use_json)
8438 vty_out(vty, "\n");
8439}
718e3744 8440
d62a17ae 8441/* flap route */
5f040085
DS
8442static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
8443 struct bgp_path_info *path, int display,
8444 afi_t afi, safi_t safi, bool use_json,
8445 json_object *json)
784d3a42 8446{
d62a17ae 8447 struct attr *attr;
8448 struct bgp_damp_info *bdi;
8449 char timebuf[BGP_UPTIME_LEN];
8450 int len;
784d3a42 8451
9b6d8fcf 8452 if (!path->extra)
d62a17ae 8453 return;
784d3a42 8454
9b6d8fcf 8455 bdi = path->extra->damp_info;
784d3a42 8456
d62a17ae 8457 /* short status lead text */
9b6d8fcf 8458 route_vty_short_status_out(vty, path, json);
784d3a42 8459
d62a17ae 8460 /* print prefix and mask */
8461 if (!use_json) {
8462 if (!display)
ae248832 8463 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8464 else
8465 vty_out(vty, "%*s", 17, " ");
8466 }
784d3a42 8467
9b6d8fcf 8468 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8469 len = 16 - len;
8470 if (len < 1) {
8471 if (!use_json)
8472 vty_out(vty, "\n%*s", 33, " ");
8473 } else {
8474 if (use_json)
8475 json_object_int_add(json, "peerHost", len);
8476 else
8477 vty_out(vty, "%*s", len, " ");
8478 }
784d3a42 8479
d62a17ae 8480 len = vty_out(vty, "%d", bdi->flap);
8481 len = 5 - len;
8482 if (len < 1) {
8483 if (!use_json)
8484 vty_out(vty, " ");
8485 } else {
8486 if (use_json)
8487 json_object_int_add(json, "bdiFlap", len);
8488 else
8489 vty_out(vty, "%*s", len, " ");
8490 }
8491
8492 if (use_json)
8493 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8494 json);
8495 else
996c9314
LB
8496 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8497 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8498
9b6d8fcf
DS
8499 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8500 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8501 if (use_json)
9b6d8fcf 8502 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8503 BGP_UPTIME_LEN, afi, safi,
8504 use_json, json);
d62a17ae 8505 else
8506 vty_out(vty, "%s ",
9b6d8fcf 8507 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8508 BGP_UPTIME_LEN, afi,
8509 safi, use_json, json));
d62a17ae 8510 } else {
8511 if (!use_json)
8512 vty_out(vty, "%*s ", 8, " ");
8513 }
8514
8515 /* Print attribute */
9b6d8fcf 8516 attr = path->attr;
d62a17ae 8517
05864da7
DS
8518 /* Print aspath */
8519 if (attr->aspath) {
d62a17ae 8520 if (use_json)
05864da7
DS
8521 json_object_string_add(json, "asPath",
8522 attr->aspath->str);
d62a17ae 8523 else
05864da7 8524 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8525 }
05864da7
DS
8526
8527 /* Print origin */
8528 if (use_json)
8529 json_object_string_add(json, "origin",
8530 bgp_origin_str[attr->origin]);
8531 else
8532 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8533
d62a17ae 8534 if (!use_json)
8535 vty_out(vty, "\n");
8536}
8537
8538static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8539 int *first, const char *header,
8540 json_object *json_adv_to)
8541{
8542 char buf1[INET6_ADDRSTRLEN];
8543 json_object *json_peer = NULL;
8544
8545 if (json_adv_to) {
8546 /* 'advertised-to' is a dictionary of peers we have advertised
8547 * this
8548 * prefix too. The key is the peer's IP or swpX, the value is
8549 * the
8550 * hostname if we know it and "" if not.
8551 */
8552 json_peer = json_object_new_object();
8553
8554 if (peer->hostname)
8555 json_object_string_add(json_peer, "hostname",
8556 peer->hostname);
8557
8558 if (peer->conf_if)
8559 json_object_object_add(json_adv_to, peer->conf_if,
8560 json_peer);
8561 else
8562 json_object_object_add(
8563 json_adv_to,
8564 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8565 json_peer);
8566 } else {
8567 if (*first) {
8568 vty_out(vty, "%s", header);
8569 *first = 0;
8570 }
8571
8572 if (peer->hostname
892fedb6 8573 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8574 if (peer->conf_if)
8575 vty_out(vty, " %s(%s)", peer->hostname,
8576 peer->conf_if);
8577 else
8578 vty_out(vty, " %s(%s)", peer->hostname,
8579 sockunion2str(&peer->su, buf1,
8580 SU_ADDRSTRLEN));
8581 } else {
8582 if (peer->conf_if)
8583 vty_out(vty, " %s", peer->conf_if);
8584 else
8585 vty_out(vty, " %s",
8586 sockunion2str(&peer->su, buf1,
8587 SU_ADDRSTRLEN));
8588 }
8589 }
784d3a42
PG
8590}
8591
dcc68b5e
MS
8592static void route_vty_out_tx_ids(struct vty *vty,
8593 struct bgp_addpath_info_data *d)
8594{
8595 int i;
8596
8597 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8598 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8599 d->addpath_tx_id[i],
8600 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8601 }
8602}
8603
0dc8ee70
DS
8604static const char *bgp_path_selection_reason2str(
8605 enum bgp_path_selection_reason reason)
8606{
8607 switch (reason) {
8608 case bgp_path_selection_none:
8609 return "Nothing to Select";
0dc8ee70
DS
8610 case bgp_path_selection_first:
8611 return "First path received";
0dc8ee70
DS
8612 case bgp_path_selection_evpn_sticky_mac:
8613 return "EVPN Sticky Mac";
0dc8ee70
DS
8614 case bgp_path_selection_evpn_seq:
8615 return "EVPN sequence number";
0dc8ee70
DS
8616 case bgp_path_selection_evpn_lower_ip:
8617 return "EVPN lower IP";
0dc8ee70
DS
8618 case bgp_path_selection_weight:
8619 return "Weight";
0dc8ee70
DS
8620 case bgp_path_selection_local_pref:
8621 return "Local Pref";
0dc8ee70
DS
8622 case bgp_path_selection_local_route:
8623 return "Local Route";
0dc8ee70
DS
8624 case bgp_path_selection_confed_as_path:
8625 return "Confederation based AS Path";
0dc8ee70
DS
8626 case bgp_path_selection_as_path:
8627 return "AS Path";
0dc8ee70
DS
8628 case bgp_path_selection_origin:
8629 return "Origin";
0dc8ee70
DS
8630 case bgp_path_selection_med:
8631 return "MED";
0dc8ee70
DS
8632 case bgp_path_selection_peer:
8633 return "Peer Type";
0dc8ee70
DS
8634 case bgp_path_selection_confed:
8635 return "Confed Peer Type";
0dc8ee70
DS
8636 case bgp_path_selection_igp_metric:
8637 return "IGP Metric";
0dc8ee70
DS
8638 case bgp_path_selection_older:
8639 return "Older Path";
0dc8ee70
DS
8640 case bgp_path_selection_router_id:
8641 return "Router ID";
0dc8ee70
DS
8642 case bgp_path_selection_cluster_length:
8643 return "Cluser length";
0dc8ee70
DS
8644 case bgp_path_selection_stale:
8645 return "Path Staleness";
0dc8ee70
DS
8646 case bgp_path_selection_local_configured:
8647 return "Locally configured route";
0dc8ee70
DS
8648 case bgp_path_selection_neighbor_ip:
8649 return "Neighbor IP";
0dc8ee70
DS
8650 case bgp_path_selection_default:
8651 return "Nothing left to compare";
0dc8ee70 8652 }
a74879b2 8653 return "Invalid (internal error)";
0dc8ee70
DS
8654}
8655
9bcb3eef
DS
8656void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
8657 struct bgp_path_info *path, afi_t afi, safi_t safi,
8658 json_object *json_paths)
d62a17ae 8659{
8660 char buf[INET6_ADDRSTRLEN];
8661 char buf1[BUFSIZ];
d62a17ae 8662 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8663 struct attr *attr = path->attr;
d62a17ae 8664 int sockunion_vty_out(struct vty *, union sockunion *);
8665 time_t tbuf;
8666 json_object *json_bestpath = NULL;
8667 json_object *json_cluster_list = NULL;
8668 json_object *json_cluster_list_list = NULL;
8669 json_object *json_ext_community = NULL;
8670 json_object *json_last_update = NULL;
7fd077aa 8671 json_object *json_pmsi = NULL;
d62a17ae 8672 json_object *json_nexthop_global = NULL;
8673 json_object *json_nexthop_ll = NULL;
8674 json_object *json_nexthops = NULL;
8675 json_object *json_path = NULL;
8676 json_object *json_peer = NULL;
8677 json_object *json_string = NULL;
8678 json_object *json_adv_to = NULL;
8679 int first = 0;
8680 struct listnode *node, *nnode;
8681 struct peer *peer;
8682 int addpath_capable;
8683 int has_adj;
8684 unsigned int first_as;
1defdda8 8685 bool nexthop_self =
9b6d8fcf 8686 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8687 int i;
2ba93fd6
DA
8688 char *nexthop_hostname =
8689 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 8690
8691 if (json_paths) {
8692 json_path = json_object_new_object();
8693 json_peer = json_object_new_object();
8694 json_nexthop_global = json_object_new_object();
8695 }
8696
44c69747 8697 if (path->extra) {
b57ba6d2 8698 char tag_buf[30];
d62a17ae 8699
d7325ee7 8700 buf2[0] = '\0';
d62a17ae 8701 tag_buf[0] = '\0';
9b6d8fcf
DS
8702 if (path->extra && path->extra->num_labels) {
8703 bgp_evpn_label2str(path->extra->label,
8704 path->extra->num_labels, tag_buf,
a4d82a8a 8705 sizeof(tag_buf));
d62a17ae 8706 }
d7325ee7 8707 if (safi == SAFI_EVPN) {
44c69747 8708 if (!json_paths) {
b54892e0
DS
8709 bgp_evpn_route2str(
8710 (struct prefix_evpn *)
9bcb3eef 8711 bgp_dest_get_prefix(bn),
b54892e0 8712 buf2, sizeof(buf2));
44c69747
LK
8713 vty_out(vty, " Route %s", buf2);
8714 if (tag_buf[0] != '\0')
8715 vty_out(vty, " VNI %s", tag_buf);
8716 vty_out(vty, "\n");
8717 } else {
8718 if (tag_buf[0])
8719 json_object_string_add(json_path, "VNI",
8720 tag_buf);
8721 }
d7325ee7
DD
8722 }
8723
44c69747 8724 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8725 struct bgp_path_info *parent_ri;
9bcb3eef 8726 struct bgp_dest *dest, *pdest;
d62a17ae 8727
9b6d8fcf 8728 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
8729 dest = parent_ri->net;
8730 if (dest && dest->pdest) {
8731 pdest = dest->pdest;
8732 prefix_rd2str(
8733 (struct prefix_rd *)bgp_dest_get_prefix(
8734 pdest),
8735 buf1, sizeof(buf1));
d7325ee7 8736 if (is_pi_family_evpn(parent_ri)) {
b54892e0
DS
8737 bgp_evpn_route2str(
8738 (struct prefix_evpn *)
9bcb3eef
DS
8739 bgp_dest_get_prefix(
8740 dest),
b54892e0 8741 buf2, sizeof(buf2));
d7325ee7
DD
8742 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8743 } else
8744 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8745 }
8746 }
8747 }
d62a17ae 8748
05864da7
DS
8749 /* Line1 display AS-path, Aggregator */
8750 if (attr->aspath) {
8751 if (json_paths) {
8752 if (!attr->aspath->json)
8753 aspath_str_update(attr->aspath, true);
8754 json_object_lock(attr->aspath->json);
8755 json_object_object_add(json_path, "aspath",
8756 attr->aspath->json);
8757 } else {
8758 if (attr->aspath->segments)
8759 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8760 else
05864da7 8761 vty_out(vty, " Local");
d62a17ae 8762 }
05864da7 8763 }
d62a17ae 8764
05864da7
DS
8765 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8766 if (json_paths)
8767 json_object_boolean_true_add(json_path, "removed");
8768 else
8769 vty_out(vty, ", (removed)");
8770 }
d62a17ae 8771
05864da7
DS
8772 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8773 if (json_paths)
8774 json_object_boolean_true_add(json_path, "stale");
8775 else
8776 vty_out(vty, ", (stale)");
8777 }
d62a17ae 8778
05864da7
DS
8779 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8780 if (json_paths) {
8781 json_object_int_add(json_path, "aggregatorAs",
8782 attr->aggregator_as);
8783 json_object_string_add(
8784 json_path, "aggregatorId",
8785 inet_ntoa(attr->aggregator_addr));
87c82131
DA
8786 if (attr->aggregator_as == BGP_AS_ZERO)
8787 json_object_boolean_true_add(
8788 json_path, "aggregatorAsMalformed");
8789 else
8790 json_object_boolean_false_add(
8791 json_path, "aggregatorAsMalformed");
05864da7 8792 } else {
87c82131
DA
8793 if (attr->aggregator_as == BGP_AS_ZERO)
8794 vty_out(vty,
8795 ", (aggregated by %u(malformed) %s)",
8796 attr->aggregator_as,
8797 inet_ntoa(attr->aggregator_addr));
8798 else
8799 vty_out(vty, ", (aggregated by %u %s)",
8800 attr->aggregator_as,
8801 inet_ntoa(attr->aggregator_addr));
d62a17ae 8802 }
05864da7 8803 }
d62a17ae 8804
05864da7
DS
8805 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8806 PEER_FLAG_REFLECTOR_CLIENT)) {
8807 if (json_paths)
8808 json_object_boolean_true_add(json_path,
8809 "rxedFromRrClient");
8810 else
8811 vty_out(vty, ", (Received from a RR-client)");
8812 }
d62a17ae 8813
05864da7
DS
8814 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8815 PEER_FLAG_RSERVER_CLIENT)) {
8816 if (json_paths)
8817 json_object_boolean_true_add(json_path,
8818 "rxedFromRsClient");
8819 else
8820 vty_out(vty, ", (Received from a RS-client)");
8821 }
d62a17ae 8822
05864da7
DS
8823 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8824 if (json_paths)
8825 json_object_boolean_true_add(json_path,
8826 "dampeningHistoryEntry");
8827 else
8828 vty_out(vty, ", (history entry)");
8829 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8830 if (json_paths)
8831 json_object_boolean_true_add(json_path,
8832 "dampeningSuppressed");
8833 else
8834 vty_out(vty, ", (suppressed due to dampening)");
8835 }
d62a17ae 8836
05864da7
DS
8837 if (!json_paths)
8838 vty_out(vty, "\n");
d62a17ae 8839
05864da7
DS
8840 /* Line2 display Next-hop, Neighbor, Router-id */
8841 /* Display the nexthop */
9bcb3eef 8842 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
8843
8844 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
8845 || bn_p->family == AF_EVPN)
05864da7
DS
8846 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8847 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8848 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8849 || safi == SAFI_EVPN) {
515c2602 8850 if (json_paths) {
d62a17ae 8851 json_object_string_add(
515c2602
DA
8852 json_nexthop_global, "ip",
8853 inet_ntoa(attr->mp_nexthop_global_in));
8854
939a97f4 8855 if (path->peer->hostname)
515c2602
DA
8856 json_object_string_add(
8857 json_nexthop_global, "hostname",
939a97f4 8858 path->peer->hostname);
aef999a2
DA
8859 } else {
8860 if (nexthop_hostname)
8861 vty_out(vty, " %pI4(%s)",
8862 &attr->mp_nexthop_global_in,
8863 nexthop_hostname);
8864 else
8865 vty_out(vty, " %pI4",
8866 &attr->mp_nexthop_global_in);
8867 }
d62a17ae 8868 } else {
515c2602 8869 if (json_paths) {
05864da7 8870 json_object_string_add(
515c2602
DA
8871 json_nexthop_global, "ip",
8872 inet_ntoa(attr->nexthop));
8873
939a97f4 8874 if (path->peer->hostname)
515c2602
DA
8875 json_object_string_add(
8876 json_nexthop_global, "hostname",
939a97f4 8877 path->peer->hostname);
aef999a2
DA
8878 } else {
8879 if (nexthop_hostname)
8880 vty_out(vty, " %pI4(%s)",
8881 &attr->nexthop,
8882 nexthop_hostname);
8883 else
8884 vty_out(vty, " %pI4",
8885 &attr->nexthop);
8886 }
d62a17ae 8887 }
8888
05864da7
DS
8889 if (json_paths)
8890 json_object_string_add(json_nexthop_global, "afi",
8891 "ipv4");
8892 } else {
8893 if (json_paths) {
8894 json_object_string_add(
515c2602
DA
8895 json_nexthop_global, "ip",
8896 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8897 buf, INET6_ADDRSTRLEN));
8898
939a97f4 8899 if (path->peer->hostname)
515c2602
DA
8900 json_object_string_add(json_nexthop_global,
8901 "hostname",
939a97f4 8902 path->peer->hostname);
515c2602 8903
05864da7
DS
8904 json_object_string_add(json_nexthop_global, "afi",
8905 "ipv6");
8906 json_object_string_add(json_nexthop_global, "scope",
8907 "global");
8908 } else {
aef999a2
DA
8909 if (nexthop_hostname)
8910 vty_out(vty, " %pI6(%s)",
8911 &attr->mp_nexthop_global,
8912 nexthop_hostname);
8913 else
8914 vty_out(vty, " %pI6",
8915 &attr->mp_nexthop_global);
d62a17ae 8916 }
05864da7 8917 }
d62a17ae 8918
05864da7
DS
8919 /* Display the IGP cost or 'inaccessible' */
8920 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8921 if (json_paths)
8922 json_object_boolean_false_add(json_nexthop_global,
8923 "accessible");
8924 else
8925 vty_out(vty, " (inaccessible)");
8926 } else {
8927 if (path->extra && path->extra->igpmetric) {
d62a17ae 8928 if (json_paths)
05864da7
DS
8929 json_object_int_add(json_nexthop_global,
8930 "metric",
8931 path->extra->igpmetric);
d62a17ae 8932 else
05864da7
DS
8933 vty_out(vty, " (metric %u)",
8934 path->extra->igpmetric);
d62a17ae 8935 }
8936
05864da7 8937 /* IGP cost is 0, display this only for json */
d62a17ae 8938 else {
d62a17ae 8939 if (json_paths)
05864da7
DS
8940 json_object_int_add(json_nexthop_global,
8941 "metric", 0);
d62a17ae 8942 }
d62a17ae 8943
05864da7
DS
8944 if (json_paths)
8945 json_object_boolean_true_add(json_nexthop_global,
8946 "accessible");
8947 }
d62a17ae 8948
05864da7
DS
8949 /* Display peer "from" output */
8950 /* This path was originated locally */
8951 if (path->peer == bgp->peer_self) {
d62a17ae 8952
05864da7 8953 if (safi == SAFI_EVPN
b54892e0 8954 || (bn_p->family == AF_INET
05864da7 8955 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8956 if (json_paths)
05864da7
DS
8957 json_object_string_add(json_peer, "peerId",
8958 "0.0.0.0");
d62a17ae 8959 else
05864da7
DS
8960 vty_out(vty, " from 0.0.0.0 ");
8961 } else {
d62a17ae 8962 if (json_paths)
05864da7
DS
8963 json_object_string_add(json_peer, "peerId",
8964 "::");
d62a17ae 8965 else
05864da7 8966 vty_out(vty, " from :: ");
d62a17ae 8967 }
d62a17ae 8968
05864da7
DS
8969 if (json_paths)
8970 json_object_string_add(json_peer, "routerId",
8971 inet_ntoa(bgp->router_id));
8972 else
8973 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8974 }
d62a17ae 8975
05864da7
DS
8976 /* We RXed this path from one of our peers */
8977 else {
8978
8979 if (json_paths) {
8980 json_object_string_add(json_peer, "peerId",
8981 sockunion2str(&path->peer->su,
8982 buf,
8983 SU_ADDRSTRLEN));
8984 json_object_string_add(json_peer, "routerId",
8985 inet_ntop(AF_INET,
8986 &path->peer->remote_id,
8987 buf1, sizeof(buf1)));
8988
8989 if (path->peer->hostname)
8990 json_object_string_add(json_peer, "hostname",
8991 path->peer->hostname);
8992
8993 if (path->peer->domainname)
8994 json_object_string_add(json_peer, "domainname",
8995 path->peer->domainname);
8996
8997 if (path->peer->conf_if)
8998 json_object_string_add(json_peer, "interface",
8999 path->peer->conf_if);
9000 } else {
9001 if (path->peer->conf_if) {
9002 if (path->peer->hostname
892fedb6
DA
9003 && CHECK_FLAG(path->peer->bgp->flags,
9004 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9005 vty_out(vty, " from %s(%s)",
9006 path->peer->hostname,
9007 path->peer->conf_if);
d62a17ae 9008 else
05864da7 9009 vty_out(vty, " from %s",
9b6d8fcf 9010 path->peer->conf_if);
d62a17ae 9011 } else {
05864da7 9012 if (path->peer->hostname
892fedb6
DA
9013 && CHECK_FLAG(path->peer->bgp->flags,
9014 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9015 vty_out(vty, " from %s(%s)",
9016 path->peer->hostname,
9017 path->peer->host);
d62a17ae 9018 else
05864da7
DS
9019 vty_out(vty, " from %s",
9020 sockunion2str(&path->peer->su,
9021 buf,
9022 SU_ADDRSTRLEN));
d62a17ae 9023 }
d62a17ae 9024
05864da7
DS
9025 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9026 vty_out(vty, " (%s)",
9027 inet_ntoa(attr->originator_id));
9028 else
9029 vty_out(vty, " (%s)",
9030 inet_ntop(AF_INET,
9031 &path->peer->remote_id, buf1,
9032 sizeof(buf1)));
d62a17ae 9033 }
05864da7 9034 }
9df8b37c 9035
05864da7
DS
9036 /*
9037 * Note when vrfid of nexthop is different from that of prefix
9038 */
9039 if (path->extra && path->extra->bgp_orig) {
9040 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9041
05864da7
DS
9042 if (json_paths) {
9043 const char *vn;
9df8b37c 9044
05864da7
DS
9045 if (path->extra->bgp_orig->inst_type
9046 == BGP_INSTANCE_TYPE_DEFAULT)
9047 vn = VRF_DEFAULT_NAME;
9048 else
9049 vn = path->extra->bgp_orig->name;
9df8b37c 9050
05864da7 9051 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9052
05864da7
DS
9053 if (nexthop_vrfid == VRF_UNKNOWN) {
9054 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9055 } else {
05864da7
DS
9056 json_object_int_add(json_path, "nhVrfId",
9057 (int)nexthop_vrfid);
9df8b37c 9058 }
05864da7
DS
9059 } else {
9060 if (nexthop_vrfid == VRF_UNKNOWN)
9061 vty_out(vty, " vrf ?");
137147c6
DS
9062 else {
9063 struct vrf *vrf;
9064
9065 vrf = vrf_lookup_by_id(nexthop_vrfid);
9066 vty_out(vty, " vrf %s(%u)",
9067 VRF_LOGNAME(vrf), nexthop_vrfid);
9068 }
9df8b37c 9069 }
05864da7 9070 }
9df8b37c 9071
05864da7
DS
9072 if (nexthop_self) {
9073 if (json_paths) {
9074 json_object_boolean_true_add(json_path,
9075 "announceNexthopSelf");
9076 } else {
9077 vty_out(vty, " announce-nh-self");
9df8b37c 9078 }
05864da7 9079 }
9df8b37c 9080
05864da7
DS
9081 if (!json_paths)
9082 vty_out(vty, "\n");
d62a17ae 9083
05864da7
DS
9084 /* display the link-local nexthop */
9085 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9086 if (json_paths) {
9087 json_nexthop_ll = json_object_new_object();
9088 json_object_string_add(
515c2602
DA
9089 json_nexthop_ll, "ip",
9090 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9091 buf, INET6_ADDRSTRLEN));
9092
939a97f4 9093 if (path->peer->hostname)
515c2602
DA
9094 json_object_string_add(json_nexthop_ll,
9095 "hostname",
939a97f4 9096 path->peer->hostname);
515c2602 9097
05864da7
DS
9098 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9099 json_object_string_add(json_nexthop_ll, "scope",
9100 "link-local");
d62a17ae 9101
05864da7
DS
9102 json_object_boolean_true_add(json_nexthop_ll,
9103 "accessible");
d62a17ae 9104
05864da7 9105 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9106 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9107 "used");
9108 else
9109 json_object_boolean_true_add(
9110 json_nexthop_global, "used");
9111 } else {
9112 vty_out(vty, " (%s) %s\n",
9113 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9114 buf, INET6_ADDRSTRLEN),
9115 attr->mp_nexthop_prefer_global
9116 ? "(prefer-global)"
9117 : "(used)");
d62a17ae 9118 }
05864da7
DS
9119 }
9120 /* If we do not have a link-local nexthop then we must flag the
9121 global as "used" */
9122 else {
9123 if (json_paths)
9124 json_object_boolean_true_add(json_nexthop_global,
9125 "used");
9126 }
d62a17ae 9127
b5e140c8
AK
9128 if (safi == SAFI_EVPN &&
9129 memcmp(&attr->esi, zero_esi, sizeof(esi_t))) {
9130 char esi_buf[ESI_STR_LEN];
9131
9132 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9133 if (json_paths)
9134 json_object_string_add(
9135 json_path, "esi",
9136 esi_buf);
9137 else
9138 vty_out(vty, " ESI %s\n",
9139 esi_buf);
9140 }
9141
05864da7
DS
9142 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9143 * Int/Ext/Local, Atomic, best */
9144 if (json_paths)
9145 json_object_string_add(json_path, "origin",
9146 bgp_origin_long_str[attr->origin]);
9147 else
9148 vty_out(vty, " Origin %s",
9149 bgp_origin_long_str[attr->origin]);
9df8b37c 9150
05864da7 9151 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9152 if (json_paths)
05864da7 9153 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9154 else
05864da7
DS
9155 vty_out(vty, ", metric %u", attr->med);
9156 }
9df8b37c 9157
05864da7
DS
9158 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9159 if (json_paths)
0fbac0b4 9160 json_object_int_add(json_path, "locPrf",
05864da7
DS
9161 attr->local_pref);
9162 else
9163 vty_out(vty, ", localpref %u", attr->local_pref);
9164 }
9df8b37c 9165
05864da7
DS
9166 if (attr->weight != 0) {
9167 if (json_paths)
9168 json_object_int_add(json_path, "weight", attr->weight);
9169 else
9170 vty_out(vty, ", weight %u", attr->weight);
9171 }
9df8b37c 9172
05864da7
DS
9173 if (attr->tag != 0) {
9174 if (json_paths)
9175 json_object_int_add(json_path, "tag", attr->tag);
9176 else
9177 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9178 }
9df8b37c 9179
05864da7
DS
9180 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9181 if (json_paths)
9182 json_object_boolean_false_add(json_path, "valid");
9183 else
9184 vty_out(vty, ", invalid");
9185 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9186 if (json_paths)
9187 json_object_boolean_true_add(json_path, "valid");
9188 else
9189 vty_out(vty, ", valid");
9190 }
9df8b37c 9191
05864da7
DS
9192 if (path->peer != bgp->peer_self) {
9193 if (path->peer->as == path->peer->local_as) {
9194 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9195 if (json_paths)
9196 json_object_string_add(
9197 json_peer, "type",
9198 "confed-internal");
d62a17ae 9199 else
05864da7 9200 vty_out(vty, ", confed-internal");
d62a17ae 9201 } else {
05864da7
DS
9202 if (json_paths)
9203 json_object_string_add(
9204 json_peer, "type", "internal");
9205 else
9206 vty_out(vty, ", internal");
9df8b37c 9207 }
05864da7
DS
9208 } else {
9209 if (bgp_confederation_peers_check(bgp,
9210 path->peer->as)) {
9211 if (json_paths)
9212 json_object_string_add(
9213 json_peer, "type",
9214 "confed-external");
d62a17ae 9215 else
05864da7 9216 vty_out(vty, ", confed-external");
d62a17ae 9217 } else {
05864da7
DS
9218 if (json_paths)
9219 json_object_string_add(
9220 json_peer, "type", "external");
9221 else
9222 vty_out(vty, ", external");
d62a17ae 9223 }
9224 }
05864da7
DS
9225 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9226 if (json_paths) {
9227 json_object_boolean_true_add(json_path, "aggregated");
9228 json_object_boolean_true_add(json_path, "local");
9229 } else {
9230 vty_out(vty, ", aggregated, local");
9231 }
9232 } else if (path->type != ZEBRA_ROUTE_BGP) {
9233 if (json_paths)
9234 json_object_boolean_true_add(json_path, "sourced");
9235 else
9236 vty_out(vty, ", sourced");
9237 } else {
9238 if (json_paths) {
9239 json_object_boolean_true_add(json_path, "sourced");
9240 json_object_boolean_true_add(json_path, "local");
9241 } else {
9242 vty_out(vty, ", sourced, local");
d62a17ae 9243 }
05864da7 9244 }
718e3744 9245
05864da7 9246 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9247 if (json_paths)
05864da7
DS
9248 json_object_boolean_true_add(json_path,
9249 "atomicAggregate");
d62a17ae 9250 else
05864da7
DS
9251 vty_out(vty, ", atomic-aggregate");
9252 }
d62a17ae 9253
05864da7
DS
9254 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9255 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9256 && bgp_path_info_mpath_count(path))) {
9257 if (json_paths)
9258 json_object_boolean_true_add(json_path, "multipath");
9259 else
9260 vty_out(vty, ", multipath");
9261 }
50e05855 9262
05864da7
DS
9263 // Mark the bestpath(s)
9264 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9265 first_as = aspath_get_first_as(attr->aspath);
718e3744 9266
05864da7
DS
9267 if (json_paths) {
9268 if (!json_bestpath)
9269 json_bestpath = json_object_new_object();
9270 json_object_int_add(json_bestpath, "bestpathFromAs",
9271 first_as);
9272 } else {
9273 if (first_as)
9274 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9275 else
05864da7 9276 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9277 }
05864da7 9278 }
718e3744 9279
05864da7
DS
9280 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9281 if (json_paths) {
9282 if (!json_bestpath)
9283 json_bestpath = json_object_new_object();
9284 json_object_boolean_true_add(json_bestpath, "overall");
9285 json_object_string_add(
9286 json_bestpath, "selectionReason",
9287 bgp_path_selection_reason2str(bn->reason));
9288 } else {
9289 vty_out(vty, ", best");
9290 vty_out(vty, " (%s)",
9291 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9292 }
05864da7 9293 }
718e3744 9294
05864da7
DS
9295 if (json_bestpath)
9296 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9297
05864da7
DS
9298 if (!json_paths)
9299 vty_out(vty, "\n");
9300
9301 /* Line 4 display Community */
9302 if (attr->community) {
9303 if (json_paths) {
9304 if (!attr->community->json)
9305 community_str(attr->community, true);
9306 json_object_lock(attr->community->json);
9307 json_object_object_add(json_path, "community",
9308 attr->community->json);
9309 } else {
9310 vty_out(vty, " Community: %s\n",
9311 attr->community->str);
d62a17ae 9312 }
05864da7 9313 }
718e3744 9314
05864da7
DS
9315 /* Line 5 display Extended-community */
9316 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9317 if (json_paths) {
9318 json_ext_community = json_object_new_object();
9319 json_object_string_add(json_ext_community, "string",
9320 attr->ecommunity->str);
9321 json_object_object_add(json_path, "extendedCommunity",
9322 json_ext_community);
d62a17ae 9323 } else {
05864da7
DS
9324 vty_out(vty, " Extended Community: %s\n",
9325 attr->ecommunity->str);
d62a17ae 9326 }
05864da7 9327 }
718e3744 9328
05864da7
DS
9329 /* Line 6 display Large community */
9330 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9331 if (json_paths) {
9332 if (!attr->lcommunity->json)
9333 lcommunity_str(attr->lcommunity, true);
9334 json_object_lock(attr->lcommunity->json);
9335 json_object_object_add(json_path, "largeCommunity",
9336 attr->lcommunity->json);
9337 } else {
9338 vty_out(vty, " Large Community: %s\n",
9339 attr->lcommunity->str);
d62a17ae 9340 }
05864da7 9341 }
718e3744 9342
05864da7
DS
9343 /* Line 7 display Originator, Cluster-id */
9344 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9345 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9346 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9347 if (json_paths)
05864da7
DS
9348 json_object_string_add(
9349 json_path, "originatorId",
9350 inet_ntoa(attr->originator_id));
d62a17ae 9351 else
05864da7
DS
9352 vty_out(vty, " Originator: %s",
9353 inet_ntoa(attr->originator_id));
d62a17ae 9354 }
856ca177 9355
05864da7
DS
9356 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9357 int i;
d62a17ae 9358
9359 if (json_paths) {
05864da7
DS
9360 json_cluster_list = json_object_new_object();
9361 json_cluster_list_list =
9362 json_object_new_array();
9363
9364 for (i = 0; i < attr->cluster->length / 4;
9365 i++) {
9366 json_string = json_object_new_string(
9367 inet_ntoa(attr->cluster
9368 ->list[i]));
9369 json_object_array_add(
9370 json_cluster_list_list,
9371 json_string);
9372 }
718e3744 9373
05864da7
DS
9374 /*
9375 * struct cluster_list does not have
9376 * "str" variable like aspath and community
9377 * do. Add this someday if someone asks
9378 * for it.
9379 * json_object_string_add(json_cluster_list,
9380 * "string", attr->cluster->str);
9381 */
9382 json_object_object_add(json_cluster_list,
9383 "list",
9384 json_cluster_list_list);
9385 json_object_object_add(json_path, "clusterList",
9386 json_cluster_list);
0dc8ee70 9387 } else {
05864da7
DS
9388 vty_out(vty, ", Cluster list: ");
9389
9390 for (i = 0; i < attr->cluster->length / 4;
9391 i++) {
9392 vty_out(vty, "%s ",
9393 inet_ntoa(attr->cluster
9394 ->list[i]));
9395 }
0dc8ee70 9396 }
d62a17ae 9397 }
718e3744 9398
d62a17ae 9399 if (!json_paths)
9400 vty_out(vty, "\n");
05864da7 9401 }
d62a17ae 9402
05864da7 9403 if (path->extra && path->extra->damp_info)
a935f597 9404 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9405
05864da7
DS
9406 /* Remote Label */
9407 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9408 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9409 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9410
05864da7
DS
9411 if (json_paths)
9412 json_object_int_add(json_path, "remoteLabel", label);
9413 else
9414 vty_out(vty, " Remote label: %d\n", label);
9415 }
d62a17ae 9416
e496b420
HS
9417 /* Remote SID */
9418 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9419 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9420 if (json_paths)
9421 json_object_string_add(json_path, "remoteSid", buf);
9422 else
9423 vty_out(vty, " Remote SID: %s\n", buf);
9424 }
9425
05864da7
DS
9426 /* Label Index */
9427 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9428 if (json_paths)
9429 json_object_int_add(json_path, "labelIndex",
9430 attr->label_index);
9431 else
9432 vty_out(vty, " Label Index: %d\n",
9433 attr->label_index);
9434 }
d62a17ae 9435
05864da7
DS
9436 /* Line 8 display Addpath IDs */
9437 if (path->addpath_rx_id
9438 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9439 if (json_paths) {
9440 json_object_int_add(json_path, "addpathRxId",
9441 path->addpath_rx_id);
d62a17ae 9442
05864da7
DS
9443 /* Keep backwards compatibility with the old API
9444 * by putting TX All's ID in the old field
9445 */
9446 json_object_int_add(
9447 json_path, "addpathTxId",
9448 path->tx_addpath
9449 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9450
05864da7
DS
9451 /* ... but create a specific field for each
9452 * strategy
9453 */
9454 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9455 json_object_int_add(
9456 json_path,
9457 bgp_addpath_names(i)->id_json_name,
9458 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9459 }
05864da7
DS
9460 } else {
9461 vty_out(vty, " AddPath ID: RX %u, ",
9462 path->addpath_rx_id);
d62a17ae 9463
05864da7 9464 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9465 }
05864da7 9466 }
520d5d76 9467
05864da7
DS
9468 /* If we used addpath to TX a non-bestpath we need to display
9469 * "Advertised to" on a path-by-path basis
9470 */
9471 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9472 first = 1;
dcc68b5e 9473
05864da7
DS
9474 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9475 addpath_capable =
9476 bgp_addpath_encode_tx(peer, afi, safi);
9477 has_adj = bgp_adj_out_lookup(
9478 peer, path->net,
9479 bgp_addpath_id_for_peer(peer, afi, safi,
9480 &path->tx_addpath));
9481
9482 if ((addpath_capable && has_adj)
9483 || (!addpath_capable && has_adj
9484 && CHECK_FLAG(path->flags,
9485 BGP_PATH_SELECTED))) {
9486 if (json_path && !json_adv_to)
9487 json_adv_to = json_object_new_object();
dcc68b5e 9488
05864da7
DS
9489 route_vty_out_advertised_to(
9490 vty, peer, &first,
9491 " Advertised to:", json_adv_to);
d62a17ae 9492 }
9493 }
718e3744 9494
05864da7
DS
9495 if (json_path) {
9496 if (json_adv_to) {
9497 json_object_object_add(
9498 json_path, "advertisedTo", json_adv_to);
d62a17ae 9499 }
05864da7
DS
9500 } else {
9501 if (!first) {
9502 vty_out(vty, "\n");
d62a17ae 9503 }
9504 }
05864da7 9505 }
b05a1c8b 9506
05864da7
DS
9507 /* Line 9 display Uptime */
9508 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9509 if (json_paths) {
9510 json_last_update = json_object_new_object();
9511 json_object_int_add(json_last_update, "epoch", tbuf);
9512 json_object_string_add(json_last_update, "string",
9513 ctime(&tbuf));
9514 json_object_object_add(json_path, "lastUpdate",
9515 json_last_update);
9516 } else
9517 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9518
05864da7
DS
9519 /* Line 10 display PMSI tunnel attribute, if present */
9520 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9521 const char *str =
9522 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9523 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9524
05864da7
DS
9525 if (json_paths) {
9526 json_pmsi = json_object_new_object();
9527 json_object_string_add(json_pmsi, "tunnelType", str);
9528 json_object_int_add(json_pmsi, "label",
9529 label2vni(&attr->label));
9530 json_object_object_add(json_path, "pmsi", json_pmsi);
9531 } else
9532 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9533 str, label2vni(&attr->label));
d62a17ae 9534 }
f1aa5d8a 9535
d62a17ae 9536 /* We've constructed the json object for this path, add it to the json
9537 * array of paths
9538 */
9539 if (json_paths) {
9540 if (json_nexthop_global || json_nexthop_ll) {
9541 json_nexthops = json_object_new_array();
f1aa5d8a 9542
d62a17ae 9543 if (json_nexthop_global)
9544 json_object_array_add(json_nexthops,
9545 json_nexthop_global);
f1aa5d8a 9546
d62a17ae 9547 if (json_nexthop_ll)
9548 json_object_array_add(json_nexthops,
9549 json_nexthop_ll);
f1aa5d8a 9550
d62a17ae 9551 json_object_object_add(json_path, "nexthops",
9552 json_nexthops);
9553 }
9554
9555 json_object_object_add(json_path, "peer", json_peer);
9556 json_object_array_add(json_paths, json_path);
05864da7 9557 }
b366b518
BB
9558}
9559
96ade3ed 9560#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9561#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9562#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9563
d62a17ae 9564static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9565 const char *prefix_list_str, afi_t afi,
9566 safi_t safi, enum bgp_show_type type);
9567static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9568 const char *filter, afi_t afi, safi_t safi,
9569 enum bgp_show_type type);
9570static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9571 const char *rmap_str, afi_t afi, safi_t safi,
9572 enum bgp_show_type type);
9573static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9574 const char *com, int exact, afi_t afi,
9575 safi_t safi);
9576static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9577 const char *prefix, afi_t afi, safi_t safi,
9578 enum bgp_show_type type);
a4d82a8a 9579static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9580 afi_t afi, safi_t safi, enum bgp_show_type type,
9581 bool use_json);
7f323236
DW
9582static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9583 const char *comstr, int exact, afi_t afi,
9f049418 9584 safi_t safi, bool use_json);
d62a17ae 9585
1ae44dfc
LB
9586
9587static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9588 struct bgp_table *table, enum bgp_show_type type,
9f049418 9589 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9590 int is_last, unsigned long *output_cum,
9591 unsigned long *total_cum,
ae248832 9592 unsigned long *json_header_depth, bool wide)
d62a17ae 9593{
40381db7 9594 struct bgp_path_info *pi;
9bcb3eef 9595 struct bgp_dest *dest;
d62a17ae 9596 int header = 1;
9597 int display;
1ae44dfc
LB
9598 unsigned long output_count = 0;
9599 unsigned long total_count = 0;
d62a17ae 9600 struct prefix *p;
d62a17ae 9601 json_object *json_paths = NULL;
9602 int first = 1;
9603
1ae44dfc
LB
9604 if (output_cum && *output_cum != 0)
9605 header = 0;
9606
9386b588 9607 if (use_json && !*json_header_depth) {
d62a17ae 9608 vty_out(vty,
6cde4b45 9609 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
01eced22 9610 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9611 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9612 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9613 ? VRF_DEFAULT_NAME
9614 : bgp->name,
01eced22
AD
9615 table->version, inet_ntoa(bgp->router_id),
9616 bgp->default_local_pref, bgp->as);
9386b588
PZ
9617 *json_header_depth = 2;
9618 if (rd) {
445c2480 9619 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9620 ++*json_header_depth;
9621 }
d62a17ae 9622 }
718e3744 9623
445c2480
DS
9624 if (use_json && rd) {
9625 vty_out(vty, " \"%s\" : { ", rd);
9626 }
9627
d62a17ae 9628 /* Start processing of routes. */
9bcb3eef
DS
9629 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
9630 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9631
9bcb3eef 9632 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 9633 if (pi == NULL)
98ce9a06 9634 continue;
d62a17ae 9635
98ce9a06 9636 display = 0;
98ce9a06
DS
9637 if (use_json)
9638 json_paths = json_object_new_array();
9639 else
9640 json_paths = NULL;
d62a17ae 9641
6f94b685 9642 for (; pi; pi = pi->next) {
98ce9a06
DS
9643 total_count++;
9644 if (type == bgp_show_type_flap_statistics
9645 || type == bgp_show_type_flap_neighbor
9646 || type == bgp_show_type_dampend_paths
9647 || type == bgp_show_type_damp_neighbor) {
40381db7 9648 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9649 continue;
9650 }
9651 if (type == bgp_show_type_regexp) {
9652 regex_t *regex = output_arg;
d62a17ae 9653
40381db7 9654 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9655 == REG_NOMATCH)
9656 continue;
9657 }
9658 if (type == bgp_show_type_prefix_list) {
9659 struct prefix_list *plist = output_arg;
d62a17ae 9660
9bcb3eef 9661 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
9662 != PREFIX_PERMIT)
9663 continue;
9664 }
9665 if (type == bgp_show_type_filter_list) {
9666 struct as_list *as_list = output_arg;
d62a17ae 9667
40381db7 9668 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9669 != AS_FILTER_PERMIT)
9670 continue;
9671 }
9672 if (type == bgp_show_type_route_map) {
9673 struct route_map *rmap = output_arg;
9b6d8fcf 9674 struct bgp_path_info path;
98ce9a06 9675 struct attr dummy_attr;
b68885f9 9676 route_map_result_t ret;
d62a17ae 9677
6f4f49b2 9678 dummy_attr = *pi->attr;
d62a17ae 9679
40381db7 9680 path.peer = pi->peer;
9b6d8fcf 9681 path.attr = &dummy_attr;
d62a17ae 9682
9bcb3eef 9683 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 9684 &path);
98ce9a06
DS
9685 if (ret == RMAP_DENYMATCH)
9686 continue;
9687 }
9688 if (type == bgp_show_type_neighbor
9689 || type == bgp_show_type_flap_neighbor
9690 || type == bgp_show_type_damp_neighbor) {
9691 union sockunion *su = output_arg;
9692
40381db7
DS
9693 if (pi->peer == NULL
9694 || pi->peer->su_remote == NULL
9695 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9696 continue;
9697 }
9698 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9699 uint32_t destination;
d62a17ae 9700
9bcb3eef 9701 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 9702 if (IN_CLASSC(destination)
9bcb3eef 9703 && dest_p->prefixlen == 24)
98ce9a06
DS
9704 continue;
9705 if (IN_CLASSB(destination)
9bcb3eef 9706 && dest_p->prefixlen == 16)
98ce9a06
DS
9707 continue;
9708 if (IN_CLASSA(destination)
9bcb3eef 9709 && dest_p->prefixlen == 8)
98ce9a06
DS
9710 continue;
9711 }
9712 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9713 p = output_arg;
9bcb3eef 9714 if (!prefix_match(p, dest_p))
98ce9a06
DS
9715 continue;
9716 }
9717 if (type == bgp_show_type_community_all) {
40381db7 9718 if (!pi->attr->community)
98ce9a06
DS
9719 continue;
9720 }
9721 if (type == bgp_show_type_community) {
9722 struct community *com = output_arg;
d62a17ae 9723
40381db7
DS
9724 if (!pi->attr->community
9725 || !community_match(pi->attr->community,
98ce9a06
DS
9726 com))
9727 continue;
9728 }
9729 if (type == bgp_show_type_community_exact) {
9730 struct community *com = output_arg;
d62a17ae 9731
40381db7
DS
9732 if (!pi->attr->community
9733 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9734 continue;
9735 }
9736 if (type == bgp_show_type_community_list) {
9737 struct community_list *list = output_arg;
d62a17ae 9738
40381db7 9739 if (!community_list_match(pi->attr->community,
a4d82a8a 9740 list))
98ce9a06
DS
9741 continue;
9742 }
a4d82a8a 9743 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9744 struct community_list *list = output_arg;
d62a17ae 9745
98ce9a06 9746 if (!community_list_exact_match(
40381db7 9747 pi->attr->community, list))
98ce9a06
DS
9748 continue;
9749 }
9750 if (type == bgp_show_type_lcommunity) {
9751 struct lcommunity *lcom = output_arg;
d62a17ae 9752
40381db7
DS
9753 if (!pi->attr->lcommunity
9754 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9755 lcom))
9756 continue;
9757 }
36a206db 9758
9759 if (type == bgp_show_type_lcommunity_exact) {
9760 struct lcommunity *lcom = output_arg;
9761
9762 if (!pi->attr->lcommunity
9763 || !lcommunity_cmp(pi->attr->lcommunity,
9764 lcom))
9765 continue;
9766 }
98ce9a06
DS
9767 if (type == bgp_show_type_lcommunity_list) {
9768 struct community_list *list = output_arg;
d62a17ae 9769
40381db7 9770 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9771 list))
98ce9a06
DS
9772 continue;
9773 }
36a206db 9774 if (type
9775 == bgp_show_type_lcommunity_list_exact) {
9776 struct community_list *list = output_arg;
9777
9778 if (!lcommunity_list_exact_match(
9779 pi->attr->lcommunity, list))
9780 continue;
9781 }
98ce9a06 9782 if (type == bgp_show_type_lcommunity_all) {
40381db7 9783 if (!pi->attr->lcommunity)
98ce9a06
DS
9784 continue;
9785 }
9786 if (type == bgp_show_type_dampend_paths
9787 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9788 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9789 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9790 continue;
9791 }
9792
9793 if (!use_json && header) {
6cde4b45 9794 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
98ce9a06
DS
9795 table->version,
9796 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9797 if (bgp->vrf_id == VRF_UNKNOWN)
9798 vty_out(vty, "%s", VRFID_NONE_STR);
9799 else
9800 vty_out(vty, "%u", bgp->vrf_id);
9801 vty_out(vty, "\n");
01eced22
AD
9802 vty_out(vty, "Default local pref %u, ",
9803 bgp->default_local_pref);
9804 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9805 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9806 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9807 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9808 if (type == bgp_show_type_dampend_paths
9809 || type == bgp_show_type_damp_neighbor)
98ce9a06 9810 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9811 else if (type == bgp_show_type_flap_statistics
9812 || type == bgp_show_type_flap_neighbor)
98ce9a06 9813 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9814 else
ae248832
MK
9815 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
9816 : BGP_SHOW_HEADER));
98ce9a06 9817 header = 0;
d62a17ae 9818 }
98ce9a06
DS
9819 if (rd != NULL && !display && !output_count) {
9820 if (!use_json)
9821 vty_out(vty,
9822 "Route Distinguisher: %s\n",
9823 rd);
d62a17ae 9824 }
98ce9a06
DS
9825 if (type == bgp_show_type_dampend_paths
9826 || type == bgp_show_type_damp_neighbor)
9bcb3eef 9827 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
9828 AFI_IP, safi, use_json,
9829 json_paths);
98ce9a06
DS
9830 else if (type == bgp_show_type_flap_statistics
9831 || type == bgp_show_type_flap_neighbor)
9bcb3eef 9832 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
9833 AFI_IP, safi, use_json,
9834 json_paths);
98ce9a06 9835 else
9bcb3eef 9836 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 9837 json_paths, wide);
98ce9a06 9838 display++;
d62a17ae 9839 }
9840
98ce9a06
DS
9841 if (display) {
9842 output_count++;
9843 if (!use_json)
9844 continue;
9845
625d2931 9846 /* encode prefix */
9bcb3eef 9847 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
9848 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9849
b54892e0
DS
9850 bgp_fs_nlri_get_string(
9851 (unsigned char *)
9bcb3eef
DS
9852 dest_p->u.prefix_flowspec.ptr,
9853 dest_p->u.prefix_flowspec.prefixlen,
b54892e0 9854 retstr, NLRI_STRING_FORMAT_MIN, NULL);
625d2931 9855 if (first)
b54892e0 9856 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 9857 dest_p->u.prefix_flowspec
b54892e0 9858 .prefixlen);
625d2931 9859 else
b54892e0 9860 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 9861 dest_p->u.prefix_flowspec
b54892e0 9862 .prefixlen);
625d2931 9863 } else {
625d2931 9864 if (first)
1b78780b 9865 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 9866 else
1b78780b 9867 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 9868 }
98ce9a06 9869 vty_out(vty, "%s",
f4ec52f7
DA
9870 json_object_to_json_string_ext(
9871 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9872 json_object_free(json_paths);
449feb8e 9873 json_paths = NULL;
98ce9a06 9874 first = 0;
1f83ed02
DS
9875 } else
9876 json_object_free(json_paths);
98ce9a06
DS
9877 }
9878
1ae44dfc
LB
9879 if (output_cum) {
9880 output_count += *output_cum;
9881 *output_cum = output_count;
9882 }
9883 if (total_cum) {
9884 total_count += *total_cum;
9885 *total_cum = total_count;
9886 }
d62a17ae 9887 if (use_json) {
9386b588 9888 if (rd) {
a4d82a8a 9889 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9890 }
9891 if (is_last) {
a4d82a8a
PZ
9892 unsigned long i;
9893 for (i = 0; i < *json_header_depth; ++i)
9894 vty_out(vty, " } ");
faf6559a 9895 vty_out(vty, "\n");
9386b588 9896 }
d62a17ae 9897 } else {
1ae44dfc
LB
9898 if (is_last) {
9899 /* No route is displayed */
9900 if (output_count == 0) {
9901 if (type == bgp_show_type_normal)
9902 vty_out(vty,
9903 "No BGP prefixes displayed, %ld exist\n",
9904 total_count);
9905 } else
d62a17ae 9906 vty_out(vty,
1ae44dfc
LB
9907 "\nDisplayed %ld routes and %ld total paths\n",
9908 output_count, total_count);
9909 }
d62a17ae 9910 }
718e3744 9911
d62a17ae 9912 return CMD_SUCCESS;
718e3744 9913}
9914
1ae44dfc
LB
9915int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9916 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9917 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 9918{
9bcb3eef 9919 struct bgp_dest *dest, *next;
1ae44dfc
LB
9920 unsigned long output_cum = 0;
9921 unsigned long total_cum = 0;
9386b588 9922 unsigned long json_header_depth = 0;
67009e22 9923 struct bgp_table *itable;
0136788c
LB
9924 bool show_msg;
9925
9926 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 9927
9bcb3eef
DS
9928 for (dest = bgp_table_top(table); dest; dest = next) {
9929 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9930
9bcb3eef
DS
9931 next = bgp_route_next(dest);
9932 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 9933 continue;
67009e22 9934
9bcb3eef 9935 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 9936 if (itable != NULL) {
1ae44dfc 9937 struct prefix_rd prd;
06b9f471 9938 char rd[RD_ADDRSTRLEN];
1ae44dfc 9939
9bcb3eef 9940 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 9941 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9942 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9943 use_json, rd, next == NULL, &output_cum,
ae248832 9944 &total_cum, &json_header_depth, false);
0136788c
LB
9945 if (next == NULL)
9946 show_msg = false;
1ae44dfc
LB
9947 }
9948 }
0136788c
LB
9949 if (show_msg) {
9950 if (output_cum == 0)
9951 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9952 total_cum);
9953 else
9954 vty_out(vty,
9955 "\nDisplayed %ld routes and %ld total paths\n",
9956 output_cum, total_cum);
9957 }
1ae44dfc
LB
9958 return CMD_SUCCESS;
9959}
d62a17ae 9960static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
ae248832
MK
9961 enum bgp_show_type type, void *output_arg, bool use_json,
9962 bool wide)
fee0f4c6 9963{
d62a17ae 9964 struct bgp_table *table;
9386b588 9965 unsigned long json_header_depth = 0;
fee0f4c6 9966
d62a17ae 9967 if (bgp == NULL) {
9968 bgp = bgp_get_default();
9969 }
fee0f4c6 9970
d62a17ae 9971 if (bgp == NULL) {
9972 if (!use_json)
9973 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9974 else
9975 vty_out(vty, "{}\n");
d62a17ae 9976 return CMD_WARNING;
9977 }
4dd6177e 9978
1ae44dfc 9979 table = bgp->rib[afi][safi];
d62a17ae 9980 /* use MPLS and ENCAP specific shows until they are merged */
9981 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9982 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9983 output_arg, use_json);
d62a17ae 9984 }
dba3c1d3
PG
9985
9986 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9987 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9988 output_arg, use_json,
9989 1, NULL, NULL);
9990 }
d62a17ae 9991 /* labeled-unicast routes live in the unicast table */
9992 else if (safi == SAFI_LABELED_UNICAST)
9993 safi = SAFI_UNICAST;
fee0f4c6 9994
1ae44dfc 9995 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
ae248832 9996 NULL, 1, NULL, NULL, &json_header_depth, wide);
fee0f4c6 9997}
9998
d62a17ae 9999static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
ae248832
MK
10000 safi_t safi, bool use_json,
10001 bool wide)
f186de26 10002{
d62a17ae 10003 struct listnode *node, *nnode;
10004 struct bgp *bgp;
10005 int is_first = 1;
9f049418 10006 bool route_output = false;
f186de26 10007
d62a17ae 10008 if (use_json)
10009 vty_out(vty, "{\n");
9f689658 10010
d62a17ae 10011 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10012 route_output = true;
d62a17ae 10013 if (use_json) {
10014 if (!is_first)
10015 vty_out(vty, ",\n");
10016 else
10017 is_first = 0;
10018
10019 vty_out(vty, "\"%s\":",
10020 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10021 ? VRF_DEFAULT_NAME
d62a17ae 10022 : bgp->name);
10023 } else {
10024 vty_out(vty, "\nInstance %s:\n",
10025 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10026 ? VRF_DEFAULT_NAME
d62a17ae 10027 : bgp->name);
10028 }
10029 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
ae248832 10030 use_json, wide);
d62a17ae 10031 }
9f689658 10032
d62a17ae 10033 if (use_json)
10034 vty_out(vty, "}\n");
9f049418
DS
10035 else if (!route_output)
10036 vty_out(vty, "%% BGP instance not found\n");
f186de26 10037}
10038
718e3744 10039/* Header of detailed BGP route information */
d62a17ae 10040void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10041 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10042 afi_t afi, safi_t safi, json_object *json)
10043{
40381db7 10044 struct bgp_path_info *pi;
b54892e0 10045 const struct prefix *p;
d62a17ae 10046 struct peer *peer;
10047 struct listnode *node, *nnode;
06b9f471 10048 char buf1[RD_ADDRSTRLEN];
d62a17ae 10049 char buf2[INET6_ADDRSTRLEN];
d62a17ae 10050 char buf3[EVPN_ROUTE_STRLEN];
0291c246 10051 char prefix_str[BUFSIZ];
d62a17ae 10052 int count = 0;
10053 int best = 0;
10054 int suppress = 0;
c5f1e1b2
C
10055 int accept_own = 0;
10056 int route_filter_translated_v4 = 0;
10057 int route_filter_v4 = 0;
10058 int route_filter_translated_v6 = 0;
10059 int route_filter_v6 = 0;
10060 int llgr_stale = 0;
10061 int no_llgr = 0;
10062 int accept_own_nexthop = 0;
10063 int blackhole = 0;
d62a17ae 10064 int no_export = 0;
10065 int no_advertise = 0;
10066 int local_as = 0;
c5f1e1b2 10067 int no_peer = 0;
d62a17ae 10068 int first = 1;
10069 int has_valid_label = 0;
10070 mpls_label_t label = 0;
10071 json_object *json_adv_to = NULL;
9bedbb1e 10072
9bcb3eef
DS
10073 p = bgp_dest_get_prefix(dest);
10074 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10075
10076 if (has_valid_label)
9bcb3eef 10077 label = label_pton(&dest->local_label);
d62a17ae 10078
44c69747 10079 if (safi == SAFI_EVPN) {
d62a17ae 10080
44c69747 10081 if (!json) {
d62a17ae 10082 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10083 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10084 : "", prd ? ":" : "",
d62a17ae 10085 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10086 buf3, sizeof(buf3)));
10087 } else {
10088 json_object_string_add(json, "rd",
10089 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10090 "");
10091 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10092 }
10093 } else {
10094 if (!json) {
d62a17ae 10095 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10096 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10097 ? prefix_rd2str(prd, buf1,
10098 sizeof(buf1))
10099 : ""),
d62a17ae 10100 safi == SAFI_MPLS_VPN ? ":" : "",
10101 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10102 INET6_ADDRSTRLEN),
d62a17ae 10103 p->prefixlen);
cd1964ff 10104
44c69747
LK
10105 } else
10106 json_object_string_add(json, "prefix",
10107 prefix2str(p, prefix_str, sizeof(prefix_str)));
10108 }
10109
10110 if (has_valid_label) {
10111 if (json)
10112 json_object_int_add(json, "localLabel", label);
10113 else
d62a17ae 10114 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10115 }
10116
10117 if (!json)
d62a17ae 10118 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10119 vty_out(vty, "not allocated\n");
718e3744 10120
9bcb3eef 10121 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10122 count++;
40381db7 10123 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10124 best = count;
40381db7 10125 if (pi->extra && pi->extra->suppress)
d62a17ae 10126 suppress = 1;
cee9c031 10127
40381db7 10128 if (pi->attr->community == NULL)
cee9c031
QY
10129 continue;
10130
10131 no_advertise += community_include(
40381db7
DS
10132 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10133 no_export += community_include(pi->attr->community,
cee9c031 10134 COMMUNITY_NO_EXPORT);
40381db7 10135 local_as += community_include(pi->attr->community,
cee9c031 10136 COMMUNITY_LOCAL_AS);
40381db7 10137 accept_own += community_include(pi->attr->community,
cee9c031
QY
10138 COMMUNITY_ACCEPT_OWN);
10139 route_filter_translated_v4 += community_include(
40381db7 10140 pi->attr->community,
cee9c031
QY
10141 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10142 route_filter_translated_v6 += community_include(
40381db7 10143 pi->attr->community,
cee9c031
QY
10144 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10145 route_filter_v4 += community_include(
40381db7 10146 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10147 route_filter_v6 += community_include(
40381db7
DS
10148 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10149 llgr_stale += community_include(pi->attr->community,
cee9c031 10150 COMMUNITY_LLGR_STALE);
40381db7 10151 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10152 COMMUNITY_NO_LLGR);
10153 accept_own_nexthop +=
40381db7 10154 community_include(pi->attr->community,
cee9c031 10155 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10156 blackhole += community_include(pi->attr->community,
cee9c031 10157 COMMUNITY_BLACKHOLE);
40381db7 10158 no_peer += community_include(pi->attr->community,
cee9c031 10159 COMMUNITY_NO_PEER);
d62a17ae 10160 }
718e3744 10161 }
718e3744 10162
d62a17ae 10163 if (!json) {
10164 vty_out(vty, "Paths: (%d available", count);
10165 if (best) {
10166 vty_out(vty, ", best #%d", best);
b84060bb
PG
10167 if (safi == SAFI_UNICAST) {
10168 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10169 vty_out(vty, ", table %s",
10170 VRF_DEFAULT_NAME);
10171 else
10172 vty_out(vty, ", vrf %s",
10173 bgp->name);
10174 }
d62a17ae 10175 } else
10176 vty_out(vty, ", no best path");
10177
c5f1e1b2
C
10178 if (accept_own)
10179 vty_out(vty,
10180 ", accept own local route exported and imported in different VRF");
10181 else if (route_filter_translated_v4)
10182 vty_out(vty,
10183 ", mark translated RTs for VPNv4 route filtering");
10184 else if (route_filter_v4)
10185 vty_out(vty,
10186 ", attach RT as-is for VPNv4 route filtering");
10187 else if (route_filter_translated_v6)
10188 vty_out(vty,
10189 ", mark translated RTs for VPNv6 route filtering");
10190 else if (route_filter_v6)
10191 vty_out(vty,
10192 ", attach RT as-is for VPNv6 route filtering");
10193 else if (llgr_stale)
10194 vty_out(vty,
10195 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10196 else if (no_llgr)
10197 vty_out(vty,
10198 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10199 else if (accept_own_nexthop)
10200 vty_out(vty,
10201 ", accept local nexthop");
10202 else if (blackhole)
10203 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10204 else if (no_export)
10205 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10206 else if (no_advertise)
10207 vty_out(vty, ", not advertised to any peer");
d62a17ae 10208 else if (local_as)
10209 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10210 else if (no_peer)
10211 vty_out(vty,
10212 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10213
10214 if (suppress)
10215 vty_out(vty,
10216 ", Advertisements suppressed by an aggregate.");
10217 vty_out(vty, ")\n");
10218 }
718e3744 10219
d62a17ae 10220 /* If we are not using addpath then we can display Advertised to and
10221 * that will
10222 * show what peers we advertised the bestpath to. If we are using
10223 * addpath
10224 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10225 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10226 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10227 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10228 if (json && !json_adv_to)
10229 json_adv_to = json_object_new_object();
10230
10231 route_vty_out_advertised_to(
10232 vty, peer, &first,
10233 " Advertised to non peer-group peers:\n ",
10234 json_adv_to);
10235 }
10236 }
10237
10238 if (json) {
10239 if (json_adv_to) {
10240 json_object_object_add(json, "advertisedTo",
10241 json_adv_to);
10242 }
10243 } else {
10244 if (first)
10245 vty_out(vty, " Not advertised to any peer");
10246 vty_out(vty, "\n");
10247 }
10248 }
718e3744 10249}
10250
44c69747 10251static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10252 struct bgp_dest *bgp_node, struct vty *vty,
10253 struct bgp *bgp, afi_t afi, safi_t safi,
10254 json_object *json, enum bgp_path_type pathtype,
10255 int *display)
44c69747
LK
10256{
10257 struct bgp_path_info *pi;
10258 int header = 1;
10259 char rdbuf[RD_ADDRSTRLEN];
10260 json_object *json_header = NULL;
10261 json_object *json_paths = NULL;
10262
9bcb3eef 10263 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10264
10265 if (json && !json_paths) {
10266 /* Instantiate json_paths only if path is valid */
10267 json_paths = json_object_new_array();
10268 if (pfx_rd) {
10269 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10270 json_header = json_object_new_object();
10271 } else
10272 json_header = json;
10273 }
10274
10275 if (header) {
10276 route_vty_out_detail_header(
10277 vty, bgp, bgp_node, pfx_rd,
10278 AFI_IP, safi, json_header);
10279 header = 0;
10280 }
10281 (*display)++;
10282
10283 if (pathtype == BGP_PATH_SHOW_ALL
10284 || (pathtype == BGP_PATH_SHOW_BESTPATH
10285 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10286 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10287 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10288 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10289 route_vty_out_detail(vty, bgp, bgp_node,
10290 pi, AFI_IP, safi,
10291 json_paths);
10292 }
10293
10294 if (json && json_paths) {
10295 json_object_object_add(json_header, "paths", json_paths);
10296
10297 if (pfx_rd)
10298 json_object_object_add(json, rdbuf, json_header);
10299 }
10300}
10301
718e3744 10302/* Display specified route of BGP table. */
d62a17ae 10303static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10304 struct bgp_table *rib, const char *ip_str,
10305 afi_t afi, safi_t safi,
10306 struct prefix_rd *prd, int prefix_check,
9f049418 10307 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10308{
10309 int ret;
d62a17ae 10310 int display = 0;
10311 struct prefix match;
9bcb3eef
DS
10312 struct bgp_dest *dest;
10313 struct bgp_dest *rm;
d62a17ae 10314 struct bgp_table *table;
10315 json_object *json = NULL;
10316 json_object *json_paths = NULL;
10317
10318 /* Check IP address argument. */
10319 ret = str2prefix(ip_str, &match);
10320 if (!ret) {
10321 vty_out(vty, "address is malformed\n");
10322 return CMD_WARNING;
10323 }
718e3744 10324
d62a17ae 10325 match.family = afi2family(afi);
b05a1c8b 10326
44c69747 10327 if (use_json)
d62a17ae 10328 json = json_object_new_object();
718e3744 10329
44c69747 10330 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
10331 for (dest = bgp_table_top(rib); dest;
10332 dest = bgp_route_next(dest)) {
10333 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10334
9bcb3eef 10335 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 10336 continue;
9bcb3eef 10337 table = bgp_dest_get_bgp_table_info(dest);
67009e22 10338 if (!table)
ea47320b 10339 continue;
d62a17ae 10340
ea47320b
DL
10341 if ((rm = bgp_node_match(table, &match)) == NULL)
10342 continue;
d62a17ae 10343
9bcb3eef 10344 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 10345 if (prefix_check
b54892e0 10346 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 10347 bgp_dest_unlock_node(rm);
ea47320b
DL
10348 continue;
10349 }
d62a17ae 10350
9bcb3eef 10351 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10352 bgp, afi, safi, json, pathtype,
10353 &display);
44c69747 10354
9bcb3eef 10355 bgp_dest_unlock_node(rm);
44c69747
LK
10356 }
10357 } else if (safi == SAFI_EVPN) {
9bcb3eef 10358 struct bgp_dest *longest_pfx;
cded3b72 10359 bool is_exact_pfxlen_match = false;
44c69747 10360
9bcb3eef
DS
10361 for (dest = bgp_table_top(rib); dest;
10362 dest = bgp_route_next(dest)) {
10363 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10364
9bcb3eef 10365 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 10366 continue;
9bcb3eef 10367 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
10368 if (!table)
10369 continue;
10370
10371 longest_pfx = NULL;
cded3b72 10372 is_exact_pfxlen_match = false;
44c69747
LK
10373 /*
10374 * Search through all the prefixes for a match. The
10375 * pfx's are enumerated in ascending order of pfxlens.
10376 * So, the last pfx match is the longest match. Set
10377 * is_exact_pfxlen_match when we get exact pfxlen match
10378 */
10379 for (rm = bgp_table_top(table); rm;
10380 rm = bgp_route_next(rm)) {
b54892e0 10381 const struct prefix *rm_p =
9bcb3eef 10382 bgp_dest_get_prefix(rm);
44c69747
LK
10383 /*
10384 * Get prefixlen of the ip-prefix within type5
10385 * evpn route
10386 */
b54892e0
DS
10387 if (evpn_type5_prefix_match(rm_p, &match)
10388 && rm->info) {
44c69747
LK
10389 longest_pfx = rm;
10390 int type5_pfxlen =
b54892e0
DS
10391 bgp_evpn_get_type5_prefixlen(
10392 rm_p);
44c69747 10393 if (type5_pfxlen == match.prefixlen) {
cded3b72 10394 is_exact_pfxlen_match = true;
9bcb3eef 10395 bgp_dest_unlock_node(rm);
44c69747
LK
10396 break;
10397 }
d62a17ae 10398 }
10399 }
ea47320b 10400
44c69747
LK
10401 if (!longest_pfx)
10402 continue;
10403
10404 if (prefix_check && !is_exact_pfxlen_match)
10405 continue;
10406
10407 rm = longest_pfx;
9bcb3eef 10408 bgp_dest_lock_node(rm);
44c69747 10409
9bcb3eef 10410 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10411 bgp, afi, safi, json, pathtype,
10412 &display);
44c69747 10413
9bcb3eef 10414 bgp_dest_unlock_node(rm);
d62a17ae 10415 }
98a9dbc7 10416 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10417 if (use_json)
10418 json_paths = json_object_new_array();
10419
63a0b7a9
PG
10420 display = bgp_flowspec_display_match_per_ip(afi, rib,
10421 &match, prefix_check,
10422 vty,
10423 use_json,
10424 json_paths);
44c69747
LK
10425 if (use_json && display)
10426 json_object_object_add(json, "paths", json_paths);
d62a17ae 10427 } else {
9bcb3eef
DS
10428 if ((dest = bgp_node_match(rib, &match)) != NULL) {
10429 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 10430 if (!prefix_check
9bcb3eef
DS
10431 || dest_p->prefixlen == match.prefixlen) {
10432 bgp_show_path_info(NULL, dest, vty, bgp, afi,
10433 safi, json, pathtype,
10434 &display);
d62a17ae 10435 }
10436
9bcb3eef 10437 bgp_dest_unlock_node(dest);
d62a17ae 10438 }
10439 }
e5eee9af 10440
d62a17ae 10441 if (use_json) {
996c9314 10442 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10443 json, JSON_C_TO_STRING_PRETTY |
10444 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10445 json_object_free(json);
10446 } else {
10447 if (!display) {
10448 vty_out(vty, "%% Network not in table\n");
10449 return CMD_WARNING;
10450 }
10451 }
b05a1c8b 10452
d62a17ae 10453 return CMD_SUCCESS;
718e3744 10454}
10455
fee0f4c6 10456/* Display specified route of Main RIB */
d62a17ae 10457static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10458 afi_t afi, safi_t safi, struct prefix_rd *prd,
10459 int prefix_check, enum bgp_path_type pathtype,
9f049418 10460 bool use_json)
d62a17ae 10461{
9b86009a 10462 if (!bgp) {
d62a17ae 10463 bgp = bgp_get_default();
9b86009a
RW
10464 if (!bgp) {
10465 if (!use_json)
10466 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10467 else
10468 vty_out(vty, "{}\n");
9b86009a
RW
10469 return CMD_WARNING;
10470 }
10471 }
d62a17ae 10472
10473 /* labeled-unicast routes live in the unicast table */
10474 if (safi == SAFI_LABELED_UNICAST)
10475 safi = SAFI_UNICAST;
10476
10477 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10478 afi, safi, prd, prefix_check, pathtype,
10479 use_json);
10480}
10481
10482static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10483 struct cmd_token **argv, bool exact, afi_t afi,
10484 safi_t safi, bool uj)
d62a17ae 10485{
10486 struct lcommunity *lcom;
10487 struct buffer *b;
10488 int i;
10489 char *str;
10490 int first = 0;
10491
10492 b = buffer_new(1024);
10493 for (i = 0; i < argc; i++) {
10494 if (first)
10495 buffer_putc(b, ' ');
10496 else {
10497 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10498 first = 1;
10499 buffer_putstr(b, argv[i]->arg);
10500 }
10501 }
10502 }
10503 buffer_putc(b, '\0');
57d187bc 10504
d62a17ae 10505 str = buffer_getstr(b);
10506 buffer_free(b);
57d187bc 10507
d62a17ae 10508 lcom = lcommunity_str2com(str);
10509 XFREE(MTYPE_TMP, str);
10510 if (!lcom) {
10511 vty_out(vty, "%% Large-community malformed\n");
10512 return CMD_WARNING;
10513 }
57d187bc 10514
36a206db 10515 return bgp_show(vty, bgp, afi, safi,
10516 (exact ? bgp_show_type_lcommunity_exact
ae248832
MK
10517 : bgp_show_type_lcommunity),
10518 lcom, uj, false);
57d187bc
JS
10519}
10520
d62a17ae 10521static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10522 const char *lcom, bool exact, afi_t afi,
10523 safi_t safi, bool uj)
57d187bc 10524{
d62a17ae 10525 struct community_list *list;
57d187bc 10526
e237b0d2 10527 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10528 LARGE_COMMUNITY_LIST_MASTER);
10529 if (list == NULL) {
10530 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10531 lcom);
10532 return CMD_WARNING;
10533 }
57d187bc 10534
36a206db 10535 return bgp_show(vty, bgp, afi, safi,
10536 (exact ? bgp_show_type_lcommunity_list_exact
ae248832
MK
10537 : bgp_show_type_lcommunity_list),
10538 list, uj, false);
fee0f4c6 10539}
10540
52951b63
DS
10541DEFUN (show_ip_bgp_large_community_list,
10542 show_ip_bgp_large_community_list_cmd,
36a206db 10543 "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
10544 SHOW_STR
10545 IP_STR
10546 BGP_STR
10547 BGP_INSTANCE_HELP_STR
9bedbb1e 10548 BGP_AFI_HELP_STR
4dd6177e 10549 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10550 "Display routes matching the large-community-list\n"
10551 "large-community-list number\n"
10552 "large-community-list name\n"
36a206db 10553 "Exact match of the large-communities\n"
52951b63
DS
10554 JSON_STR)
10555{
d62a17ae 10556 afi_t afi = AFI_IP6;
10557 safi_t safi = SAFI_UNICAST;
10558 int idx = 0;
36a206db 10559 bool exact_match = 0;
4d678463 10560 struct bgp *bgp = NULL;
9f049418 10561 bool uj = use_json(argc, argv);
d62a17ae 10562
4d678463
KA
10563 if (uj)
10564 argc--;
10565
10566 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10567 &bgp, uj);
10568 if (!idx)
10569 return CMD_WARNING;
d62a17ae 10570
10571 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10572
10573 const char *clist_number_or_name = argv[++idx]->arg;
10574
10575 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10576 exact_match = 1;
10577
10578 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10579 exact_match, afi, safi, uj);
52951b63
DS
10580}
10581DEFUN (show_ip_bgp_large_community,
10582 show_ip_bgp_large_community_cmd,
36a206db 10583 "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
10584 SHOW_STR
10585 IP_STR
10586 BGP_STR
10587 BGP_INSTANCE_HELP_STR
9bedbb1e 10588 BGP_AFI_HELP_STR
4dd6177e 10589 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10590 "Display routes matching the large-communities\n"
10591 "List of large-community numbers\n"
36a206db 10592 "Exact match of the large-communities\n"
52951b63
DS
10593 JSON_STR)
10594{
d62a17ae 10595 afi_t afi = AFI_IP6;
10596 safi_t safi = SAFI_UNICAST;
10597 int idx = 0;
36a206db 10598 bool exact_match = 0;
4d678463 10599 struct bgp *bgp = NULL;
9f049418 10600 bool uj = use_json(argc, argv);
d62a17ae 10601
4d678463
KA
10602 if (uj)
10603 argc--;
10604
10605 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10606 &bgp, uj);
10607 if (!idx)
10608 return CMD_WARNING;
d62a17ae 10609
36a206db 10610 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10611 if (argv_find(argv, argc, "exact-match", &idx))
10612 exact_match = 1;
10613 return bgp_show_lcommunity(vty, bgp, argc, argv,
10614 exact_match, afi, safi, uj);
10615 } else
d62a17ae 10616 return bgp_show(vty, bgp, afi, safi,
ae248832 10617 bgp_show_type_lcommunity_all, NULL, uj, false);
52951b63
DS
10618}
10619
71f1613a
DA
10620static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
10621 safi_t safi, struct json_object *json_array);
d62a17ae 10622static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 10623 safi_t safi, struct json_object *json);
e01ca200 10624
7b2ff250 10625
9ab0cf58
PG
10626DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
10627 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10628 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10629 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
10630{
10631 bool uj = use_json(argc, argv);
10632 struct bgp *bgp = NULL;
ec76a1d1
DA
10633 safi_t safi = SAFI_UNICAST;
10634 afi_t afi = AFI_IP6;
4265b261 10635 int idx = 0;
6c9d22e2
PG
10636 struct json_object *json_all = NULL;
10637 struct json_object *json_afi_safi = NULL;
4265b261
PG
10638
10639 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10640 &bgp, false);
71f1613a 10641 if (!idx)
4265b261 10642 return CMD_WARNING;
6c9d22e2 10643
4265b261 10644 if (uj)
6c9d22e2 10645 json_all = json_object_new_object();
4265b261 10646
9ab0cf58
PG
10647 FOREACH_AFI_SAFI (afi, safi) {
10648 /*
10649 * So limit output to those afi/safi pairs that
10650 * actually have something interesting in them
10651 */
10652 if (strmatch(get_afi_safi_str(afi, safi, true),
10653 "Unknown")) {
10654 continue;
10655 }
10656 if (uj) {
10657 json_afi_safi = json_object_new_array();
10658 json_object_object_add(
10659 json_all,
10660 get_afi_safi_str(afi, safi, true),
10661 json_afi_safi);
10662 } else {
10663 json_afi_safi = NULL;
6c9d22e2 10664 }
9ab0cf58
PG
10665
10666 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 10667 }
6c9d22e2
PG
10668
10669 if (uj) {
9ab0cf58
PG
10670 vty_out(vty, "%s",
10671 json_object_to_json_string_ext(
10672 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 10673 json_object_free(json_all);
4265b261 10674 }
6c9d22e2 10675
4265b261
PG
10676 return CMD_SUCCESS;
10677}
10678
7b2ff250 10679/* BGP route print out function without JSON */
14718643
PG
10680DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
10681 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 10682 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
10683 SHOW_STR
10684 IP_STR
10685 BGP_STR
10686 BGP_INSTANCE_HELP_STR
10687 L2VPN_HELP_STR
10688 EVPN_HELP_STR
10689 "BGP RIB advertisement statistics\n"
10690 JSON_STR)
10691{
ec76a1d1
DA
10692 afi_t afi = AFI_IP6;
10693 safi_t safi = SAFI_UNICAST;
14718643
PG
10694 struct bgp *bgp = NULL;
10695 int idx = 0, ret;
10696 bool uj = use_json(argc, argv);
10697 struct json_object *json_afi_safi = NULL, *json = NULL;
10698
10699 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10700 &bgp, false);
10701 if (!idx)
10702 return CMD_WARNING;
10703
10704 if (uj)
10705 json_afi_safi = json_object_new_array();
10706 else
10707 json_afi_safi = NULL;
10708
10709 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10710
10711 if (uj) {
10712 json = json_object_new_object();
10713 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10714 json_afi_safi);
10715 vty_out(vty, "%s", json_object_to_json_string_ext(
10716 json, JSON_C_TO_STRING_PRETTY));
10717 json_object_free(json);
10718 }
10719 return ret;
10720}
10721
893cccd0 10722/* BGP route print out function without JSON */
9ab0cf58
PG
10723DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
10724 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10725 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10726 "]]\
893cccd0 10727 statistics [json]",
9ab0cf58
PG
10728 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10729 BGP_SAFI_WITH_LABEL_HELP_STR
10730 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 10731{
ec76a1d1
DA
10732 afi_t afi = AFI_IP6;
10733 safi_t safi = SAFI_UNICAST;
893cccd0
PG
10734 struct bgp *bgp = NULL;
10735 int idx = 0, ret;
10736 bool uj = use_json(argc, argv);
6c9d22e2 10737 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
10738
10739 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10740 &bgp, false);
10741 if (!idx)
10742 return CMD_WARNING;
6c9d22e2 10743
893cccd0 10744 if (uj)
6c9d22e2
PG
10745 json_afi_safi = json_object_new_array();
10746 else
10747 json_afi_safi = NULL;
10748
10749 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10750
10751 if (uj) {
10752 json = json_object_new_object();
10753 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10754 json_afi_safi);
9ab0cf58
PG
10755 vty_out(vty, "%s",
10756 json_object_to_json_string_ext(
10757 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
10758 json_object_free(json);
10759 }
10760 return ret;
893cccd0 10761}
7b2ff250
DW
10762
10763/* BGP route print out function without JSON */
9ab0cf58
PG
10764DEFUN(show_ip_bgp, show_ip_bgp_cmd,
10765 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10766 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10767 "]]\
7b2ff250
DW
10768 <dampening <parameters>\
10769 |route-map WORD\
10770 |prefix-list WORD\
10771 |filter-list WORD\
7b2ff250
DW
10772 |community-list <(1-500)|WORD> [exact-match]\
10773 |A.B.C.D/M longer-prefixes\
10774 |X:X::X:X/M longer-prefixes\
893cccd0 10775 >",
9ab0cf58
PG
10776 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10777 BGP_SAFI_WITH_LABEL_HELP_STR
10778 "Display detailed information about dampening\n"
10779 "Display detail of configured dampening parameters\n"
10780 "Display routes matching the route-map\n"
10781 "A route-map to match on\n"
10782 "Display routes conforming to the prefix-list\n"
10783 "Prefix-list name\n"
10784 "Display routes conforming to the filter-list\n"
10785 "Regular expression access list name\n"
10786 "Display routes matching the community-list\n"
10787 "community-list number\n"
10788 "community-list name\n"
10789 "Exact match of the communities\n"
10790 "IPv4 prefix\n"
10791 "Display route and more specific routes\n"
10792 "IPv6 prefix\n"
10793 "Display route and more specific routes\n")
718e3744 10794{
d62a17ae 10795 afi_t afi = AFI_IP6;
10796 safi_t safi = SAFI_UNICAST;
10797 int exact_match = 0;
d62a17ae 10798 struct bgp *bgp = NULL;
10799 int idx = 0;
10800
10801 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10802 &bgp, false);
d62a17ae 10803 if (!idx)
10804 return CMD_WARNING;
10805
d62a17ae 10806 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10807 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10808 return bgp_show_dampening_parameters(vty, afi, safi);
10809 }
c016b6c7 10810
d62a17ae 10811 if (argv_find(argv, argc, "prefix-list", &idx))
10812 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10813 safi, bgp_show_type_prefix_list);
10814
10815 if (argv_find(argv, argc, "filter-list", &idx))
10816 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10817 safi, bgp_show_type_filter_list);
10818
d62a17ae 10819 if (argv_find(argv, argc, "route-map", &idx))
10820 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10821 safi, bgp_show_type_route_map);
10822
d62a17ae 10823 if (argv_find(argv, argc, "community-list", &idx)) {
10824 const char *clist_number_or_name = argv[++idx]->arg;
10825 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10826 exact_match = 1;
10827 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10828 exact_match, afi, safi);
10829 }
10830 /* prefix-longer */
10831 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10832 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10833 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10834 safi,
10835 bgp_show_type_prefix_longer);
10836
7b2ff250
DW
10837 return CMD_WARNING;
10838}
10839
10840/* BGP route print out function with JSON */
ae248832 10841DEFPY (show_ip_bgp_json,
7b2ff250
DW
10842 show_ip_bgp_json_cmd,
10843 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10844 [cidr-only\
10845 |dampening <flap-statistics|dampened-paths>\
10846 |community [AA:NN|local-AS|no-advertise|no-export\
10847 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10848 |accept-own|accept-own-nexthop|route-filter-v6\
10849 |route-filter-v4|route-filter-translated-v6\
10850 |route-filter-translated-v4] [exact-match]\
ae248832 10851 ] [json$uj | wide$wide]",
7b2ff250
DW
10852 SHOW_STR
10853 IP_STR
10854 BGP_STR
10855 BGP_INSTANCE_HELP_STR
10856 BGP_AFI_HELP_STR
10857 BGP_SAFI_WITH_LABEL_HELP_STR
10858 "Display only routes with non-natural netmasks\n"
10859 "Display detailed information about dampening\n"
10860 "Display flap statistics of routes\n"
10861 "Display paths suppressed due to dampening\n"
10862 "Display routes matching the communities\n"
d0086e8e
AD
10863 COMMUNITY_AANN_STR
10864 "Do not send outside local AS (well-known community)\n"
10865 "Do not advertise to any peer (well-known community)\n"
10866 "Do not export to next AS (well-known community)\n"
10867 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10868 "Do not export to any peer (well-known community)\n"
10869 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10870 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10871 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10872 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10873 "Should accept VPN route with local nexthop (well-known community)\n"
10874 "RT VPNv6 route filtering (well-known community)\n"
10875 "RT VPNv4 route filtering (well-known community)\n"
10876 "RT translated VPNv6 route filtering (well-known community)\n"
10877 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10878 "Exact match of the communities\n"
ae248832
MK
10879 JSON_STR
10880 "Increase table width for longer prefixes\n")
7b2ff250
DW
10881{
10882 afi_t afi = AFI_IP6;
10883 safi_t safi = SAFI_UNICAST;
10884 enum bgp_show_type sh_type = bgp_show_type_normal;
10885 struct bgp *bgp = NULL;
10886 int idx = 0;
d0086e8e 10887 int exact_match = 0;
9f049418
DS
10888
10889 if (uj)
10890 argc--;
7b2ff250
DW
10891
10892 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10893 &bgp, uj);
7b2ff250
DW
10894 if (!idx)
10895 return CMD_WARNING;
10896
7b2ff250
DW
10897 if (argv_find(argv, argc, "cidr-only", &idx))
10898 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
ae248832 10899 NULL, uj, wide);
7b2ff250
DW
10900
10901 if (argv_find(argv, argc, "dampening", &idx)) {
10902 if (argv_find(argv, argc, "dampened-paths", &idx))
10903 return bgp_show(vty, bgp, afi, safi,
ae248832
MK
10904 bgp_show_type_dampend_paths, NULL, uj,
10905 wide);
7b2ff250
DW
10906 else if (argv_find(argv, argc, "flap-statistics", &idx))
10907 return bgp_show(vty, bgp, afi, safi,
ae248832
MK
10908 bgp_show_type_flap_statistics, NULL, uj,
10909 wide);
7b2ff250
DW
10910 }
10911
10912 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10913 char *maybecomm = NULL;
cf4898bc 10914 char *community = NULL;
d0086e8e 10915
79bc257a
RW
10916 if (idx + 1 < argc) {
10917 if (argv[idx + 1]->type == VARIABLE_TKN)
10918 maybecomm = argv[idx + 1]->arg;
10919 else
10920 maybecomm = argv[idx + 1]->text;
10921 }
10922
cf4898bc
QY
10923 if (maybecomm && !strmatch(maybecomm, "json")
10924 && !strmatch(maybecomm, "exact-match"))
10925 community = maybecomm;
d0086e8e 10926
cf4898bc
QY
10927 if (argv_find(argv, argc, "exact-match", &idx))
10928 exact_match = 1;
d0086e8e 10929
cf4898bc
QY
10930 if (community)
10931 return bgp_show_community(vty, bgp, community,
10932 exact_match, afi, safi, uj);
10933 else
d0086e8e 10934 return (bgp_show(vty, bgp, afi, safi,
ae248832
MK
10935 bgp_show_type_community_all, NULL, uj,
10936 wide));
7b2ff250 10937 }
d0086e8e 10938
ae248832 10939 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj, wide);
a636c635 10940}
47fc97cc 10941
718e3744 10942DEFUN (show_ip_bgp_route,
10943 show_ip_bgp_route_cmd,
3efd0893 10944 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10945 SHOW_STR
10946 IP_STR
10947 BGP_STR
a636c635 10948 BGP_INSTANCE_HELP_STR
4f280b15 10949 BGP_AFI_HELP_STR
4dd6177e 10950 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10951 "Network in the BGP routing table to display\n"
0c7b1b01 10952 "IPv4 prefix\n"
8c3deaae 10953 "Network in the BGP routing table to display\n"
0c7b1b01 10954 "IPv6 prefix\n"
4092b06c 10955 "Display only the bestpath\n"
b05a1c8b 10956 "Display only multipaths\n"
9973d184 10957 JSON_STR)
4092b06c 10958{
d62a17ae 10959 int prefix_check = 0;
ae19d7dd 10960
d62a17ae 10961 afi_t afi = AFI_IP6;
10962 safi_t safi = SAFI_UNICAST;
10963 char *prefix = NULL;
10964 struct bgp *bgp = NULL;
10965 enum bgp_path_type path_type;
9f049418 10966 bool uj = use_json(argc, argv);
b05a1c8b 10967
d62a17ae 10968 int idx = 0;
ae19d7dd 10969
d62a17ae 10970 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10971 &bgp, uj);
d62a17ae 10972 if (!idx)
10973 return CMD_WARNING;
c41247f5 10974
d62a17ae 10975 if (!bgp) {
10976 vty_out(vty,
10977 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10978 return CMD_WARNING;
10979 }
a636c635 10980
d62a17ae 10981 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10982 if (argv_find(argv, argc, "A.B.C.D", &idx)
10983 || argv_find(argv, argc, "X:X::X:X", &idx))
10984 prefix_check = 0;
10985 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10986 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10987 prefix_check = 1;
10988
10989 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10990 && afi != AFI_IP6) {
10991 vty_out(vty,
10992 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10993 return CMD_WARNING;
10994 }
10995 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10996 && afi != AFI_IP) {
10997 vty_out(vty,
10998 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10999 return CMD_WARNING;
11000 }
11001
11002 prefix = argv[idx]->arg;
11003
11004 /* [<bestpath|multipath>] */
11005 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11006 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11007 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11008 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11009 else
360660c6 11010 path_type = BGP_PATH_SHOW_ALL;
a636c635 11011
d62a17ae 11012 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11013 path_type, uj);
4092b06c
DS
11014}
11015
8c3deaae
QY
11016DEFUN (show_ip_bgp_regexp,
11017 show_ip_bgp_regexp_cmd,
3e5b31b3 11018 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11019 SHOW_STR
11020 IP_STR
11021 BGP_STR
b00b230a 11022 BGP_INSTANCE_HELP_STR
4f280b15 11023 BGP_AFI_HELP_STR
4dd6177e 11024 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11025 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11026 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11027 JSON_STR)
8c3deaae 11028{
d62a17ae 11029 afi_t afi = AFI_IP6;
11030 safi_t safi = SAFI_UNICAST;
11031 struct bgp *bgp = NULL;
3e5b31b3
DA
11032 bool uj = use_json(argc, argv);
11033 char *regstr = NULL;
8c3deaae 11034
d62a17ae 11035 int idx = 0;
11036 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11037 &bgp, false);
d62a17ae 11038 if (!idx)
11039 return CMD_WARNING;
8c3deaae 11040
d62a17ae 11041 // get index of regex
3e5b31b3
DA
11042 if (argv_find(argv, argc, "REGEX", &idx))
11043 regstr = argv[idx]->arg;
8c3deaae 11044
5f71d11c 11045 assert(regstr);
3e5b31b3
DA
11046 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11047 bgp_show_type_regexp, uj);
8c3deaae
QY
11048}
11049
ae248832 11050DEFPY (show_ip_bgp_instance_all,
a636c635 11051 show_ip_bgp_instance_all_cmd,
ae248832 11052 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11053 SHOW_STR
a636c635 11054 IP_STR
4092b06c 11055 BGP_STR
a636c635 11056 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11057 BGP_AFI_HELP_STR
4dd6177e 11058 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11059 JSON_STR
11060 "Increase table width for longer prefixes\n")
4092b06c 11061{
d62a17ae 11062 afi_t afi = AFI_IP;
11063 safi_t safi = SAFI_UNICAST;
11064 struct bgp *bgp = NULL;
d62a17ae 11065 int idx = 0;
ae19d7dd 11066
d62a17ae 11067 if (uj)
11068 argc--;
e3e29b32 11069
9f049418
DS
11070 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11071 &bgp, uj);
11072 if (!idx)
11073 return CMD_WARNING;
11074
ae248832 11075 bgp_show_all_instances_routes_vty(vty, afi, safi, uj, wide);
d62a17ae 11076 return CMD_SUCCESS;
e3e29b32
LB
11077}
11078
a4d82a8a 11079static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11080 afi_t afi, safi_t safi, enum bgp_show_type type,
11081 bool use_json)
718e3744 11082{
d62a17ae 11083 regex_t *regex;
11084 int rc;
e3e29b32 11085
c3900853 11086 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11087 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11088 regstr);
11089 return CMD_WARNING_CONFIG_FAILED;
11090 }
11091
d62a17ae 11092 regex = bgp_regcomp(regstr);
11093 if (!regex) {
11094 vty_out(vty, "Can't compile regexp %s\n", regstr);
11095 return CMD_WARNING;
11096 }
a636c635 11097
ae248832 11098 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json, false);
d62a17ae 11099 bgp_regex_free(regex);
11100 return rc;
e3e29b32
LB
11101}
11102
d62a17ae 11103static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11104 const char *prefix_list_str, afi_t afi,
11105 safi_t safi, enum bgp_show_type type)
e3e29b32 11106{
d62a17ae 11107 struct prefix_list *plist;
718e3744 11108
d62a17ae 11109 plist = prefix_list_lookup(afi, prefix_list_str);
11110 if (plist == NULL) {
11111 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11112 prefix_list_str);
11113 return CMD_WARNING;
11114 }
718e3744 11115
ae248832 11116 return bgp_show(vty, bgp, afi, safi, type, plist, 0, false);
4092b06c
DS
11117}
11118
d62a17ae 11119static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11120 const char *filter, afi_t afi, safi_t safi,
11121 enum bgp_show_type type)
4092b06c 11122{
d62a17ae 11123 struct as_list *as_list;
718e3744 11124
d62a17ae 11125 as_list = as_list_lookup(filter);
11126 if (as_list == NULL) {
11127 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11128 filter);
11129 return CMD_WARNING;
11130 }
a636c635 11131
ae248832 11132 return bgp_show(vty, bgp, afi, safi, type, as_list, 0, false);
718e3744 11133}
11134
d62a17ae 11135static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11136 const char *rmap_str, afi_t afi, safi_t safi,
11137 enum bgp_show_type type)
718e3744 11138{
d62a17ae 11139 struct route_map *rmap;
bb46e94f 11140
d62a17ae 11141 rmap = route_map_lookup_by_name(rmap_str);
11142 if (!rmap) {
11143 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11144 return CMD_WARNING;
11145 }
11146
ae248832 11147 return bgp_show(vty, bgp, afi, safi, type, rmap, 0, false);
d62a17ae 11148}
11149
7f323236
DW
11150static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11151 const char *comstr, int exact, afi_t afi,
9f049418 11152 safi_t safi, bool use_json)
d62a17ae 11153{
11154 struct community *com;
d62a17ae 11155 int ret = 0;
11156
7f323236 11157 com = community_str2com(comstr);
d62a17ae 11158 if (!com) {
7f323236 11159 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11160 return CMD_WARNING;
11161 }
11162
11163 ret = bgp_show(vty, bgp, afi, safi,
11164 (exact ? bgp_show_type_community_exact
11165 : bgp_show_type_community),
ae248832 11166 com, use_json, false);
3c1f53de 11167 community_free(&com);
46c3ce83 11168
d62a17ae 11169 return ret;
718e3744 11170}
11171
d62a17ae 11172static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11173 const char *com, int exact, afi_t afi,
11174 safi_t safi)
50ef26d4 11175{
d62a17ae 11176 struct community_list *list;
50ef26d4 11177
e237b0d2 11178 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 11179 if (list == NULL) {
11180 vty_out(vty, "%% %s is not a valid community-list name\n", com);
11181 return CMD_WARNING;
11182 }
718e3744 11183
d62a17ae 11184 return bgp_show(vty, bgp, afi, safi,
11185 (exact ? bgp_show_type_community_list_exact
11186 : bgp_show_type_community_list),
ae248832 11187 list, 0, false);
50ef26d4 11188}
11189
d62a17ae 11190static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
11191 const char *prefix, afi_t afi, safi_t safi,
11192 enum bgp_show_type type)
718e3744 11193{
d62a17ae 11194 int ret;
11195 struct prefix *p;
47fc97cc 11196
d62a17ae 11197 p = prefix_new();
95cbbd2a 11198
d62a17ae 11199 ret = str2prefix(prefix, p);
11200 if (!ret) {
11201 vty_out(vty, "%% Malformed Prefix\n");
11202 return CMD_WARNING;
11203 }
47e9b292 11204
ae248832 11205 ret = bgp_show(vty, bgp, afi, safi, type, p, 0, false);
63265b5c 11206 prefix_free(&p);
d62a17ae 11207 return ret;
11208}
11209
d62a17ae 11210enum bgp_stats {
11211 BGP_STATS_MAXBITLEN = 0,
11212 BGP_STATS_RIB,
11213 BGP_STATS_PREFIXES,
11214 BGP_STATS_TOTPLEN,
11215 BGP_STATS_UNAGGREGATEABLE,
11216 BGP_STATS_MAX_AGGREGATEABLE,
11217 BGP_STATS_AGGREGATES,
11218 BGP_STATS_SPACE,
11219 BGP_STATS_ASPATH_COUNT,
11220 BGP_STATS_ASPATH_MAXHOPS,
11221 BGP_STATS_ASPATH_TOTHOPS,
11222 BGP_STATS_ASPATH_MAXSIZE,
11223 BGP_STATS_ASPATH_TOTSIZE,
11224 BGP_STATS_ASN_HIGHEST,
11225 BGP_STATS_MAX,
a636c635 11226};
2815e61f 11227
9ab0cf58 11228#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
11229#define TABLE_STATS_IDX_JSON 1
11230
11231static const char *table_stats_strs[][2] = {
6c9d22e2
PG
11232 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
11233 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
11234 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
11235 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
11236 "unaggregateablePrefixes"},
11237 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
11238 "maximumAggregateablePrefixes"},
11239 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
11240 "bgpAggregateAdvertisements"},
6c9d22e2
PG
11241 [BGP_STATS_SPACE] = {"Address space advertised",
11242 "addressSpaceAdvertised"},
9ab0cf58
PG
11243 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
11244 "advertisementsWithPaths"},
11245 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
11246 "longestAsPath"},
11247 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
11248 "largestAsPath"},
11249 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
11250 "averageAsPathLengthHops"},
11251 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
11252 "averageAsPathSizeBytes"},
11253 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 11254 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 11255};
2815e61f 11256
d62a17ae 11257struct bgp_table_stats {
11258 struct bgp_table *table;
11259 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11260 double total_space;
ff7924f6
PJ
11261};
11262
a636c635
DW
11263#if 0
11264#define TALLY_SIGFIG 100000
11265static unsigned long
11266ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11267{
a636c635
DW
11268 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11269 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11270 unsigned long ret = newtot / count;
07d0c4ed 11271
a636c635
DW
11272 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11273 return ret + 1;
11274 else
11275 return ret;
11276}
11277#endif
ff7924f6 11278
9bcb3eef 11279static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 11280 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11281{
9bcb3eef 11282 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 11283 struct bgp_path_info *pi;
b54892e0 11284 const struct prefix *rn_p;
d62a17ae 11285
9bcb3eef 11286 if (dest == top)
9c14ec72 11287 return;
d62a17ae 11288
9bcb3eef 11289 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 11290 return;
d62a17ae 11291
9bcb3eef 11292 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 11293 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11294 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11295
a636c635
DW
11296#if 0
11297 ts->counts[BGP_STATS_AVGPLEN]
11298 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11299 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11300 rn_p->prefixlen);
a636c635 11301#endif
d62a17ae 11302
9c14ec72 11303 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
11304 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
11305 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 11306
9bcb3eef 11307 if (pdest == NULL || pdest == top) {
9c14ec72
RW
11308 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11309 /* announced address space */
11310 if (space)
b54892e0 11311 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 11312 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 11313 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11314
9c14ec72 11315
9bcb3eef 11316 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
11317 ts->counts[BGP_STATS_RIB]++;
11318
05864da7
DS
11319 if (CHECK_FLAG(pi->attr->flag,
11320 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11321 ts->counts[BGP_STATS_AGGREGATES]++;
11322
11323 /* as-path stats */
05864da7 11324 if (pi->attr->aspath) {
9c14ec72
RW
11325 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11326 unsigned int size = aspath_size(pi->attr->aspath);
11327 as_t highest = aspath_highest(pi->attr->aspath);
11328
11329 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11330
11331 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11332 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11333
11334 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11335 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11336
11337 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11338 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11339#if 0
07d0c4ed 11340 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11341 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11342 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11343 hops);
11344 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11345 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11346 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11347 size);
11348#endif
9c14ec72
RW
11349 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11350 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11351 }
11352 }
11353}
11354
11355static int bgp_table_stats_walker(struct thread *t)
11356{
9bcb3eef
DS
11357 struct bgp_dest *dest, *ndest;
11358 struct bgp_dest *top;
9c14ec72
RW
11359 struct bgp_table_stats *ts = THREAD_ARG(t);
11360 unsigned int space = 0;
11361
11362 if (!(top = bgp_table_top(ts->table)))
11363 return 0;
11364
11365 switch (ts->table->afi) {
11366 case AFI_IP:
11367 space = IPV4_MAX_BITLEN;
11368 break;
11369 case AFI_IP6:
11370 space = IPV6_MAX_BITLEN;
11371 break;
11372 default:
11373 return 0;
11374 }
11375
11376 ts->counts[BGP_STATS_MAXBITLEN] = space;
11377
9bcb3eef 11378 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
11379 if (ts->table->safi == SAFI_MPLS_VPN
11380 || ts->table->safi == SAFI_ENCAP
11381 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
11382 struct bgp_table *table;
11383
9bcb3eef 11384 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
11385 if (!table)
11386 continue;
11387
11388 top = bgp_table_top(table);
9bcb3eef
DS
11389 for (ndest = bgp_table_top(table); ndest;
11390 ndest = bgp_route_next(ndest))
11391 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 11392 } else {
9bcb3eef 11393 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 11394 }
11395 }
9c14ec72 11396
d62a17ae 11397 return 0;
2815e61f 11398}
ff7924f6 11399
71f1613a
DA
11400static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
11401 struct json_object *json_array)
11402{
11403 struct listnode *node, *nnode;
11404 struct bgp *bgp;
11405
11406 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
11407 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11408}
11409
11410static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11411 safi_t safi, struct json_object *json_array)
2815e61f 11412{
d62a17ae 11413 struct bgp_table_stats ts;
11414 unsigned int i;
893cccd0
PG
11415 int ret = CMD_SUCCESS;
11416 char temp_buf[20];
6c9d22e2
PG
11417 struct json_object *json = NULL;
11418
11419 if (json_array)
11420 json = json_object_new_object();
019386c2 11421
d62a17ae 11422 if (!bgp->rib[afi][safi]) {
893cccd0
PG
11423 char warning_msg[50];
11424
11425 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
11426 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
11427 safi);
6c9d22e2
PG
11428
11429 if (!json)
893cccd0
PG
11430 vty_out(vty, "%s\n", warning_msg);
11431 else
9ab0cf58 11432 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 11433
893cccd0
PG
11434 ret = CMD_WARNING;
11435 goto end_table_stats;
d62a17ae 11436 }
019386c2 11437
893cccd0 11438 if (!json)
5290ceab
DA
11439 vty_out(vty, "BGP %s RIB statistics (%s)\n",
11440 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
11441 else
11442 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 11443
d62a17ae 11444 /* labeled-unicast routes live in the unicast table */
11445 if (safi == SAFI_LABELED_UNICAST)
11446 safi = SAFI_UNICAST;
019386c2 11447
d62a17ae 11448 memset(&ts, 0, sizeof(ts));
11449 ts.table = bgp->rib[afi][safi];
11450 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11451
d62a17ae 11452 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
11453 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
11454 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 11455 continue;
11456
11457 switch (i) {
a636c635
DW
11458#if 0
11459 case BGP_STATS_ASPATH_AVGHOPS:
11460 case BGP_STATS_ASPATH_AVGSIZE:
11461 case BGP_STATS_AVGPLEN:
11462 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11463 vty_out (vty, "%12.2f",
11464 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11465 break;
11466#endif
d62a17ae 11467 case BGP_STATS_ASPATH_TOTHOPS:
11468 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 11469 if (!json) {
9ab0cf58
PG
11470 snprintf(
11471 temp_buf, sizeof(temp_buf), "%12.2f",
11472 ts.counts[i]
11473 ? (float)ts.counts[i]
11474 / (float)ts.counts
11475 [BGP_STATS_ASPATH_COUNT]
11476 : 0);
893cccd0 11477 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11478 table_stats_strs[i]
11479 [TABLE_STATS_IDX_VTY],
893cccd0 11480 temp_buf);
9ab0cf58
PG
11481 } else {
11482 json_object_double_add(
11483 json,
11484 table_stats_strs[i]
11485 [TABLE_STATS_IDX_JSON],
11486 ts.counts[i]
11487 ? (double)ts.counts[i]
11488 / (double)ts.counts
d62a17ae 11489 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
11490 : 0);
11491 }
d62a17ae 11492 break;
11493 case BGP_STATS_TOTPLEN:
6c9d22e2 11494 if (!json) {
9ab0cf58
PG
11495 snprintf(
11496 temp_buf, sizeof(temp_buf), "%12.2f",
11497 ts.counts[i]
11498 ? (float)ts.counts[i]
11499 / (float)ts.counts
11500 [BGP_STATS_PREFIXES]
11501 : 0);
893cccd0 11502 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11503 table_stats_strs[i]
11504 [TABLE_STATS_IDX_VTY],
893cccd0 11505 temp_buf);
9ab0cf58
PG
11506 } else {
11507 json_object_double_add(
11508 json,
11509 table_stats_strs[i]
11510 [TABLE_STATS_IDX_JSON],
11511 ts.counts[i]
11512 ? (double)ts.counts[i]
11513 / (double)ts.counts
d62a17ae 11514 [BGP_STATS_PREFIXES]
9ab0cf58
PG
11515 : 0);
11516 }
d62a17ae 11517 break;
11518 case BGP_STATS_SPACE:
6c9d22e2
PG
11519 if (!json) {
11520 snprintf(temp_buf, sizeof(temp_buf), "%12g",
11521 ts.total_space);
893cccd0 11522 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
11523 table_stats_strs[i]
11524 [TABLE_STATS_IDX_VTY],
893cccd0 11525 temp_buf);
9ab0cf58
PG
11526 } else {
11527 json_object_double_add(
11528 json,
11529 table_stats_strs[i]
11530 [TABLE_STATS_IDX_JSON],
11531 (double)ts.total_space);
11532 }
8d0ab76d 11533 if (afi == AFI_IP6) {
6c9d22e2
PG
11534 if (!json) {
11535 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11536 "%12g",
11537 ts.total_space
11538 * pow(2.0, -128 + 32));
6c9d22e2
PG
11539 vty_out(vty, "%30s: %s\n",
11540 "/32 equivalent %s\n",
11541 temp_buf);
9ab0cf58
PG
11542 } else {
11543 json_object_double_add(
11544 json, "/32equivalent",
11545 (double)(ts.total_space
11546 * pow(2.0,
11547 -128 + 32)));
11548 }
6c9d22e2
PG
11549 if (!json) {
11550 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11551 "%12g",
11552 ts.total_space
11553 * pow(2.0, -128 + 48));
6c9d22e2
PG
11554 vty_out(vty, "%30s: %s\n",
11555 "/48 equivalent %s\n",
11556 temp_buf);
9ab0cf58
PG
11557 } else {
11558 json_object_double_add(
11559 json, "/48equivalent",
11560 (double)(ts.total_space
11561 * pow(2.0,
11562 -128 + 48)));
11563 }
8d0ab76d 11564 } else {
6c9d22e2
PG
11565 if (!json) {
11566 snprintf(temp_buf, sizeof(temp_buf),
11567 "%12.2f",
9ab0cf58
PG
11568 ts.total_space * 100.
11569 * pow(2.0, -32));
6c9d22e2 11570 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11571 "% announced ", temp_buf);
11572 } else {
11573 json_object_double_add(
11574 json, "%announced",
11575 (double)(ts.total_space * 100.
11576 * pow(2.0, -32)));
11577 }
6c9d22e2
PG
11578 if (!json) {
11579 snprintf(temp_buf, sizeof(temp_buf),
11580 "%12.2f",
9ab0cf58
PG
11581 ts.total_space
11582 * pow(2.0, -32 + 8));
6c9d22e2
PG
11583 vty_out(vty, "%30s: %s\n",
11584 "/8 equivalent ", temp_buf);
9ab0cf58
PG
11585 } else {
11586 json_object_double_add(
11587 json, "/8equivalent",
11588 (double)(ts.total_space
11589 * pow(2.0, -32 + 8)));
11590 }
6c9d22e2
PG
11591 if (!json) {
11592 snprintf(temp_buf, sizeof(temp_buf),
11593 "%12.2f",
9ab0cf58
PG
11594 ts.total_space
11595 * pow(2.0, -32 + 24));
6c9d22e2 11596 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11597 "/24 equivalent ", temp_buf);
11598 } else {
11599 json_object_double_add(
11600 json, "/24equivalent",
11601 (double)(ts.total_space
11602 * pow(2.0, -32 + 24)));
11603 }
8d0ab76d 11604 }
d62a17ae 11605 break;
11606 default:
6c9d22e2
PG
11607 if (!json) {
11608 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
11609 ts.counts[i]);
893cccd0 11610 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11611 table_stats_strs[i]
11612 [TABLE_STATS_IDX_VTY],
11613 temp_buf);
11614 } else {
11615 json_object_int_add(
11616 json,
11617 table_stats_strs[i]
11618 [TABLE_STATS_IDX_JSON],
11619 ts.counts[i]);
11620 }
d62a17ae 11621 }
893cccd0
PG
11622 if (!json)
11623 vty_out(vty, "\n");
d62a17ae 11624 }
9ab0cf58 11625end_table_stats:
6c9d22e2
PG
11626 if (json)
11627 json_object_array_add(json_array, json);
893cccd0 11628 return ret;
d62a17ae 11629}
11630
71f1613a
DA
11631static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11632 safi_t safi, struct json_object *json_array)
11633{
11634 if (!bgp) {
11635 bgp_table_stats_all(vty, afi, safi, json_array);
11636 return CMD_SUCCESS;
11637 }
11638
11639 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11640}
11641
d62a17ae 11642enum bgp_pcounts {
11643 PCOUNT_ADJ_IN = 0,
11644 PCOUNT_DAMPED,
11645 PCOUNT_REMOVED,
11646 PCOUNT_HISTORY,
11647 PCOUNT_STALE,
11648 PCOUNT_VALID,
11649 PCOUNT_ALL,
11650 PCOUNT_COUNTED,
7e3d9632 11651 PCOUNT_BPATH_SELECTED,
d62a17ae 11652 PCOUNT_PFCNT, /* the figure we display to users */
11653 PCOUNT_MAX,
a636c635 11654};
718e3744 11655
2b64873d 11656static const char *const pcount_strs[] = {
9d303b37
DL
11657 [PCOUNT_ADJ_IN] = "Adj-in",
11658 [PCOUNT_DAMPED] = "Damped",
11659 [PCOUNT_REMOVED] = "Removed",
11660 [PCOUNT_HISTORY] = "History",
11661 [PCOUNT_STALE] = "Stale",
11662 [PCOUNT_VALID] = "Valid",
11663 [PCOUNT_ALL] = "All RIB",
11664 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 11665 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
11666 [PCOUNT_PFCNT] = "Useable",
11667 [PCOUNT_MAX] = NULL,
a636c635 11668};
718e3744 11669
d62a17ae 11670struct peer_pcounts {
11671 unsigned int count[PCOUNT_MAX];
11672 const struct peer *peer;
11673 const struct bgp_table *table;
54317cba 11674 safi_t safi;
a636c635 11675};
47fc97cc 11676
9bcb3eef 11677static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 11678{
54317cba
JW
11679 const struct bgp_adj_in *ain;
11680 const struct bgp_path_info *pi;
d62a17ae 11681 const struct peer *peer = pc->peer;
11682
54317cba
JW
11683 for (ain = rn->adj_in; ain; ain = ain->next)
11684 if (ain->peer == peer)
11685 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11686
9bcb3eef 11687 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11688
54317cba
JW
11689 if (pi->peer != peer)
11690 continue;
d62a17ae 11691
54317cba 11692 pc->count[PCOUNT_ALL]++;
d62a17ae 11693
54317cba
JW
11694 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11695 pc->count[PCOUNT_DAMPED]++;
11696 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11697 pc->count[PCOUNT_HISTORY]++;
11698 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11699 pc->count[PCOUNT_REMOVED]++;
11700 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11701 pc->count[PCOUNT_STALE]++;
11702 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11703 pc->count[PCOUNT_VALID]++;
11704 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11705 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
11706 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11707 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
11708
11709 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11710 pc->count[PCOUNT_COUNTED]++;
11711 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11712 flog_err(
11713 EC_LIB_DEVELOPMENT,
11714 "Attempting to count but flags say it is unusable");
11715 } else {
40381db7 11716 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11717 flog_err(
11718 EC_LIB_DEVELOPMENT,
11719 "Not counted but flags say we should");
d62a17ae 11720 }
11721 }
54317cba
JW
11722}
11723
11724static int bgp_peer_count_walker(struct thread *t)
11725{
9bcb3eef 11726 struct bgp_dest *rn, *rm;
54317cba
JW
11727 const struct bgp_table *table;
11728 struct peer_pcounts *pc = THREAD_ARG(t);
11729
11730 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11731 || pc->safi == SAFI_EVPN) {
11732 /* Special handling for 2-level routing tables. */
11733 for (rn = bgp_table_top(pc->table); rn;
11734 rn = bgp_route_next(rn)) {
9bcb3eef 11735 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
11736 if (table != NULL)
11737 for (rm = bgp_table_top(table); rm;
11738 rm = bgp_route_next(rm))
11739 bgp_peer_count_proc(rm, pc);
11740 }
11741 } else
11742 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11743 bgp_peer_count_proc(rn, pc);
11744
d62a17ae 11745 return 0;
718e3744 11746}
11747
d62a17ae 11748static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11749 safi_t safi, bool use_json)
856ca177 11750{
d62a17ae 11751 struct peer_pcounts pcounts = {.peer = peer};
11752 unsigned int i;
11753 json_object *json = NULL;
11754 json_object *json_loop = NULL;
856ca177 11755
d62a17ae 11756 if (use_json) {
11757 json = json_object_new_object();
11758 json_loop = json_object_new_object();
11759 }
718e3744 11760
d62a17ae 11761 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11762 || !peer->bgp->rib[afi][safi]) {
11763 if (use_json) {
11764 json_object_string_add(
11765 json, "warning",
11766 "No such neighbor or address family");
11767 vty_out(vty, "%s\n", json_object_to_json_string(json));
11768 json_object_free(json);
11769 } else
11770 vty_out(vty, "%% No such neighbor or address family\n");
11771
11772 return CMD_WARNING;
11773 }
2a71e9ce 11774
d62a17ae 11775 memset(&pcounts, 0, sizeof(pcounts));
11776 pcounts.peer = peer;
11777 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11778 pcounts.safi = safi;
d62a17ae 11779
11780 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11781 * stats for the thread-walk (i.e. ensure this can't be blamed on
11782 * on just vty_read()).
11783 */
d62a17ae 11784 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11785
11786 if (use_json) {
11787 json_object_string_add(json, "prefixCountsFor", peer->host);
11788 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11789 get_afi_safi_str(afi, safi, true));
d62a17ae 11790 json_object_int_add(json, "pfxCounter",
11791 peer->pcount[afi][safi]);
11792
11793 for (i = 0; i < PCOUNT_MAX; i++)
11794 json_object_int_add(json_loop, pcount_strs[i],
11795 pcounts.count[i]);
11796
11797 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11798
11799 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11800 json_object_string_add(json, "pfxctDriftFor",
11801 peer->host);
11802 json_object_string_add(
11803 json, "recommended",
11804 "Please report this bug, with the above command output");
11805 }
996c9314
LB
11806 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11807 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11808 json_object_free(json);
11809 } else {
11810
11811 if (peer->hostname
892fedb6 11812 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 11813 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11814 peer->hostname, peer->host,
5cb5f4d0 11815 get_afi_safi_str(afi, safi, false));
d62a17ae 11816 } else {
11817 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11818 get_afi_safi_str(afi, safi, false));
d62a17ae 11819 }
11820
6cde4b45 11821 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 11822 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11823
11824 for (i = 0; i < PCOUNT_MAX; i++)
11825 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11826 pcounts.count[i]);
11827
11828 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11829 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11830 vty_out(vty,
11831 "Please report this bug, with the above command output\n");
11832 }
11833 }
11834
11835 return CMD_SUCCESS;
718e3744 11836}
11837
a636c635
DW
11838DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11839 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 11840 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11841 SHOW_STR
11842 IP_STR
11843 BGP_STR
8386ac43 11844 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11845 BGP_AFI_HELP_STR
11846 BGP_SAFI_HELP_STR
0b16f239
DS
11847 "Detailed information on TCP and BGP neighbor connections\n"
11848 "Neighbor to display information about\n"
11849 "Neighbor to display information about\n"
91d37724 11850 "Neighbor on BGP configured interface\n"
a636c635 11851 "Display detailed prefix count information\n"
9973d184 11852 JSON_STR)
0b16f239 11853{
d62a17ae 11854 afi_t afi = AFI_IP6;
11855 safi_t safi = SAFI_UNICAST;
11856 struct peer *peer;
11857 int idx = 0;
11858 struct bgp *bgp = NULL;
9f049418
DS
11859 bool uj = use_json(argc, argv);
11860
11861 if (uj)
11862 argc--;
856ca177 11863
d62a17ae 11864 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11865 &bgp, uj);
d62a17ae 11866 if (!idx)
11867 return CMD_WARNING;
0b16f239 11868
d62a17ae 11869 argv_find(argv, argc, "neighbors", &idx);
11870 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11871 if (!peer)
11872 return CMD_WARNING;
bb46e94f 11873
29c8d9da 11874 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11875}
0b16f239 11876
d6902373
PG
11877#ifdef KEEP_OLD_VPN_COMMANDS
11878DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11879 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11880 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11881 SHOW_STR
11882 IP_STR
11883 BGP_STR
d6902373 11884 BGP_VPNVX_HELP_STR
91d37724 11885 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11886 "Detailed information on TCP and BGP neighbor connections\n"
11887 "Neighbor to display information about\n"
11888 "Neighbor to display information about\n"
91d37724 11889 "Neighbor on BGP configured interface\n"
a636c635 11890 "Display detailed prefix count information\n"
9973d184 11891 JSON_STR)
a636c635 11892{
d62a17ae 11893 int idx_peer = 6;
11894 struct peer *peer;
9f049418 11895 bool uj = use_json(argc, argv);
a636c635 11896
d62a17ae 11897 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11898 if (!peer)
11899 return CMD_WARNING;
11900
11901 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11902}
11903
d6902373
PG
11904DEFUN (show_ip_bgp_vpn_all_route_prefix,
11905 show_ip_bgp_vpn_all_route_prefix_cmd,
11906 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11907 SHOW_STR
11908 IP_STR
11909 BGP_STR
d6902373 11910 BGP_VPNVX_HELP_STR
91d37724
QY
11911 "Display information about all VPNv4 NLRIs\n"
11912 "Network in the BGP routing table to display\n"
3a2d747c 11913 "Network in the BGP routing table to display\n"
9973d184 11914 JSON_STR)
91d37724 11915{
d62a17ae 11916 int idx = 0;
11917 char *network = NULL;
11918 struct bgp *bgp = bgp_get_default();
11919 if (!bgp) {
11920 vty_out(vty, "Can't find default instance\n");
11921 return CMD_WARNING;
11922 }
87e34b58 11923
d62a17ae 11924 if (argv_find(argv, argc, "A.B.C.D", &idx))
11925 network = argv[idx]->arg;
11926 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11927 network = argv[idx]->arg;
11928 else {
11929 vty_out(vty, "Unable to figure out Network\n");
11930 return CMD_WARNING;
11931 }
87e34b58 11932
d62a17ae 11933 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11934 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11935}
d6902373 11936#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11937
44c69747
LK
11938DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11939 show_bgp_l2vpn_evpn_route_prefix_cmd,
11940 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11941 SHOW_STR
4c63a661
PG
11942 BGP_STR
11943 L2VPN_HELP_STR
11944 EVPN_HELP_STR
44c69747
LK
11945 "Network in the BGP routing table to display\n"
11946 "Network in the BGP routing table to display\n"
4c63a661
PG
11947 "Network in the BGP routing table to display\n"
11948 "Network in the BGP routing table to display\n"
11949 JSON_STR)
11950{
d62a17ae 11951 int idx = 0;
11952 char *network = NULL;
44c69747 11953 int prefix_check = 0;
a636c635 11954
44c69747
LK
11955 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11956 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11957 network = argv[idx]->arg;
44c69747 11958 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11959 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11960 network = argv[idx]->arg;
44c69747
LK
11961 prefix_check = 1;
11962 } else {
d62a17ae 11963 vty_out(vty, "Unable to figure out Network\n");
11964 return CMD_WARNING;
11965 }
44c69747
LK
11966 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11967 prefix_check, BGP_PATH_SHOW_ALL,
11968 use_json(argc, argv));
d62a17ae 11969}
11970
2f9bc755
DS
11971static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
11972 struct bgp_table *table, int *header1,
11973 int *header2, json_object *json,
11974 json_object *json_scode,
11975 json_object *json_ocode, bool wide)
11976{
11977 uint64_t version = table ? table->version : 0;
11978
11979 if (*header1) {
11980 if (json) {
11981 json_object_int_add(json, "bgpTableVersion", version);
11982 json_object_string_add(json, "bgpLocalRouterId",
11983 inet_ntoa(bgp->router_id));
11984 json_object_int_add(json, "defaultLocPrf",
11985 bgp->default_local_pref);
11986 json_object_int_add(json, "localAS", bgp->as);
11987 json_object_object_add(json, "bgpStatusCodes",
11988 json_scode);
11989 json_object_object_add(json, "bgpOriginCodes",
11990 json_ocode);
11991 } else {
11992 vty_out(vty,
11993 "BGP table version is %" PRIu64 ", local router ID is %s, vrf id ",
11994 version, inet_ntoa(bgp->router_id));
11995 if (bgp->vrf_id == VRF_UNKNOWN)
11996 vty_out(vty, "%s", VRFID_NONE_STR);
11997 else
11998 vty_out(vty, "%u", bgp->vrf_id);
11999 vty_out(vty, "\n");
12000 vty_out(vty, "Default local pref %u, ",
12001 bgp->default_local_pref);
12002 vty_out(vty, "local AS %u\n", bgp->as);
12003 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12004 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12005 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12006 }
12007 *header1 = 0;
12008 }
12009 if (*header2) {
12010 if (!json)
12011 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12012 : BGP_SHOW_HEADER));
12013 *header2 = 0;
12014 }
12015}
12016
d62a17ae 12017static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12018 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 12019 const char *rmap_name, bool use_json,
ae248832 12020 json_object *json, bool wide)
d62a17ae 12021{
12022 struct bgp_table *table;
12023 struct bgp_adj_in *ain;
12024 struct bgp_adj_out *adj;
74a630b6
NT
12025 unsigned long output_count = 0;
12026 unsigned long filtered_count = 0;
9bcb3eef 12027 struct bgp_dest *dest;
d62a17ae 12028 int header1 = 1;
12029 struct bgp *bgp;
12030 int header2 = 1;
12031 struct attr attr;
12032 int ret;
12033 struct update_subgroup *subgrp;
12034 json_object *json_scode = NULL;
12035 json_object *json_ocode = NULL;
12036 json_object *json_ar = NULL;
12037 struct peer_af *paf;
f99def61 12038 bool route_filtered;
d62a17ae 12039
12040 if (use_json) {
12041 json_scode = json_object_new_object();
12042 json_ocode = json_object_new_object();
12043 json_ar = json_object_new_object();
12044
12045 json_object_string_add(json_scode, "suppressed", "s");
12046 json_object_string_add(json_scode, "damped", "d");
12047 json_object_string_add(json_scode, "history", "h");
12048 json_object_string_add(json_scode, "valid", "*");
12049 json_object_string_add(json_scode, "best", ">");
12050 json_object_string_add(json_scode, "multipath", "=");
12051 json_object_string_add(json_scode, "internal", "i");
12052 json_object_string_add(json_scode, "ribFailure", "r");
12053 json_object_string_add(json_scode, "stale", "S");
12054 json_object_string_add(json_scode, "removed", "R");
12055
12056 json_object_string_add(json_ocode, "igp", "i");
12057 json_object_string_add(json_ocode, "egp", "e");
12058 json_object_string_add(json_ocode, "incomplete", "?");
12059 }
a636c635 12060
d62a17ae 12061 bgp = peer->bgp;
a636c635 12062
d62a17ae 12063 if (!bgp) {
12064 if (use_json) {
12065 json_object_string_add(json, "alert", "no BGP");
12066 vty_out(vty, "%s\n", json_object_to_json_string(json));
12067 json_object_free(json);
12068 } else
12069 vty_out(vty, "%% No bgp\n");
12070 return;
12071 }
a636c635 12072
c512a642
EDP
12073 /* labeled-unicast routes live in the unicast table */
12074 if (safi == SAFI_LABELED_UNICAST)
12075 table = bgp->rib[afi][SAFI_UNICAST];
12076 else
12077 table = bgp->rib[afi][safi];
d62a17ae 12078
12079 output_count = filtered_count = 0;
12080 subgrp = peer_subgroup(peer, afi, safi);
12081
6392aaa6 12082 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12083 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
12084 if (use_json) {
12085 json_object_int_add(json, "bgpTableVersion",
12086 table->version);
12087 json_object_string_add(json, "bgpLocalRouterId",
12088 inet_ntoa(bgp->router_id));
01eced22
AD
12089 json_object_int_add(json, "defaultLocPrf",
12090 bgp->default_local_pref);
12091 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12092 json_object_object_add(json, "bgpStatusCodes",
12093 json_scode);
12094 json_object_object_add(json, "bgpOriginCodes",
12095 json_ocode);
07d0c4ed
DA
12096 json_object_string_add(
12097 json, "bgpOriginatingDefaultNetwork",
12098 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12099 } else {
6cde4b45 12100 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
d62a17ae 12101 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
12102 if (bgp->vrf_id == VRF_UNKNOWN)
12103 vty_out(vty, "%s", VRFID_NONE_STR);
12104 else
12105 vty_out(vty, "%u", bgp->vrf_id);
12106 vty_out(vty, "\n");
01eced22
AD
12107 vty_out(vty, "Default local pref %u, ",
12108 bgp->default_local_pref);
12109 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12110 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12111 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12112 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12113
07d0c4ed
DA
12114 vty_out(vty, "Originating default network %s\n\n",
12115 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12116 }
12117 header1 = 0;
12118 }
a636c635 12119
9bcb3eef 12120 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12121 if (type == bgp_show_adj_route_received
12122 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12123 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12124 if (ain->peer != peer)
ea47320b 12125 continue;
6392aaa6 12126
2f9bc755
DS
12127 show_adj_route_header(
12128 vty, bgp, table, &header1, &header2,
12129 json, json_scode, json_ocode, wide);
6392aaa6 12130
6f4f49b2 12131 attr = *ain->attr;
f99def61
AD
12132 route_filtered = false;
12133
12134 /* Filter prefix using distribute list,
12135 * filter list or prefix list
12136 */
b54892e0 12137 const struct prefix *rn_p =
9bcb3eef 12138 bgp_dest_get_prefix(dest);
b54892e0
DS
12139 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12140 safi))
12141 == FILTER_DENY)
f99def61
AD
12142 route_filtered = true;
12143
12144 /* Filter prefix using route-map */
b54892e0
DS
12145 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12146 safi, rmap_name, NULL,
12147 0, NULL);
6392aaa6 12148
13c8e163
AD
12149 if (type == bgp_show_adj_route_filtered &&
12150 !route_filtered && ret != RMAP_DENY) {
b755861b 12151 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12152 continue;
d62a17ae 12153 }
6392aaa6 12154
13c8e163
AD
12155 if (type == bgp_show_adj_route_received &&
12156 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12157 filtered_count++;
12158
b54892e0 12159 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 12160 use_json, json_ar, wide);
b755861b 12161 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12162 output_count++;
d62a17ae 12163 }
6392aaa6 12164 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 12165 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 12166 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 12167 if (paf->peer != peer || !adj->attr)
924c3f6a 12168 continue;
d62a17ae 12169
2f9bc755
DS
12170 show_adj_route_header(
12171 vty, bgp, table, &header1,
12172 &header2, json, json_scode,
12173 json_ocode, wide);
d62a17ae 12174
b54892e0 12175 const struct prefix *rn_p =
9bcb3eef 12176 bgp_dest_get_prefix(dest);
b54892e0 12177
6f4f49b2 12178 attr = *adj->attr;
b755861b 12179 ret = bgp_output_modifier(
b54892e0 12180 peer, rn_p, &attr, afi, safi,
b755861b 12181 rmap_name);
f46d8e1e 12182
b755861b 12183 if (ret != RMAP_DENY) {
b54892e0
DS
12184 route_vty_out_tmp(
12185 vty, rn_p, &attr, safi,
ae248832
MK
12186 use_json, json_ar,
12187 wide);
b755861b
PM
12188 output_count++;
12189 } else {
12190 filtered_count++;
a2addae8 12191 }
b755861b
PM
12192
12193 bgp_attr_undup(&attr, adj->attr);
924c3f6a 12194 }
f20ce998
DS
12195 } else if (type == bgp_show_adj_route_bestpath) {
12196 struct bgp_path_info *pi;
12197
12198 show_adj_route_header(vty, bgp, table, &header1,
12199 &header2, json, json_scode,
12200 json_ocode, wide);
12201
12202 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
12203 pi = pi->next) {
12204 if (pi->peer != peer)
12205 continue;
12206
12207 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12208 continue;
12209
12210 route_vty_out_tmp(vty,
12211 bgp_dest_get_prefix(dest),
12212 pi->attr, safi, use_json,
12213 json_ar, wide);
12214 output_count++;
12215 }
d62a17ae 12216 }
12217 }
d62a17ae 12218
d62a17ae 12219 if (use_json) {
6392aaa6
PM
12220 json_object_object_add(json, "advertisedRoutes", json_ar);
12221 json_object_int_add(json, "totalPrefixCounter", output_count);
12222 json_object_int_add(json, "filteredPrefixCounter",
12223 filtered_count);
12224
996c9314
LB
12225 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12226 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
12227
12228 if (!output_count && !filtered_count) {
12229 json_object_free(json_scode);
12230 json_object_free(json_ocode);
12231 }
12232
d62a17ae 12233 json_object_free(json);
6392aaa6
PM
12234 } else if (output_count > 0) {
12235 if (filtered_count > 0)
12236 vty_out(vty,
12237 "\nTotal number of prefixes %ld (%ld filtered)\n",
12238 output_count, filtered_count);
12239 else
12240 vty_out(vty, "\nTotal number of prefixes %ld\n",
12241 output_count);
d62a17ae 12242 }
a636c635 12243}
2a71e9ce 12244
d62a17ae 12245static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12246 safi_t safi, enum bgp_show_adj_route_type type,
ae248832 12247 const char *rmap_name, bool use_json, bool wide)
0b16f239 12248{
d62a17ae 12249 json_object *json = NULL;
0b16f239 12250
d62a17ae 12251 if (use_json)
12252 json = json_object_new_object();
0b16f239 12253
d62a17ae 12254 if (!peer || !peer->afc[afi][safi]) {
12255 if (use_json) {
12256 json_object_string_add(
12257 json, "warning",
12258 "No such neighbor or address family");
12259 vty_out(vty, "%s\n", json_object_to_json_string(json));
12260 json_object_free(json);
12261 } else
12262 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 12263
d62a17ae 12264 return CMD_WARNING;
12265 }
12266
6392aaa6
PM
12267 if ((type == bgp_show_adj_route_received
12268 || type == bgp_show_adj_route_filtered)
d62a17ae 12269 && !CHECK_FLAG(peer->af_flags[afi][safi],
12270 PEER_FLAG_SOFT_RECONFIG)) {
12271 if (use_json) {
12272 json_object_string_add(
12273 json, "warning",
12274 "Inbound soft reconfiguration not enabled");
12275 vty_out(vty, "%s\n", json_object_to_json_string(json));
12276 json_object_free(json);
12277 } else
12278 vty_out(vty,
12279 "%% Inbound soft reconfiguration not enabled\n");
12280
12281 return CMD_WARNING;
12282 }
0b16f239 12283
ae248832
MK
12284 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json,
12285 wide);
0b16f239 12286
d62a17ae 12287 return CMD_SUCCESS;
a636c635 12288}
50ef26d4 12289
f20ce998
DS
12290DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
12291 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
12292 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]",
12293 SHOW_STR
12294 IP_STR
12295 BGP_STR
12296 BGP_INSTANCE_HELP_STR
12297 BGP_AFI_HELP_STR
12298 BGP_SAFI_WITH_LABEL_HELP_STR
12299 "Detailed information on TCP and BGP neighbor connections\n"
12300 "Neighbor to display information about\n"
12301 "Neighbor to display information about\n"
12302 "Neighbor on BGP configured interface\n"
12303 "Display the routes selected by best path\n"
12304 JSON_STR
12305 "Increase table width for longer prefixes\n")
12306{
12307 afi_t afi = AFI_IP6;
12308 safi_t safi = SAFI_UNICAST;
12309 char *rmap_name = NULL;
12310 char *peerstr = NULL;
12311 struct bgp *bgp = NULL;
12312 struct peer *peer;
12313 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
12314 int idx = 0;
12315
12316 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12317 &bgp, uj);
12318
12319 if (!idx)
12320 return CMD_WARNING;
12321
12322 argv_find(argv, argc, "neighbors", &idx);
12323 peerstr = argv[++idx]->arg;
12324
12325 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12326 if (!peer)
12327 return CMD_WARNING;
12328
12329 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide);
12330}
12331
ae248832 12332DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 12333 show_ip_bgp_instance_neighbor_advertised_route_cmd,
ae248832 12334 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
718e3744 12335 SHOW_STR
12336 IP_STR
12337 BGP_STR
a636c635 12338 BGP_INSTANCE_HELP_STR
7395a2c9 12339 BGP_AFI_HELP_STR
4dd6177e 12340 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12341 "Detailed information on TCP and BGP neighbor connections\n"
12342 "Neighbor to display information about\n"
12343 "Neighbor to display information about\n"
91d37724 12344 "Neighbor on BGP configured interface\n"
a636c635 12345 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
12346 "Display the received routes from neighbor\n"
12347 "Display the filtered routes received from neighbor\n"
a636c635
DW
12348 "Route-map to modify the attributes\n"
12349 "Name of the route map\n"
ae248832
MK
12350 JSON_STR
12351 "Increase table width for longer prefixes\n")
718e3744 12352{
d62a17ae 12353 afi_t afi = AFI_IP6;
12354 safi_t safi = SAFI_UNICAST;
12355 char *rmap_name = NULL;
12356 char *peerstr = NULL;
d62a17ae 12357 struct bgp *bgp = NULL;
12358 struct peer *peer;
6392aaa6 12359 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 12360 int idx = 0;
6392aaa6 12361
d62a17ae 12362 if (uj)
12363 argc--;
30a6a167 12364
9f049418
DS
12365 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12366 &bgp, uj);
12367 if (!idx)
12368 return CMD_WARNING;
12369
d62a17ae 12370 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12371 argv_find(argv, argc, "neighbors", &idx);
12372 peerstr = argv[++idx]->arg;
8c3deaae 12373
d62a17ae 12374 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12375 if (!peer)
12376 return CMD_WARNING;
856ca177 12377
d62a17ae 12378 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12379 type = bgp_show_adj_route_advertised;
12380 else if (argv_find(argv, argc, "received-routes", &idx))
12381 type = bgp_show_adj_route_received;
12382 else if (argv_find(argv, argc, "filtered-routes", &idx))
12383 type = bgp_show_adj_route_filtered;
12384
d62a17ae 12385 if (argv_find(argv, argc, "route-map", &idx))
12386 rmap_name = argv[++idx]->arg;
95cbbd2a 12387
ae248832 12388 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide);
95cbbd2a
ML
12389}
12390
718e3744 12391DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12392 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12393 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12394 SHOW_STR
12395 IP_STR
12396 BGP_STR
8c3deaae
QY
12397 "Address Family\n"
12398 "Address Family\n"
718e3744 12399 "Address Family modifier\n"
12400 "Detailed information on TCP and BGP neighbor connections\n"
12401 "Neighbor to display information about\n"
12402 "Neighbor to display information about\n"
91d37724 12403 "Neighbor on BGP configured interface\n"
718e3744 12404 "Display information received from a BGP neighbor\n"
856ca177 12405 "Display the prefixlist filter\n"
9973d184 12406 JSON_STR)
718e3744 12407{
d62a17ae 12408 afi_t afi = AFI_IP6;
12409 safi_t safi = SAFI_UNICAST;
12410 char *peerstr = NULL;
12411
12412 char name[BUFSIZ];
12413 union sockunion su;
12414 struct peer *peer;
12415 int count, ret;
12416
12417 int idx = 0;
12418
12419 /* show [ip] bgp */
12420 if (argv_find(argv, argc, "ip", &idx))
12421 afi = AFI_IP;
12422 /* [<ipv4|ipv6> [unicast]] */
12423 if (argv_find(argv, argc, "ipv4", &idx))
12424 afi = AFI_IP;
12425 if (argv_find(argv, argc, "ipv6", &idx))
12426 afi = AFI_IP6;
12427 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12428 argv_find(argv, argc, "neighbors", &idx);
12429 peerstr = argv[++idx]->arg;
12430
9f049418 12431 bool uj = use_json(argc, argv);
d62a17ae 12432
12433 ret = str2sockunion(peerstr, &su);
12434 if (ret < 0) {
12435 peer = peer_lookup_by_conf_if(NULL, peerstr);
12436 if (!peer) {
12437 if (uj)
12438 vty_out(vty, "{}\n");
12439 else
12440 vty_out(vty,
12441 "%% Malformed address or name: %s\n",
12442 peerstr);
12443 return CMD_WARNING;
12444 }
12445 } else {
12446 peer = peer_lookup(NULL, &su);
12447 if (!peer) {
12448 if (uj)
12449 vty_out(vty, "{}\n");
12450 else
12451 vty_out(vty, "No peer\n");
12452 return CMD_WARNING;
12453 }
12454 }
718e3744 12455
4ced1a2c 12456 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 12457 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12458 if (count) {
12459 if (!uj)
12460 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12461 get_afi_safi_str(afi, safi, false));
d62a17ae 12462 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12463 } else {
12464 if (uj)
12465 vty_out(vty, "{}\n");
12466 else
12467 vty_out(vty, "No functional output\n");
12468 }
718e3744 12469
d62a17ae 12470 return CMD_SUCCESS;
12471}
12472
12473static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12474 afi_t afi, safi_t safi,
9f049418 12475 enum bgp_show_type type, bool use_json)
d62a17ae 12476{
8a893163
DW
12477 /* labeled-unicast routes live in the unicast table */
12478 if (safi == SAFI_LABELED_UNICAST)
12479 safi = SAFI_UNICAST;
12480
d62a17ae 12481 if (!peer || !peer->afc[afi][safi]) {
12482 if (use_json) {
12483 json_object *json_no = NULL;
12484 json_no = json_object_new_object();
12485 json_object_string_add(
12486 json_no, "warning",
12487 "No such neighbor or address family");
12488 vty_out(vty, "%s\n",
12489 json_object_to_json_string(json_no));
12490 json_object_free(json_no);
12491 } else
12492 vty_out(vty, "%% No such neighbor or address family\n");
12493 return CMD_WARNING;
12494 }
47fc97cc 12495
ae248832
MK
12496 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json,
12497 false);
718e3744 12498}
12499
dba3c1d3
PG
12500DEFUN (show_ip_bgp_flowspec_routes_detailed,
12501 show_ip_bgp_flowspec_routes_detailed_cmd,
12502 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12503 SHOW_STR
12504 IP_STR
12505 BGP_STR
12506 BGP_INSTANCE_HELP_STR
12507 BGP_AFI_HELP_STR
12508 "SAFI Flowspec\n"
12509 "Detailed information on flowspec entries\n"
12510 JSON_STR)
12511{
12512 afi_t afi = AFI_IP;
12513 safi_t safi = SAFI_UNICAST;
12514 struct bgp *bgp = NULL;
12515 int idx = 0;
9f049418
DS
12516 bool uj = use_json(argc, argv);
12517
12518 if (uj)
12519 argc--;
dba3c1d3
PG
12520
12521 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12522 &bgp, uj);
dba3c1d3
PG
12523 if (!idx)
12524 return CMD_WARNING;
12525
ae248832
MK
12526 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj,
12527 false);
dba3c1d3
PG
12528}
12529
718e3744 12530DEFUN (show_ip_bgp_neighbor_routes,
12531 show_ip_bgp_neighbor_routes_cmd,
3efd0893 12532 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 12533 SHOW_STR
12534 IP_STR
12535 BGP_STR
8386ac43 12536 BGP_INSTANCE_HELP_STR
4f280b15 12537 BGP_AFI_HELP_STR
4dd6177e 12538 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12539 "Detailed information on TCP and BGP neighbor connections\n"
12540 "Neighbor to display information about\n"
12541 "Neighbor to display information about\n"
91d37724 12542 "Neighbor on BGP configured interface\n"
2525cf39 12543 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12544 "Display the dampened routes received from neighbor\n"
12545 "Display routes learned from neighbor\n"
9973d184 12546 JSON_STR)
718e3744 12547{
d62a17ae 12548 char *peerstr = NULL;
12549 struct bgp *bgp = NULL;
12550 afi_t afi = AFI_IP6;
12551 safi_t safi = SAFI_UNICAST;
12552 struct peer *peer;
12553 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12554 int idx = 0;
9f049418
DS
12555 bool uj = use_json(argc, argv);
12556
12557 if (uj)
12558 argc--;
bb46e94f 12559
d62a17ae 12560 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12561 &bgp, uj);
d62a17ae 12562 if (!idx)
12563 return CMD_WARNING;
c493f2d8 12564
d62a17ae 12565 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12566 argv_find(argv, argc, "neighbors", &idx);
12567 peerstr = argv[++idx]->arg;
8c3deaae 12568
d62a17ae 12569 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12570 if (!peer)
d62a17ae 12571 return CMD_WARNING;
bb46e94f 12572
d62a17ae 12573 if (argv_find(argv, argc, "flap-statistics", &idx))
12574 sh_type = bgp_show_type_flap_neighbor;
12575 else if (argv_find(argv, argc, "dampened-routes", &idx))
12576 sh_type = bgp_show_type_damp_neighbor;
12577 else if (argv_find(argv, argc, "routes", &idx))
12578 sh_type = bgp_show_type_neighbor;
2525cf39 12579
d62a17ae 12580 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12581}
6b0655a2 12582
734b349e 12583struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12584
d62a17ae 12585struct bgp_distance {
12586 /* Distance value for the IP source prefix. */
d7c0a89a 12587 uint8_t distance;
718e3744 12588
d62a17ae 12589 /* Name of the access-list to be matched. */
12590 char *access_list;
718e3744 12591};
12592
4f280b15
LB
12593DEFUN (show_bgp_afi_vpn_rd_route,
12594 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12595 "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
12596 SHOW_STR
12597 BGP_STR
12598 BGP_AFI_HELP_STR
12599 "Address Family modifier\n"
12600 "Display information for a route distinguisher\n"
12601 "Route Distinguisher\n"
7395a2c9
DS
12602 "Network in the BGP routing table to display\n"
12603 "Network in the BGP routing table to display\n"
12604 JSON_STR)
4f280b15 12605{
d62a17ae 12606 int ret;
12607 struct prefix_rd prd;
12608 afi_t afi = AFI_MAX;
12609 int idx = 0;
4f280b15 12610
ff6566f3
DS
12611 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12612 vty_out(vty, "%% Malformed Address Family\n");
12613 return CMD_WARNING;
12614 }
12615
d62a17ae 12616 ret = str2prefix_rd(argv[5]->arg, &prd);
12617 if (!ret) {
12618 vty_out(vty, "%% Malformed Route Distinguisher\n");
12619 return CMD_WARNING;
12620 }
ff6566f3 12621
d62a17ae 12622 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12623 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12624}
12625
d62a17ae 12626static struct bgp_distance *bgp_distance_new(void)
718e3744 12627{
d62a17ae 12628 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12629}
12630
d62a17ae 12631static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12632{
d62a17ae 12633 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12634}
12635
d62a17ae 12636static int bgp_distance_set(struct vty *vty, const char *distance_str,
12637 const char *ip_str, const char *access_list_str)
718e3744 12638{
d62a17ae 12639 int ret;
12640 afi_t afi;
12641 safi_t safi;
12642 struct prefix p;
d7c0a89a 12643 uint8_t distance;
9bcb3eef 12644 struct bgp_dest *dest;
d62a17ae 12645 struct bgp_distance *bdistance;
718e3744 12646
d62a17ae 12647 afi = bgp_node_afi(vty);
12648 safi = bgp_node_safi(vty);
734b349e 12649
d62a17ae 12650 ret = str2prefix(ip_str, &p);
12651 if (ret == 0) {
12652 vty_out(vty, "Malformed prefix\n");
12653 return CMD_WARNING_CONFIG_FAILED;
12654 }
718e3744 12655
d62a17ae 12656 distance = atoi(distance_str);
718e3744 12657
d62a17ae 12658 /* Get BGP distance node. */
9bcb3eef
DS
12659 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
12660 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 12661 if (bdistance)
9bcb3eef 12662 bgp_dest_unlock_node(dest);
ca2e160d 12663 else {
d62a17ae 12664 bdistance = bgp_distance_new();
9bcb3eef 12665 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 12666 }
718e3744 12667
d62a17ae 12668 /* Set distance value. */
12669 bdistance->distance = distance;
718e3744 12670
d62a17ae 12671 /* Reset access-list configuration. */
e1b36e13 12672 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12673 if (access_list_str)
12674 bdistance->access_list =
12675 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12676
d62a17ae 12677 return CMD_SUCCESS;
718e3744 12678}
12679
d62a17ae 12680static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12681 const char *ip_str, const char *access_list_str)
718e3744 12682{
d62a17ae 12683 int ret;
12684 afi_t afi;
12685 safi_t safi;
12686 struct prefix p;
12687 int distance;
9bcb3eef 12688 struct bgp_dest *dest;
d62a17ae 12689 struct bgp_distance *bdistance;
718e3744 12690
d62a17ae 12691 afi = bgp_node_afi(vty);
12692 safi = bgp_node_safi(vty);
734b349e 12693
d62a17ae 12694 ret = str2prefix(ip_str, &p);
12695 if (ret == 0) {
12696 vty_out(vty, "Malformed prefix\n");
12697 return CMD_WARNING_CONFIG_FAILED;
12698 }
718e3744 12699
9bcb3eef
DS
12700 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
12701 if (!dest) {
d62a17ae 12702 vty_out(vty, "Can't find specified prefix\n");
12703 return CMD_WARNING_CONFIG_FAILED;
12704 }
718e3744 12705
9bcb3eef 12706 bdistance = bgp_dest_get_bgp_distance_info(dest);
d62a17ae 12707 distance = atoi(distance_str);
1f9a9fff 12708
d62a17ae 12709 if (bdistance->distance != distance) {
12710 vty_out(vty, "Distance does not match configured\n");
12711 return CMD_WARNING_CONFIG_FAILED;
12712 }
718e3744 12713
0a22ddfb 12714 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12715 bgp_distance_free(bdistance);
718e3744 12716
9bcb3eef
DS
12717 bgp_dest_set_bgp_path_info(dest, NULL);
12718 bgp_dest_unlock_node(dest);
12719 bgp_dest_unlock_node(dest);
718e3744 12720
d62a17ae 12721 return CMD_SUCCESS;
718e3744 12722}
12723
718e3744 12724/* Apply BGP information to distance method. */
b8685f9b 12725uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12726 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12727{
9bcb3eef 12728 struct bgp_dest *dest;
d62a17ae 12729 struct prefix q;
12730 struct peer *peer;
12731 struct bgp_distance *bdistance;
12732 struct access_list *alist;
12733 struct bgp_static *bgp_static;
12734
12735 if (!bgp)
12736 return 0;
12737
40381db7 12738 peer = pinfo->peer;
d62a17ae 12739
7b7d48e5
DS
12740 if (pinfo->attr->distance)
12741 return pinfo->attr->distance;
12742
d62a17ae 12743 /* Check source address. */
12744 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
12745 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
12746 if (dest) {
12747 bdistance = bgp_dest_get_bgp_distance_info(dest);
12748 bgp_dest_unlock_node(dest);
d62a17ae 12749
12750 if (bdistance->access_list) {
12751 alist = access_list_lookup(afi, bdistance->access_list);
12752 if (alist
12753 && access_list_apply(alist, p) == FILTER_PERMIT)
12754 return bdistance->distance;
12755 } else
12756 return bdistance->distance;
718e3744 12757 }
718e3744 12758
d62a17ae 12759 /* Backdoor check. */
9bcb3eef
DS
12760 dest = bgp_node_lookup(bgp->route[afi][safi], p);
12761 if (dest) {
12762 bgp_static = bgp_dest_get_bgp_static_info(dest);
12763 bgp_dest_unlock_node(dest);
718e3744 12764
d62a17ae 12765 if (bgp_static->backdoor) {
12766 if (bgp->distance_local[afi][safi])
12767 return bgp->distance_local[afi][safi];
12768 else
12769 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12770 }
718e3744 12771 }
718e3744 12772
d62a17ae 12773 if (peer->sort == BGP_PEER_EBGP) {
12774 if (bgp->distance_ebgp[afi][safi])
12775 return bgp->distance_ebgp[afi][safi];
12776 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12777 } else {
12778 if (bgp->distance_ibgp[afi][safi])
12779 return bgp->distance_ibgp[afi][safi];
12780 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12781 }
718e3744 12782}
12783
a612fb77
DA
12784/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12785 * we should tell ZEBRA update the routes for a specific
12786 * AFI/SAFI to reflect changes in RIB.
12787 */
8b54bc30
DA
12788static void bgp_announce_routes_distance_update(struct bgp *bgp,
12789 afi_t update_afi,
12790 safi_t update_safi)
a612fb77
DA
12791{
12792 afi_t afi;
12793 safi_t safi;
12794
12795 FOREACH_AFI_SAFI (afi, safi) {
12796 if (!bgp_fibupd_safi(safi))
12797 continue;
12798
8b54bc30
DA
12799 if (afi != update_afi && safi != update_safi)
12800 continue;
12801
12802 if (BGP_DEBUG(zebra, ZEBRA))
12803 zlog_debug(
12804 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12805 __func__, afi, safi);
12806 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12807 }
12808}
12809
718e3744 12810DEFUN (bgp_distance,
12811 bgp_distance_cmd,
6147e2c6 12812 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12813 "Define an administrative distance\n"
12814 "BGP distance\n"
12815 "Distance for routes external to the AS\n"
12816 "Distance for routes internal to the AS\n"
12817 "Distance for local routes\n")
12818{
d62a17ae 12819 VTY_DECLVAR_CONTEXT(bgp, bgp);
12820 int idx_number = 2;
12821 int idx_number_2 = 3;
12822 int idx_number_3 = 4;
8b54bc30
DA
12823 int distance_ebgp = atoi(argv[idx_number]->arg);
12824 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12825 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12826 afi_t afi;
12827 safi_t safi;
718e3744 12828
d62a17ae 12829 afi = bgp_node_afi(vty);
12830 safi = bgp_node_safi(vty);
718e3744 12831
8b54bc30
DA
12832 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12833 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12834 || bgp->distance_local[afi][safi] != distance_local) {
12835 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12836 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12837 bgp->distance_local[afi][safi] = distance_local;
12838 bgp_announce_routes_distance_update(bgp, afi, safi);
12839 }
d62a17ae 12840 return CMD_SUCCESS;
718e3744 12841}
12842
12843DEFUN (no_bgp_distance,
12844 no_bgp_distance_cmd,
a636c635 12845 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12846 NO_STR
12847 "Define an administrative distance\n"
12848 "BGP distance\n"
12849 "Distance for routes external to the AS\n"
12850 "Distance for routes internal to the AS\n"
12851 "Distance for local routes\n")
12852{
d62a17ae 12853 VTY_DECLVAR_CONTEXT(bgp, bgp);
12854 afi_t afi;
12855 safi_t safi;
718e3744 12856
d62a17ae 12857 afi = bgp_node_afi(vty);
12858 safi = bgp_node_safi(vty);
718e3744 12859
8b54bc30
DA
12860 if (bgp->distance_ebgp[afi][safi] != 0
12861 || bgp->distance_ibgp[afi][safi] != 0
12862 || bgp->distance_local[afi][safi] != 0) {
12863 bgp->distance_ebgp[afi][safi] = 0;
12864 bgp->distance_ibgp[afi][safi] = 0;
12865 bgp->distance_local[afi][safi] = 0;
12866 bgp_announce_routes_distance_update(bgp, afi, safi);
12867 }
d62a17ae 12868 return CMD_SUCCESS;
718e3744 12869}
12870
718e3744 12871
12872DEFUN (bgp_distance_source,
12873 bgp_distance_source_cmd,
6147e2c6 12874 "distance (1-255) A.B.C.D/M",
718e3744 12875 "Define an administrative distance\n"
12876 "Administrative distance\n"
12877 "IP source prefix\n")
12878{
d62a17ae 12879 int idx_number = 1;
12880 int idx_ipv4_prefixlen = 2;
12881 bgp_distance_set(vty, argv[idx_number]->arg,
12882 argv[idx_ipv4_prefixlen]->arg, NULL);
12883 return CMD_SUCCESS;
718e3744 12884}
12885
12886DEFUN (no_bgp_distance_source,
12887 no_bgp_distance_source_cmd,
6147e2c6 12888 "no distance (1-255) A.B.C.D/M",
718e3744 12889 NO_STR
12890 "Define an administrative distance\n"
12891 "Administrative distance\n"
12892 "IP source prefix\n")
12893{
d62a17ae 12894 int idx_number = 2;
12895 int idx_ipv4_prefixlen = 3;
12896 bgp_distance_unset(vty, argv[idx_number]->arg,
12897 argv[idx_ipv4_prefixlen]->arg, NULL);
12898 return CMD_SUCCESS;
718e3744 12899}
12900
12901DEFUN (bgp_distance_source_access_list,
12902 bgp_distance_source_access_list_cmd,
6147e2c6 12903 "distance (1-255) A.B.C.D/M WORD",
718e3744 12904 "Define an administrative distance\n"
12905 "Administrative distance\n"
12906 "IP source prefix\n"
12907 "Access list name\n")
12908{
d62a17ae 12909 int idx_number = 1;
12910 int idx_ipv4_prefixlen = 2;
12911 int idx_word = 3;
12912 bgp_distance_set(vty, argv[idx_number]->arg,
12913 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12914 return CMD_SUCCESS;
718e3744 12915}
12916
12917DEFUN (no_bgp_distance_source_access_list,
12918 no_bgp_distance_source_access_list_cmd,
6147e2c6 12919 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12920 NO_STR
12921 "Define an administrative distance\n"
12922 "Administrative distance\n"
12923 "IP source prefix\n"
12924 "Access list name\n")
12925{
d62a17ae 12926 int idx_number = 2;
12927 int idx_ipv4_prefixlen = 3;
12928 int idx_word = 4;
12929 bgp_distance_unset(vty, argv[idx_number]->arg,
12930 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12931 return CMD_SUCCESS;
718e3744 12932}
6b0655a2 12933
734b349e
MZ
12934DEFUN (ipv6_bgp_distance_source,
12935 ipv6_bgp_distance_source_cmd,
39e92c06 12936 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12937 "Define an administrative distance\n"
12938 "Administrative distance\n"
12939 "IP source prefix\n")
12940{
d62a17ae 12941 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12942 return CMD_SUCCESS;
734b349e
MZ
12943}
12944
12945DEFUN (no_ipv6_bgp_distance_source,
12946 no_ipv6_bgp_distance_source_cmd,
39e92c06 12947 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12948 NO_STR
12949 "Define an administrative distance\n"
12950 "Administrative distance\n"
12951 "IP source prefix\n")
12952{
d62a17ae 12953 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12954 return CMD_SUCCESS;
734b349e
MZ
12955}
12956
12957DEFUN (ipv6_bgp_distance_source_access_list,
12958 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12959 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12960 "Define an administrative distance\n"
12961 "Administrative distance\n"
12962 "IP source prefix\n"
12963 "Access list name\n")
12964{
d62a17ae 12965 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12966 return CMD_SUCCESS;
734b349e
MZ
12967}
12968
12969DEFUN (no_ipv6_bgp_distance_source_access_list,
12970 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12971 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12972 NO_STR
12973 "Define an administrative distance\n"
12974 "Administrative distance\n"
12975 "IP source prefix\n"
12976 "Access list name\n")
12977{
d62a17ae 12978 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12979 return CMD_SUCCESS;
734b349e
MZ
12980}
12981
718e3744 12982DEFUN (bgp_damp_set,
12983 bgp_damp_set_cmd,
31500417 12984 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12985 "BGP Specific commands\n"
12986 "Enable route-flap dampening\n"
12987 "Half-life time for the penalty\n"
12988 "Value to start reusing a route\n"
12989 "Value to start suppressing a route\n"
12990 "Maximum duration to suppress a stable route\n")
12991{
d62a17ae 12992 VTY_DECLVAR_CONTEXT(bgp, bgp);
12993 int idx_half_life = 2;
12994 int idx_reuse = 3;
12995 int idx_suppress = 4;
12996 int idx_max_suppress = 5;
12997 int half = DEFAULT_HALF_LIFE * 60;
12998 int reuse = DEFAULT_REUSE;
12999 int suppress = DEFAULT_SUPPRESS;
13000 int max = 4 * half;
13001
13002 if (argc == 6) {
13003 half = atoi(argv[idx_half_life]->arg) * 60;
13004 reuse = atoi(argv[idx_reuse]->arg);
13005 suppress = atoi(argv[idx_suppress]->arg);
13006 max = atoi(argv[idx_max_suppress]->arg) * 60;
13007 } else if (argc == 3) {
13008 half = atoi(argv[idx_half_life]->arg) * 60;
13009 max = 4 * half;
13010 }
718e3744 13011
6d24b7cc
DS
13012 /*
13013 * These can't be 0 but our SA doesn't understand the
13014 * way our cli is constructed
13015 */
13016 assert(reuse);
13017 assert(half);
d62a17ae 13018 if (suppress < reuse) {
13019 vty_out(vty,
13020 "Suppress value cannot be less than reuse value \n");
13021 return 0;
13022 }
7ebe9748 13023
d62a17ae 13024 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
13025 reuse, suppress, max);
718e3744 13026}
13027
718e3744 13028DEFUN (bgp_damp_unset,
13029 bgp_damp_unset_cmd,
d04c479d 13030 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 13031 NO_STR
13032 "BGP Specific commands\n"
16cedbb0
QY
13033 "Enable route-flap dampening\n"
13034 "Half-life time for the penalty\n"
13035 "Value to start reusing a route\n"
13036 "Value to start suppressing a route\n"
13037 "Maximum duration to suppress a stable route\n")
718e3744 13038{
d62a17ae 13039 VTY_DECLVAR_CONTEXT(bgp, bgp);
13040 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 13041}
13042
718e3744 13043/* Display specified route of BGP table. */
d62a17ae 13044static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13045 const char *ip_str, afi_t afi, safi_t safi,
13046 struct prefix_rd *prd, int prefix_check)
13047{
13048 int ret;
13049 struct prefix match;
9bcb3eef
DS
13050 struct bgp_dest *dest;
13051 struct bgp_dest *rm;
40381db7
DS
13052 struct bgp_path_info *pi;
13053 struct bgp_path_info *pi_temp;
d62a17ae 13054 struct bgp *bgp;
13055 struct bgp_table *table;
13056
13057 /* BGP structure lookup. */
13058 if (view_name) {
13059 bgp = bgp_lookup_by_name(view_name);
13060 if (bgp == NULL) {
13061 vty_out(vty, "%% Can't find BGP instance %s\n",
13062 view_name);
13063 return CMD_WARNING;
13064 }
13065 } else {
13066 bgp = bgp_get_default();
13067 if (bgp == NULL) {
13068 vty_out(vty, "%% No BGP process is configured\n");
13069 return CMD_WARNING;
13070 }
718e3744 13071 }
718e3744 13072
d62a17ae 13073 /* Check IP address argument. */
13074 ret = str2prefix(ip_str, &match);
13075 if (!ret) {
13076 vty_out(vty, "%% address is malformed\n");
13077 return CMD_WARNING;
13078 }
718e3744 13079
d62a17ae 13080 match.family = afi2family(afi);
13081
13082 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13083 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
13084 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
13085 dest = bgp_route_next(dest)) {
13086 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13087
9bcb3eef 13088 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 13089 continue;
9bcb3eef 13090 table = bgp_dest_get_bgp_table_info(dest);
67009e22 13091 if (!table)
ea47320b
DL
13092 continue;
13093 if ((rm = bgp_node_match(table, &match)) == NULL)
13094 continue;
d62a17ae 13095
9bcb3eef 13096 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 13097
ea47320b 13098 if (!prefix_check
b54892e0 13099 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 13100 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
13101 while (pi) {
13102 if (pi->extra && pi->extra->damp_info) {
13103 pi_temp = pi->next;
ea47320b 13104 bgp_damp_info_free(
40381db7 13105 pi->extra->damp_info,
a935f597 13106 1, afi, safi);
40381db7 13107 pi = pi_temp;
ea47320b 13108 } else
40381db7 13109 pi = pi->next;
d62a17ae 13110 }
ea47320b
DL
13111 }
13112
9bcb3eef 13113 bgp_dest_unlock_node(rm);
d62a17ae 13114 }
13115 } else {
9bcb3eef 13116 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 13117 != NULL) {
9bcb3eef 13118 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13119
d62a17ae 13120 if (!prefix_check
9bcb3eef
DS
13121 || dest_p->prefixlen == match.prefixlen) {
13122 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
13123 while (pi) {
13124 if (pi->extra && pi->extra->damp_info) {
13125 pi_temp = pi->next;
d62a17ae 13126 bgp_damp_info_free(
40381db7 13127 pi->extra->damp_info,
a935f597 13128 1, afi, safi);
40381db7 13129 pi = pi_temp;
d62a17ae 13130 } else
40381db7 13131 pi = pi->next;
d62a17ae 13132 }
13133 }
13134
9bcb3eef 13135 bgp_dest_unlock_node(dest);
d62a17ae 13136 }
13137 }
718e3744 13138
d62a17ae 13139 return CMD_SUCCESS;
718e3744 13140}
13141
13142DEFUN (clear_ip_bgp_dampening,
13143 clear_ip_bgp_dampening_cmd,
13144 "clear ip bgp dampening",
13145 CLEAR_STR
13146 IP_STR
13147 BGP_STR
13148 "Clear route flap dampening information\n")
13149{
a935f597 13150 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 13151 return CMD_SUCCESS;
718e3744 13152}
13153
13154DEFUN (clear_ip_bgp_dampening_prefix,
13155 clear_ip_bgp_dampening_prefix_cmd,
13156 "clear ip bgp dampening A.B.C.D/M",
13157 CLEAR_STR
13158 IP_STR
13159 BGP_STR
13160 "Clear route flap dampening information\n"
0c7b1b01 13161 "IPv4 prefix\n")
718e3744 13162{
d62a17ae 13163 int idx_ipv4_prefixlen = 4;
13164 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
13165 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 13166}
13167
13168DEFUN (clear_ip_bgp_dampening_address,
13169 clear_ip_bgp_dampening_address_cmd,
13170 "clear ip bgp dampening A.B.C.D",
13171 CLEAR_STR
13172 IP_STR
13173 BGP_STR
13174 "Clear route flap dampening information\n"
13175 "Network to clear damping information\n")
13176{
d62a17ae 13177 int idx_ipv4 = 4;
13178 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
13179 SAFI_UNICAST, NULL, 0);
718e3744 13180}
13181
13182DEFUN (clear_ip_bgp_dampening_address_mask,
13183 clear_ip_bgp_dampening_address_mask_cmd,
13184 "clear ip bgp dampening A.B.C.D A.B.C.D",
13185 CLEAR_STR
13186 IP_STR
13187 BGP_STR
13188 "Clear route flap dampening information\n"
13189 "Network to clear damping information\n"
13190 "Network mask\n")
13191{
d62a17ae 13192 int idx_ipv4 = 4;
13193 int idx_ipv4_2 = 5;
13194 int ret;
13195 char prefix_str[BUFSIZ];
718e3744 13196
d62a17ae 13197 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
13198 prefix_str);
13199 if (!ret) {
13200 vty_out(vty, "%% Inconsistent address and mask\n");
13201 return CMD_WARNING;
13202 }
718e3744 13203
d62a17ae 13204 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
13205 NULL, 0);
718e3744 13206}
6b0655a2 13207
e3b78da8 13208static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
13209{
13210 struct vty *vty = arg;
e3b78da8 13211 struct peer *peer = bucket->data;
825d9834
DS
13212 char buf[SU_ADDRSTRLEN];
13213
13214 vty_out(vty, "\tPeer: %s %s\n", peer->host,
13215 sockunion2str(&peer->su, buf, sizeof(buf)));
13216}
13217
2a0e69ae
DS
13218DEFUN (show_bgp_listeners,
13219 show_bgp_listeners_cmd,
13220 "show bgp listeners",
13221 SHOW_STR
13222 BGP_STR
13223 "Display Listen Sockets and who created them\n")
13224{
13225 bgp_dump_listener_info(vty);
13226
13227 return CMD_SUCCESS;
13228}
13229
825d9834
DS
13230DEFUN (show_bgp_peerhash,
13231 show_bgp_peerhash_cmd,
13232 "show bgp peerhash",
13233 SHOW_STR
13234 BGP_STR
13235 "Display information about the BGP peerhash\n")
13236{
13237 struct list *instances = bm->bgp;
13238 struct listnode *node;
13239 struct bgp *bgp;
13240
13241 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
13242 vty_out(vty, "BGP: %s\n", bgp->name);
13243 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
13244 vty);
13245 }
13246
13247 return CMD_SUCCESS;
13248}
13249
587ff0fd 13250/* also used for encap safi */
2b791107
DL
13251static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
13252 afi_t afi, safi_t safi)
d62a17ae 13253{
9bcb3eef
DS
13254 struct bgp_dest *pdest;
13255 struct bgp_dest *dest;
d62a17ae 13256 struct bgp_table *table;
b54892e0
DS
13257 const struct prefix *p;
13258 const struct prefix_rd *prd;
d62a17ae 13259 struct bgp_static *bgp_static;
13260 mpls_label_t label;
13261 char buf[SU_ADDRSTRLEN];
13262 char rdbuf[RD_ADDRSTRLEN];
13263
13264 /* Network configuration. */
9bcb3eef
DS
13265 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13266 pdest = bgp_route_next(pdest)) {
13267 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13268 if (!table)
ea47320b 13269 continue;
d62a17ae 13270
9bcb3eef
DS
13271 for (dest = bgp_table_top(table); dest;
13272 dest = bgp_route_next(dest)) {
13273 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13274 if (bgp_static == NULL)
ea47320b 13275 continue;
d62a17ae 13276
9bcb3eef
DS
13277 p = bgp_dest_get_prefix(dest);
13278 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13279 pdest);
d62a17ae 13280
ea47320b 13281 /* "network" configuration display. */
06b9f471 13282 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
13283 label = decode_label(&bgp_static->label);
13284
13285 vty_out(vty, " network %s/%d rd %s",
13286 inet_ntop(p->family, &p->u.prefix, buf,
13287 SU_ADDRSTRLEN),
13288 p->prefixlen, rdbuf);
13289 if (safi == SAFI_MPLS_VPN)
13290 vty_out(vty, " label %u", label);
13291
13292 if (bgp_static->rmap.name)
13293 vty_out(vty, " route-map %s",
13294 bgp_static->rmap.name);
e2a86ad9
DS
13295
13296 if (bgp_static->backdoor)
13297 vty_out(vty, " backdoor");
13298
ea47320b
DL
13299 vty_out(vty, "\n");
13300 }
13301 }
d62a17ae 13302}
13303
2b791107
DL
13304static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
13305 afi_t afi, safi_t safi)
d62a17ae 13306{
9bcb3eef
DS
13307 struct bgp_dest *pdest;
13308 struct bgp_dest *dest;
d62a17ae 13309 struct bgp_table *table;
b54892e0
DS
13310 const struct prefix *p;
13311 const struct prefix_rd *prd;
d62a17ae 13312 struct bgp_static *bgp_static;
ff44f570 13313 char buf[PREFIX_STRLEN * 2];
d62a17ae 13314 char buf2[SU_ADDRSTRLEN];
13315 char rdbuf[RD_ADDRSTRLEN];
0a50c248 13316 char esi_buf[ESI_BYTES];
d62a17ae 13317
13318 /* Network configuration. */
9bcb3eef
DS
13319 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13320 pdest = bgp_route_next(pdest)) {
13321 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13322 if (!table)
ea47320b 13323 continue;
d62a17ae 13324
9bcb3eef
DS
13325 for (dest = bgp_table_top(table); dest;
13326 dest = bgp_route_next(dest)) {
13327 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13328 if (bgp_static == NULL)
ea47320b 13329 continue;
d62a17ae 13330
ea47320b 13331 char *macrouter = NULL;
d62a17ae 13332
ea47320b
DL
13333 if (bgp_static->router_mac)
13334 macrouter = prefix_mac2str(
13335 bgp_static->router_mac, NULL, 0);
13336 if (bgp_static->eth_s_id)
0a50c248
AK
13337 esi_to_str(bgp_static->eth_s_id,
13338 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
13339 p = bgp_dest_get_prefix(dest);
13340 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 13341
ea47320b 13342 /* "network" configuration display. */
06b9f471 13343 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
13344 if (p->u.prefix_evpn.route_type == 5) {
13345 char local_buf[PREFIX_STRLEN];
3714a385 13346 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
13347 struct prefix_evpn *)p)
13348 ? AF_INET
13349 : AF_INET6;
3714a385 13350 inet_ntop(family,
13351 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 13352 local_buf, PREFIX_STRLEN);
772270f3
QY
13353 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
13354 p->u.prefix_evpn.prefix_addr
13355 .ip_prefix_length);
197cb530
PG
13356 } else {
13357 prefix2str(p, buf, sizeof(buf));
13358 }
ea47320b 13359
a4d82a8a
PZ
13360 if (bgp_static->gatewayIp.family == AF_INET
13361 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
13362 inet_ntop(bgp_static->gatewayIp.family,
13363 &bgp_static->gatewayIp.u.prefix, buf2,
13364 sizeof(buf2));
ea47320b 13365 vty_out(vty,
7bcc8dac 13366 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 13367 buf, rdbuf,
13368 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 13369 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
13370 macrouter);
13371
0a22ddfb 13372 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
13373 }
13374 }
3da6fcd5
PG
13375}
13376
718e3744 13377/* Configuration of static route announcement and aggregate
13378 information. */
2b791107
DL
13379void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13380 safi_t safi)
d62a17ae 13381{
9bcb3eef 13382 struct bgp_dest *dest;
b54892e0 13383 const struct prefix *p;
d62a17ae 13384 struct bgp_static *bgp_static;
13385 struct bgp_aggregate *bgp_aggregate;
13386 char buf[SU_ADDRSTRLEN];
13387
2b791107
DL
13388 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13389 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13390 return;
13391 }
d62a17ae 13392
2b791107
DL
13393 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13394 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13395 return;
13396 }
d62a17ae 13397
13398 /* Network configuration. */
9bcb3eef
DS
13399 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
13400 dest = bgp_route_next(dest)) {
13401 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13402 if (bgp_static == NULL)
ea47320b 13403 continue;
d62a17ae 13404
9bcb3eef 13405 p = bgp_dest_get_prefix(dest);
d62a17ae 13406
d8a9922d
DS
13407 vty_out(vty, " network %s/%d",
13408 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13409 p->prefixlen);
d62a17ae 13410
ea47320b
DL
13411 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13412 vty_out(vty, " label-index %u",
13413 bgp_static->label_index);
d62a17ae 13414
ea47320b
DL
13415 if (bgp_static->rmap.name)
13416 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13417
13418 if (bgp_static->backdoor)
13419 vty_out(vty, " backdoor");
718e3744 13420
ea47320b
DL
13421 vty_out(vty, "\n");
13422 }
13423
d62a17ae 13424 /* Aggregate-address configuration. */
9bcb3eef
DS
13425 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
13426 dest = bgp_route_next(dest)) {
13427 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 13428 if (bgp_aggregate == NULL)
ea47320b 13429 continue;
d62a17ae 13430
9bcb3eef 13431 p = bgp_dest_get_prefix(dest);
d62a17ae 13432
d8a9922d
DS
13433 vty_out(vty, " aggregate-address %s/%d",
13434 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13435 p->prefixlen);
d62a17ae 13436
ea47320b
DL
13437 if (bgp_aggregate->as_set)
13438 vty_out(vty, " as-set");
d62a17ae 13439
ea47320b
DL
13440 if (bgp_aggregate->summary_only)
13441 vty_out(vty, " summary-only");
718e3744 13442
20894f50
DA
13443 if (bgp_aggregate->rmap.name)
13444 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13445
229757f1
DA
13446 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13447 vty_out(vty, " origin %s",
13448 bgp_origin2str(bgp_aggregate->origin));
13449
ea47320b
DL
13450 vty_out(vty, "\n");
13451 }
d62a17ae 13452}
734b349e 13453
2b791107 13454void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13455 safi_t safi)
d62a17ae 13456{
9bcb3eef 13457 struct bgp_dest *dest;
d62a17ae 13458 struct bgp_distance *bdistance;
13459
13460 /* Distance configuration. */
13461 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13462 && bgp->distance_local[afi][safi]
13463 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13464 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13465 || bgp->distance_local[afi][safi]
13466 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13467 vty_out(vty, " distance bgp %d %d %d\n",
13468 bgp->distance_ebgp[afi][safi],
13469 bgp->distance_ibgp[afi][safi],
13470 bgp->distance_local[afi][safi]);
13471 }
734b349e 13472
9bcb3eef
DS
13473 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
13474 dest = bgp_route_next(dest)) {
13475 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0
DS
13476 if (bdistance != NULL)
13477 vty_out(vty, " distance %d %pRN %s\n",
9bcb3eef 13478 bdistance->distance, dest,
d62a17ae 13479 bdistance->access_list ? bdistance->access_list
13480 : "");
ca2e160d 13481 }
718e3744 13482}
13483
13484/* Allocate routing table structure and install commands. */
d62a17ae 13485void bgp_route_init(void)
13486{
13487 afi_t afi;
13488 safi_t safi;
13489
13490 /* Init BGP distance table. */
05c7a1cc 13491 FOREACH_AFI_SAFI (afi, safi)
960035b2 13492 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13493
13494 /* IPv4 BGP commands. */
13495 install_element(BGP_NODE, &bgp_table_map_cmd);
13496 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13497 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13498
13499 install_element(BGP_NODE, &aggregate_address_cmd);
13500 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13501 install_element(BGP_NODE, &no_aggregate_address_cmd);
13502 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13503
13504 /* IPv4 unicast configuration. */
13505 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13506 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13507 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13508
13509 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13510 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13511 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13512 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13513
13514 /* IPv4 multicast configuration. */
13515 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13516 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13517 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13518 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13519 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13520 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13521 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13522
13523 /* IPv4 labeled-unicast configuration. */
fb985e0c
DA
13524 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
13525 install_element(BGP_IPV4L_NODE, &aggregate_address_cmd);
13526 install_element(BGP_IPV4L_NODE, &aggregate_address_mask_cmd);
13527 install_element(BGP_IPV4L_NODE, &no_aggregate_address_cmd);
13528 install_element(BGP_IPV4L_NODE, &no_aggregate_address_mask_cmd);
13529
d62a17ae 13530 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13531 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 13532 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 13533 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 13534 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13535 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13536 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 13537 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 13538
13539 install_element(VIEW_NODE,
13540 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
13541 install_element(VIEW_NODE,
13542 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 13543 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13544 install_element(VIEW_NODE,
13545 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13546#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13547 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13548#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13549 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13550 install_element(VIEW_NODE,
44c69747 13551 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13552
d62a17ae 13553 /* BGP dampening clear commands */
13554 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13555 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13556
d62a17ae 13557 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13558 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13559
13560 /* prefix count */
13561 install_element(ENABLE_NODE,
13562 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13563#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13564 install_element(ENABLE_NODE,
13565 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13566#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13567
d62a17ae 13568 /* New config IPv6 BGP commands. */
13569 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13570 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13571 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13572
13573 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13574 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13575
13576 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13577
fb985e0c
DA
13578 /* IPv6 labeled unicast address family. */
13579 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
13580 install_element(BGP_IPV6L_NODE, &ipv6_aggregate_address_cmd);
13581 install_element(BGP_IPV6L_NODE, &no_ipv6_aggregate_address_cmd);
13582
d62a17ae 13583 install_element(BGP_NODE, &bgp_distance_cmd);
13584 install_element(BGP_NODE, &no_bgp_distance_cmd);
13585 install_element(BGP_NODE, &bgp_distance_source_cmd);
13586 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13587 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13588 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13589 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13590 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13591 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13592 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13593 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13594 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13595 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13596 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13597 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13598 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13599 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13600 install_element(BGP_IPV4M_NODE,
13601 &no_bgp_distance_source_access_list_cmd);
13602 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13603 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13604 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13605 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13606 install_element(BGP_IPV6_NODE,
13607 &ipv6_bgp_distance_source_access_list_cmd);
13608 install_element(BGP_IPV6_NODE,
13609 &no_ipv6_bgp_distance_source_access_list_cmd);
13610 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13611 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13612 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13613 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13614 install_element(BGP_IPV6M_NODE,
13615 &ipv6_bgp_distance_source_access_list_cmd);
13616 install_element(BGP_IPV6M_NODE,
13617 &no_ipv6_bgp_distance_source_access_list_cmd);
13618
ef5f4b23 13619 /* BGP dampening */
d62a17ae 13620 install_element(BGP_NODE, &bgp_damp_set_cmd);
13621 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13622 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13623 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
d62a17ae 13624 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13625 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
ef5f4b23
DA
13626 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
13627 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
13628 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
13629 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
13630 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
13631 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
13632 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
13633 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 13634
13635 /* Large Communities */
13636 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13637 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13638
13639 /* show bgp ipv4 flowspec detailed */
13640 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13641
2a0e69ae 13642 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 13643 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13644}
13645
13646void bgp_route_finish(void)
13647{
13648 afi_t afi;
13649 safi_t safi;
13650
05c7a1cc
QY
13651 FOREACH_AFI_SAFI (afi, safi) {
13652 bgp_table_unlock(bgp_distance_table[afi][safi]);
13653 bgp_distance_table[afi][safi] = NULL;
13654 }
228da428 13655}