]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
zebra: Make GR debug logs at least vrf aware
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* BGP routing information
896014f4
DL
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
896014f4 5 */
718e3744 6
7#include <zebra.h>
8d0ab76d 8#include <math.h>
718e3744 9
2618a52e 10#include "printfrr.h"
a70a28a5 11#include "frrstr.h"
718e3744 12#include "prefix.h"
13#include "linklist.h"
14#include "memory.h"
15#include "command.h"
16#include "stream.h"
17#include "filter.h"
718e3744 18#include "log.h"
19#include "routemap.h"
20#include "buffer.h"
21#include "sockunion.h"
22#include "plist.h"
23#include "thread.h"
200df115 24#include "workqueue.h"
3f9c7369 25#include "queue.h"
6e919709 26#include "memory.h"
e496b420 27#include "srv6.h"
4dcadbef 28#include "lib/json.h"
d8d084d9 29#include "lib_errors.h"
8c48b3b6 30#include "zclient.h"
718e3744 31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_table.h"
33#include "bgpd/bgp_route.h"
34#include "bgpd/bgp_attr.h"
35#include "bgpd/bgp_debug.h"
14454c9f 36#include "bgpd/bgp_errors.h"
718e3744 37#include "bgpd/bgp_aspath.h"
38#include "bgpd/bgp_regex.h"
39#include "bgpd/bgp_community.h"
ed0e57e3 40#include "bgpd/bgp_community_alias.h"
718e3744 41#include "bgpd/bgp_ecommunity.h"
57d187bc 42#include "bgpd/bgp_lcommunity.h"
718e3744 43#include "bgpd/bgp_clist.h"
44#include "bgpd/bgp_packet.h"
45#include "bgpd/bgp_filter.h"
46#include "bgpd/bgp_fsm.h"
47#include "bgpd/bgp_mplsvpn.h"
48#include "bgpd/bgp_nexthop.h"
49#include "bgpd/bgp_damp.h"
50#include "bgpd/bgp_advertise.h"
51#include "bgpd/bgp_zebra.h"
0a486e5f 52#include "bgpd/bgp_vty.h"
96450faf 53#include "bgpd/bgp_mpath.h"
fc9a856f 54#include "bgpd/bgp_nht.h"
3f9c7369 55#include "bgpd/bgp_updgrp.h"
cd1964ff 56#include "bgpd/bgp_label.h"
dcc68b5e 57#include "bgpd/bgp_addpath.h"
4e802e66 58#include "bgpd/bgp_mac.h"
2a0e69ae 59#include "bgpd/bgp_network.h"
6401252f 60#include "bgpd/bgp_trace.h"
fdeb5a81 61#include "bgpd/bgp_rpki.h"
718e3744 62
49e5a4a0 63#ifdef ENABLE_BGP_VNC
f8b6f499
LB
64#include "bgpd/rfapi/rfapi_backend.h"
65#include "bgpd/rfapi/vnc_import_bgp.h"
66#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 67#endif
aee875b5
PG
68#include "bgpd/bgp_encap_types.h"
69#include "bgpd/bgp_encap_tlv.h"
684a7227 70#include "bgpd/bgp_evpn.h"
0a50c248 71#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 72#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 73#include "bgpd/bgp_flowspec.h"
98a9dbc7 74#include "bgpd/bgp_flowspec_util.h"
45918cfb 75#include "bgpd/bgp_pbr.h"
65efcfce 76
e2a86ad9 77#include "bgpd/bgp_route_clippy.c"
aee875b5 78
7fd28dd2
PR
79DEFINE_HOOK(bgp_snmp_update_stats,
80 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 81 (rn, pi, added));
7fd28dd2 82
b5b99af8
DS
83DEFINE_HOOK(bgp_rpki_prefix_status,
84 (struct peer *peer, struct attr *attr,
85 const struct prefix *prefix),
8451921b 86 (peer, attr, prefix));
b5b99af8 87
718e3744 88/* Extern from bgp_dump.c */
dde72586
SH
89extern const char *bgp_origin_str[];
90extern const char *bgp_origin_long_str[];
3742de8d 91
b7d08f5a 92/* PMSI strings. */
93#define PMSI_TNLTYPE_STR_NO_INFO "No info"
94#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95static const struct message bgp_pmsi_tnltype_str[] = {
96 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 104 {0}
105};
b7d08f5a 106
9df8b37c 107#define VRFID_NONE_STR "-"
46aeabed 108#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 109
4a11bf2c 110DEFINE_HOOK(bgp_process,
9bcb3eef
DS
111 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
112 struct peer *peer, bool withdraw),
8451921b 113 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 114
4056a5f6
RZ
115/** Test if path is suppressed. */
116static bool bgp_path_suppressed(struct bgp_path_info *pi)
117{
118 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
119 return false;
120
121 return listcount(pi->extra->aggr_suppressors) > 0;
122}
4a11bf2c 123
9bcb3eef 124struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 125 safi_t safi, const struct prefix *p,
d62a17ae 126 struct prefix_rd *prd)
127{
9bcb3eef
DS
128 struct bgp_dest *dest;
129 struct bgp_dest *pdest = NULL;
d62a17ae 130
131 assert(table);
d62a17ae 132
133 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
134 || (safi == SAFI_EVPN)) {
9bcb3eef 135 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 136
9bcb3eef
DS
137 if (!bgp_dest_has_bgp_path_info_data(pdest))
138 bgp_dest_set_bgp_table_info(
139 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 140 else
9bcb3eef
DS
141 bgp_dest_unlock_node(pdest);
142 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 143 }
718e3744 144
9bcb3eef 145 dest = bgp_node_get(table, p);
718e3744 146
d62a17ae 147 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
148 || (safi == SAFI_EVPN))
9bcb3eef 149 dest->pdest = pdest;
718e3744 150
9bcb3eef 151 return dest;
718e3744 152}
6b0655a2 153
9bcb3eef 154struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 155 safi_t safi, const struct prefix *p,
d62a17ae 156 struct prefix_rd *prd)
128ea8ab 157{
9bcb3eef
DS
158 struct bgp_dest *dest;
159 struct bgp_dest *pdest = NULL;
128ea8ab 160
d62a17ae 161 if (!table)
162 return NULL;
128ea8ab 163
d62a17ae 164 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
165 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
166 pdest = bgp_node_lookup(table, (struct prefix *)prd);
167 if (!pdest)
d62a17ae 168 return NULL;
128ea8ab 169
9bcb3eef
DS
170 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
171 bgp_dest_unlock_node(pdest);
d62a17ae 172 return NULL;
173 }
128ea8ab 174
9bcb3eef 175 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 176 }
128ea8ab 177
9bcb3eef 178 dest = bgp_node_lookup(table, p);
128ea8ab 179
9bcb3eef 180 return dest;
128ea8ab 181}
182
18ee8310
DS
183/* Allocate bgp_path_info_extra */
184static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 185{
4b7e6066
DS
186 struct bgp_path_info_extra *new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
188 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
189 new->label[0] = MPLS_INVALID_LABEL;
190 new->num_labels = 0;
3e3708cb
PG
191 new->bgp_fs_pbr = NULL;
192 new->bgp_fs_iprule = NULL;
d62a17ae 193 return new;
fb982c25
PJ
194}
195
a2e219fe 196void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 197{
4b7e6066 198 struct bgp_path_info_extra *e;
d62a17ae 199
c93a3b77
DS
200 if (!extra || !*extra)
201 return;
d62a17ae 202
c93a3b77 203 e = *extra;
4538f895 204 if (e->damp_info)
b4f7f45b
IR
205 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
206 e->damp_info->safi);
4538f895 207
c93a3b77
DS
208 e->damp_info = NULL;
209 if (e->parent) {
40381db7 210 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 211
40381db7 212 if (bpi->net) {
0e70e6c8
DL
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
216 *
40381db7
DS
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
0e70e6c8
DL
220 */
221 unsigned refcount;
222
40381db7 223 bpi = bgp_path_info_lock(bpi);
c10e14e9 224 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 225 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 226 if (!refcount)
40381db7
DS
227 bpi->net = NULL;
228 bgp_path_info_unlock(bpi);
0e70e6c8 229 }
18ee8310 230 bgp_path_info_unlock(e->parent);
c93a3b77 231 e->parent = NULL;
d62a17ae 232 }
c93a3b77
DS
233
234 if (e->bgp_orig)
235 bgp_unlock(e->bgp_orig);
c26edcda 236
4cd690ae
PG
237 if (e->peer_orig)
238 peer_unlock(e->peer_orig);
239
ff3bf9a4
DS
240 if (e->aggr_suppressors)
241 list_delete(&e->aggr_suppressors);
242
60605cbc
AK
243 if (e->mh_info)
244 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 245
ce3c0614
PG
246 if ((*extra)->bgp_fs_iprule)
247 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 248 if ((*extra)->bgp_fs_pbr)
6a154c88 249 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 250 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
251}
252
18ee8310
DS
253/* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
fb982c25 255 */
40381db7 256struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 257{
40381db7
DS
258 if (!pi->extra)
259 pi->extra = bgp_path_info_extra_new();
260 return pi->extra;
fb982c25
PJ
261}
262
718e3744 263/* Free bgp route information. */
eb473185
DA
264void bgp_path_info_free_with_caller(const char *name,
265 struct bgp_path_info *path)
718e3744 266{
eb473185 267 frrtrace(2, frr_bgp, bgp_path_info_free, path, name);
05864da7 268 bgp_attr_unintern(&path->attr);
fb018d25 269
9b6d8fcf
DS
270 bgp_unlink_nexthop(path);
271 bgp_path_info_extra_free(&path->extra);
272 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
273 if (path->net)
274 bgp_addpath_free_info_data(&path->tx_addpath,
275 &path->net->tx_addpath);
718e3744 276
9b6d8fcf 277 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 278
9b6d8fcf 279 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 280}
281
9b6d8fcf 282struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 283{
9b6d8fcf
DS
284 path->lock++;
285 return path;
200df115 286}
287
9b6d8fcf 288struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 289{
9b6d8fcf
DS
290 assert(path && path->lock > 0);
291 path->lock--;
d62a17ae 292
9b6d8fcf 293 if (path->lock == 0) {
9b6d8fcf 294 bgp_path_info_free(path);
d62a17ae 295 return NULL;
296 }
200df115 297
9b6d8fcf 298 return path;
200df115 299}
300
f009ff26 301/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 302static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 303{
304 struct peer *peer;
305 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 306 bool set_flag = false;
f009ff26 307 struct bgp *bgp = NULL;
308 struct bgp_table *table = NULL;
309 afi_t afi = 0;
310 safi_t safi = 0;
f009ff26 311
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
314 */
9bcb3eef 315 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 316 return 0;
317
9bcb3eef 318 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 319 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 320 zlog_debug(
56ca3b5b
DL
321 "Route %pBD is in workqueue and being processed, not deferred.",
322 dest);
b54892e0 323
5f9c1aa2 324 return 0;
325 }
326
9bcb3eef 327 table = bgp_dest_table(dest);
f009ff26 328 if (table) {
329 bgp = table->bgp;
330 afi = table->afi;
331 safi = table->safi;
332 }
333
9bcb3eef 334 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 335 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
336 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
337 continue;
338
339 /* Route selection is deferred if there is a stale path which
340 * which indicates peer is in restart mode
341 */
36235319
QY
342 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
343 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 344 set_flag = true;
f009ff26 345 } else {
346 /* If the peer is graceful restart capable and peer is
347 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
348 */
349 peer = old_pi->peer;
36235319
QY
350 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
351 && BGP_PEER_RESTARTING_MODE(peer)
352 && (old_pi
353 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 354 set_flag = true;
f009ff26 355 }
356 }
357 if (set_flag)
358 break;
359 }
360
361 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
362 * is active
363 */
2ba1fe69 364 if (set_flag && table) {
f009ff26 365 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
366 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
367 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 368 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 369 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
370 zlog_debug("DEFER route %pBD, dest %p", dest,
371 dest);
f009ff26 372 return 0;
373 }
374 }
375 return -1;
376}
377
eb473185
DA
378void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
379 struct bgp_path_info *pi)
718e3744 380{
c6b077a5 381 frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
4b7e6066 382 struct bgp_path_info *top;
718e3744 383
9bcb3eef 384 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 385
6f94b685 386 pi->next = top;
40381db7 387 pi->prev = NULL;
d62a17ae 388 if (top)
40381db7 389 top->prev = pi;
9bcb3eef 390 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 391
40381db7 392 bgp_path_info_lock(pi);
9bcb3eef 393 bgp_dest_lock_node(dest);
40381db7 394 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 395 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 396 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 397}
398
d62a17ae 399/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 400 completion callback *only* */
9bcb3eef 401void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 402{
40381db7
DS
403 if (pi->next)
404 pi->next->prev = pi->prev;
405 if (pi->prev)
406 pi->prev->next = pi->next;
d62a17ae 407 else
9bcb3eef 408 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 409
40381db7
DS
410 bgp_path_info_mpath_dequeue(pi);
411 bgp_path_info_unlock(pi);
7fd28dd2 412 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 413 bgp_dest_unlock_node(dest);
718e3744 414}
415
9bcb3eef 416void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 417{
9bcb3eef 418 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 419 /* set of previous already took care of pcount */
40381db7 420 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 421}
422
18ee8310 423/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
424 called when a route is deleted and then quickly re-added before the
425 deletion has been processed */
9bcb3eef 426void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 427{
9bcb3eef 428 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 429 /* unset of previous already took care of pcount */
40381db7 430 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
431}
432
d62a17ae 433/* Adjust pcount as required */
9bcb3eef 434static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 435{
d62a17ae 436 struct bgp_table *table;
67174041 437
9bcb3eef 438 assert(dest && bgp_dest_table(dest));
40381db7 439 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 440
9bcb3eef 441 table = bgp_dest_table(dest);
67174041 442
40381db7 443 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 444 return;
445
40381db7
DS
446 if (!BGP_PATH_COUNTABLE(pi)
447 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 448
40381db7 449 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 450
451 /* slight hack, but more robust against errors. */
40381db7
DS
452 if (pi->peer->pcount[table->afi][table->safi])
453 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 454 else
450971aa 455 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 456 "Asked to decrement 0 prefix count for peer");
40381db7
DS
457 } else if (BGP_PATH_COUNTABLE(pi)
458 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
459 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
460 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 461 }
1a392d46
PJ
462}
463
40381db7
DS
464static int bgp_label_index_differs(struct bgp_path_info *pi1,
465 struct bgp_path_info *pi2)
28d58fd7 466{
40381db7 467 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 468}
1a392d46 469
18ee8310 470/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
471 * This is here primarily to keep prefix-count in check.
472 */
9bcb3eef 473void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 474 uint32_t flag)
1a392d46 475{
40381db7 476 SET_FLAG(pi->flags, flag);
d62a17ae 477
478 /* early bath if we know it's not a flag that changes countability state
479 */
480 if (!CHECK_FLAG(flag,
1defdda8 481 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 482 return;
483
9bcb3eef 484 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
485}
486
9bcb3eef 487void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 UNSET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
718e3744 501/* Get MED value. If MED value is missing and "bgp bestpath
502 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 503static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 504{
505 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
506 return attr->med;
507 else {
892fedb6 508 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 509 return BGP_MED_MAX;
510 else
511 return 0;
512 }
718e3744 513}
514
7533cad7
QY
515void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
516 size_t buf_len)
2ec1e66f 517{
b1ff5529
PG
518 struct peer *peer;
519
520 if (pi->sub_type == BGP_ROUTE_IMPORTED &&
521 bgp_get_imported_bpi_ultimate(pi))
522 peer = bgp_get_imported_bpi_ultimate(pi)->peer;
523 else
524 peer = pi->peer;
525
40381db7 526 if (pi->addpath_rx_id)
b1ff5529
PG
527 snprintf(buf, buf_len, "path %s (addpath rxid %d)", peer->host,
528 pi->addpath_rx_id);
d62a17ae 529 else
b1ff5529 530 snprintf(buf, buf_len, "path %s", peer->host);
d62a17ae 531}
9fbdd100 532
da0c0ef7
KM
533
534/*
535 * Get the ultimate path info.
536 */
537struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
538{
539 struct bgp_path_info *bpi_ultimate;
540
541 if (info->sub_type != BGP_ROUTE_IMPORTED)
542 return info;
543
544 for (bpi_ultimate = info;
545 bpi_ultimate->extra && bpi_ultimate->extra->parent;
546 bpi_ultimate = bpi_ultimate->extra->parent)
547 ;
548
549 return bpi_ultimate;
550}
551
d62a17ae 552/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
553 */
18ee8310
DS
554static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
555 struct bgp_path_info *exist, int *paths_eq,
556 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
557 char *pfx_buf, afi_t afi, safi_t safi,
558 enum bgp_path_selection_reason *reason)
d62a17ae 559{
5df26422 560 const struct prefix *new_p;
d62a17ae 561 struct attr *newattr, *existattr;
3061acc2
DA
562 enum bgp_peer_sort new_sort;
563 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
564 uint32_t new_pref;
565 uint32_t exist_pref;
566 uint32_t new_med;
567 uint32_t exist_med;
568 uint32_t new_weight;
569 uint32_t exist_weight;
d62a17ae 570 uint32_t newm, existm;
571 struct in_addr new_id;
572 struct in_addr exist_id;
573 int new_cluster;
574 int exist_cluster;
575 int internal_as_route;
576 int confed_as_route;
04d14c8b 577 int ret = 0;
ee88563a
JM
578 int igp_metric_ret = 0;
579 int peer_sort_ret = -1;
d62a17ae 580 char new_buf[PATH_ADDPATH_STR_BUFFER];
581 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
582 uint32_t new_mm_seq;
583 uint32_t exist_mm_seq;
6d8c603a 584 int nh_cmp;
d071f237
AK
585 esi_t *exist_esi;
586 esi_t *new_esi;
587 bool same_esi;
588 bool old_proxy;
589 bool new_proxy;
33c6e933 590 bool new_origin, exist_origin;
da0c0ef7 591 struct bgp_path_info *bpi_ultimate;
cefda028 592 struct peer *peer_new, *peer_exist;
d62a17ae 593
594 *paths_eq = 0;
595
596 /* 0. Null check. */
597 if (new == NULL) {
fdf81fa0 598 *reason = bgp_path_selection_none;
d62a17ae 599 if (debug)
600 zlog_debug("%s: new is NULL", pfx_buf);
601 return 0;
602 }
2ec1e66f 603
da0c0ef7
KM
604 if (debug) {
605 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
606 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 607 sizeof(new_buf));
da0c0ef7 608 }
718e3744 609
d62a17ae 610 if (exist == NULL) {
fdf81fa0 611 *reason = bgp_path_selection_first;
d62a17ae 612 if (debug)
4378495a
DS
613 zlog_debug("%s(%s): %s is the initial bestpath",
614 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 615 return 1;
616 }
2ec1e66f 617
d62a17ae 618 if (debug) {
da0c0ef7
KM
619 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
620 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 621 sizeof(exist_buf));
4378495a
DS
622 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
623 pfx_buf, bgp->name_pretty, new_buf, new->flags,
624 exist_buf, exist->flags);
d62a17ae 625 }
8ff56318 626
d62a17ae 627 newattr = new->attr;
628 existattr = exist->attr;
629
1479ed2f
DA
630 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
631 * Capability" to a neighbor MUST perform the following upon receiving
632 * a route from that neighbor with the "LLGR_STALE" community, or upon
633 * attaching the "LLGR_STALE" community itself per Section 4.2:
634 *
635 * Treat the route as the least-preferred in route selection (see
636 * below). See the Risks of Depreferencing Routes section (Section 5.2)
637 * for a discussion of potential risks inherent in doing this.
638 */
9a706b42
DA
639 if (bgp_attr_get_community(newattr) &&
640 community_include(bgp_attr_get_community(newattr),
641 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
642 if (debug)
643 zlog_debug(
644 "%s: %s wins over %s due to LLGR_STALE community",
645 pfx_buf, new_buf, exist_buf);
646 return 0;
647 }
648
9a706b42
DA
649 if (bgp_attr_get_community(existattr) &&
650 community_include(bgp_attr_get_community(existattr),
651 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
652 if (debug)
653 zlog_debug(
654 "%s: %s loses to %s due to LLGR_STALE community",
655 pfx_buf, new_buf, exist_buf);
656 return 1;
657 }
658
5df26422
NS
659 new_p = bgp_dest_get_prefix(new->net);
660
d62a17ae 661 /* For EVPN routes, we cannot just go by local vs remote, we have to
662 * look at the MAC mobility sequence number, if present.
663 */
5df26422
NS
664 if ((safi == SAFI_EVPN)
665 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 666 /* This is an error condition described in RFC 7432 Section
667 * 15.2. The RFC
668 * states that in this scenario "the PE MUST alert the operator"
669 * but it
670 * does not state what other action to take. In order to provide
671 * some
672 * consistency in this scenario we are going to prefer the path
673 * with the
674 * sticky flag.
675 */
676 if (newattr->sticky != existattr->sticky) {
677 if (!debug) {
5df26422
NS
678 prefix2str(new_p, pfx_buf,
679 sizeof(*pfx_buf)
680 * PREFIX2STR_BUFFER);
18ee8310 681 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
682 new, new_buf, sizeof(new_buf));
683 bgp_path_info_path_with_addpath_rx_str(
684 exist, exist_buf, sizeof(exist_buf));
d62a17ae 685 }
686
687 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 688 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
689 if (debug)
690 zlog_debug(
691 "%s: %s wins over %s due to sticky MAC flag",
692 pfx_buf, new_buf, exist_buf);
d62a17ae 693 return 1;
694 }
695
696 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 697 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
698 if (debug)
699 zlog_debug(
700 "%s: %s loses to %s due to sticky MAC flag",
701 pfx_buf, new_buf, exist_buf);
d62a17ae 702 return 0;
703 }
704 }
128ea8ab 705
d071f237
AK
706 new_esi = bgp_evpn_attr_get_esi(newattr);
707 exist_esi = bgp_evpn_attr_get_esi(existattr);
708 if (bgp_evpn_is_esi_valid(new_esi) &&
709 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
710 same_esi = true;
711 } else {
712 same_esi = false;
713 }
714
715 /* If both paths have the same non-zero ES and
716 * one path is local it wins.
717 * PS: Note the local path wins even if the remote
718 * has the higher MM seq. The local path's
719 * MM seq will be fixed up to match the highest
720 * rem seq, subsequently.
721 */
722 if (same_esi) {
723 char esi_buf[ESI_STR_LEN];
724
725 if (bgp_evpn_is_path_local(bgp, new)) {
726 *reason = bgp_path_selection_evpn_local_path;
727 if (debug)
728 zlog_debug(
729 "%s: %s wins over %s as ES %s is same and local",
730 pfx_buf, new_buf, exist_buf,
731 esi_to_str(new_esi, esi_buf,
732 sizeof(esi_buf)));
733 return 1;
734 }
735 if (bgp_evpn_is_path_local(bgp, exist)) {
736 *reason = bgp_path_selection_evpn_local_path;
737 if (debug)
738 zlog_debug(
739 "%s: %s loses to %s as ES %s is same and local",
740 pfx_buf, new_buf, exist_buf,
741 esi_to_str(new_esi, esi_buf,
742 sizeof(esi_buf)));
743 return 0;
744 }
745 }
746
d62a17ae 747 new_mm_seq = mac_mobility_seqnum(newattr);
748 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 749
d62a17ae 750 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 751 *reason = bgp_path_selection_evpn_seq;
d62a17ae 752 if (debug)
753 zlog_debug(
754 "%s: %s wins over %s due to MM seq %u > %u",
755 pfx_buf, new_buf, exist_buf, new_mm_seq,
756 exist_mm_seq);
757 return 1;
758 }
8ff56318 759
d62a17ae 760 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 761 *reason = bgp_path_selection_evpn_seq;
d62a17ae 762 if (debug)
763 zlog_debug(
764 "%s: %s loses to %s due to MM seq %u < %u",
765 pfx_buf, new_buf, exist_buf, new_mm_seq,
766 exist_mm_seq);
767 return 0;
768 }
6d8c603a 769
d071f237
AK
770 /* if the sequence numbers and ESI are the same and one path
771 * is non-proxy it wins (over proxy)
772 */
773 new_proxy = bgp_evpn_attr_is_proxy(newattr);
774 old_proxy = bgp_evpn_attr_is_proxy(existattr);
775 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
776 old_proxy != new_proxy) {
777 if (!new_proxy) {
778 *reason = bgp_path_selection_evpn_non_proxy;
779 if (debug)
780 zlog_debug(
781 "%s: %s wins over %s, same seq/es and non-proxy",
782 pfx_buf, new_buf, exist_buf);
783 return 1;
784 }
785
786 *reason = bgp_path_selection_evpn_non_proxy;
787 if (debug)
788 zlog_debug(
789 "%s: %s loses to %s, same seq/es and non-proxy",
790 pfx_buf, new_buf, exist_buf);
791 return 0;
792 }
793
6d8c603a
AK
794 /*
795 * if sequence numbers are the same path with the lowest IP
796 * wins
797 */
798 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
799 if (nh_cmp < 0) {
fdf81fa0 800 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
801 if (debug)
802 zlog_debug(
23d0a753 803 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 804 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 805 &new->attr->nexthop);
6d8c603a
AK
806 return 1;
807 }
808 if (nh_cmp > 0) {
fdf81fa0 809 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
810 if (debug)
811 zlog_debug(
23d0a753 812 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 813 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 814 &new->attr->nexthop);
6d8c603a
AK
815 return 0;
816 }
d62a17ae 817 }
9fbdd100 818
d62a17ae 819 /* 1. Weight check. */
d62a17ae 820 new_weight = newattr->weight;
821 exist_weight = existattr->weight;
8ff56318 822
d62a17ae 823 if (new_weight > exist_weight) {
fdf81fa0 824 *reason = bgp_path_selection_weight;
d62a17ae 825 if (debug)
826 zlog_debug("%s: %s wins over %s due to weight %d > %d",
827 pfx_buf, new_buf, exist_buf, new_weight,
828 exist_weight);
829 return 1;
830 }
718e3744 831
d62a17ae 832 if (new_weight < exist_weight) {
fdf81fa0 833 *reason = bgp_path_selection_weight;
d62a17ae 834 if (debug)
835 zlog_debug("%s: %s loses to %s due to weight %d < %d",
836 pfx_buf, new_buf, exist_buf, new_weight,
837 exist_weight);
838 return 0;
839 }
9fbdd100 840
d62a17ae 841 /* 2. Local preference check. */
842 new_pref = exist_pref = bgp->default_local_pref;
843
844 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
845 new_pref = newattr->local_pref;
846 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
847 exist_pref = existattr->local_pref;
848
849 if (new_pref > exist_pref) {
fdf81fa0 850 *reason = bgp_path_selection_local_pref;
d62a17ae 851 if (debug)
852 zlog_debug(
853 "%s: %s wins over %s due to localpref %d > %d",
854 pfx_buf, new_buf, exist_buf, new_pref,
855 exist_pref);
856 return 1;
857 }
718e3744 858
d62a17ae 859 if (new_pref < exist_pref) {
fdf81fa0 860 *reason = bgp_path_selection_local_pref;
d62a17ae 861 if (debug)
862 zlog_debug(
863 "%s: %s loses to %s due to localpref %d < %d",
864 pfx_buf, new_buf, exist_buf, new_pref,
865 exist_pref);
866 return 0;
867 }
9fbdd100 868
46dbf9d0
DA
869 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
870 * extensions defined in this document, the following step is inserted
871 * after the LOCAL_PREF comparison step in the BGP decision process:
872 * When comparing a pair of routes for a BGP destination, the
873 * route with the ACCEPT_OWN community attached is preferred over
874 * the route that does not have the community.
875 * This extra step MUST only be invoked during the best path selection
876 * process of VPN-IP routes.
877 */
878 if (safi == SAFI_MPLS_VPN &&
879 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
880 CHECK_FLAG(exist->peer->af_flags[afi][safi],
881 PEER_FLAG_ACCEPT_OWN))) {
882 bool new_accept_own = false;
883 bool exist_accept_own = false;
884 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
885
886 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
887 new_accept_own = community_include(
888 bgp_attr_get_community(newattr), accept_own);
889 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
890 exist_accept_own = community_include(
891 bgp_attr_get_community(existattr), accept_own);
892
893 if (new_accept_own && !exist_accept_own) {
894 *reason = bgp_path_selection_accept_own;
895 if (debug)
896 zlog_debug(
897 "%s: %s wins over %s due to accept-own",
898 pfx_buf, new_buf, exist_buf);
899 return 1;
900 }
901
902 if (!new_accept_own && exist_accept_own) {
903 *reason = bgp_path_selection_accept_own;
904 if (debug)
905 zlog_debug(
906 "%s: %s loses to %s due to accept-own",
907 pfx_buf, new_buf, exist_buf);
908 return 0;
909 }
910 }
911
97a52c82
DA
912 /* Tie-breaker - AIGP (Metric TLV) attribute */
913 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
914 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
915 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
916 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
917 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
918
919 if (new_aigp < exist_aigp) {
920 *reason = bgp_path_selection_aigp;
921 if (debug)
922 zlog_debug(
923 "%s: %s wins over %s due to AIGP %" PRIu64
924 " < %" PRIu64,
925 pfx_buf, new_buf, exist_buf, new_aigp,
926 exist_aigp);
927 return 1;
928 }
929
930 if (new_aigp > exist_aigp) {
931 *reason = bgp_path_selection_aigp;
932 if (debug)
933 zlog_debug(
934 "%s: %s loses to %s due to AIGP %" PRIu64
935 " > %" PRIu64,
936 pfx_buf, new_buf, exist_buf, new_aigp,
937 exist_aigp);
938 return 0;
939 }
940 }
941
d62a17ae 942 /* 3. Local route check. We prefer:
943 * - BGP_ROUTE_STATIC
944 * - BGP_ROUTE_AGGREGATE
945 * - BGP_ROUTE_REDISTRIBUTE
946 */
33c6e933
DS
947 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
948 new->sub_type == BGP_ROUTE_IMPORTED);
949 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
950 exist->sub_type == BGP_ROUTE_IMPORTED);
951
952 if (new_origin && !exist_origin) {
fdf81fa0 953 *reason = bgp_path_selection_local_route;
d62a17ae 954 if (debug)
955 zlog_debug(
956 "%s: %s wins over %s due to preferred BGP_ROUTE type",
957 pfx_buf, new_buf, exist_buf);
958 return 1;
959 }
718e3744 960
33c6e933 961 if (!new_origin && exist_origin) {
fdf81fa0 962 *reason = bgp_path_selection_local_route;
d62a17ae 963 if (debug)
964 zlog_debug(
965 "%s: %s loses to %s due to preferred BGP_ROUTE type",
966 pfx_buf, new_buf, exist_buf);
967 return 0;
6811845b 968 }
718e3744 969
da0c0ef7
KM
970 /* Here if these are imported routes then get ultimate pi for
971 * path compare.
972 */
973 new = bgp_get_imported_bpi_ultimate(new);
974 exist = bgp_get_imported_bpi_ultimate(exist);
975 newattr = new->attr;
976 existattr = exist->attr;
977
d62a17ae 978 /* 4. AS path length check. */
892fedb6 979 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 980 int exist_hops = aspath_count_hops(existattr->aspath);
981 int exist_confeds = aspath_count_confeds(existattr->aspath);
982
892fedb6 983 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 984 int aspath_hops;
985
986 aspath_hops = aspath_count_hops(newattr->aspath);
987 aspath_hops += aspath_count_confeds(newattr->aspath);
988
989 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 990 *reason = bgp_path_selection_confed_as_path;
d62a17ae 991 if (debug)
992 zlog_debug(
993 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
994 pfx_buf, new_buf, exist_buf,
995 aspath_hops,
996 (exist_hops + exist_confeds));
997 return 1;
998 }
999
1000 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 1001 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1002 if (debug)
1003 zlog_debug(
1004 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1005 pfx_buf, new_buf, exist_buf,
1006 aspath_hops,
1007 (exist_hops + exist_confeds));
1008 return 0;
1009 }
1010 } else {
1011 int newhops = aspath_count_hops(newattr->aspath);
1012
1013 if (newhops < exist_hops) {
fdf81fa0 1014 *reason = bgp_path_selection_as_path;
d62a17ae 1015 if (debug)
1016 zlog_debug(
1017 "%s: %s wins over %s due to aspath hopcount %d < %d",
1018 pfx_buf, new_buf, exist_buf,
1019 newhops, exist_hops);
1020 return 1;
1021 }
1022
1023 if (newhops > exist_hops) {
fdf81fa0 1024 *reason = bgp_path_selection_as_path;
d62a17ae 1025 if (debug)
1026 zlog_debug(
1027 "%s: %s loses to %s due to aspath hopcount %d > %d",
1028 pfx_buf, new_buf, exist_buf,
1029 newhops, exist_hops);
1030 return 0;
1031 }
1032 }
1033 }
9fbdd100 1034
d62a17ae 1035 /* 5. Origin check. */
1036 if (newattr->origin < existattr->origin) {
fdf81fa0 1037 *reason = bgp_path_selection_origin;
d62a17ae 1038 if (debug)
1039 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1040 pfx_buf, new_buf, exist_buf,
1041 bgp_origin_long_str[newattr->origin],
1042 bgp_origin_long_str[existattr->origin]);
1043 return 1;
1044 }
718e3744 1045
d62a17ae 1046 if (newattr->origin > existattr->origin) {
fdf81fa0 1047 *reason = bgp_path_selection_origin;
d62a17ae 1048 if (debug)
1049 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1050 pfx_buf, new_buf, exist_buf,
1051 bgp_origin_long_str[newattr->origin],
1052 bgp_origin_long_str[existattr->origin]);
1053 return 0;
1054 }
718e3744 1055
d62a17ae 1056 /* 6. MED check. */
1057 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1058 && aspath_count_hops(existattr->aspath) == 0);
1059 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1060 && aspath_count_confeds(existattr->aspath) > 0
1061 && aspath_count_hops(newattr->aspath) == 0
1062 && aspath_count_hops(existattr->aspath) == 0);
1063
892fedb6
DA
1064 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1065 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1066 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1067 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1068 || internal_as_route) {
1069 new_med = bgp_med_value(new->attr, bgp);
1070 exist_med = bgp_med_value(exist->attr, bgp);
1071
1072 if (new_med < exist_med) {
fdf81fa0 1073 *reason = bgp_path_selection_med;
d62a17ae 1074 if (debug)
1075 zlog_debug(
1076 "%s: %s wins over %s due to MED %d < %d",
1077 pfx_buf, new_buf, exist_buf, new_med,
1078 exist_med);
1079 return 1;
1080 }
8ff56318 1081
d62a17ae 1082 if (new_med > exist_med) {
fdf81fa0 1083 *reason = bgp_path_selection_med;
d62a17ae 1084 if (debug)
1085 zlog_debug(
1086 "%s: %s loses to %s due to MED %d > %d",
1087 pfx_buf, new_buf, exist_buf, new_med,
1088 exist_med);
1089 return 0;
1090 }
1091 }
9fbdd100 1092
8cd3d070
PG
1093 if (exist->sub_type == BGP_ROUTE_IMPORTED) {
1094 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
1095 peer_exist = bpi_ultimate->peer;
1096 } else
1097 peer_exist = exist->peer;
1098
1099 if (new->sub_type == BGP_ROUTE_IMPORTED) {
1100 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
1101 peer_new = bpi_ultimate->peer;
1102 } else
1103 peer_new = new->peer;
1104
d62a17ae 1105 /* 7. Peer type check. */
8cd3d070
PG
1106 new_sort = peer_new->sort;
1107 exist_sort = peer_exist->sort;
d62a17ae 1108
1109 if (new_sort == BGP_PEER_EBGP
1110 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1111 *reason = bgp_path_selection_peer;
d62a17ae 1112 if (debug)
1113 zlog_debug(
1114 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1115 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1116 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1117 return 1;
1118 peer_sort_ret = 1;
d62a17ae 1119 }
718e3744 1120
d62a17ae 1121 if (exist_sort == BGP_PEER_EBGP
1122 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1123 *reason = bgp_path_selection_peer;
d62a17ae 1124 if (debug)
1125 zlog_debug(
1126 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1127 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1128 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1129 return 0;
1130 peer_sort_ret = 0;
d62a17ae 1131 }
8ff56318 1132
d62a17ae 1133 /* 8. IGP metric check. */
1134 newm = existm = 0;
8ff56318 1135
d62a17ae 1136 if (new->extra)
1137 newm = new->extra->igpmetric;
1138 if (exist->extra)
1139 existm = exist->extra->igpmetric;
9fbdd100 1140
d62a17ae 1141 if (newm < existm) {
ee88563a 1142 if (debug && peer_sort_ret < 0)
d62a17ae 1143 zlog_debug(
d588b995 1144 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1145 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1146 igp_metric_ret = 1;
d62a17ae 1147 }
718e3744 1148
d62a17ae 1149 if (newm > existm) {
ee88563a 1150 if (debug && peer_sort_ret < 0)
d62a17ae 1151 zlog_debug(
d588b995 1152 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1153 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1154 igp_metric_ret = 0;
5e242b0d 1155 }
5e242b0d 1156
d62a17ae 1157 /* 9. Same IGP metric. Compare the cluster list length as
1158 representative of IGP hops metric. Rewrite the metric value
1159 pair (newm, existm) with the cluster list length. Prefer the
1160 path with smaller cluster list length. */
1161 if (newm == existm) {
8cd3d070
PG
1162 if (peer_sort_lookup(peer_new) == BGP_PEER_IBGP &&
1163 peer_sort_lookup(peer_exist) == BGP_PEER_IBGP &&
aa53c036 1164 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1165 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1166 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1167
1168 if (newm < existm) {
ee88563a 1169 if (debug && peer_sort_ret < 0)
d62a17ae 1170 zlog_debug(
d588b995 1171 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1172 pfx_buf, new_buf, exist_buf,
1173 newm, existm);
ee88563a 1174 igp_metric_ret = 1;
d62a17ae 1175 }
1176
1177 if (newm > existm) {
ee88563a 1178 if (debug && peer_sort_ret < 0)
d62a17ae 1179 zlog_debug(
d588b995 1180 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1181 pfx_buf, new_buf, exist_buf,
1182 newm, existm);
ee88563a 1183 igp_metric_ret = 0;
d62a17ae 1184 }
1185 }
1186 }
31a4638f 1187
d62a17ae 1188 /* 10. confed-external vs. confed-internal */
1189 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1190 if (new_sort == BGP_PEER_CONFED
1191 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1192 *reason = bgp_path_selection_confed;
d62a17ae 1193 if (debug)
1194 zlog_debug(
1195 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1196 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1197 if (!CHECK_FLAG(bgp->flags,
1198 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1199 return 1;
1200 peer_sort_ret = 1;
d62a17ae 1201 }
718e3744 1202
d62a17ae 1203 if (exist_sort == BGP_PEER_CONFED
1204 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1205 *reason = bgp_path_selection_confed;
d62a17ae 1206 if (debug)
1207 zlog_debug(
1208 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1209 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1210 if (!CHECK_FLAG(bgp->flags,
1211 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1212 return 0;
1213 peer_sort_ret = 0;
d62a17ae 1214 }
1215 }
718e3744 1216
d62a17ae 1217 /* 11. Maximum path check. */
1218 if (newm == existm) {
1219 /* If one path has a label but the other does not, do not treat
1220 * them as equals for multipath
1221 */
d2d71b04 1222 int newl, existl;
1223
1224 newl = existl = 0;
1225
1226 if (new->extra)
1227 newl = new->extra->num_labels;
1228 if (exist->extra)
1229 existl = exist->extra->num_labels;
1230 if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
1231 (exist->extra &&
1232 bgp_is_valid_label(&exist->extra->label[0]))) ||
1233 (newl != existl)) {
d62a17ae 1234 if (debug)
1235 zlog_debug(
1236 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1237 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1238 } else if (CHECK_FLAG(bgp->flags,
1239 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1240
1241 /*
1242 * For the two paths, all comparison steps till IGP
1243 * metric
1244 * have succeeded - including AS_PATH hop count. Since
1245 * 'bgp
1246 * bestpath as-path multipath-relax' knob is on, we
1247 * don't need
1248 * an exact match of AS_PATH. Thus, mark the paths are
1249 * equal.
1250 * That will trigger both these paths to get into the
1251 * multipath
1252 * array.
1253 */
1254 *paths_eq = 1;
1255
1256 if (debug)
1257 zlog_debug(
1258 "%s: %s and %s are equal via multipath-relax",
1259 pfx_buf, new_buf, exist_buf);
8cd3d070 1260 } else if (peer_new->sort == BGP_PEER_IBGP) {
d62a17ae 1261 if (aspath_cmp(new->attr->aspath,
1262 exist->attr->aspath)) {
1263 *paths_eq = 1;
1264
1265 if (debug)
1266 zlog_debug(
1267 "%s: %s and %s are equal via matching aspaths",
1268 pfx_buf, new_buf, exist_buf);
1269 }
8cd3d070 1270 } else if (peer_new->as == peer_exist->as) {
d62a17ae 1271 *paths_eq = 1;
1272
1273 if (debug)
1274 zlog_debug(
1275 "%s: %s and %s are equal via same remote-as",
1276 pfx_buf, new_buf, exist_buf);
1277 }
1278 } else {
1279 /*
1280 * TODO: If unequal cost ibgp multipath is enabled we can
1281 * mark the paths as equal here instead of returning
1282 */
ee88563a
JM
1283
1284 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1285 * if either step 7 or 10 (peer type checks) yielded a winner,
1286 * that result was returned immediately. Returning from step 10
1287 * ignored the return value computed in steps 8 and 9 (IGP
1288 * metric checks). In order to preserve that behavior, if
1289 * peer_sort_ret is set, return that rather than igp_metric_ret.
1290 */
1291 ret = peer_sort_ret;
1292 if (peer_sort_ret < 0) {
1293 ret = igp_metric_ret;
1294 if (debug) {
1295 if (ret == 1)
1296 zlog_debug(
1297 "%s: %s wins over %s after IGP metric comparison",
1298 pfx_buf, new_buf, exist_buf);
1299 else
1300 zlog_debug(
1301 "%s: %s loses to %s after IGP metric comparison",
1302 pfx_buf, new_buf, exist_buf);
1303 }
1304 *reason = bgp_path_selection_igp_metric;
d62a17ae 1305 }
1306 return ret;
1307 }
718e3744 1308
ee88563a
JM
1309 /*
1310 * At this point, the decision whether to set *paths_eq = 1 has been
1311 * completed. If we deferred returning because of bestpath peer-type
1312 * relax configuration, return now.
1313 */
1314 if (peer_sort_ret >= 0)
1315 return peer_sort_ret;
1316
d62a17ae 1317 /* 12. If both paths are external, prefer the path that was received
1318 first (the oldest one). This step minimizes route-flap, since a
1319 newer path won't displace an older one, even if it was the
1320 preferred route based on the additional decision criteria below. */
892fedb6 1321 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1322 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1323 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1324 *reason = bgp_path_selection_older;
d62a17ae 1325 if (debug)
1326 zlog_debug(
1327 "%s: %s wins over %s due to oldest external",
1328 pfx_buf, new_buf, exist_buf);
1329 return 1;
1330 }
9fbdd100 1331
1defdda8 1332 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1333 *reason = bgp_path_selection_older;
d62a17ae 1334 if (debug)
1335 zlog_debug(
1336 "%s: %s loses to %s due to oldest external",
1337 pfx_buf, new_buf, exist_buf);
1338 return 0;
1339 }
1340 }
718e3744 1341
ce5002c6 1342 /* 13. Router-ID comparison. */
d62a17ae 1343 /* If one of the paths is "stale", the corresponding peer router-id will
1344 * be 0 and would always win over the other path. If originator id is
ce5002c6 1345 * used for the comparison, it will decide which path is better.
d62a17ae 1346 */
1347 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1348 new_id.s_addr = newattr->originator_id.s_addr;
1349 else
8cd3d070 1350 new_id.s_addr = peer_new->remote_id.s_addr;
d62a17ae 1351 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1352 exist_id.s_addr = existattr->originator_id.s_addr;
1353 else
8cd3d070 1354 exist_id.s_addr = peer_exist->remote_id.s_addr;
d62a17ae 1355
1356 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1357 *reason = bgp_path_selection_router_id;
d62a17ae 1358 if (debug)
1359 zlog_debug(
1360 "%s: %s wins over %s due to Router-ID comparison",
1361 pfx_buf, new_buf, exist_buf);
1362 return 1;
1363 }
718e3744 1364
d62a17ae 1365 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1366 *reason = bgp_path_selection_router_id;
d62a17ae 1367 if (debug)
1368 zlog_debug(
1369 "%s: %s loses to %s due to Router-ID comparison",
1370 pfx_buf, new_buf, exist_buf);
1371 return 0;
1372 }
9fbdd100 1373
ce5002c6 1374 /* 14. Cluster length comparison. */
d62a17ae 1375 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1376 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1377
1378 if (new_cluster < exist_cluster) {
fdf81fa0 1379 *reason = bgp_path_selection_cluster_length;
d62a17ae 1380 if (debug)
1381 zlog_debug(
1382 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1383 pfx_buf, new_buf, exist_buf, new_cluster,
1384 exist_cluster);
1385 return 1;
1386 }
718e3744 1387
d62a17ae 1388 if (new_cluster > exist_cluster) {
fdf81fa0 1389 *reason = bgp_path_selection_cluster_length;
d62a17ae 1390 if (debug)
1391 zlog_debug(
1392 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1393 pfx_buf, new_buf, exist_buf, new_cluster,
1394 exist_cluster);
1395 return 0;
1396 }
9fbdd100 1397
ce5002c6 1398 /* 15. Neighbor address comparison. */
d62a17ae 1399 /* Do this only if neither path is "stale" as stale paths do not have
1400 * valid peer information (as the connection may or may not be up).
1401 */
1defdda8 1402 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1403 *reason = bgp_path_selection_stale;
d62a17ae 1404 if (debug)
1405 zlog_debug(
1406 "%s: %s wins over %s due to latter path being STALE",
1407 pfx_buf, new_buf, exist_buf);
1408 return 1;
1409 }
0de5153c 1410
1defdda8 1411 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1412 *reason = bgp_path_selection_stale;
d62a17ae 1413 if (debug)
1414 zlog_debug(
1415 "%s: %s loses to %s due to former path being STALE",
1416 pfx_buf, new_buf, exist_buf);
1417 return 0;
1418 }
718e3744 1419
d62a17ae 1420 /* locally configured routes to advertise do not have su_remote */
8cd3d070 1421 if (peer_new->su_remote == NULL) {
fdf81fa0 1422 *reason = bgp_path_selection_local_configured;
d62a17ae 1423 return 0;
8cd3d070 1424 }
cefda028 1425
8cd3d070 1426 if (peer_exist->su_remote == NULL) {
fdf81fa0 1427 *reason = bgp_path_selection_local_configured;
d62a17ae 1428 return 1;
8cd3d070 1429 }
9fbdd100 1430
cefda028 1431 ret = sockunion_cmp(peer_new->su_remote, peer_exist->su_remote);
d62a17ae 1432
1433 if (ret == 1) {
fdf81fa0 1434 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1435 if (debug)
1436 zlog_debug(
1437 "%s: %s loses to %s due to Neighor IP comparison",
1438 pfx_buf, new_buf, exist_buf);
1439 return 0;
1440 }
1441
1442 if (ret == -1) {
fdf81fa0 1443 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1444 if (debug)
1445 zlog_debug(
1446 "%s: %s wins over %s due to Neighor IP comparison",
1447 pfx_buf, new_buf, exist_buf);
1448 return 1;
1449 }
9fbdd100 1450
fdf81fa0 1451 *reason = bgp_path_selection_default;
d62a17ae 1452 if (debug)
1453 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1454 pfx_buf, new_buf, exist_buf);
718e3744 1455
d62a17ae 1456 return 1;
718e3744 1457}
1458
d071f237
AK
1459
1460int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1461 struct bgp_path_info *exist, int *paths_eq)
1462{
1463 enum bgp_path_selection_reason reason;
1464 char pfx_buf[PREFIX2STR_BUFFER];
1465
1466 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1467 AFI_L2VPN, SAFI_EVPN, &reason);
1468}
1469
65efcfce
LB
1470/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1471 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1472 * multipath is enabled
65efcfce 1473 * This version is compatible with */
18ee8310
DS
1474int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1475 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1476 afi_t afi, safi_t safi,
1477 enum bgp_path_selection_reason *reason)
d62a17ae 1478{
1479 int paths_eq;
1480 int ret;
18ee8310 1481 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1482 afi, safi, reason);
d62a17ae 1483
1484 if (paths_eq)
1485 ret = 0;
1486 else {
1487 if (ret == 1)
1488 ret = -1;
1489 else
1490 ret = 1;
1491 }
1492 return ret;
65efcfce
LB
1493}
1494
5a1ae2c2
DS
1495static enum filter_type bgp_input_filter(struct peer *peer,
1496 const struct prefix *p,
d62a17ae 1497 struct attr *attr, afi_t afi,
1498 safi_t safi)
718e3744 1499{
d62a17ae 1500 struct bgp_filter *filter;
6401252f 1501 enum filter_type ret = FILTER_PERMIT;
718e3744 1502
d62a17ae 1503 filter = &peer->filter[afi][safi];
718e3744 1504
d62a17ae 1505#define FILTER_EXIST_WARN(F, f, filter) \
1506 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1507 zlog_debug("%s: Could not find configured input %s-list %s!", \
1508 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1509
1510 if (DISTRIBUTE_IN_NAME(filter)) {
1511 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1512
6401252f
QY
1513 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1514 == FILTER_DENY) {
1515 ret = FILTER_DENY;
1516 goto done;
1517 }
d62a17ae 1518 }
1519
1520 if (PREFIX_LIST_IN_NAME(filter)) {
1521 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1522
6401252f
QY
1523 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1524 == PREFIX_DENY) {
1525 ret = FILTER_DENY;
1526 goto done;
1527 }
d62a17ae 1528 }
1529
1530 if (FILTER_LIST_IN_NAME(filter)) {
1531 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1532
1533 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1534 == AS_FILTER_DENY) {
1535 ret = FILTER_DENY;
1536 goto done;
1537 }
d62a17ae 1538 }
1539
6401252f 1540done:
c7bb4f00 1541 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1542 char pfxprint[PREFIX2STR_BUFFER];
1543
1544 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1545 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1546 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1547 }
1548
1549 return ret;
650f76c2 1550#undef FILTER_EXIST_WARN
718e3744 1551}
1552
b8685f9b
DS
1553static enum filter_type bgp_output_filter(struct peer *peer,
1554 const struct prefix *p,
d62a17ae 1555 struct attr *attr, afi_t afi,
1556 safi_t safi)
718e3744 1557{
d62a17ae 1558 struct bgp_filter *filter;
6401252f 1559 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1560
1561 filter = &peer->filter[afi][safi];
1562
1563#define FILTER_EXIST_WARN(F, f, filter) \
1564 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1565 zlog_debug("%s: Could not find configured output %s-list %s!", \
1566 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1567
d62a17ae 1568 if (DISTRIBUTE_OUT_NAME(filter)) {
1569 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1570
6401252f
QY
1571 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1572 == FILTER_DENY) {
1573 ret = FILTER_DENY;
1574 goto done;
1575 }
d62a17ae 1576 }
1577
1578 if (PREFIX_LIST_OUT_NAME(filter)) {
1579 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1580
d62a17ae 1581 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1582 == PREFIX_DENY) {
1583 ret = FILTER_DENY;
1584 goto done;
1585 }
d62a17ae 1586 }
718e3744 1587
d62a17ae 1588 if (FILTER_LIST_OUT_NAME(filter)) {
1589 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1590
d62a17ae 1591 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1592 == AS_FILTER_DENY) {
1593 ret = FILTER_DENY;
1594 goto done;
1595 }
1596 }
1597
c7bb4f00 1598 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1599 char pfxprint[PREFIX2STR_BUFFER];
1600
1601 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1602 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1603 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1604 }
718e3744 1605
6401252f
QY
1606done:
1607 return ret;
650f76c2 1608#undef FILTER_EXIST_WARN
718e3744 1609}
1610
1611/* If community attribute includes no_export then return 1. */
3dc339cd 1612static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1613{
9a706b42 1614 if (bgp_attr_get_community(attr)) {
d62a17ae 1615 /* NO_ADVERTISE check. */
9a706b42
DA
1616 if (community_include(bgp_attr_get_community(attr),
1617 COMMUNITY_NO_ADVERTISE))
3dc339cd 1618 return true;
d62a17ae 1619
1620 /* NO_EXPORT check. */
9a706b42
DA
1621 if (peer->sort == BGP_PEER_EBGP &&
1622 community_include(bgp_attr_get_community(attr),
1623 COMMUNITY_NO_EXPORT))
3dc339cd 1624 return true;
d62a17ae 1625
1626 /* NO_EXPORT_SUBCONFED check. */
1627 if (peer->sort == BGP_PEER_EBGP
1628 || peer->sort == BGP_PEER_CONFED)
9a706b42 1629 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1630 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1631 return true;
d62a17ae 1632 }
3dc339cd 1633 return false;
718e3744 1634}
1635
1636/* Route reflection loop check. */
3dc339cd 1637static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1638{
d62a17ae 1639 struct in_addr cluster_id;
779fee93 1640 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1641
779fee93 1642 if (cluster) {
d62a17ae 1643 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1644 cluster_id = peer->bgp->cluster_id;
1645 else
1646 cluster_id = peer->bgp->router_id;
1647
779fee93 1648 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1649 return true;
d62a17ae 1650 }
3dc339cd 1651 return false;
718e3744 1652}
6b0655a2 1653
d864dd9e
EB
1654static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1655{
1656 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1657 if (peer->local_role == ROLE_PROVIDER ||
1658 peer->local_role == ROLE_RS_SERVER)
1659 return true;
1660 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1661 return true;
1662 return false;
1663 }
1664 if (peer->local_role == ROLE_CUSTOMER ||
1665 peer->local_role == ROLE_PEER ||
1666 peer->local_role == ROLE_RS_CLIENT) {
1667 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1668 attr->otc = peer->as;
1669 }
1670 return false;
1671}
1672
1673static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1674{
1675 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1676 if (peer->local_role == ROLE_CUSTOMER ||
1677 peer->local_role == ROLE_RS_CLIENT ||
1678 peer->local_role == ROLE_PEER)
1679 return true;
1680 return false;
1681 }
1682 if (peer->local_role == ROLE_PROVIDER ||
1683 peer->local_role == ROLE_PEER ||
1684 peer->local_role == ROLE_RS_SERVER) {
1685 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1686 attr->otc = peer->bgp->as;
1687 }
1688 return false;
1689}
1690
5a78f2bc
EB
1691static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1692{
1693 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1694}
1695
5a1ae2c2 1696static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1697 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1698 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1699 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1700{
d62a17ae 1701 struct bgp_filter *filter;
82b692c0
LK
1702 struct bgp_path_info rmap_path = { 0 };
1703 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1704 route_map_result_t ret;
1705 struct route_map *rmap = NULL;
718e3744 1706
d62a17ae 1707 filter = &peer->filter[afi][safi];
718e3744 1708
d62a17ae 1709 /* Apply default weight value. */
1710 if (peer->weight[afi][safi])
1711 attr->weight = peer->weight[afi][safi];
718e3744 1712
d62a17ae 1713 if (rmap_name) {
1714 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1715
d62a17ae 1716 if (rmap == NULL)
1717 return RMAP_DENY;
1718 } else {
1719 if (ROUTE_MAP_IN_NAME(filter)) {
1720 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1721
d62a17ae 1722 if (rmap == NULL)
1723 return RMAP_DENY;
1724 }
1725 }
0b16f239 1726
d62a17ae 1727 /* Route map apply. */
1728 if (rmap) {
6006b807 1729 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1730 /* Duplicate current value to new structure for modification. */
40381db7
DS
1731 rmap_path.peer = peer;
1732 rmap_path.attr = attr;
82b692c0 1733 rmap_path.extra = &extra;
9bcb3eef 1734 rmap_path.net = dest;
196c6b09 1735
82b692c0
LK
1736 extra.num_labels = num_labels;
1737 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1738 memcpy(extra.label, label,
1739 num_labels * sizeof(mpls_label_t));
718e3744 1740
d62a17ae 1741 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1742
d62a17ae 1743 /* Apply BGP route map to the attribute. */
1782514f 1744 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1745
d62a17ae 1746 peer->rmap_type = 0;
0b16f239 1747
1f2263be 1748 if (ret == RMAP_DENYMATCH)
d62a17ae 1749 return RMAP_DENY;
0b16f239 1750 }
d62a17ae 1751 return RMAP_PERMIT;
0b16f239
DS
1752}
1753
5f040085 1754static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1755 struct attr *attr, afi_t afi, safi_t safi,
1756 const char *rmap_name)
0b16f239 1757{
40381db7 1758 struct bgp_path_info rmap_path;
d62a17ae 1759 route_map_result_t ret;
1760 struct route_map *rmap = NULL;
d7c0a89a 1761 uint8_t rmap_type;
0b16f239 1762
b787157a
DS
1763 /*
1764 * So if we get to this point and have no rmap_name
1765 * we want to just show the output as it currently
1766 * exists.
1767 */
1768 if (!rmap_name)
1769 return RMAP_PERMIT;
0b16f239 1770
d62a17ae 1771 /* Apply default weight value. */
1772 if (peer->weight[afi][safi])
1773 attr->weight = peer->weight[afi][safi];
0b16f239 1774
b787157a 1775 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1776
b787157a
DS
1777 /*
1778 * If we have a route map name and we do not find
1779 * the routemap that means we have an implicit
1780 * deny.
1781 */
1782 if (rmap == NULL)
1783 return RMAP_DENY;
0b16f239 1784
6006b807 1785 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1786 /* Route map apply. */
544be979 1787 /* Duplicate current value to new structure for modification. */
40381db7
DS
1788 rmap_path.peer = peer;
1789 rmap_path.attr = attr;
0b16f239 1790
0f672529 1791 rmap_type = peer->rmap_type;
b787157a 1792 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1793
b787157a 1794 /* Apply BGP route map to the attribute. */
1782514f 1795 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1796
0f672529 1797 peer->rmap_type = rmap_type;
b787157a
DS
1798
1799 if (ret == RMAP_DENYMATCH)
1800 /*
1801 * caller has multiple error paths with bgp_attr_flush()
1802 */
1803 return RMAP_DENY;
ac41b2a2 1804
d62a17ae 1805 return RMAP_PERMIT;
718e3744 1806}
6b0655a2 1807
5000f21c 1808/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1809static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1810 struct peer *peer, struct attr *attr)
1811{
1812 if (peer->sort == BGP_PEER_EBGP
1813 && (peer_af_flag_check(peer, afi, safi,
1814 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1815 || peer_af_flag_check(peer, afi, safi,
1816 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1817 || peer_af_flag_check(peer, afi, safi,
1818 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1819 || peer_af_flag_check(peer, afi, safi,
1820 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1821 // Take action on the entire aspath
1822 if (peer_af_flag_check(peer, afi, safi,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1824 || peer_af_flag_check(peer, afi, safi,
1825 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1826 if (peer_af_flag_check(
1827 peer, afi, safi,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1829 attr->aspath = aspath_replace_private_asns(
bf26b80e 1830 attr->aspath, bgp->as, peer->as);
d62a17ae 1831
179d5a0e
TA
1832 /*
1833 * Even if the aspath consists of just private ASNs we
1834 * need to walk the AS-Path to maintain all instances
1835 * of the peer's ASN to break possible loops.
1836 */
d62a17ae 1837 else
1838 attr->aspath = aspath_remove_private_asns(
bf26b80e 1839 attr->aspath, peer->as);
d62a17ae 1840 }
1841
1842 // 'all' was not specified so the entire aspath must be private
1843 // ASNs
1844 // for us to do anything
1845 else if (aspath_private_as_check(attr->aspath)) {
1846 if (peer_af_flag_check(
1847 peer, afi, safi,
1848 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1849 attr->aspath = aspath_replace_private_asns(
bf26b80e 1850 attr->aspath, bgp->as, peer->as);
d62a17ae 1851 else
179d5a0e
TA
1852 /*
1853 * Walk the aspath to retain any instances of
1854 * the peer_asn
1855 */
1856 attr->aspath = aspath_remove_private_asns(
1857 attr->aspath, peer->as);
d62a17ae 1858 }
1859 }
5000f21c
DS
1860}
1861
c7122e14 1862/* If this is an EBGP peer with as-override */
d62a17ae 1863static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1864 struct peer *peer, struct attr *attr)
1865{
bbe7bc46
DA
1866 struct aspath *aspath;
1867
9bbdb457 1868 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1869 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1870 if (attr->aspath->refcnt)
1871 aspath = aspath_dup(attr->aspath);
1872 else
1873 aspath = attr->aspath;
1874
1875 attr->aspath = aspath_intern(
1876 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1877
1878 aspath_free(aspath);
1879 }
d62a17ae 1880}
1881
1479ed2f
DA
1882void bgp_attr_add_llgr_community(struct attr *attr)
1883{
1884 struct community *old;
1885 struct community *new;
1886 struct community *merge;
1887 struct community *llgr;
1888
9a706b42 1889 old = bgp_attr_get_community(attr);
1479ed2f
DA
1890 llgr = community_str2com("llgr-stale");
1891
1892 assert(llgr);
1893
1894 if (old) {
1895 merge = community_merge(community_dup(old), llgr);
1896
1897 if (old->refcnt == 0)
1898 community_free(&old);
1899
1900 new = community_uniq_sort(merge);
1901 community_free(&merge);
1902 } else {
1903 new = community_dup(llgr);
1904 }
1905
1906 community_free(&llgr);
1907
9a706b42 1908 bgp_attr_set_community(attr, new);
1479ed2f
DA
1909}
1910
7f323236
DW
1911void bgp_attr_add_gshut_community(struct attr *attr)
1912{
1913 struct community *old;
1914 struct community *new;
1915 struct community *merge;
1916 struct community *gshut;
1917
9a706b42 1918 old = bgp_attr_get_community(attr);
7f323236
DW
1919 gshut = community_str2com("graceful-shutdown");
1920
990f4f91 1921 assert(gshut);
1922
7f323236
DW
1923 if (old) {
1924 merge = community_merge(community_dup(old), gshut);
1925
a4d82a8a 1926 if (old->refcnt == 0)
3c1f53de 1927 community_free(&old);
7f323236
DW
1928
1929 new = community_uniq_sort(merge);
3c1f53de 1930 community_free(&merge);
7f323236
DW
1931 } else {
1932 new = community_dup(gshut);
1933 }
1934
3c1f53de 1935 community_free(&gshut);
9a706b42 1936 bgp_attr_set_community(attr, new);
7f323236
DW
1937
1938 /* When we add the graceful-shutdown community we must also
1939 * lower the local-preference */
1940 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1941 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1942}
1943
1944
e73c112e
MK
1945/* Notify BGP Conditional advertisement scanner process. */
1946void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1947{
e73c112e 1948 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1949 afi_t afi = SUBGRP_AFI(subgrp);
1950 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1951 struct bgp_filter *filter = &peer->filter[afi][safi];
1952
1953 if (!ADVERTISE_MAP_NAME(filter))
1954 return;
1955
52979c3b
DS
1956 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1957 return;
e73c112e 1958
52979c3b 1959 peer->advmap_table_change = true;
e73c112e
MK
1960}
1961
1962
f2ee6d5c 1963void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1964{
960035b2 1965 if (family == AF_INET) {
975a328e
DA
1966 attr->nexthop.s_addr = INADDR_ANY;
1967 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1968 }
d62a17ae 1969 if (family == AF_INET6)
1970 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1971 if (family == AF_EVPN)
1972 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1973}
1974
9bcb3eef 1975bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1976 struct update_subgroup *subgrp,
7f7940e6 1977 const struct prefix *p, struct attr *attr,
51c3a7de 1978 struct attr *post_attr)
d62a17ae 1979{
1980 struct bgp_filter *filter;
1981 struct peer *from;
1982 struct peer *peer;
1983 struct peer *onlypeer;
1984 struct bgp *bgp;
40381db7 1985 struct attr *piattr;
b68885f9 1986 route_map_result_t ret;
d62a17ae 1987 int transparent;
1988 int reflect;
1989 afi_t afi;
1990 safi_t safi;
1991 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1992 bool nh_reset = false;
1993 uint64_t cum_bw;
d62a17ae 1994
1995 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1996 return false;
d62a17ae 1997
1998 afi = SUBGRP_AFI(subgrp);
1999 safi = SUBGRP_SAFI(subgrp);
2000 peer = SUBGRP_PEER(subgrp);
2001 onlypeer = NULL;
2002 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2003 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2004
40381db7 2005 from = pi->peer;
d62a17ae 2006 filter = &peer->filter[afi][safi];
2007 bgp = SUBGRP_INST(subgrp);
40381db7
DS
2008 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2009 : pi->attr;
3f9c7369 2010
d0bf49ec
LS
2011 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2012 peer->pmax_out[afi][safi] != 0 &&
2013 subgrp->pscount >= peer->pmax_out[afi][safi]) {
2014 if (BGP_DEBUG(update, UPDATE_OUT) ||
2015 BGP_DEBUG(update, UPDATE_PREFIX)) {
2016 zlog_debug("%s reached maximum prefix to be send (%u)",
2017 peer->host, peer->pmax_out[afi][safi]);
2018 }
2019 return false;
2020 }
2021
49e5a4a0 2022#ifdef ENABLE_BGP_VNC
d62a17ae 2023 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2024 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2025 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2026
2027 /*
2028 * direct and direct_ext type routes originate internally even
2029 * though they can have peer pointers that reference other
2030 * systems
2031 */
8228a9a7
DS
2032 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2033 __func__, p);
d62a17ae 2034 samepeer_safe = 1;
2035 }
65efcfce
LB
2036#endif
2037
ddb5b488
PZ
2038 if (((afi == AFI_IP) || (afi == AFI_IP6))
2039 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2040 && (pi->type == ZEBRA_ROUTE_BGP)
2041 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2042
2043 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2044
2045 samepeer_safe = 1;
2046 }
2047
d62a17ae 2048 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2049 * pi is valid */
2050 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2051 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2052 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2053 return false;
d62a17ae 2054 }
adbac85e 2055
d62a17ae 2056 /* If this is not the bestpath then check to see if there is an enabled
2057 * addpath
2058 * feature that requires us to advertise it */
8ccee4b8
DA
2059 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2060 if (!bgp_addpath_capable(pi, peer, afi, safi))
3dc339cd 2061 return false;
06370dac 2062
d62a17ae 2063 /* Aggregate-address suppress check. */
4056a5f6
RZ
2064 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2065 return false;
3f9c7369 2066
13b7e7f0
DS
2067 /*
2068 * If we are doing VRF 2 VRF leaking via the import
2069 * statement, we want to prevent the route going
2070 * off box as that the RT and RD created are localy
2071 * significant and globaly useless.
2072 */
40381db7
DS
2073 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2074 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2075 return false;
13b7e7f0 2076
d62a17ae 2077 /* If it's labeled safi, make sure the route has a valid label. */
2078 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2079 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2080 if (!bgp_is_valid_label(&label)) {
2081 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2082 zlog_debug("u%" PRIu64 ":s%" PRIu64
2083 " %pFX is filtered - no label (%p)",
d62a17ae 2084 subgrp->update_group->id, subgrp->id,
8228a9a7 2085 p, &label);
3dc339cd 2086 return false;
d62a17ae 2087 }
2088 }
cd1964ff 2089
d62a17ae 2090 /* Do not send back route to sender. */
2091 if (onlypeer && from == onlypeer) {
3dc339cd 2092 return false;
d62a17ae 2093 }
3f9c7369 2094
d62a17ae 2095 /* Do not send the default route in the BGP table if the neighbor is
2096 * configured for default-originate */
2097 if (CHECK_FLAG(peer->af_flags[afi][safi],
2098 PEER_FLAG_DEFAULT_ORIGINATE)) {
2099 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2100 return false;
d62a17ae 2101 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2102 return false;
d62a17ae 2103 }
4125bb67 2104
d62a17ae 2105 /* Transparency check. */
2106 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2107 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2108 transparent = 1;
2109 else
2110 transparent = 0;
2111
2112 /* If community is not disabled check the no-export and local. */
40381db7 2113 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2114 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2115 zlog_debug("%s: community filter check fail for %pFX",
2116 __func__, p);
3dc339cd 2117 return false;
d62a17ae 2118 }
3f9c7369 2119
d62a17ae 2120 /* If the attribute has originator-id and it is same as remote
2121 peer's id. */
40381db7
DS
2122 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2123 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2124 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2125 zlog_debug(
a9f3f4f5
DA
2126 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2127 onlypeer, p);
3dc339cd 2128 return false;
d62a17ae 2129 }
3f9c7369 2130
d62a17ae 2131 /* ORF prefix-list filter check */
2132 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2133 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2134 || CHECK_FLAG(peer->af_cap[afi][safi],
2135 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2136 if (peer->orf_plist[afi][safi]) {
2137 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2138 == PREFIX_DENY) {
2139 if (bgp_debug_update(NULL, p,
2140 subgrp->update_group, 0))
2141 zlog_debug(
a9f3f4f5
DA
2142 "%pBP [Update:SEND] %pFX is filtered via ORF",
2143 peer, p);
3dc339cd 2144 return false;
d62a17ae 2145 }
2146 }
2147
2148 /* Output filter check. */
40381db7 2149 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2150 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2151 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2152 p);
3dc339cd 2153 return false;
d62a17ae 2154 }
3f9c7369 2155
d62a17ae 2156 /* AS path loop check. */
25851bf0
DA
2157 if (peer->as_path_loop_detection &&
2158 aspath_loop_check(piattr->aspath, peer->as)) {
d62a17ae 2159 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2160 zlog_debug(
a9f3f4f5 2161 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
25851bf0 2162 peer, peer->as);
3dc339cd 2163 return false;
d62a17ae 2164 }
3f9c7369 2165
d62a17ae 2166 /* If we're a CONFED we need to loop check the CONFED ID too */
2167 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
b0a8f709 2168 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
d62a17ae 2169 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2170 zlog_debug(
a9f3f4f5
DA
2171 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2172 peer, bgp->confed_id);
3dc339cd 2173 return false;
d62a17ae 2174 }
3f9c7369 2175 }
3f9c7369 2176
d62a17ae 2177 /* Route-Reflect check. */
2178 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2179 reflect = 1;
2180 else
2181 reflect = 0;
2182
2183 /* IBGP reflection check. */
2184 if (reflect && !samepeer_safe) {
2185 /* A route from a Client peer. */
2186 if (CHECK_FLAG(from->af_flags[afi][safi],
2187 PEER_FLAG_REFLECTOR_CLIENT)) {
2188 /* Reflect to all the Non-Client peers and also to the
2189 Client peers other than the originator. Originator
2190 check
2191 is already done. So there is noting to do. */
2192 /* no bgp client-to-client reflection check. */
892fedb6
DA
2193 if (CHECK_FLAG(bgp->flags,
2194 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2195 if (CHECK_FLAG(peer->af_flags[afi][safi],
2196 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2197 return false;
d62a17ae 2198 } else {
2199 /* A route from a Non-client peer. Reflect to all other
2200 clients. */
2201 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2202 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2203 return false;
d62a17ae 2204 }
2205 }
3f9c7369 2206
51c3a7de
DA
2207 /* For modify attribute, copy it to temporary structure.
2208 * post_attr comes from BGP conditional advertisements, where
2209 * attributes are already processed by advertise-map route-map,
2210 * and this needs to be saved instead of overwriting from the
2211 * path attributes.
2212 */
2213 if (post_attr)
2214 *attr = *post_attr;
2215 else
2216 *attr = *piattr;
d62a17ae 2217
2218 /* If local-preference is not set. */
2219 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2220 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2221 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2222 attr->local_pref = bgp->default_local_pref;
3f9c7369 2223 }
3f9c7369 2224
d62a17ae 2225 /* If originator-id is not set and the route is to be reflected,
2226 set the originator id */
2227 if (reflect
2228 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2229 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2230 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2231 }
3f9c7369 2232
d62a17ae 2233 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2234 */
2235 if (peer->sort == BGP_PEER_EBGP
2236 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2237 if (from != bgp->peer_self && !transparent
2238 && !CHECK_FLAG(peer->af_flags[afi][safi],
2239 PEER_FLAG_MED_UNCHANGED))
2240 attr->flag &=
2241 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2242 }
3f9c7369 2243
d62a17ae 2244 /* Since the nexthop attribute can vary per peer, it is not explicitly
2245 * set
2246 * in announce check, only certain flags and length (or number of
2247 * nexthops
2248 * -- for IPv6/MP_REACH) are set here in order to guide the update
2249 * formation
2250 * code in setting the nexthop(s) on a per peer basis in
2251 * reformat_peer().
2252 * Typically, the source nexthop in the attribute is preserved but in
2253 * the
2254 * scenarios where we know it will always be overwritten, we reset the
2255 * nexthop to "0" in an attempt to achieve better Update packing. An
2256 * example of this is when a prefix from each of 2 IBGP peers needs to
2257 * be
2258 * announced to an EBGP peer (and they have the same attributes barring
2259 * their nexthop).
2260 */
2261 if (reflect)
2262 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2263
2264#define NEXTHOP_IS_V6 \
2265 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2266 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2267 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2268 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2269
2270 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2271 * if
2272 * the peer (group) is configured to receive link-local nexthop
2273 * unchanged
c728d027
DA
2274 * and it is available in the prefix OR we're not reflecting the route,
2275 * link-local nexthop address is valid and
d62a17ae 2276 * the peer (group) to whom we're going to announce is on a shared
2277 * network
2278 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2279 * By checking if nexthop LL address is valid we are sure that
2280 * we do not announce LL address as `::`.
d62a17ae 2281 */
2282 if (NEXTHOP_IS_V6) {
2283 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2284 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2285 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2286 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2287 || (!reflect && !transparent
c728d027
DA
2288 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2289 && peer->shared_network
d62a17ae 2290 && (from == bgp->peer_self
2291 || peer->sort == BGP_PEER_EBGP))) {
f7a0eb6a
PG
2292 if (safi == SAFI_MPLS_VPN)
2293 attr->mp_nexthop_len =
2294 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2295 else
2296 attr->mp_nexthop_len =
2297 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 2298 }
3f9c7369 2299
d62a17ae 2300 /* Clear off link-local nexthop in source, whenever it is not
2301 * needed to
2302 * ensure more prefixes share the same attribute for
2303 * announcement.
2304 */
2305 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2306 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2307 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2308 }
3f9c7369 2309
5a78f2bc
EB
2310 if (bgp_check_role_applicability(afi, safi) &&
2311 bgp_otc_egress(peer, attr))
d864dd9e
EB
2312 return false;
2313
d62a17ae 2314 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2315 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2316
0655090c
QY
2317 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2318 filter->advmap.aname &&
2319 route_map_lookup_by_name(filter->advmap.aname)) {
2320 struct bgp_path_info rmap_path = {0};
2321 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2322 struct attr dummy_attr = *attr;
2323
2324 /* Fill temp path_info */
2325 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2326 pi, peer, &dummy_attr);
2327
2328 struct route_map *amap =
2329 route_map_lookup_by_name(filter->advmap.aname);
2330
2331 ret = route_map_apply(amap, p, &rmap_path);
2332
2333 bgp_attr_flush(&dummy_attr);
2334
2335 /*
2336 * The conditional advertisement mode is Withdraw and this
2337 * prefix is a conditional prefix. Don't advertise it
2338 */
2339 if (ret == RMAP_PERMITMATCH)
2340 return false;
2341 }
2342
d62a17ae 2343 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2344 if (!post_attr &&
2345 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2346 struct bgp_path_info rmap_path = {0};
2347 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2348 struct attr dummy_attr = {0};
d62a17ae 2349
e34291b8 2350 /* Fill temp path_info */
9bcb3eef
DS
2351 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2352 pi, peer, attr);
16f7ce2b 2353
d62a17ae 2354 /* don't confuse inbound and outbound setting */
2355 RESET_FLAG(attr->rmap_change_flags);
2356
2357 /*
2358 * The route reflector is not allowed to modify the attributes
2359 * of the reflected IBGP routes unless explicitly allowed.
2360 */
2361 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2362 && !CHECK_FLAG(bgp->flags,
2363 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2364 dummy_attr = *attr;
40381db7 2365 rmap_path.attr = &dummy_attr;
d62a17ae 2366 }
3f9c7369 2367
d62a17ae 2368 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2369
4056a5f6 2370 if (bgp_path_suppressed(pi))
d62a17ae 2371 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2372 &rmap_path);
d62a17ae 2373 else
2374 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2375 &rmap_path);
d62a17ae 2376
7e7639f5 2377 bgp_attr_flush(&dummy_attr);
d62a17ae 2378 peer->rmap_type = 0;
2379
2380 if (ret == RMAP_DENYMATCH) {
778048bf 2381 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2382 zlog_debug(
a9f3f4f5
DA
2383 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2384 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2385 bgp_attr_flush(rmap_path.attr);
3dc339cd 2386 return false;
d62a17ae 2387 }
3f9c7369 2388 }
3f9c7369 2389
9dac9fc8
DA
2390 /* RFC 8212 to prevent route leaks.
2391 * This specification intends to improve this situation by requiring the
2392 * explicit configuration of both BGP Import and Export Policies for any
2393 * External BGP (EBGP) session such as customers, peers, or
2394 * confederation boundaries for all enabled address families. Through
2395 * codification of the aforementioned requirement, operators will
2396 * benefit from consistent behavior across different BGP
2397 * implementations.
2398 */
1d3fdccf 2399 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2400 if (!bgp_outbound_policy_exists(peer, filter)) {
2401 if (monotime_since(&bgp->ebgprequirespolicywarning,
2402 NULL) > FIFTEENMINUTE2USEC ||
2403 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2404 zlog_warn(
2405 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2406 monotime(&bgp->ebgprequirespolicywarning);
2407 }
3dc339cd 2408 return false;
b17826b7 2409 }
9dac9fc8 2410
fb29348a
DA
2411 /* draft-ietf-idr-deprecate-as-set-confed-set
2412 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2413 * Eventually, This document (if approved) updates RFC 4271
2414 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2415 * and obsoletes RFC 6472.
2416 */
7f972cd8 2417 if (peer->bgp->reject_as_sets)
fb29348a 2418 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2419 return false;
fb29348a 2420
8c4d4624 2421 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2422 * SoO extended community and validate against the configured
2423 * one. If they match, do not announce, to prevent routing
2424 * loops.
2425 */
2426 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2427 peer->soo[afi][safi]) {
2428 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2429 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2430
2431 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2432 ECOMMUNITY_SITE_ORIGIN) ||
2433 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2434 ECOMMUNITY_SITE_ORIGIN) ||
2435 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2436 ECOMMUNITY_SITE_ORIGIN)) &&
2437 ecommunity_include(ecomm, ecomm_soo)) {
2438 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2439 zlog_debug(
2440 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2441 peer, p, ecommunity_str(ecomm_soo));
2442 return false;
2443 }
2444 }
2445
33d022bc
DA
2446 /* Codification of AS 0 Processing */
2447 if (aspath_check_as_zero(attr->aspath))
e2369003 2448 return false;
33d022bc 2449
637e5ba4 2450 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2451 if (peer->sort == BGP_PEER_IBGP
2452 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2453 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2454 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2455 } else {
2456 bgp_attr_add_gshut_community(attr);
2457 }
2458 }
2459
1479ed2f
DA
2460 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2461 * Capability" to a neighbor MUST perform the following upon receiving
2462 * a route from that neighbor with the "LLGR_STALE" community, or upon
2463 * attaching the "LLGR_STALE" community itself per Section 4.2:
2464 *
2465 * The route SHOULD NOT be advertised to any neighbor from which the
2466 * Long-lived Graceful Restart Capability has not been received.
2467 */
9a706b42
DA
2468 if (bgp_attr_get_community(attr) &&
2469 community_include(bgp_attr_get_community(attr),
2470 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2471 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2472 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2473 return false;
2474
d62a17ae 2475 /* After route-map has been applied, we check to see if the nexthop to
2476 * be carried in the attribute (that is used for the announcement) can
2477 * be cleared off or not. We do this in all cases where we would be
2478 * setting the nexthop to "ourselves". For IPv6, we only need to
2479 * consider
2480 * the global nexthop here; the link-local nexthop would have been
2481 * cleared
2482 * already, and if not, it is required by the update formation code.
2483 * Also see earlier comments in this function.
2484 */
2485 /*
2486 * If route-map has performed some operation on the nexthop or the peer
2487 * configuration says to pass it unchanged, we cannot reset the nexthop
2488 * here, so only attempt to do it if these aren't true. Note that the
2489 * route-map handler itself might have cleared the nexthop, if for
2490 * example,
2491 * it is configured as 'peer-address'.
2492 */
2493 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2494 piattr->rmap_change_flags)
d62a17ae 2495 && !transparent
2496 && !CHECK_FLAG(peer->af_flags[afi][safi],
2497 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2498 /* We can reset the nexthop, if setting (or forcing) it to
2499 * 'self' */
2500 if (CHECK_FLAG(peer->af_flags[afi][safi],
2501 PEER_FLAG_NEXTHOP_SELF)
2502 || CHECK_FLAG(peer->af_flags[afi][safi],
2503 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2504 if (!reflect
2505 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2506 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2507 subgroup_announce_reset_nhop(
2508 (peer_cap_enhe(peer, afi, safi)
2509 ? AF_INET6
2510 : p->family),
2511 attr);
7b651a32 2512 nh_reset = true;
2513 }
d62a17ae 2514 } else if (peer->sort == BGP_PEER_EBGP) {
2515 /* Can also reset the nexthop if announcing to EBGP, but
2516 * only if
2517 * no peer in the subgroup is on a shared subnet.
2518 * Note: 3rd party nexthop currently implemented for
2519 * IPv4 only.
2520 */
737af885
BS
2521 if ((p->family == AF_INET) &&
2522 (!bgp_subgrp_multiaccess_check_v4(
2523 piattr->nexthop,
7b651a32 2524 subgrp, from))) {
d62a17ae 2525 subgroup_announce_reset_nhop(
2526 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2527 ? AF_INET6
2528 : p->family),
737af885 2529 attr);
7b651a32 2530 nh_reset = true;
2531 }
737af885
BS
2532
2533 if ((p->family == AF_INET6) &&
2534 (!bgp_subgrp_multiaccess_check_v6(
2535 piattr->mp_nexthop_global,
7b651a32 2536 subgrp, from))) {
737af885
BS
2537 subgroup_announce_reset_nhop(
2538 (peer_cap_enhe(peer, afi, safi)
2539 ? AF_INET6
2540 : p->family),
2541 attr);
7b651a32 2542 nh_reset = true;
2543 }
737af885
BS
2544
2545
2546
40381db7 2547 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2548 /*
2549 * This flag is used for leaked vpn-vrf routes
2550 */
2551 int family = p->family;
2552
2553 if (peer_cap_enhe(peer, afi, safi))
2554 family = AF_INET6;
2555
2556 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2557 zlog_debug(
6cf8a4bf
DA
2558 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2559 __func__, p, family2str(family));
960035b2 2560 subgroup_announce_reset_nhop(family, attr);
7b651a32 2561 nh_reset = true;
d62a17ae 2562 }
63696f1d 2563 }
960035b2 2564
63696f1d 2565 /* If IPv6/MP and nexthop does not have any override and happens
2566 * to
2567 * be a link-local address, reset it so that we don't pass along
2568 * the
2569 * source's link-local IPv6 address to recipients who may not be
2570 * on
2571 * the same interface.
2572 */
2573 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2574 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2575 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2576 nh_reset = true;
2577 }
d62a17ae 2578 }
3f9c7369 2579
7b27cf7b
DA
2580 /* If this is an iBGP, send Origin Validation State (OVS)
2581 * extended community (rfc8097).
2582 */
2583 if (peer->sort == BGP_PEER_IBGP) {
2584 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2585
2586 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2587
2588 if (rpki_state != RPKI_NOT_BEING_USED)
2589 bgp_attr_set_ecommunity(
2590 attr, ecommunity_add_origin_validation_state(
2591 rpki_state,
2592 bgp_attr_get_ecommunity(attr)));
2593 }
2594
7b651a32 2595 /*
2596 * When the next hop is set to ourselves, if all multipaths have
2597 * link-bandwidth announce the cumulative bandwidth as that makes
2598 * the most sense. However, don't modify if the link-bandwidth has
2599 * been explicitly set by user policy.
2600 */
2601 if (nh_reset &&
f7e1c681 2602 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2603 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2604 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2605 bgp_attr_set_ecommunity(
2606 attr,
2607 ecommunity_replace_linkbw(
2608 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2609 CHECK_FLAG(
2610 peer->flags,
2611 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2612
3dc339cd 2613 return true;
3f9c7369
DS
2614}
2615
cc9f21da 2616static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2617{
2618 struct afi_safi_info *info;
2619 afi_t afi;
2620 safi_t safi;
2621 struct bgp *bgp;
2622
2623 info = THREAD_ARG(thread);
2624 afi = info->afi;
2625 safi = info->safi;
2626 bgp = info->bgp;
2627
f009ff26 2628 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2629 XFREE(MTYPE_TMP, info);
2630
2631 /* Best path selection */
cc9f21da 2632 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2633}
2634
9bcb3eef 2635void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2636 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2637 struct bgp_path_info_pair *result, afi_t afi,
2638 safi_t safi)
2639{
2640 struct bgp_path_info *new_select;
2641 struct bgp_path_info *old_select;
40381db7
DS
2642 struct bgp_path_info *pi;
2643 struct bgp_path_info *pi1;
2644 struct bgp_path_info *pi2;
2645 struct bgp_path_info *nextpi = NULL;
d62a17ae 2646 int paths_eq, do_mpath, debug;
2647 struct list mp_list;
2648 char pfx_buf[PREFIX2STR_BUFFER];
2649 char path_buf[PATH_ADDPATH_STR_BUFFER];
2650
2651 bgp_mp_list_init(&mp_list);
2652 do_mpath =
2653 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2654
9bcb3eef 2655 debug = bgp_debug_bestpath(dest);
d62a17ae 2656
2657 if (debug)
9bcb3eef 2658 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2659
9bcb3eef 2660 dest->reason = bgp_path_selection_none;
d62a17ae 2661 /* bgp deterministic-med */
2662 new_select = NULL;
892fedb6 2663 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2664
1defdda8 2665 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2666 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2667 pi1 = pi1->next)
9bcb3eef 2668 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2669 BGP_PATH_DMED_SELECTED);
d62a17ae 2670
9bcb3eef 2671 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2672 pi1 = pi1->next) {
40381db7 2673 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2674 continue;
40381db7 2675 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2676 continue;
de692a4e 2677 if (pi1->peer != bgp->peer_self &&
2678 !CHECK_FLAG(pi1->peer->sflags,
2679 PEER_STATUS_NSF_WAIT)) {
feb17238 2680 if (!peer_established(pi1->peer))
d62a17ae 2681 continue;
de692a4e 2682 }
d62a17ae 2683
40381db7
DS
2684 new_select = pi1;
2685 if (pi1->next) {
2686 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2687 if (CHECK_FLAG(pi2->flags,
1defdda8 2688 BGP_PATH_DMED_CHECK))
d62a17ae 2689 continue;
40381db7 2690 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2691 continue;
ea8b2282 2692 if (pi2->peer != bgp->peer_self
d62a17ae 2693 && !CHECK_FLAG(
ea8b2282
DS
2694 pi2->peer->sflags,
2695 PEER_STATUS_NSF_WAIT))
40381db7 2696 if (pi2->peer->status
d62a17ae 2697 != Established)
2698 continue;
2699
121e245d
DS
2700 if (!aspath_cmp_left(pi1->attr->aspath,
2701 pi2->attr->aspath)
2702 && !aspath_cmp_left_confed(
40381db7 2703 pi1->attr->aspath,
121e245d
DS
2704 pi2->attr->aspath))
2705 continue;
d62a17ae 2706
121e245d
DS
2707 if (bgp_path_info_cmp(
2708 bgp, pi2, new_select,
2709 &paths_eq, mpath_cfg, debug,
fdf81fa0 2710 pfx_buf, afi, safi,
9bcb3eef 2711 &dest->reason)) {
121e245d 2712 bgp_path_info_unset_flag(
9bcb3eef 2713 dest, new_select,
121e245d
DS
2714 BGP_PATH_DMED_SELECTED);
2715 new_select = pi2;
d62a17ae 2716 }
121e245d
DS
2717
2718 bgp_path_info_set_flag(
9bcb3eef 2719 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2720 }
2721 }
9bcb3eef 2722 bgp_path_info_set_flag(dest, new_select,
18ee8310 2723 BGP_PATH_DMED_CHECK);
9bcb3eef 2724 bgp_path_info_set_flag(dest, new_select,
18ee8310 2725 BGP_PATH_DMED_SELECTED);
d62a17ae 2726
2727 if (debug) {
18ee8310 2728 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2729 new_select, path_buf, sizeof(path_buf));
8228a9a7 2730 zlog_debug(
4378495a
DS
2731 "%pBD(%s): %s is the bestpath from AS %u",
2732 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2733 aspath_get_first_as(
2734 new_select->attr->aspath));
d62a17ae 2735 }
2736 }
2737 }
96450faf 2738
d62a17ae 2739 /* Check old selected route and new selected route. */
2740 old_select = NULL;
2741 new_select = NULL;
9bcb3eef 2742 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2743 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2744 enum bgp_path_selection_reason reason;
2745
40381db7
DS
2746 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2747 old_select = pi;
d62a17ae 2748
40381db7 2749 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2750 /* reap REMOVED routes, if needs be
2751 * selected route must stay for a while longer though
2752 */
40381db7
DS
2753 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2754 && (pi != old_select))
9bcb3eef 2755 bgp_path_info_reap(dest, pi);
d62a17ae 2756
ddb5b488 2757 if (debug)
40381db7
DS
2758 zlog_debug("%s: pi %p in holddown", __func__,
2759 pi);
ddb5b488 2760
d62a17ae 2761 continue;
2762 }
96450faf 2763
40381db7
DS
2764 if (pi->peer && pi->peer != bgp->peer_self
2765 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2766 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2767
2768 if (debug)
2769 zlog_debug(
40381db7
DS
2770 "%s: pi %p non self peer %s not estab state",
2771 __func__, pi, pi->peer->host);
ddb5b488 2772
d62a17ae 2773 continue;
ddb5b488 2774 }
9fbdd100 2775
892fedb6 2776 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2777 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2778 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2779 if (debug)
40381db7 2780 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2781 continue;
2782 }
9fbdd100 2783
9bcb3eef 2784 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2785
9bcb3eef 2786 reason = dest->reason;
40381db7 2787 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2788 debug, pfx_buf, afi, safi,
2789 &dest->reason)) {
19ea4cec
DS
2790 if (new_select == NULL &&
2791 reason != bgp_path_selection_none)
9bcb3eef 2792 dest->reason = reason;
40381db7 2793 new_select = pi;
d62a17ae 2794 }
2795 }
718e3744 2796
d62a17ae 2797 /* Now that we know which path is the bestpath see if any of the other
2798 * paths
2799 * qualify as multipaths
2800 */
2801 if (debug) {
2802 if (new_select)
7533cad7
QY
2803 bgp_path_info_path_with_addpath_rx_str(
2804 new_select, path_buf, sizeof(path_buf));
d62a17ae 2805 else
772270f3 2806 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2807 zlog_debug(
4378495a
DS
2808 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2809 dest, bgp->name_pretty, path_buf,
d62a17ae 2810 old_select ? old_select->peer->host : "NONE");
96450faf 2811 }
9fbdd100 2812
d62a17ae 2813 if (do_mpath && new_select) {
9bcb3eef 2814 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2815 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2816
2817 if (debug)
18ee8310 2818 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2819 pi, path_buf, sizeof(path_buf));
d62a17ae 2820
40381db7 2821 if (pi == new_select) {
d62a17ae 2822 if (debug)
2823 zlog_debug(
4378495a
DS
2824 "%pBD(%s): %s is the bestpath, add to the multipath list",
2825 dest, bgp->name_pretty,
2826 path_buf);
40381db7 2827 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2828 continue;
2829 }
2830
40381db7 2831 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2832 continue;
2833
40381db7
DS
2834 if (pi->peer && pi->peer != bgp->peer_self
2835 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2836 PEER_STATUS_NSF_WAIT))
feb17238 2837 if (!peer_established(pi->peer))
d62a17ae 2838 continue;
2839
40381db7 2840 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2841 if (debug)
2842 zlog_debug(
8228a9a7
DS
2843 "%pBD: %s has the same nexthop as the bestpath, skip it",
2844 dest, path_buf);
d62a17ae 2845 continue;
2846 }
2847
40381db7 2848 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2849 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2850 &dest->reason);
d62a17ae 2851
2852 if (paths_eq) {
2853 if (debug)
2854 zlog_debug(
8228a9a7
DS
2855 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2856 dest, path_buf);
40381db7 2857 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2858 }
2859 }
2860 }
fee0f4c6 2861
4378495a 2862 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2863 mpath_cfg);
2864 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2865 bgp_mp_list_clear(&mp_list);
96450faf 2866
9bcb3eef 2867 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2868
d62a17ae 2869 result->old = old_select;
2870 result->new = new_select;
96450faf 2871
d62a17ae 2872 return;
fee0f4c6 2873}
2874
3f9c7369
DS
2875/*
2876 * A new route/change in bestpath of an existing route. Evaluate the path
2877 * for advertisement to the subgroup.
2878 */
3dc339cd
DA
2879void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2880 struct bgp_path_info *selected,
9bcb3eef 2881 struct bgp_dest *dest,
3dc339cd 2882 uint32_t addpath_tx_id)
d62a17ae 2883{
b54892e0 2884 const struct prefix *p;
d62a17ae 2885 struct peer *onlypeer;
2886 struct attr attr;
2887 afi_t afi;
2888 safi_t safi;
a77e2f4b
S
2889 struct bgp *bgp;
2890 bool advertise;
adbac85e 2891
9bcb3eef 2892 p = bgp_dest_get_prefix(dest);
d62a17ae 2893 afi = SUBGRP_AFI(subgrp);
2894 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2895 bgp = SUBGRP_INST(subgrp);
d62a17ae 2896 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2897 : NULL);
2898
2dbe669b
DA
2899 if (BGP_DEBUG(update, UPDATE_OUT))
2900 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2901
d62a17ae 2902 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2903 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2904 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2905 return;
d62a17ae 2906
6006b807 2907 memset(&attr, 0, sizeof(attr));
d62a17ae 2908 /* It's initialized in bgp_announce_check() */
2909
a77e2f4b
S
2910 /* Announcement to the subgroup. If the route is filtered withdraw it.
2911 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2912 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2913 * route
d62a17ae 2914 */
a77e2f4b
S
2915 advertise = bgp_check_advertise(bgp, dest);
2916
d62a17ae 2917 if (selected) {
7f7940e6 2918 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2919 NULL)) {
a77e2f4b
S
2920 /* Route is selected, if the route is already installed
2921 * in FIB, then it is advertised
2922 */
be785e35 2923 if (advertise) {
84ef27fc
DA
2924 if (!bgp_check_withdrawal(bgp, dest)) {
2925 struct attr *adv_attr =
2926 bgp_attr_intern(&attr);
2927
2928 bgp_adj_out_set_subgroup(dest, subgrp,
2929 adv_attr,
2930 selected);
2931 } else
be785e35
DS
2932 bgp_adj_out_unset_subgroup(
2933 dest, subgrp, 1, addpath_tx_id);
2934 }
a77e2f4b 2935 } else
9bcb3eef 2936 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2937 addpath_tx_id);
d62a17ae 2938 }
2939
2940 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2941 else {
9bcb3eef 2942 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2943 }
200df115 2944}
fee0f4c6 2945
3064bf43 2946/*
e1072051 2947 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2948 * This is called at the end of route processing.
3064bf43 2949 */
9bcb3eef 2950void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2951{
40381db7 2952 struct bgp_path_info *pi;
3064bf43 2953
9bcb3eef 2954 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2955 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2956 continue;
40381db7
DS
2957 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2958 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2959 }
3064bf43 2960}
2961
2962/*
2963 * Has the route changed from the RIB's perspective? This is invoked only
2964 * if the route selection returns the same best route as earlier - to
2965 * determine if we need to update zebra or not.
2966 */
9bcb3eef 2967bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2968{
4b7e6066 2969 struct bgp_path_info *mpinfo;
d62a17ae 2970
2bb9eff4
DS
2971 /* If this is multipath, check all selected paths for any nexthop
2972 * change or attribute change. Some attribute changes (e.g., community)
2973 * aren't of relevance to the RIB, but we'll update zebra to ensure
2974 * we handle the case of BGP nexthop change. This is the behavior
2975 * when the best path has an attribute change anyway.
d62a17ae 2976 */
1defdda8 2977 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2978 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2979 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2980 return true;
d62a17ae 2981
2bb9eff4
DS
2982 /*
2983 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2984 */
18ee8310
DS
2985 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2986 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2987 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2988 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2989 return true;
d62a17ae 2990 }
3064bf43 2991
d62a17ae 2992 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2993 return false;
3064bf43 2994}
2995
d62a17ae 2996struct bgp_process_queue {
2997 struct bgp *bgp;
9bcb3eef 2998 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2999#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3000 unsigned int flags;
3001 unsigned int queued;
200df115 3002};
3003
3b0c17e1 3004static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3005 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3006 struct bgp_path_info *new_select,
3007 struct bgp_path_info *old_select)
3008{
9bcb3eef 3009 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3010
3011 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3012 return;
3013
3014 if (advertise_type5_routes(bgp, afi) && new_select
3015 && is_route_injectable_into_evpn(new_select)) {
3016
3017 /* apply the route-map */
3018 if (bgp->adv_cmd_rmap[afi][safi].map) {
3019 route_map_result_t ret;
3020 struct bgp_path_info rmap_path;
3021 struct bgp_path_info_extra rmap_path_extra;
3022 struct attr dummy_attr;
3023
3024 dummy_attr = *new_select->attr;
3025
3026 /* Fill temp path_info */
9bcb3eef 3027 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3028 new_select, new_select->peer,
3029 &dummy_attr);
3030
3031 RESET_FLAG(dummy_attr.rmap_change_flags);
3032
3033 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3034 p, &rmap_path);
3b0c17e1 3035
3036 if (ret == RMAP_DENYMATCH) {
3037 bgp_attr_flush(&dummy_attr);
3038 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3039 safi);
3040 } else
3041 bgp_evpn_advertise_type5_route(
3042 bgp, p, &dummy_attr, afi, safi);
3043 } else {
3044 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3045 afi, safi);
3046 }
3047 } else if (advertise_type5_routes(bgp, afi) && old_select
3048 && is_route_injectable_into_evpn(old_select))
3049 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3050}
3051
bb2ca692
MS
3052/*
3053 * Utility to determine whether a particular path_info should use
3054 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3055 * in a path where we basically _know_ this is a BGP-LU route.
3056 */
3057static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3058{
3059 /* Certain types get imp null; so do paths where the nexthop is
3060 * not labeled.
3061 */
3062 if (new_select->sub_type == BGP_ROUTE_STATIC
3063 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3064 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3065 return true;
3066 else if (new_select->extra == NULL ||
3067 !bgp_is_valid_label(&new_select->extra->label[0]))
3068 /* TODO -- should be configurable? */
3069 return true;
3070 else
3071 return false;
3072}
3073
3103e8d2
DS
3074/*
3075 * old_select = The old best path
3076 * new_select = the new best path
3077 *
3078 * if (!old_select && new_select)
3079 * We are sending new information on.
3080 *
3081 * if (old_select && new_select) {
3082 * if (new_select != old_select)
3083 * We have a new best path send a change
3084 * else
3085 * We've received a update with new attributes that needs
3086 * to be passed on.
3087 * }
3088 *
3089 * if (old_select && !new_select)
3090 * We have no eligible route that we can announce or the rn
3091 * is being removed.
3092 */
9bcb3eef 3093static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3094 afi_t afi, safi_t safi)
d62a17ae 3095{
4b7e6066
DS
3096 struct bgp_path_info *new_select;
3097 struct bgp_path_info *old_select;
3098 struct bgp_path_info_pair old_and_new;
ddb5b488 3099 int debug = 0;
d62a17ae 3100
892fedb6 3101 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3102 if (dest)
3103 debug = bgp_debug_bestpath(dest);
b54892e0 3104 if (debug)
f4c713ae 3105 zlog_debug(
56ca3b5b 3106 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3107 __func__, dest);
f4c713ae
LB
3108 return;
3109 }
d62a17ae 3110 /* Is it end of initial update? (after startup) */
9bcb3eef 3111 if (!dest) {
e36f61b5
DS
3112 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3113 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3114
3115 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3116 FOREACH_AFI_SAFI (afi, safi) {
3117 if (bgp_fibupd_safi(safi))
3118 bgp_zebra_announce_table(bgp, afi, safi);
3119 }
d62a17ae 3120 bgp->main_peers_update_hold = 0;
3121
3122 bgp_start_routeadv(bgp);
aac24838 3123 return;
d62a17ae 3124 }
cb1faec9 3125
9bcb3eef 3126 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3127
9bcb3eef 3128 debug = bgp_debug_bestpath(dest);
b54892e0 3129 if (debug)
4378495a
DS
3130 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3131 dest, bgp->name_pretty, afi2str(afi),
3132 safi2str(safi));
ddb5b488 3133
f009ff26 3134 /* The best path calculation for the route is deferred if
3135 * BGP_NODE_SELECT_DEFER is set
3136 */
9bcb3eef 3137 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3138 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3139 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3140 return;
3141 }
3142
d62a17ae 3143 /* Best path selection. */
9bcb3eef 3144 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3145 afi, safi);
3146 old_select = old_and_new.old;
3147 new_select = old_and_new.new;
3148
3149 /* Do we need to allocate or free labels?
3150 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3151 * necessary to do this upon changes to best path. Exceptions:
3152 * - label index has changed -> recalculate resulting label
3153 * - path_info sub_type changed -> switch to/from implicit-null
3154 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3155 */
318cac96 3156 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3157 if (new_select) {
3158 if (!old_select
3159 || bgp_label_index_differs(new_select, old_select)
57592a53 3160 || new_select->sub_type != old_select->sub_type
9bcb3eef 3161 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3162 /* Enforced penultimate hop popping:
3163 * implicit-null for local routes, aggregate
3164 * and redistributed routes
3165 */
bb2ca692 3166 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3167 if (CHECK_FLAG(
9bcb3eef 3168 dest->flags,
992dd67e
PR
3169 BGP_NODE_REGISTERED_FOR_LABEL)
3170 || CHECK_FLAG(
3171 dest->flags,
3172 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3173 bgp_unregister_for_label(dest);
67f67ba4
DA
3174 dest->local_label = mpls_lse_encode(
3175 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3176 1);
9bcb3eef 3177 bgp_set_valid_label(&dest->local_label);
d62a17ae 3178 } else
9bcb3eef
DS
3179 bgp_register_for_label(dest,
3180 new_select);
d62a17ae 3181 }
9bcb3eef 3182 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3183 BGP_NODE_REGISTERED_FOR_LABEL)
3184 || CHECK_FLAG(dest->flags,
3185 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3186 bgp_unregister_for_label(dest);
318cac96 3187 }
992dd67e
PR
3188 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3189 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3190 bgp_unregister_for_label(dest);
d62a17ae 3191 }
cd1964ff 3192
b54892e0 3193 if (debug)
ddb5b488 3194 zlog_debug(
4378495a
DS
3195 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3196 __func__, dest, bgp->name_pretty, afi2str(afi),
3197 safi2str(safi), old_select, new_select);
ddb5b488 3198
d62a17ae 3199 /* If best route remains the same and this is not due to user-initiated
3200 * clear, see exactly what needs to be done.
3201 */
d62a17ae 3202 if (old_select && old_select == new_select
9bcb3eef 3203 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3204 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3205 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3206 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3207#ifdef ENABLE_BGP_VNC
d62a17ae 3208 vnc_import_bgp_add_route(bgp, p, old_select);
3209 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3210#endif
bb744275 3211 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3212 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3213
be785e35
DS
3214 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3215 && new_select->sub_type == BGP_ROUTE_NORMAL)
3216 SET_FLAG(dest->flags,
3217 BGP_NODE_FIB_INSTALL_PENDING);
3218
ddb5b488
PZ
3219 if (new_select->type == ZEBRA_ROUTE_BGP
3220 && (new_select->sub_type == BGP_ROUTE_NORMAL
3221 || new_select->sub_type
3222 == BGP_ROUTE_IMPORTED))
3223
9bcb3eef 3224 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3225 bgp, afi, safi);
3226 }
d62a17ae 3227 }
d62a17ae 3228
3229 /* If there is a change of interest to peers, reannounce the
3230 * route. */
1defdda8 3231 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3232 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3233 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3234 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3235
3236 /* unicast routes must also be annouced to
3237 * labeled-unicast update-groups */
3238 if (safi == SAFI_UNICAST)
3239 group_announce_route(bgp, afi,
9bcb3eef 3240 SAFI_LABELED_UNICAST, dest,
d62a17ae 3241 new_select);
3242
1defdda8 3243 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3244 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3245 }
fee0f4c6 3246
3b0c17e1 3247 /* advertise/withdraw type-5 routes */
3248 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3249 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3250 bgp_process_evpn_route_injection(
9bcb3eef 3251 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3252
b1875e65 3253 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3254 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3255 bgp_zebra_clear_route_change_flags(dest);
3256 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3257 return;
d62a17ae 3258 }
8ad7271d 3259
d62a17ae 3260 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3261 */
9bcb3eef 3262 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3263
3264 /* bestpath has changed; bump version */
3265 if (old_select || new_select) {
9bcb3eef 3266 bgp_bump_version(dest);
d62a17ae 3267
3268 if (!bgp->t_rmap_def_originate_eval) {
3269 bgp_lock(bgp);
3270 thread_add_timer(
3271 bm->master,
3272 update_group_refresh_default_originate_route_map,
3273 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3274 &bgp->t_rmap_def_originate_eval);
3275 }
3276 }
3f9c7369 3277
d62a17ae 3278 if (old_select)
9bcb3eef 3279 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3280 if (new_select) {
ddb5b488
PZ
3281 if (debug)
3282 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3283 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3284 bgp_path_info_unset_flag(dest, new_select,
3285 BGP_PATH_ATTR_CHANGED);
1defdda8 3286 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3287 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3288 }
338b3424 3289
49e5a4a0 3290#ifdef ENABLE_BGP_VNC
d62a17ae 3291 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3292 if (old_select != new_select) {
3293 if (old_select) {
3294 vnc_import_bgp_exterior_del_route(bgp, p,
3295 old_select);
3296 vnc_import_bgp_del_route(bgp, p, old_select);
3297 }
3298 if (new_select) {
3299 vnc_import_bgp_exterior_add_route(bgp, p,
3300 new_select);
3301 vnc_import_bgp_add_route(bgp, p, new_select);
3302 }
3303 }
3304 }
65efcfce
LB
3305#endif
3306
9bcb3eef 3307 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3308
3309 /* unicast routes must also be annouced to labeled-unicast update-groups
3310 */
3311 if (safi == SAFI_UNICAST)
9bcb3eef 3312 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3313 new_select);
3314
3315 /* FIB update. */
3316 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3317 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3318
d62a17ae 3319 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3320 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3321 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3322 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3323
be785e35
DS
3324 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3325 SET_FLAG(dest->flags,
3326 BGP_NODE_FIB_INSTALL_PENDING);
3327
2b659f33
MK
3328 /* if this is an evpn imported type-5 prefix,
3329 * we need to withdraw the route first to clear
3330 * the nh neigh and the RMAC entry.
3331 */
3332 if (old_select &&
3333 is_route_parent_evpn(old_select))
3334 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3335
9bcb3eef 3336 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3337 } else {
d62a17ae 3338 /* Withdraw the route from the kernel. */
3339 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3340 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3341 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3342 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3343
568e10ca 3344 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3345 }
718e3744 3346 }
3064bf43 3347
9bcb3eef 3348 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3349 old_select);
5424b7ba 3350
d62a17ae 3351 /* Clear any route change flags. */
9bcb3eef 3352 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3353
18ee8310 3354 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3355 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3356 bgp_path_info_reap(dest, old_select);
d62a17ae 3357
9bcb3eef 3358 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3359 return;
718e3744 3360}
3361
f009ff26 3362/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3363void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3364{
9bcb3eef 3365 struct bgp_dest *dest;
f009ff26 3366 int cnt = 0;
3367 struct afi_safi_info *thread_info;
f009ff26 3368
56c226e7
DS
3369 if (bgp->gr_info[afi][safi].t_route_select) {
3370 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3371
3372 thread_info = THREAD_ARG(t);
3373 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3374 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3375 }
f009ff26 3376
3377 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3378 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3379 get_afi_safi_str(afi, safi, false),
26742171 3380 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3381 }
3382
3383 /* Process the route list */
6338d242 3384 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3385 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3386 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3387 dest = bgp_route_next(dest)) {
3388 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3389 continue;
3390
3391 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3392 bgp->gr_info[afi][safi].gr_deferred--;
3393 bgp_process_main_one(bgp, dest, afi, safi);
3394 cnt++;
067ea165
CB
3395 }
3396 /* If iteration stopped before the entire table was traversed then the
3397 * node needs to be unlocked.
3398 */
3399 if (dest) {
3400 bgp_dest_unlock_node(dest);
3401 dest = NULL;
f009ff26 3402 }
3403
9e3b51a7 3404 /* Send EOR message when all routes are processed */
6338d242 3405 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3406 bgp_send_delayed_eor(bgp);
8c48b3b6 3407 /* Send route processing complete message to RIB */
3408 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3409 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3410 return;
9e3b51a7 3411 }
f009ff26 3412
3413 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3414
3415 thread_info->afi = afi;
3416 thread_info->safi = safi;
3417 thread_info->bgp = bgp;
3418
3419 /* If there are more routes to be processed, start the
3420 * selection timer
3421 */
3422 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3423 BGP_ROUTE_SELECT_DELAY,
3424 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3425}
3426
aac24838 3427static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3428{
aac24838
JB
3429 struct bgp_process_queue *pqnode = data;
3430 struct bgp *bgp = pqnode->bgp;
d62a17ae 3431 struct bgp_table *table;
9bcb3eef 3432 struct bgp_dest *dest;
aac24838
JB
3433
3434 /* eoiu marker */
3435 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3436 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3437 /* should always have dedicated wq call */
3438 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3439 return WQ_SUCCESS;
3440 }
3441
ac021f40 3442 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3443 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3444 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3445 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3446 table = bgp_dest_table(dest);
3447 /* note, new DESTs may be added as part of processing */
3448 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3449
9bcb3eef 3450 bgp_dest_unlock_node(dest);
d62a17ae 3451 bgp_table_unlock(table);
3452 }
aac24838
JB
3453
3454 return WQ_SUCCESS;
3455}
3456
3457static void bgp_processq_del(struct work_queue *wq, void *data)
3458{
3459 struct bgp_process_queue *pqnode = data;
3460
3461 bgp_unlock(pqnode->bgp);
3462
3463 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3464}
3465
b6c386bb 3466void bgp_process_queue_init(struct bgp *bgp)
200df115 3467{
b6c386bb
DS
3468 if (!bgp->process_queue) {
3469 char name[BUFSIZ];
3470
3471 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3472 bgp->process_queue = work_queue_new(bm->master, name);
3473 }
3474
3475 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3476 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3477 bgp->process_queue->spec.max_retries = 0;
3478 bgp->process_queue->spec.hold = 50;
d62a17ae 3479 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3480 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3481}
3482
cfe8d15a 3483static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3484{
3485 struct bgp_process_queue *pqnode;
3486
a4d82a8a
PZ
3487 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3488 sizeof(struct bgp_process_queue));
aac24838
JB
3489
3490 /* unlocked in bgp_processq_del */
3491 pqnode->bgp = bgp_lock(bgp);
3492 STAILQ_INIT(&pqnode->pqueue);
3493
aac24838
JB
3494 return pqnode;
3495}
3496
9bcb3eef 3497void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3498{
aac24838 3499#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3500 struct work_queue *wq = bgp->process_queue;
d62a17ae 3501 struct bgp_process_queue *pqnode;
cfe8d15a 3502 int pqnode_reuse = 0;
495f0b13 3503
d62a17ae 3504 /* already scheduled for processing? */
9bcb3eef 3505 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3506 return;
2e02b9b2 3507
f009ff26 3508 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3509 * the workqueue
3510 */
9bcb3eef 3511 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3512 if (BGP_DEBUG(update, UPDATE_OUT))
3513 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3514 dest);
f009ff26 3515 return;
3516 }
3517
46aeabed
LS
3518 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3519 if (BGP_DEBUG(update, UPDATE_OUT))
3520 zlog_debug(
3521 "Soft reconfigure table in progress for route %p",
3522 dest);
3523 return;
3524 }
3525
aac24838 3526 if (wq == NULL)
d62a17ae 3527 return;
3528
aac24838 3529 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3530 limit only if is from the same BGP view and it's not an EOIU marker
3531 */
aac24838
JB
3532 if (work_queue_item_count(wq)) {
3533 struct work_queue_item *item = work_queue_last_item(wq);
3534 pqnode = item->data;
228da428 3535
a4d82a8a
PZ
3536 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3537 || pqnode->bgp != bgp
3538 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3539 pqnode = bgp_processq_alloc(bgp);
3540 else
3541 pqnode_reuse = 1;
aac24838 3542 } else
cfe8d15a 3543 pqnode = bgp_processq_alloc(bgp);
aac24838 3544 /* all unlocked in bgp_process_wq */
9bcb3eef 3545 bgp_table_lock(bgp_dest_table(dest));
aac24838 3546
9bcb3eef
DS
3547 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3548 bgp_dest_lock_node(dest);
aac24838 3549
60466a63 3550 /* can't be enqueued twice */
9bcb3eef
DS
3551 assert(STAILQ_NEXT(dest, pq) == NULL);
3552 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3553 pqnode->queued++;
3554
cfe8d15a
LB
3555 if (!pqnode_reuse)
3556 work_queue_add(wq, pqnode);
3557
d62a17ae 3558 return;
fee0f4c6 3559}
0a486e5f 3560
d62a17ae 3561void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3562{
d62a17ae 3563 struct bgp_process_queue *pqnode;
cb1faec9 3564
b6c386bb 3565 if (bgp->process_queue == NULL)
d62a17ae 3566 return;
2e02b9b2 3567
cfe8d15a 3568 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3569
aac24838 3570 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3571 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3572}
3573
cc9f21da 3574static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3575{
d62a17ae 3576 struct peer *peer;
0a486e5f 3577
d62a17ae 3578 peer = THREAD_ARG(thread);
3579 peer->t_pmax_restart = NULL;
0a486e5f 3580
d62a17ae 3581 if (bgp_debug_neighbor_events(peer))
3582 zlog_debug(
3583 "%s Maximum-prefix restart timer expired, restore peering",
3584 peer->host);
0a486e5f 3585
a9bafa95 3586 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3587 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3588}
3589
9cbd06e0
DA
3590static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3591 safi_t safi)
3592{
3593 uint32_t count = 0;
f41b0459 3594 bool filtered = false;
9cbd06e0
DA
3595 struct bgp_dest *dest;
3596 struct bgp_adj_in *ain;
40bb2ccf 3597 struct attr attr = {};
9cbd06e0
DA
3598 struct bgp_table *table = peer->bgp->rib[afi][safi];
3599
3600 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3601 for (ain = dest->adj_in; ain; ain = ain->next) {
3602 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3603
3604 attr = *ain->attr;
9cbd06e0
DA
3605
3606 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3607 == FILTER_DENY)
f41b0459
DA
3608 filtered = true;
3609
3610 if (bgp_input_modifier(
3611 peer, rn_p, &attr, afi, safi,
3612 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3613 NULL, 0, NULL)
3614 == RMAP_DENY)
3615 filtered = true;
3616
3617 if (filtered)
9cbd06e0 3618 count++;
f41b0459 3619
d498917e 3620 bgp_attr_flush(&attr);
9cbd06e0
DA
3621 }
3622 }
3623
3624 return count;
3625}
3626
3dc339cd
DA
3627bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3628 int always)
718e3744 3629{
d62a17ae 3630 iana_afi_t pkt_afi;
5c525538 3631 iana_safi_t pkt_safi;
9cbd06e0
DA
3632 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3633 PEER_FLAG_MAX_PREFIX_FORCE))
3634 ? bgp_filtered_routes_count(peer, afi, safi)
3635 + peer->pcount[afi][safi]
3636 : peer->pcount[afi][safi];
9cabb64b 3637
d62a17ae 3638 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3639 return false;
e0701b79 3640
9cbd06e0 3641 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3642 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3643 PEER_STATUS_PREFIX_LIMIT)
3644 && !always)
3dc339cd 3645 return false;
e0701b79 3646
d62a17ae 3647 zlog_info(
f70c91dc
DA
3648 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3649 get_afi_safi_str(afi, safi, false), peer, pcount,
3650 peer->pmax[afi][safi]);
d62a17ae 3651 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3652
3653 if (CHECK_FLAG(peer->af_flags[afi][safi],
3654 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3655 return false;
d62a17ae 3656
3657 /* Convert AFI, SAFI to values for packet. */
3658 pkt_afi = afi_int2iana(afi);
3659 pkt_safi = safi_int2iana(safi);
3660 {
d7c0a89a 3661 uint8_t ndata[7];
d62a17ae 3662
3663 ndata[0] = (pkt_afi >> 8);
3664 ndata[1] = pkt_afi;
3665 ndata[2] = pkt_safi;
3666 ndata[3] = (peer->pmax[afi][safi] >> 24);
3667 ndata[4] = (peer->pmax[afi][safi] >> 16);
3668 ndata[5] = (peer->pmax[afi][safi] >> 8);
3669 ndata[6] = (peer->pmax[afi][safi]);
3670
3671 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3672 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3673 BGP_NOTIFY_CEASE_MAX_PREFIX,
3674 ndata, 7);
3675 }
3676
3677 /* Dynamic peers will just close their connection. */
3678 if (peer_dynamic_neighbor(peer))
3dc339cd 3679 return true;
d62a17ae 3680
3681 /* restart timer start */
3682 if (peer->pmax_restart[afi][safi]) {
3683 peer->v_pmax_restart =
3684 peer->pmax_restart[afi][safi] * 60;
3685
3686 if (bgp_debug_neighbor_events(peer))
3687 zlog_debug(
f70c91dc
DA
3688 "%pBP Maximum-prefix restart timer started for %d secs",
3689 peer, peer->v_pmax_restart);
d62a17ae 3690
3691 BGP_TIMER_ON(peer->t_pmax_restart,
3692 bgp_maximum_prefix_restart_timer,
3693 peer->v_pmax_restart);
3694 }
3695
3dc339cd 3696 return true;
d62a17ae 3697 } else
3698 UNSET_FLAG(peer->af_sflags[afi][safi],
3699 PEER_STATUS_PREFIX_LIMIT);
3700
b1823b69
DS
3701 if (pcount
3702 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3703 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3704 PEER_STATUS_PREFIX_THRESHOLD)
3705 && !always)
3dc339cd 3706 return false;
d62a17ae 3707
3708 zlog_info(
f70c91dc
DA
3709 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3710 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3711 peer->pmax[afi][safi]);
d62a17ae 3712 SET_FLAG(peer->af_sflags[afi][safi],
3713 PEER_STATUS_PREFIX_THRESHOLD);
3714 } else
3715 UNSET_FLAG(peer->af_sflags[afi][safi],
3716 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3717 return false;
718e3744 3718}
3719
b40d939b 3720/* Unconditionally remove the route from the RIB, without taking
3721 * damping into consideration (eg, because the session went down)
3722 */
9bcb3eef 3723void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3724 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3725{
f009ff26 3726
3727 struct bgp *bgp = NULL;
3728 bool delete_route = false;
3729
9bcb3eef
DS
3730 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3731 safi);
d62a17ae 3732
f009ff26 3733 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3734 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3735
f009ff26 3736 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3737 * flag
3738 */
3739 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3740 delete_route = true;
9bcb3eef 3741 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3742 delete_route = true;
f009ff26 3743 if (delete_route) {
9bcb3eef
DS
3744 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3745 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3746 bgp = pi->peer->bgp;
26742171 3747 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3748 }
3749 }
3750 }
4a11bf2c 3751
9bcb3eef
DS
3752 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3753 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3754}
3755
9bcb3eef 3756static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3757 struct peer *peer, afi_t afi, safi_t safi,
3758 struct prefix_rd *prd)
3759{
9bcb3eef 3760 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3761
d62a17ae 3762 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3763 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3764 */
b4f7f45b
IR
3765 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3766 && peer->sort == BGP_PEER_EBGP)
3767 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3768 == BGP_DAMP_SUPPRESSED) {
3769 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3770 safi);
3771 return;
d62a17ae 3772 }
3773
49e5a4a0 3774#ifdef ENABLE_BGP_VNC
d62a17ae 3775 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3776 struct bgp_dest *pdest = NULL;
d62a17ae 3777 struct bgp_table *table = NULL;
3778
9bcb3eef
DS
3779 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3780 (struct prefix *)prd);
3781 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3782 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3783
3784 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3785 peer->bgp, prd, table, p, pi);
d62a17ae 3786 }
9bcb3eef 3787 bgp_dest_unlock_node(pdest);
d62a17ae 3788 }
3789 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3790 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3791
b54892e0
DS
3792 vnc_import_bgp_del_route(peer->bgp, p, pi);
3793 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3794 }
65efcfce 3795 }
d62a17ae 3796#endif
128ea8ab 3797
d62a17ae 3798 /* If this is an EVPN route, process for un-import. */
3799 if (safi == SAFI_EVPN)
b54892e0 3800 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3801
9bcb3eef 3802 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3803}
3804
4b7e6066
DS
3805struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3806 struct peer *peer, struct attr *attr,
9bcb3eef 3807 struct bgp_dest *dest)
fb018d25 3808{
4b7e6066 3809 struct bgp_path_info *new;
fb018d25 3810
d62a17ae 3811 /* Make new BGP info. */
4b7e6066 3812 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3813 new->type = type;
3814 new->instance = instance;
3815 new->sub_type = sub_type;
3816 new->peer = peer;
3817 new->attr = attr;
083ec940 3818 new->uptime = monotime(NULL);
9bcb3eef 3819 new->net = dest;
d62a17ae 3820 return new;
fb018d25
DS
3821}
3822
c265ee22 3823/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3824bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3825 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3826 struct bgp_dest *dest)
d62a17ae 3827{
2dbe3fa9 3828 bool ret = false;
b099a5c8
DA
3829 bool is_bgp_static_route =
3830 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3831 : false;
d62a17ae 3832
e8442016
DS
3833 /*
3834 * Only validated for unicast and multicast currently.
3835 * Also valid for EVPN where the nexthop is an IP address.
3836 * If we are a bgp static route being checked then there is
3837 * no need to check to see if the nexthop is martian as
3838 * that it should be ok.
3839 */
3840 if (is_bgp_static_route ||
3841 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3842 return false;
d62a17ae 3843
3844 /* If NEXT_HOP is present, validate it. */
3845 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3846 if (attr->nexthop.s_addr == INADDR_ANY ||
3847 !ipv4_unicast_valid(&attr->nexthop) ||
3848 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3849 return true;
d62a17ae 3850 }
c265ee22 3851
d62a17ae 3852 /* If MP_NEXTHOP is present, validate it. */
3853 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3854 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3855 * it is not an IPv6 link-local address.
0355b41d
DA
3856 *
3857 * If we receive an UPDATE with nexthop length set to 32 bytes
3858 * we shouldn't discard an UPDATE if it's set to (::).
3859 * The link-local (2st) is validated along the code path later.
d62a17ae 3860 */
3861 if (attr->mp_nexthop_len) {
3862 switch (attr->mp_nexthop_len) {
3863 case BGP_ATTR_NHLEN_IPV4:
3864 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3865 ret = (attr->mp_nexthop_global_in.s_addr ==
3866 INADDR_ANY ||
3867 !ipv4_unicast_valid(
3868 &attr->mp_nexthop_global_in) ||
3869 bgp_nexthop_self(bgp, afi, type, stype, attr,
3870 dest));
d62a17ae 3871 break;
3872
3873 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3874 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3875 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3876 &attr->mp_nexthop_global)
d62a17ae 3877 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3878 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3879 &attr->mp_nexthop_global)
3880 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3881 dest));
d62a17ae 3882 break;
0355b41d
DA
3883 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3884 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3885 || IN6_IS_ADDR_MULTICAST(
3886 &attr->mp_nexthop_global)
3887 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3888 dest));
0355b41d 3889 break;
d62a17ae 3890
3891 default:
3dc339cd 3892 ret = true;
d62a17ae 3893 break;
3894 }
3895 }
c265ee22 3896
d62a17ae 3897 return ret;
3898}
3899
aade37d7 3900static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3901{
3902 struct community *old;
3903 struct community *new;
3904 struct community *merge;
aade37d7 3905 struct community *no_export;
2721dd61 3906
9a706b42 3907 old = bgp_attr_get_community(attr);
aade37d7 3908 no_export = community_str2com("no-export");
2721dd61 3909
b4efa101
DA
3910 assert(no_export);
3911
2721dd61 3912 if (old) {
aade37d7 3913 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3914
3915 if (!old->refcnt)
3916 community_free(&old);
3917
3918 new = community_uniq_sort(merge);
3919 community_free(&merge);
3920 } else {
aade37d7 3921 new = community_dup(no_export);
2721dd61
DA
3922 }
3923
aade37d7 3924 community_free(&no_export);
2721dd61 3925
9a706b42 3926 bgp_attr_set_community(attr, new);
2721dd61
DA
3927}
3928
46dbf9d0
DA
3929static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3930 struct attr *attr, const struct prefix *prefix,
3931 int *sub_type)
3932{
3933 struct listnode *node, *nnode;
3934 struct bgp *bgp;
3935 bool accept_own_found = false;
3936
3937 if (safi != SAFI_MPLS_VPN)
3938 return false;
3939
3940 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3941 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3942 return false;
3943
3944 /* The route in question carries the ACCEPT_OWN community */
3945 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3946 struct community *comm = bgp_attr_get_community(attr);
3947
3948 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3949 accept_own_found = true;
3950 }
3951
3952 /* The route in question is targeted to one or more destination VRFs
3953 * on the router (as determined by inspecting the Route Target(s)).
3954 */
3955 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3956 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3957 continue;
3958
3959 if (accept_own_found &&
3960 ecommunity_include(
3961 bgp->vpn_policy[afi]
3962 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3963 bgp_attr_get_ecommunity(attr))) {
3964 if (bgp_debug_update(peer, prefix, NULL, 1))
3965 zlog_debug(
3966 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3967 peer, prefix);
3968
3969 /* Treat this route as imported, because it's leaked
3970 * already from another VRF, and we got an updated
3971 * version from route-reflector with ACCEPT_OWN
3972 * community.
3973 */
3974 *sub_type = BGP_ROUTE_IMPORTED;
3975
3976 return true;
3977 }
3978 }
3979
3980 return false;
3981}
3982
367b458c
DS
3983void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3984 struct attr *attr, afi_t afi, safi_t safi, int type,
3985 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3986 uint32_t num_labels, int soft_reconfig,
3987 struct bgp_route_evpn *evpn)
d62a17ae 3988{
3989 int ret;
3990 int aspath_loop_count = 0;
9bcb3eef 3991 struct bgp_dest *dest;
d62a17ae 3992 struct bgp *bgp;
3993 struct attr new_attr;
3994 struct attr *attr_new;
40381db7 3995 struct bgp_path_info *pi;
819e6767 3996 struct bgp_path_info *new = NULL;
4b7e6066 3997 struct bgp_path_info_extra *extra;
d62a17ae 3998 const char *reason;
3999 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4000 int connected = 0;
4001 int do_loop_check = 1;
4002 int has_valid_label = 0;
7c312383 4003 afi_t nh_afi;
9146341f 4004 bool force_evpn_import = false;
907707db 4005 safi_t orig_safi = safi;
a486300b 4006 bool leak_success = true;
b2ac1d0d 4007 int allowas_in = 0;
949b0f24 4008
c7bb4f00 4009 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4010 char pfxprint[PREFIX2STR_BUFFER];
4011
4012 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4013 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4014 afi, safi, attr);
6401252f
QY
4015 }
4016
49e5a4a0 4017#ifdef ENABLE_BGP_VNC
d62a17ae 4018 int vnc_implicit_withdraw = 0;
65efcfce 4019#endif
d62a17ae 4020 int same_attr = 0;
f8745525 4021 const struct prefix *bgp_nht_param_prefix;
718e3744 4022
907707db
MS
4023 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4024 if (orig_safi == SAFI_LABELED_UNICAST)
4025 safi = SAFI_UNICAST;
4026
6006b807 4027 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4028 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4029 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4030
d62a17ae 4031 bgp = peer->bgp;
9bcb3eef 4032 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4033 /* TODO: Check to see if we can get rid of "is_valid_label" */
4034 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4035 has_valid_label = (num_labels > 0) ? 1 : 0;
4036 else
4037 has_valid_label = bgp_is_valid_label(label);
718e3744 4038
28f66de2
MS
4039 if (has_valid_label)
4040 assert(label != NULL);
4041
66ff6089
AD
4042 /* Update overlay index of the attribute */
4043 if (afi == AFI_L2VPN && evpn)
4044 memcpy(&attr->evpn_overlay, evpn,
4045 sizeof(struct bgp_route_evpn));
4046
d62a17ae 4047 /* When peer's soft reconfiguration enabled. Record input packet in
4048 Adj-RIBs-In. */
4049 if (!soft_reconfig
4050 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4051 && peer != bgp->peer_self)
9bcb3eef 4052 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4053
b2ac1d0d
MS
4054 /* Update permitted loop count */
4055 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4056 allowas_in = peer->allowas_in[afi][safi];
4057
d62a17ae 4058 /* Check previously received route. */
9bcb3eef 4059 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4060 if (pi->peer == peer && pi->type == type
4061 && pi->sub_type == sub_type
4062 && pi->addpath_rx_id == addpath_id)
d62a17ae 4063 break;
4064
4065 /* AS path local-as loop check. */
4066 if (peer->change_local_as) {
b2ac1d0d
MS
4067 if (allowas_in)
4068 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4069 else if (!CHECK_FLAG(peer->flags,
4070 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4071 aspath_loop_count = 1;
4072
4073 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4074 > aspath_loop_count) {
b4d46cc9 4075 peer->stat_pfx_aspath_loop++;
692174a1 4076 reason = "as-path contains our own AS;";
d62a17ae 4077 goto filtered;
4078 }
718e3744 4079 }
718e3744 4080
d62a17ae 4081 /* If the peer is configured for "allowas-in origin" and the last ASN in
4082 * the
4083 * as-path is our ASN then we do not need to call aspath_loop_check
4084 */
4085 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4086 if (aspath_get_last_as(attr->aspath) == bgp->as)
4087 do_loop_check = 0;
4088
f8745525
PG
4089 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4090 bgp_nht_param_prefix = NULL;
4091 else
4092 bgp_nht_param_prefix = p;
4093
d62a17ae 4094 /* AS path loop check. */
4095 if (do_loop_check) {
b0a8f709
FD
4096 if (aspath_loop_check(attr->aspath, bgp->as) >
4097 peer->allowas_in[afi][safi]) {
b4d46cc9 4098 peer->stat_pfx_aspath_loop++;
d62a17ae 4099 reason = "as-path contains our own AS;";
4100 goto filtered;
4101 }
4102 }
aac9ef6c 4103
b0a8f709
FD
4104 /* If we're a CONFED we need to loop check the CONFED ID too */
4105 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4106 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4107 peer->allowas_in[afi][safi]) {
4108 peer->stat_pfx_aspath_loop++;
4109 reason = "as-path contains our own confed AS;";
4110 goto filtered;
4111 }
4112
46dbf9d0
DA
4113 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4114 * enabled, then take care of that too.
4115 */
4116 bool accept_own = false;
4117
d62a17ae 4118 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4119 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4120 accept_own =
4121 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4122 if (!accept_own) {
4123 peer->stat_pfx_originator_loop++;
4124 reason = "originator is us;";
4125 goto filtered;
4126 }
d62a17ae 4127 }
718e3744 4128
d62a17ae 4129 /* Route reflector cluster ID check. */
4130 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4131 peer->stat_pfx_cluster_loop++;
d62a17ae 4132 reason = "reflected from the same cluster;";
4133 goto filtered;
4134 }
718e3744 4135
d62a17ae 4136 /* Apply incoming filter. */
907707db 4137 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4138 peer->stat_pfx_filter++;
d62a17ae 4139 reason = "filter;";
4140 goto filtered;
4141 }
718e3744 4142
a8b72dc6
DA
4143 /* RFC 8212 to prevent route leaks.
4144 * This specification intends to improve this situation by requiring the
4145 * explicit configuration of both BGP Import and Export Policies for any
4146 * External BGP (EBGP) session such as customers, peers, or
4147 * confederation boundaries for all enabled address families. Through
4148 * codification of the aforementioned requirement, operators will
4149 * benefit from consistent behavior across different BGP
4150 * implementations.
4151 */
1d3fdccf 4152 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4153 if (!bgp_inbound_policy_exists(peer,
4154 &peer->filter[afi][safi])) {
4155 reason = "inbound policy missing";
b17826b7
DS
4156 if (monotime_since(&bgp->ebgprequirespolicywarning,
4157 NULL) > FIFTEENMINUTE2USEC ||
4158 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4159 zlog_warn(
4160 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4161 monotime(&bgp->ebgprequirespolicywarning);
4162 }
a8b72dc6
DA
4163 goto filtered;
4164 }
4165
fb29348a
DA
4166 /* draft-ietf-idr-deprecate-as-set-confed-set
4167 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4168 * Eventually, This document (if approved) updates RFC 4271
4169 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4170 * and obsoletes RFC 6472.
4171 */
7f972cd8 4172 if (peer->bgp->reject_as_sets)
fb29348a
DA
4173 if (aspath_check_as_sets(attr->aspath)) {
4174 reason =
4175 "as-path contains AS_SET or AS_CONFED_SET type;";
4176 goto filtered;
4177 }
4178
6f4f49b2 4179 new_attr = *attr;
d62a17ae 4180
4181 /* Apply incoming route-map.
4182 * NB: new_attr may now contain newly allocated values from route-map
4183 * "set"
4184 * commands, so we need bgp_attr_flush in the error paths, until we
4185 * intern
4186 * the attr (which takes over the memory references) */
907707db 4187 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4188 num_labels, dest)
4189 == RMAP_DENY) {
b4d46cc9 4190 peer->stat_pfx_filter++;
d62a17ae 4191 reason = "route-map;";
4192 bgp_attr_flush(&new_attr);
4193 goto filtered;
4194 }
718e3744 4195
05864da7 4196 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4197 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4198 /* remove from RIB previous entry */
4199 bgp_zebra_withdraw(p, pi, bgp, safi);
4200 }
4201
7f323236
DW
4202 if (peer->sort == BGP_PEER_EBGP) {
4203
2721dd61
DA
4204 /* rfc7999:
4205 * A BGP speaker receiving an announcement tagged with the
4206 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4207 * NO_EXPORT community as defined in RFC1997, or a
4208 * similar community, to prevent propagation of the
4209 * prefix outside the local AS. The community to prevent
4210 * propagation SHOULD be chosen according to the operator's
4211 * routing policy.
4212 */
9a706b42
DA
4213 if (bgp_attr_get_community(&new_attr) &&
4214 community_include(bgp_attr_get_community(&new_attr),
4215 COMMUNITY_BLACKHOLE))
aade37d7 4216 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4217
a4d82a8a
PZ
4218 /* If we receive the graceful-shutdown community from an eBGP
4219 * peer we must lower local-preference */
9a706b42
DA
4220 if (bgp_attr_get_community(&new_attr) &&
4221 community_include(bgp_attr_get_community(&new_attr),
4222 COMMUNITY_GSHUT)) {
7f323236
DW
4223 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4224 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4225
4f770cf1
DA
4226 /* If graceful-shutdown is configured globally or
4227 * per neighbor, then add the GSHUT community to
4228 * all paths received from eBGP peers. */
4229 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4230 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4231 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4232 }
4233
d62a17ae 4234 /* next hop check. */
860ad3f9
DS
4235 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4236 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4237 &new_attr, dest)) {
b4d46cc9 4238 peer->stat_pfx_nh_invalid++;
d62a17ae 4239 reason = "martian or self next-hop;";
4240 bgp_attr_flush(&new_attr);
4241 goto filtered;
4242 }
718e3744 4243
5c14a191 4244 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4245 peer->stat_pfx_nh_invalid++;
4e802e66 4246 reason = "self mac;";
4dbf2038 4247 bgp_attr_flush(&new_attr);
4e802e66
DS
4248 goto filtered;
4249 }
4250
5a78f2bc
EB
4251 if (bgp_check_role_applicability(afi, safi) &&
4252 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4253 reason = "failing otc validation";
4254 bgp_attr_flush(&new_attr);
4255 goto filtered;
4256 }
a1b773e2
DS
4257 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4258 * condition :
4259 * Suppress fib is enabled
4260 * BGP_OPT_NO_FIB is not enabled
4261 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4262 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4263 */
4264 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4265 && (sub_type == BGP_ROUTE_NORMAL)
4266 && (!bgp_option_check(BGP_OPT_NO_FIB))
4267 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4268 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4269
01da2d26
DA
4270 /* If neighbor soo is configured, tag all incoming routes with
4271 * this SoO tag and then filter out advertisements in
4272 * subgroup_announce_check() if it matches the configured SoO
4273 * on the other peer.
4274 */
4275 if (peer->soo[afi][safi]) {
4276 struct ecommunity *old_ecomm =
4277 bgp_attr_get_ecommunity(&new_attr);
4278 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4279 struct ecommunity *new_ecomm;
4280
4281 if (old_ecomm) {
4282 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4283 ecomm_soo);
4284
4285 if (!old_ecomm->refcnt)
4286 ecommunity_free(&old_ecomm);
4287 } else {
4288 new_ecomm = ecommunity_dup(ecomm_soo);
4289 }
4290
4291 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4292 }
4293
4dbf2038 4294 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4295
d62a17ae 4296 /* If the update is implicit withdraw. */
40381db7 4297 if (pi) {
083ec940 4298 pi->uptime = monotime(NULL);
40381db7 4299 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4300
9bcb3eef 4301 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4302
d62a17ae 4303 /* Same attribute comes in. */
40381db7 4304 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4305 && same_attr
d62a17ae 4306 && (!has_valid_label
40381db7 4307 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4308 num_labels * sizeof(mpls_label_t))
66ff6089 4309 == 0)) {
b4f7f45b
IR
4310 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4311 BGP_CONFIG_DAMPENING)
d62a17ae 4312 && peer->sort == BGP_PEER_EBGP
40381db7 4313 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4314 if (bgp_debug_update(peer, p, NULL, 1)) {
4315 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4316 afi, safi, prd, p, label,
4317 num_labels, addpath_id ? 1 : 0,
66ff6089 4318 addpath_id, evpn, pfx_buf,
a4d82a8a 4319 sizeof(pfx_buf));
f70c91dc 4320 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4321 pfx_buf);
4322 }
4323
9bcb3eef 4324 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4325 != BGP_DAMP_SUPPRESSED) {
40381db7 4326 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4327 safi);
9bcb3eef 4328 bgp_process(bgp, dest, afi, safi);
d62a17ae 4329 }
4330 } else /* Duplicate - odd */
4331 {
4332 if (bgp_debug_update(peer, p, NULL, 1)) {
4333 if (!peer->rcvd_attr_printed) {
4334 zlog_debug(
f70c91dc
DA
4335 "%pBP rcvd UPDATE w/ attr: %s",
4336 peer,
d62a17ae 4337 peer->rcvd_attr_str);
4338 peer->rcvd_attr_printed = 1;
4339 }
4340
4341 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4342 afi, safi, prd, p, label,
4343 num_labels, addpath_id ? 1 : 0,
66ff6089 4344 addpath_id, evpn, pfx_buf,
a4d82a8a 4345 sizeof(pfx_buf));
d62a17ae 4346 zlog_debug(
f70c91dc
DA
4347 "%pBP rcvd %s...duplicate ignored",
4348 peer, pfx_buf);
d62a17ae 4349 }
4350
4351 /* graceful restart STALE flag unset. */
40381db7 4352 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4353 bgp_path_info_unset_flag(
9bcb3eef
DS
4354 dest, pi, BGP_PATH_STALE);
4355 bgp_dest_set_defer_flag(dest, false);
4356 bgp_process(bgp, dest, afi, safi);
d62a17ae 4357 }
4358 }
4359
9bcb3eef 4360 bgp_dest_unlock_node(dest);
d62a17ae 4361 bgp_attr_unintern(&attr_new);
4362
367b458c 4363 return;
d62a17ae 4364 }
718e3744 4365
d62a17ae 4366 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4367 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4368 if (bgp_debug_update(peer, p, NULL, 1)) {
4369 bgp_debug_rdpfxpath2str(
a4d82a8a 4370 afi, safi, prd, p, label, num_labels,
66ff6089 4371 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4372 pfx_buf, sizeof(pfx_buf));
d62a17ae 4373 zlog_debug(
f70c91dc
DA
4374 "%pBP rcvd %s, flapped quicker than processing",
4375 peer, pfx_buf);
d62a17ae 4376 }
4377
9bcb3eef 4378 bgp_path_info_restore(dest, pi);
9146341f 4379
4380 /*
4381 * If the BGP_PATH_REMOVED flag is set, then EVPN
4382 * routes would have been unimported already when a
4383 * prior BGP withdraw processing happened. Such routes
4384 * need to be imported again, so flag accordingly.
4385 */
4386 force_evpn_import = true;
704e189e 4387 } else {
4388 /* implicit withdraw, decrement aggregate and pcount
4389 * here. only if update is accepted, they'll increment
4390 * below.
4391 */
4392 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4393 }
718e3744 4394
d62a17ae 4395 /* Received Logging. */
4396 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4397 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4398 num_labels, addpath_id ? 1 : 0,
66ff6089 4399 addpath_id, evpn, pfx_buf,
a4d82a8a 4400 sizeof(pfx_buf));
f70c91dc 4401 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4402 }
718e3744 4403
d62a17ae 4404 /* graceful restart STALE flag unset. */
f009ff26 4405 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4406 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4407 bgp_dest_set_defer_flag(dest, false);
f009ff26 4408 }
d62a17ae 4409
4410 /* The attribute is changed. */
9bcb3eef 4411 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4412
d62a17ae 4413 /* Update bgp route dampening information. */
b4f7f45b 4414 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4415 && peer->sort == BGP_PEER_EBGP) {
4416 /* This is implicit withdraw so we should update
b4f7f45b
IR
4417 dampening
4418 information. */
40381db7 4419 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4420 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4421 }
49e5a4a0 4422#ifdef ENABLE_BGP_VNC
d62a17ae 4423 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4424 struct bgp_dest *pdest = NULL;
d62a17ae 4425 struct bgp_table *table = NULL;
4426
9bcb3eef
DS
4427 pdest = bgp_node_get(bgp->rib[afi][safi],
4428 (struct prefix *)prd);
4429 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4430 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4431
4432 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4433 bgp, prd, table, p, pi);
d62a17ae 4434 }
9bcb3eef 4435 bgp_dest_unlock_node(pdest);
d62a17ae 4436 }
4437 if ((afi == AFI_IP || afi == AFI_IP6)
4438 && (safi == SAFI_UNICAST)) {
40381db7 4439 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4440 /*
4441 * Implicit withdraw case.
4442 */
4443 ++vnc_implicit_withdraw;
40381db7
DS
4444 vnc_import_bgp_del_route(bgp, p, pi);
4445 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4446 }
4447 }
65efcfce 4448#endif
128ea8ab 4449
d62a17ae 4450 /* Special handling for EVPN update of an existing route. If the
4451 * extended community attribute has changed, we need to
4452 * un-import
4453 * the route using its existing extended community. It will be
4454 * subsequently processed for import with the new extended
4455 * community.
4456 */
6f8c9c11
PR
4457 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4458 && !same_attr) {
40381db7 4459 if ((pi->attr->flag
d62a17ae 4460 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4461 && (attr_new->flag
4462 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4463 int cmp;
4464
b53e67a3
DA
4465 cmp = ecommunity_cmp(
4466 bgp_attr_get_ecommunity(pi->attr),
4467 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4468 if (!cmp) {
4469 if (bgp_debug_update(peer, p, NULL, 1))
4470 zlog_debug(
4471 "Change in EXT-COMM, existing %s new %s",
4472 ecommunity_str(
b53e67a3
DA
4473 bgp_attr_get_ecommunity(
4474 pi->attr)),
d62a17ae 4475 ecommunity_str(
b53e67a3
DA
4476 bgp_attr_get_ecommunity(
4477 attr_new)));
6f8c9c11
PR
4478 if (safi == SAFI_EVPN)
4479 bgp_evpn_unimport_route(
4480 bgp, afi, safi, p, pi);
4481 else /* SAFI_MPLS_VPN */
1aa2c93e 4482 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4483 }
4484 }
4485 }
718e3744 4486
d62a17ae 4487 /* Update to new attribute. */
40381db7
DS
4488 bgp_attr_unintern(&pi->attr);
4489 pi->attr = attr_new;
d62a17ae 4490
4491 /* Update MPLS label */
4492 if (has_valid_label) {
40381db7 4493 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4494 if (extra->label != label) {
4495 memcpy(&extra->label, label,
dbd587da 4496 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4497 extra->num_labels = num_labels;
4498 }
b57ba6d2
MK
4499 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4500 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4501 }
718e3744 4502
e496b420
HS
4503 /* Update SRv6 SID */
4504 if (attr->srv6_l3vpn) {
4505 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4506 if (sid_diff(&extra->sid[0].sid,
4507 &attr->srv6_l3vpn->sid)) {
4508 sid_copy(&extra->sid[0].sid,
e496b420
HS
4509 &attr->srv6_l3vpn->sid);
4510 extra->num_sids = 1;
cc8f05df 4511
16f3db2d
RS
4512 extra->sid[0].loc_block_len = 0;
4513 extra->sid[0].loc_node_len = 0;
4514 extra->sid[0].func_len = 0;
4515 extra->sid[0].arg_len = 0;
ea7cd161
RS
4516 extra->sid[0].transposition_len = 0;
4517 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4518
4519 if (attr->srv6_l3vpn->loc_block_len != 0) {
4520 extra->sid[0].loc_block_len =
4521 attr->srv6_l3vpn->loc_block_len;
4522 extra->sid[0].loc_node_len =
4523 attr->srv6_l3vpn->loc_node_len;
4524 extra->sid[0].func_len =
4525 attr->srv6_l3vpn->func_len;
4526 extra->sid[0].arg_len =
4527 attr->srv6_l3vpn->arg_len;
ea7cd161 4528 extra->sid[0].transposition_len =
cc8f05df 4529 attr->srv6_l3vpn
ea7cd161
RS
4530 ->transposition_len;
4531 extra->sid[0].transposition_offset =
cc8f05df 4532 attr->srv6_l3vpn
ea7cd161
RS
4533 ->transposition_offset;
4534 }
e496b420
HS
4535 }
4536 } else if (attr->srv6_vpn) {
4537 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4538 if (sid_diff(&extra->sid[0].sid,
4539 &attr->srv6_vpn->sid)) {
4540 sid_copy(&extra->sid[0].sid,
4541 &attr->srv6_vpn->sid);
e496b420
HS
4542 extra->num_sids = 1;
4543 }
4544 }
4545
49e5a4a0 4546#ifdef ENABLE_BGP_VNC
d62a17ae 4547 if ((afi == AFI_IP || afi == AFI_IP6)
4548 && (safi == SAFI_UNICAST)) {
4549 if (vnc_implicit_withdraw) {
4550 /*
4551 * Add back the route with its new attributes
4552 * (e.g., nexthop).
4553 * The route is still selected, until the route
4554 * selection
4555 * queued by bgp_process actually runs. We have
4556 * to make this
4557 * update to the VNC side immediately to avoid
4558 * racing against
4559 * configuration changes (e.g., route-map
4560 * changes) which
4561 * trigger re-importation of the entire RIB.
4562 */
40381db7
DS
4563 vnc_import_bgp_add_route(bgp, p, pi);
4564 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4565 }
4566 }
65efcfce
LB
4567#endif
4568
d62a17ae 4569 /* Update bgp route dampening information. */
b4f7f45b 4570 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4571 && peer->sort == BGP_PEER_EBGP) {
4572 /* Now we do normal update dampening. */
9bcb3eef 4573 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4574 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4575 bgp_dest_unlock_node(dest);
367b458c 4576 return;
d62a17ae 4577 }
4578 }
128ea8ab 4579
d62a17ae 4580 /* Nexthop reachability check - for unicast and
4581 * labeled-unicast.. */
7c312383
AD
4582 if (((afi == AFI_IP || afi == AFI_IP6)
4583 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4584 || (safi == SAFI_EVPN &&
4585 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4586 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4587 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4588 && !CHECK_FLAG(peer->flags,
4589 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4590 && !CHECK_FLAG(bgp->flags,
4591 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4592 connected = 1;
4593 else
4594 connected = 0;
4595
960035b2
PZ
4596 struct bgp *bgp_nexthop = bgp;
4597
40381db7
DS
4598 if (pi->extra && pi->extra->bgp_orig)
4599 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4600
7c312383
AD
4601 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4602
4603 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4604 safi, pi, NULL, connected,
f8745525
PG
4605 bgp_nht_param_prefix) ||
4606 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4607 bgp_path_info_set_flag(dest, pi,
4608 BGP_PATH_VALID);
d62a17ae 4609 else {
4610 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4611 zlog_debug("%s(%pI4): NH unresolved",
4612 __func__,
4613 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4614 }
9bcb3eef 4615 bgp_path_info_unset_flag(dest, pi,
18ee8310 4616 BGP_PATH_VALID);
d62a17ae 4617 }
46dbf9d0
DA
4618 } else {
4619 if (accept_own)
4620 bgp_path_info_set_flag(dest, pi,
4621 BGP_PATH_ACCEPT_OWN);
4622
9bcb3eef 4623 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4624 }
d62a17ae 4625
49e5a4a0 4626#ifdef ENABLE_BGP_VNC
d62a17ae 4627 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4628 struct bgp_dest *pdest = NULL;
d62a17ae 4629 struct bgp_table *table = NULL;
4630
9bcb3eef
DS
4631 pdest = bgp_node_get(bgp->rib[afi][safi],
4632 (struct prefix *)prd);
4633 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4634 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4635
4636 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4637 bgp, prd, table, p, pi);
d62a17ae 4638 }
9bcb3eef 4639 bgp_dest_unlock_node(pdest);
d62a17ae 4640 }
4641#endif
718e3744 4642
d62a17ae 4643 /* If this is an EVPN route and some attribute has changed,
9146341f 4644 * or we are explicitly told to perform a route import, process
d62a17ae 4645 * route for import. If the extended community has changed, we
4646 * would
4647 * have done the un-import earlier and the import would result
4648 * in the
4649 * route getting injected into appropriate L2 VNIs. If it is
4650 * just
4651 * some other attribute change, the import will result in
4652 * updating
4653 * the attributes for the route in the VNI(s).
4654 */
9146341f 4655 if (safi == SAFI_EVPN &&
4656 (!same_attr || force_evpn_import) &&
7c312383 4657 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4658 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4659
4660 /* Process change. */
40381db7 4661 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4662
9bcb3eef
DS
4663 bgp_process(bgp, dest, afi, safi);
4664 bgp_dest_unlock_node(dest);
558d1fec 4665
ddb5b488
PZ
4666 if (SAFI_UNICAST == safi
4667 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4668 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4669
40381db7 4670 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4671 }
4672 if ((SAFI_MPLS_VPN == safi)
4673 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4674 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4675 }
4676
49e5a4a0 4677#ifdef ENABLE_BGP_VNC
d62a17ae 4678 if (SAFI_MPLS_VPN == safi) {
4679 mpls_label_t label_decoded = decode_label(label);
28070ee3 4680
d62a17ae 4681 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4682 type, sub_type, &label_decoded);
4683 }
4684 if (SAFI_ENCAP == safi) {
4685 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4686 type, sub_type, NULL);
4687 }
28070ee3 4688#endif
a486300b
PG
4689 if ((safi == SAFI_MPLS_VPN) &&
4690 !CHECK_FLAG(bgp->af_flags[afi][safi],
4691 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4692 !leak_success) {
4693 bgp_unlink_nexthop(pi);
4694 bgp_path_info_delete(dest, pi);
4695 }
367b458c 4696 return;
d62a17ae 4697 } // End of implicit withdraw
718e3744 4698
d62a17ae 4699 /* Received Logging. */
4700 if (bgp_debug_update(peer, p, NULL, 1)) {
4701 if (!peer->rcvd_attr_printed) {
f70c91dc 4702 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4703 peer->rcvd_attr_str);
4704 peer->rcvd_attr_printed = 1;
4705 }
718e3744 4706
a4d82a8a 4707 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4708 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4709 pfx_buf, sizeof(pfx_buf));
f70c91dc 4710 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4711 }
718e3744 4712
d62a17ae 4713 /* Make new BGP info. */
9bcb3eef 4714 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4715
d62a17ae 4716 /* Update MPLS label */
4717 if (has_valid_label) {
18ee8310 4718 extra = bgp_path_info_extra_get(new);
8ba71050 4719 if (extra->label != label) {
dbd587da
QY
4720 memcpy(&extra->label, label,
4721 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4722 extra->num_labels = num_labels;
4723 }
b57ba6d2
MK
4724 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4725 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4726 }
718e3744 4727
e496b420
HS
4728 /* Update SRv6 SID */
4729 if (safi == SAFI_MPLS_VPN) {
4730 extra = bgp_path_info_extra_get(new);
4731 if (attr->srv6_l3vpn) {
16f3db2d 4732 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4733 extra->num_sids = 1;
cc8f05df 4734
16f3db2d
RS
4735 extra->sid[0].loc_block_len =
4736 attr->srv6_l3vpn->loc_block_len;
4737 extra->sid[0].loc_node_len =
4738 attr->srv6_l3vpn->loc_node_len;
4739 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4740 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4741 extra->sid[0].transposition_len =
4742 attr->srv6_l3vpn->transposition_len;
4743 extra->sid[0].transposition_offset =
4744 attr->srv6_l3vpn->transposition_offset;
e496b420 4745 } else if (attr->srv6_vpn) {
16f3db2d 4746 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4747 extra->num_sids = 1;
4748 }
4749 }
4750
d62a17ae 4751 /* Nexthop reachability check. */
7c312383
AD
4752 if (((afi == AFI_IP || afi == AFI_IP6)
4753 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4754 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4755 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4756 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4757 && !CHECK_FLAG(peer->flags,
4758 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4759 && !CHECK_FLAG(bgp->flags,
4760 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4761 connected = 1;
4762 else
4763 connected = 0;
4764
7c312383
AD
4765 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4766
4053e952 4767 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4768 connected, bgp_nht_param_prefix) ||
4769 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4770 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4771 else {
07380148
DA
4772 if (BGP_DEBUG(nht, NHT))
4773 zlog_debug("%s(%pI4): NH unresolved", __func__,
4774 &attr_new->nexthop);
9bcb3eef 4775 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4776 }
46dbf9d0
DA
4777 } else {
4778 if (accept_own)
4779 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4780
9bcb3eef 4781 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4782 }
a82478b9 4783
b381ed97
DA
4784 /* If maximum prefix count is configured and current prefix
4785 * count exeed it.
4786 */
4787 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4788 reason = "maximum-prefix overflow";
4789 bgp_attr_flush(&new_attr);
b381ed97
DA
4790 goto filtered;
4791 }
4792
d62a17ae 4793 /* Addpath ID */
4794 new->addpath_rx_id = addpath_id;
4795
4796 /* Increment prefix */
4797 bgp_aggregate_increment(bgp, p, new, afi, safi);
4798
4799 /* Register new BGP information. */
9bcb3eef 4800 bgp_path_info_add(dest, new);
d62a17ae 4801
4802 /* route_node_get lock */
9bcb3eef 4803 bgp_dest_unlock_node(dest);
558d1fec 4804
49e5a4a0 4805#ifdef ENABLE_BGP_VNC
d62a17ae 4806 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4807 struct bgp_dest *pdest = NULL;
d62a17ae 4808 struct bgp_table *table = NULL;
4809
9bcb3eef
DS
4810 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4811 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4812 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4813
4814 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4815 bgp, prd, table, p, new);
4816 }
9bcb3eef 4817 bgp_dest_unlock_node(pdest);
d62a17ae 4818 }
65efcfce
LB
4819#endif
4820
d62a17ae 4821 /* If this is an EVPN route, process for import. */
7c312383 4822 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4823 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4824
9bcb3eef 4825 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4826
d62a17ae 4827 /* Process change. */
9bcb3eef 4828 bgp_process(bgp, dest, afi, safi);
718e3744 4829
ddb5b488
PZ
4830 if (SAFI_UNICAST == safi
4831 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4832 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4833 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4834 }
4835 if ((SAFI_MPLS_VPN == safi)
4836 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4837 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4838 }
49e5a4a0 4839#ifdef ENABLE_BGP_VNC
d62a17ae 4840 if (SAFI_MPLS_VPN == safi) {
4841 mpls_label_t label_decoded = decode_label(label);
28070ee3 4842
d62a17ae 4843 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4844 sub_type, &label_decoded);
4845 }
4846 if (SAFI_ENCAP == safi) {
4847 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4848 sub_type, NULL);
4849 }
28070ee3 4850#endif
a486300b
PG
4851 if ((safi == SAFI_MPLS_VPN) &&
4852 !CHECK_FLAG(bgp->af_flags[afi][safi],
4853 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4854 !leak_success) {
4855 bgp_unlink_nexthop(new);
4856 bgp_path_info_delete(dest, new);
4857 }
28070ee3 4858
367b458c 4859 return;
718e3744 4860
d62a17ae 4861/* This BGP update is filtered. Log the reason then update BGP
4862 entry. */
4863filtered:
819e6767
DA
4864 if (new) {
4865 bgp_unlink_nexthop(new);
4866 bgp_path_info_delete(dest, new);
4867 bgp_path_info_extra_free(&new->extra);
4868 XFREE(MTYPE_BGP_ROUTE, new);
4869 }
4870
9bcb3eef 4871 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4872
d62a17ae 4873 if (bgp_debug_update(peer, p, NULL, 1)) {
4874 if (!peer->rcvd_attr_printed) {
f70c91dc 4875 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4876 peer->rcvd_attr_str);
4877 peer->rcvd_attr_printed = 1;
4878 }
718e3744 4879
a4d82a8a 4880 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4881 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4882 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4883 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4884 peer, pfx_buf, reason);
d62a17ae 4885 }
128ea8ab 4886
40381db7 4887 if (pi) {
d62a17ae 4888 /* If this is an EVPN route, un-import it as it is now filtered.
4889 */
4890 if (safi == SAFI_EVPN)
40381db7 4891 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4892
ddb5b488
PZ
4893 if (SAFI_UNICAST == safi
4894 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4895 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4896
40381db7 4897 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4898 }
4899 if ((SAFI_MPLS_VPN == safi)
4900 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4901
1aa2c93e 4902 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4903 }
4904
9bcb3eef 4905 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4906 }
4907
9bcb3eef 4908 bgp_dest_unlock_node(dest);
558d1fec 4909
49e5a4a0 4910#ifdef ENABLE_BGP_VNC
d62a17ae 4911 /*
4912 * Filtered update is treated as an implicit withdrawal (see
4913 * bgp_rib_remove()
4914 * a few lines above)
4915 */
4916 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4917 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4918 0);
4919 }
97736e32
PZ
4920#endif
4921
367b458c 4922 return;
718e3744 4923}
4924
367b458c 4925void bgp_withdraw(struct peer *peer, const struct prefix *p,
bf0c6163
DA
4926 uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4927 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4928 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4929{
d62a17ae 4930 struct bgp *bgp;
4931 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4932 struct bgp_dest *dest;
40381db7 4933 struct bgp_path_info *pi;
718e3744 4934
49e5a4a0 4935#ifdef ENABLE_BGP_VNC
d62a17ae 4936 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4937 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4938 0);
4939 }
28070ee3
PZ
4940#endif
4941
d62a17ae 4942 bgp = peer->bgp;
4943
4944 /* Lookup node. */
9bcb3eef 4945 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4946
4947 /* If peer is soft reconfiguration enabled. Record input packet for
4948 * further calculation.
4949 *
4950 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4951 * routes that are filtered. This tanks out Quagga RS pretty badly due
4952 * to
4953 * the iteration over all RS clients.
4954 * Since we need to remove the entry from adj_in anyway, do that first
4955 * and
4956 * if there was no entry, we don't need to do anything more.
4957 */
4958 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4959 && peer != bgp->peer_self)
9bcb3eef 4960 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4961 peer->stat_pfx_dup_withdraw++;
4962
d62a17ae 4963 if (bgp_debug_update(peer, p, NULL, 1)) {
4964 bgp_debug_rdpfxpath2str(
a4d82a8a 4965 afi, safi, prd, p, label, num_labels,
6c995628
AD
4966 addpath_id ? 1 : 0, addpath_id, NULL,
4967 pfx_buf, sizeof(pfx_buf));
d62a17ae 4968 zlog_debug(
4969 "%s withdrawing route %s not in adj-in",
4970 peer->host, pfx_buf);
4971 }
9bcb3eef 4972 bgp_dest_unlock_node(dest);
367b458c 4973 return;
d62a17ae 4974 }
cd808e74 4975
d62a17ae 4976 /* Lookup withdrawn route. */
9bcb3eef 4977 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4978 if (pi->peer == peer && pi->type == type
4979 && pi->sub_type == sub_type
4980 && pi->addpath_rx_id == addpath_id)
d62a17ae 4981 break;
4982
4983 /* Logging. */
4984 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4985 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4986 addpath_id ? 1 : 0, addpath_id, NULL,
4987 pfx_buf, sizeof(pfx_buf));
f70c91dc 4988 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4989 pfx_buf);
4990 }
718e3744 4991
d62a17ae 4992 /* Withdraw specified route from routing table. */
40381db7 4993 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4994 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4995 if (SAFI_UNICAST == safi
4996 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4997 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4998 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4999 }
5000 if ((SAFI_MPLS_VPN == safi)
5001 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5002
1aa2c93e 5003 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
5004 }
5005 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5006 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5007 addpath_id ? 1 : 0, addpath_id, NULL,
5008 pfx_buf, sizeof(pfx_buf));
d62a17ae 5009 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5010 }
718e3744 5011
d62a17ae 5012 /* Unlock bgp_node_get() lock. */
9bcb3eef 5013 bgp_dest_unlock_node(dest);
d62a17ae 5014
367b458c 5015 return;
718e3744 5016}
6b0655a2 5017
d62a17ae 5018void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5019 int withdraw)
718e3744 5020{
d62a17ae 5021 struct update_subgroup *subgrp;
5022 subgrp = peer_subgroup(peer, afi, safi);
5023 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5024}
6182d65b 5025
718e3744 5026
3f9c7369
DS
5027/*
5028 * bgp_stop_announce_route_timer
5029 */
d62a17ae 5030void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5031{
d62a17ae 5032 if (!paf->t_announce_route)
5033 return;
5034
c3aaa89a 5035 THREAD_OFF(paf->t_announce_route);
718e3744 5036}
6b0655a2 5037
3f9c7369
DS
5038/*
5039 * bgp_announce_route_timer_expired
5040 *
5041 * Callback that is invoked when the route announcement timer for a
5042 * peer_af expires.
5043 */
cc9f21da 5044static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5045{
d62a17ae 5046 struct peer_af *paf;
5047 struct peer *peer;
558d1fec 5048
d62a17ae 5049 paf = THREAD_ARG(t);
5050 peer = paf->peer;
718e3744 5051
feb17238 5052 if (!peer_established(peer))
cc9f21da 5053 return;
3f9c7369 5054
d62a17ae 5055 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5056 return;
3f9c7369 5057
d62a17ae 5058 peer_af_announce_route(paf, 1);
c5aec50b
MK
5059
5060 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5061 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5062}
5063
3f9c7369
DS
5064/*
5065 * bgp_announce_route
5066 *
5067 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5068 *
5069 * if force is true we will force an update even if the update
5070 * limiting code is attempted to kick in.
3f9c7369 5071 */
e1a32ec1 5072void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5073{
5074 struct peer_af *paf;
5075 struct update_subgroup *subgrp;
5076
5077 paf = peer_af_find(peer, afi, safi);
5078 if (!paf)
5079 return;
5080 subgrp = PAF_SUBGRP(paf);
5081
5082 /*
5083 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5084 * or a refresh has already been triggered.
5085 */
5086 if (!subgrp || paf->t_announce_route)
5087 return;
5088
e1a32ec1
DS
5089 if (force)
5090 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5091
d62a17ae 5092 /*
5093 * Start a timer to stagger/delay the announce. This serves
5094 * two purposes - announcement can potentially be combined for
5095 * multiple peers and the announcement doesn't happen in the
5096 * vty context.
5097 */
5098 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5099 (subgrp->peer_count == 1)
5100 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5101 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5102 &paf->t_announce_route);
3f9c7369
DS
5103}
5104
5105/*
5106 * Announce routes from all AF tables to a peer.
5107 *
5108 * This should ONLY be called when there is a need to refresh the
5109 * routes to the peer based on a policy change for this peer alone
5110 * or a route refresh request received from the peer.
5111 * The operation will result in splitting the peer from its existing
5112 * subgroups and putting it in new subgroups.
5113 */
d62a17ae 5114void bgp_announce_route_all(struct peer *peer)
718e3744 5115{
d62a17ae 5116 afi_t afi;
5117 safi_t safi;
5118
05c7a1cc 5119 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5120 bgp_announce_route(peer, afi, safi, false);
718e3744 5121}
6b0655a2 5122
46aeabed
LS
5123/* Flag or unflag bgp_dest to determine whether it should be treated by
5124 * bgp_soft_reconfig_table_task.
5125 * Flag if flag is true. Unflag if flag is false.
5126 */
5127static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5128{
5129 struct bgp_dest *dest;
5130 struct bgp_adj_in *ain;
5131
5132 if (!table)
5133 return;
5134
5135 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5136 for (ain = dest->adj_in; ain; ain = ain->next) {
5137 if (ain->peer != NULL)
5138 break;
5139 }
5140 if (flag && ain != NULL && ain->peer != NULL)
5141 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5142 else
5143 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5144 }
5145}
5146
367b458c
DS
5147static void bgp_soft_reconfig_table_update(struct peer *peer,
5148 struct bgp_dest *dest,
5149 struct bgp_adj_in *ain, afi_t afi,
5150 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5151{
5152 struct bgp_path_info *pi;
5153 uint32_t num_labels = 0;
5154 mpls_label_t *label_pnt = NULL;
5155 struct bgp_route_evpn evpn;
5156
5157 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5158 if (pi->peer == peer)
5159 break;
5160
5161 if (pi && pi->extra)
5162 num_labels = pi->extra->num_labels;
5163 if (num_labels)
5164 label_pnt = &pi->extra->label[0];
5165 if (pi)
5166 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5167 sizeof(evpn));
5168 else
5169 memset(&evpn, 0, sizeof(evpn));
5170
367b458c
DS
5171 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5172 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5173 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5174}
5175
d62a17ae 5176static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5177 struct bgp_table *table,
5178 struct prefix_rd *prd)
718e3744 5179{
9bcb3eef 5180 struct bgp_dest *dest;
d62a17ae 5181 struct bgp_adj_in *ain;
718e3744 5182
d62a17ae 5183 if (!table)
5184 table = peer->bgp->rib[afi][safi];
718e3744 5185
9bcb3eef
DS
5186 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5187 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5188 if (ain->peer != peer)
5189 continue;
8692c506 5190
367b458c
DS
5191 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5192 safi, prd);
d62a17ae 5193 }
718e3744 5194}
5195
46aeabed
LS
5196/* Do soft reconfig table per bgp table.
5197 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5198 * when BGP_NODE_SOFT_RECONFIG is set,
5199 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5200 * Schedule a new thread to continue the job.
5201 * Without splitting the full job into several part,
5202 * vtysh waits for the job to finish before responding to a BGP command
5203 */
cc9f21da 5204static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5205{
5206 uint32_t iter, max_iter;
46aeabed
LS
5207 struct bgp_dest *dest;
5208 struct bgp_adj_in *ain;
5209 struct peer *peer;
5210 struct bgp_table *table;
5211 struct prefix_rd *prd;
5212 struct listnode *node, *nnode;
5213
5214 table = THREAD_ARG(thread);
5215 prd = NULL;
5216
5217 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5218 if (table->soft_reconfig_init) {
5219 /* first call of the function with a new srta structure.
5220 * Don't do any treatment this time on nodes
5221 * in order vtysh to respond quickly
5222 */
5223 max_iter = 0;
5224 }
5225
5226 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5227 dest = bgp_route_next(dest)) {
5228 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5229 continue;
5230
5231 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5232
5233 for (ain = dest->adj_in; ain; ain = ain->next) {
5234 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5235 nnode, peer)) {
5236 if (ain->peer != peer)
5237 continue;
5238
367b458c 5239 bgp_soft_reconfig_table_update(
46aeabed
LS
5240 peer, dest, ain, table->afi,
5241 table->safi, prd);
5242 iter++;
46aeabed
LS
5243 }
5244 }
5245 }
5246
5247 /* we're either starting the initial iteration,
5248 * or we're going to continue an ongoing iteration
5249 */
5250 if (dest || table->soft_reconfig_init) {
5251 table->soft_reconfig_init = false;
5252 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5253 table, 0, &table->soft_reconfig_thread);
cc9f21da 5254 return;
46aeabed
LS
5255 }
5256 /* we're done, clean up the background iteration context info and
5257 schedule route annoucement
5258 */
5259 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5260 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5261 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5262 }
5263
5264 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5265}
5266
5267
5268/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5269 * and peer.
5270 * - bgp cannot be NULL
5271 * - if table and peer are NULL, cancel all threads within the bgp instance
5272 * - if table is NULL and peer is not,
5273 * remove peer in all threads within the bgp instance
5274 * - if peer is NULL, cancel all threads matching table within the bgp instance
5275 */
5276void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5277 const struct bgp_table *table,
5278 const struct peer *peer)
5279{
5280 struct peer *npeer;
5281 struct listnode *node, *nnode;
5282 int afi, safi;
5283 struct bgp_table *ntable;
5284
5285 if (!bgp)
5286 return;
5287
5288 FOREACH_AFI_SAFI (afi, safi) {
5289 ntable = bgp->rib[afi][safi];
5290 if (!ntable)
5291 continue;
5292 if (table && table != ntable)
5293 continue;
5294
5295 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5296 npeer)) {
5297 if (peer && peer != npeer)
5298 continue;
5299 listnode_delete(ntable->soft_reconfig_peers, npeer);
5300 }
5301
5302 if (!ntable->soft_reconfig_peers
5303 || !list_isempty(ntable->soft_reconfig_peers))
5304 continue;
5305
5306 list_delete(&ntable->soft_reconfig_peers);
5307 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5308 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5309 }
5310}
5311
89c73443
DS
5312/*
5313 * Returns false if the peer is not configured for soft reconfig in
5314 */
5315bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5316{
9bcb3eef 5317 struct bgp_dest *dest;
d62a17ae 5318 struct bgp_table *table;
46aeabed
LS
5319 struct listnode *node, *nnode;
5320 struct peer *npeer;
5321 struct peer_af *paf;
718e3744 5322
89c73443
DS
5323 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5324 return false;
718e3744 5325
d62a17ae 5326 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5327 && (safi != SAFI_EVPN)) {
5328 table = peer->bgp->rib[afi][safi];
5329 if (!table)
89c73443 5330 return true;
46aeabed
LS
5331
5332 table->soft_reconfig_init = true;
5333
5334 if (!table->soft_reconfig_peers)
5335 table->soft_reconfig_peers = list_new();
5336 npeer = NULL;
5337 /* add peer to the table soft_reconfig_peers if not already
5338 * there
5339 */
5340 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5341 npeer)) {
5342 if (peer == npeer)
5343 break;
5344 }
5345 if (peer != npeer)
5346 listnode_add(table->soft_reconfig_peers, peer);
5347
5348 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5349 * on table would start back at the beginning.
5350 */
5351 bgp_soft_reconfig_table_flag(table, true);
5352
5353 if (!table->soft_reconfig_thread)
5354 thread_add_event(bm->master,
5355 bgp_soft_reconfig_table_task, table, 0,
5356 &table->soft_reconfig_thread);
5357 /* Cancel bgp_announce_route_timer_expired threads.
5358 * bgp_announce_route_timer_expired threads have been scheduled
5359 * to announce routes as soon as the soft_reconfigure process
5360 * finishes.
5361 * In this case, soft_reconfigure is also scheduled by using
5362 * a thread but is planned after the
5363 * bgp_announce_route_timer_expired threads. It means that,
5364 * without cancelling the threads, the route announcement task
5365 * would run before the soft reconfiguration one. That would
5366 * useless and would block vtysh during several seconds. Route
5367 * announcements are rescheduled as soon as the soft_reconfigure
5368 * process finishes.
5369 */
5370 paf = peer_af_find(peer, afi, safi);
5371 if (paf)
5372 bgp_stop_announce_route_timer(paf);
5373 } else
9bcb3eef
DS
5374 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5375 dest = bgp_route_next(dest)) {
5376 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5377
b54892e0
DS
5378 if (table == NULL)
5379 continue;
8692c506 5380
9bcb3eef 5381 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5382 struct prefix_rd prd;
5383
5384 prd.family = AF_UNSPEC;
5385 prd.prefixlen = 64;
5386 memcpy(&prd.val, p->u.val, 8);
5387
5388 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5389 }
89c73443
DS
5390
5391 return true;
718e3744 5392}
6b0655a2 5393
228da428 5394
d62a17ae 5395struct bgp_clear_node_queue {
9bcb3eef 5396 struct bgp_dest *dest;
228da428
CC
5397};
5398
d62a17ae 5399static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5400{
d62a17ae 5401 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5402 struct bgp_dest *dest = cnq->dest;
d62a17ae 5403 struct peer *peer = wq->spec.data;
40381db7 5404 struct bgp_path_info *pi;
3103e8d2 5405 struct bgp *bgp;
9bcb3eef
DS
5406 afi_t afi = bgp_dest_table(dest)->afi;
5407 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5408
9bcb3eef 5409 assert(dest && peer);
3103e8d2 5410 bgp = peer->bgp;
d62a17ae 5411
5412 /* It is possible that we have multiple paths for a prefix from a peer
5413 * if that peer is using AddPath.
5414 */
9bcb3eef 5415 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5416 if (pi->peer != peer)
ea47320b
DL
5417 continue;
5418
5419 /* graceful restart STALE flag set. */
9af52ccf
DA
5420 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5421 && peer->nsf[afi][safi])
5422 || CHECK_FLAG(peer->af_sflags[afi][safi],
5423 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5424 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5425 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5426 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5427 else {
5428 /* If this is an EVPN route, process for
5429 * un-import. */
5430 if (safi == SAFI_EVPN)
9bcb3eef
DS
5431 bgp_evpn_unimport_route(
5432 bgp, afi, safi,
5433 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5434 /* Handle withdraw for VRF route-leaking and L3VPN */
5435 if (SAFI_UNICAST == safi
5436 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5437 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5438 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5439 bgp, pi);
960035b2 5440 }
3103e8d2 5441 if (SAFI_MPLS_VPN == safi &&
960035b2 5442 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5443 vpn_leak_to_vrf_withdraw(pi);
960035b2 5444 }
3103e8d2 5445
9bcb3eef 5446 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5447 }
ea47320b 5448 }
d62a17ae 5449 return WQ_SUCCESS;
200df115 5450}
5451
d62a17ae 5452static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5453{
d62a17ae 5454 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5455 struct bgp_dest *dest = cnq->dest;
5456 struct bgp_table *table = bgp_dest_table(dest);
228da428 5457
9bcb3eef 5458 bgp_dest_unlock_node(dest);
d62a17ae 5459 bgp_table_unlock(table);
5460 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5461}
5462
d62a17ae 5463static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5464{
d62a17ae 5465 struct peer *peer = wq->spec.data;
64e580a7 5466
d62a17ae 5467 /* Tickle FSM to start moving again */
5468 BGP_EVENT_ADD(peer, Clearing_Completed);
5469
5470 peer_unlock(peer); /* bgp_clear_route */
200df115 5471}
718e3744 5472
d62a17ae 5473static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5474{
d62a17ae 5475 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5476
5477 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5478#undef CLEAR_QUEUE_NAME_LEN
5479
0ce1ca80 5480 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5481 peer->clear_node_queue->spec.hold = 10;
5482 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5483 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5484 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5485 peer->clear_node_queue->spec.max_retries = 0;
5486
5487 /* we only 'lock' this peer reference when the queue is actually active
5488 */
5489 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5490}
5491
d62a17ae 5492static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5493 struct bgp_table *table)
65ca75e0 5494{
9bcb3eef 5495 struct bgp_dest *dest;
b6c386bb 5496 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5497
d62a17ae 5498 if (!table)
5499 table = peer->bgp->rib[afi][safi];
dc83d712 5500
d62a17ae 5501 /* If still no table => afi/safi isn't configured at all or smth. */
5502 if (!table)
5503 return;
dc83d712 5504
9bcb3eef 5505 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5506 struct bgp_path_info *pi, *next;
d62a17ae 5507 struct bgp_adj_in *ain;
5508 struct bgp_adj_in *ain_next;
5509
5510 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5511 * queued for every clearing peer, regardless of whether it is
5512 * relevant to the peer at hand.
5513 *
5514 * Overview: There are 3 different indices which need to be
5515 * scrubbed, potentially, when a peer is removed:
5516 *
5517 * 1 peer's routes visible via the RIB (ie accepted routes)
5518 * 2 peer's routes visible by the (optional) peer's adj-in index
5519 * 3 other routes visible by the peer's adj-out index
5520 *
5521 * 3 there is no hurry in scrubbing, once the struct peer is
5522 * removed from bgp->peer, we could just GC such deleted peer's
5523 * adj-outs at our leisure.
5524 *
5525 * 1 and 2 must be 'scrubbed' in some way, at least made
5526 * invisible via RIB index before peer session is allowed to be
5527 * brought back up. So one needs to know when such a 'search' is
5528 * complete.
5529 *
5530 * Ideally:
5531 *
5532 * - there'd be a single global queue or a single RIB walker
5533 * - rather than tracking which route_nodes still need to be
5534 * examined on a peer basis, we'd track which peers still
5535 * aren't cleared
5536 *
5537 * Given that our per-peer prefix-counts now should be reliable,
5538 * this may actually be achievable. It doesn't seem to be a huge
5539 * problem at this time,
5540 *
5541 * It is possible that we have multiple paths for a prefix from
5542 * a peer
5543 * if that peer is using AddPath.
5544 */
9bcb3eef 5545 ain = dest->adj_in;
d62a17ae 5546 while (ain) {
5547 ain_next = ain->next;
5548
6a840fd9 5549 if (ain->peer == peer)
9bcb3eef 5550 bgp_adj_in_remove(dest, ain);
d62a17ae 5551
5552 ain = ain_next;
5553 }
5554
9bcb3eef 5555 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5556 next = pi->next;
5557 if (pi->peer != peer)
d62a17ae 5558 continue;
5559
5560 if (force)
9bcb3eef 5561 bgp_path_info_reap(dest, pi);
d62a17ae 5562 else {
5563 struct bgp_clear_node_queue *cnq;
5564
5565 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5566 bgp_table_lock(bgp_dest_table(dest));
5567 bgp_dest_lock_node(dest);
d62a17ae 5568 cnq = XCALLOC(
5569 MTYPE_BGP_CLEAR_NODE_QUEUE,
5570 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5571 cnq->dest = dest;
d62a17ae 5572 work_queue_add(peer->clear_node_queue, cnq);
5573 break;
5574 }
5575 }
5576 }
5577 return;
5578}
5579
5580void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5581{
9bcb3eef 5582 struct bgp_dest *dest;
d62a17ae 5583 struct bgp_table *table;
5584
5585 if (peer->clear_node_queue == NULL)
5586 bgp_clear_node_queue_init(peer);
5587
5588 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5589 * Idle until it receives a Clearing_Completed event. This protects
5590 * against peers which flap faster than we can we clear, which could
5591 * lead to:
5592 *
5593 * a) race with routes from the new session being installed before
5594 * clear_route_node visits the node (to delete the route of that
5595 * peer)
5596 * b) resource exhaustion, clear_route_node likely leads to an entry
5597 * on the process_main queue. Fast-flapping could cause that queue
5598 * to grow and grow.
5599 */
5600
5601 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5602 * the unlock will happen upon work-queue completion; other wise, the
5603 * unlock happens at the end of this function.
5604 */
5605 if (!peer->clear_node_queue->thread)
5606 peer_lock(peer);
5607
5608 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5609 bgp_clear_route_table(peer, afi, safi, NULL);
5610 else
9bcb3eef
DS
5611 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5612 dest = bgp_route_next(dest)) {
5613 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5614 if (!table)
5615 continue;
5616
5617 bgp_clear_route_table(peer, afi, safi, table);
5618 }
d62a17ae 5619
5620 /* unlock if no nodes got added to the clear-node-queue. */
5621 if (!peer->clear_node_queue->thread)
5622 peer_unlock(peer);
718e3744 5623}
d62a17ae 5624
5625void bgp_clear_route_all(struct peer *peer)
718e3744 5626{
d62a17ae 5627 afi_t afi;
5628 safi_t safi;
718e3744 5629
05c7a1cc
QY
5630 FOREACH_AFI_SAFI (afi, safi)
5631 bgp_clear_route(peer, afi, safi);
65efcfce 5632
49e5a4a0 5633#ifdef ENABLE_BGP_VNC
d62a17ae 5634 rfapiProcessPeerDown(peer);
65efcfce 5635#endif
718e3744 5636}
5637
d62a17ae 5638void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5639{
d62a17ae 5640 struct bgp_table *table;
9bcb3eef 5641 struct bgp_dest *dest;
d62a17ae 5642 struct bgp_adj_in *ain;
5643 struct bgp_adj_in *ain_next;
718e3744 5644
d62a17ae 5645 table = peer->bgp->rib[afi][safi];
718e3744 5646
d62a17ae 5647 /* It is possible that we have multiple paths for a prefix from a peer
5648 * if that peer is using AddPath.
5649 */
9bcb3eef
DS
5650 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5651 ain = dest->adj_in;
43143c8f 5652
d62a17ae 5653 while (ain) {
5654 ain_next = ain->next;
43143c8f 5655
6a840fd9 5656 if (ain->peer == peer)
9bcb3eef 5657 bgp_adj_in_remove(dest, ain);
43143c8f 5658
d62a17ae 5659 ain = ain_next;
5660 }
5661 }
718e3744 5662}
93406d87 5663
1479ed2f
DA
5664/* If any of the routes from the peer have been marked with the NO_LLGR
5665 * community, either as sent by the peer, or as the result of a configured
5666 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5667 * operation of [RFC4271].
5668 */
d62a17ae 5669void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5670{
9bcb3eef 5671 struct bgp_dest *dest;
40381db7 5672 struct bgp_path_info *pi;
d62a17ae 5673 struct bgp_table *table;
5674
9af52ccf 5675 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5676 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5677 dest = bgp_route_next(dest)) {
5678 struct bgp_dest *rm;
d62a17ae 5679
5680 /* look for neighbor in tables */
9bcb3eef 5681 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5682 if (!table)
ea47320b
DL
5683 continue;
5684
5685 for (rm = bgp_table_top(table); rm;
5686 rm = bgp_route_next(rm))
9bcb3eef 5687 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5688 pi = pi->next) {
40381db7 5689 if (pi->peer != peer)
ea47320b 5690 continue;
1479ed2f
DA
5691 if (CHECK_FLAG(
5692 peer->af_sflags[afi][safi],
5693 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5694 bgp_attr_get_community(pi->attr) &&
1479ed2f 5695 !community_include(
9a706b42
DA
5696 bgp_attr_get_community(
5697 pi->attr),
1479ed2f 5698 COMMUNITY_NO_LLGR))
e3015d91 5699 continue;
40381db7 5700 if (!CHECK_FLAG(pi->flags,
1defdda8 5701 BGP_PATH_STALE))
e3015d91 5702 continue;
ea47320b 5703
641065d4
KM
5704 /*
5705 * If this is VRF leaked route
5706 * process for withdraw.
5707 */
5708 if (pi->sub_type ==
5709 BGP_ROUTE_IMPORTED &&
5710 peer->bgp->inst_type ==
5711 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5712 vpn_leak_to_vrf_withdraw(pi);
641065d4 5713
40381db7 5714 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5715 break;
5716 }
d62a17ae 5717 }
5718 } else {
9bcb3eef
DS
5719 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5720 dest = bgp_route_next(dest))
5721 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5722 pi = pi->next) {
40381db7 5723 if (pi->peer != peer)
ea47320b 5724 continue;
1479ed2f
DA
5725 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5726 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5727 bgp_attr_get_community(pi->attr) &&
5728 !community_include(
5729 bgp_attr_get_community(pi->attr),
5730 COMMUNITY_NO_LLGR))
e3015d91 5731 continue;
40381db7 5732 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5733 continue;
641065d4
KM
5734 if (safi == SAFI_UNICAST &&
5735 (peer->bgp->inst_type ==
5736 BGP_INSTANCE_TYPE_VRF ||
5737 peer->bgp->inst_type ==
5738 BGP_INSTANCE_TYPE_DEFAULT))
5739 vpn_leak_from_vrf_withdraw(
5740 bgp_get_default(), peer->bgp,
5741 pi);
5742
9bcb3eef 5743 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5744 break;
5745 }
d62a17ae 5746 }
93406d87 5747}
6b0655a2 5748
9af52ccf
DA
5749void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5750{
5751 struct bgp_dest *dest, *ndest;
5752 struct bgp_path_info *pi;
5753 struct bgp_table *table;
5754
5755 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5756 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5757 dest = bgp_route_next(dest)) {
5758 table = bgp_dest_get_bgp_table_info(dest);
5759 if (!table)
5760 continue;
5761
5762 for (ndest = bgp_table_top(table); ndest;
5763 ndest = bgp_route_next(ndest)) {
5764 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5765 pi = pi->next) {
5766 if (pi->peer != peer)
5767 continue;
5768
5769 if ((CHECK_FLAG(
5770 peer->af_sflags[afi][safi],
5771 PEER_STATUS_ENHANCED_REFRESH))
5772 && !CHECK_FLAG(pi->flags,
5773 BGP_PATH_STALE)
5774 && !CHECK_FLAG(
5775 pi->flags,
5776 BGP_PATH_UNUSEABLE)) {
5777 if (bgp_debug_neighbor_events(
5778 peer))
5779 zlog_debug(
58e111f6
DA
5780 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5781 peer,
9af52ccf
DA
5782 afi2str(afi),
5783 safi2str(safi),
5784 bgp_dest_get_prefix(
5785 ndest));
5786
5787 bgp_path_info_set_flag(
5788 ndest, pi,
5789 BGP_PATH_STALE);
5790 }
5791 }
5792 }
5793 }
5794 } else {
5795 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5796 dest = bgp_route_next(dest)) {
5797 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5798 pi = pi->next) {
5799 if (pi->peer != peer)
5800 continue;
5801
5802 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5803 PEER_STATUS_ENHANCED_REFRESH))
5804 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5805 && !CHECK_FLAG(pi->flags,
5806 BGP_PATH_UNUSEABLE)) {
5807 if (bgp_debug_neighbor_events(peer))
5808 zlog_debug(
58e111f6
DA
5809 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5810 peer, afi2str(afi),
9af52ccf
DA
5811 safi2str(safi),
5812 bgp_dest_get_prefix(
5813 dest));
5814
5815 bgp_path_info_set_flag(dest, pi,
5816 BGP_PATH_STALE);
5817 }
5818 }
5819 }
5820 }
5821}
5822
3dc339cd 5823bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5824{
e0df4c04 5825 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5826 return true;
e0df4c04 5827
9dac9fc8
DA
5828 if (peer->sort == BGP_PEER_EBGP
5829 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5830 || FILTER_LIST_OUT_NAME(filter)
5831 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5832 return true;
5833 return false;
9dac9fc8
DA
5834}
5835
3dc339cd 5836bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5837{
e0df4c04 5838 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5839 return true;
e0df4c04 5840
9dac9fc8
DA
5841 if (peer->sort == BGP_PEER_EBGP
5842 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5843 || FILTER_LIST_IN_NAME(filter)
5844 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5845 return true;
5846 return false;
9dac9fc8
DA
5847}
5848
568e10ca 5849static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5850 safi_t safi)
bb86c601 5851{
9bcb3eef 5852 struct bgp_dest *dest;
40381db7 5853 struct bgp_path_info *pi;
4b7e6066 5854 struct bgp_path_info *next;
bb86c601 5855
9bcb3eef
DS
5856 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5858 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5859
40381db7 5860 next = pi->next;
1b7bb747
CS
5861
5862 /* Unimport EVPN routes from VRFs */
5863 if (safi == SAFI_EVPN)
5864 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5865 SAFI_EVPN, p, pi);
1b7bb747 5866
40381db7
DS
5867 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5868 && pi->type == ZEBRA_ROUTE_BGP
5869 && (pi->sub_type == BGP_ROUTE_NORMAL
5870 || pi->sub_type == BGP_ROUTE_AGGREGATE
5871 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5872
d62a17ae 5873 if (bgp_fibupd_safi(safi))
b54892e0 5874 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5875 }
9514b37d 5876
9bcb3eef 5877 bgp_path_info_reap(dest, pi);
d62a17ae 5878 }
bb86c601
LB
5879}
5880
718e3744 5881/* Delete all kernel routes. */
d62a17ae 5882void bgp_cleanup_routes(struct bgp *bgp)
5883{
5884 afi_t afi;
9bcb3eef 5885 struct bgp_dest *dest;
67009e22 5886 struct bgp_table *table;
d62a17ae 5887
5888 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5889 if (afi == AFI_L2VPN)
5890 continue;
568e10ca 5891 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5892 SAFI_UNICAST);
d62a17ae 5893 /*
5894 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5895 */
5896 if (afi != AFI_L2VPN) {
5897 safi_t safi;
5898 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5899 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5900 dest = bgp_route_next(dest)) {
5901 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5902 if (table != NULL) {
5903 bgp_cleanup_table(bgp, table, safi);
5904 bgp_table_finish(&table);
9bcb3eef
DS
5905 bgp_dest_set_bgp_table_info(dest, NULL);
5906 bgp_dest_unlock_node(dest);
d62a17ae 5907 }
5908 }
5909 safi = SAFI_ENCAP;
9bcb3eef
DS
5910 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5911 dest = bgp_route_next(dest)) {
5912 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5913 if (table != NULL) {
5914 bgp_cleanup_table(bgp, table, safi);
5915 bgp_table_finish(&table);
9bcb3eef
DS
5916 bgp_dest_set_bgp_table_info(dest, NULL);
5917 bgp_dest_unlock_node(dest);
d62a17ae 5918 }
5919 }
5920 }
5921 }
9bcb3eef
DS
5922 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5923 dest = bgp_route_next(dest)) {
5924 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5925 if (table != NULL) {
5926 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5927 bgp_table_finish(&table);
9bcb3eef
DS
5928 bgp_dest_set_bgp_table_info(dest, NULL);
5929 bgp_dest_unlock_node(dest);
d62a17ae 5930 }
bb86c601 5931 }
718e3744 5932}
5933
d62a17ae 5934void bgp_reset(void)
718e3744 5935{
d62a17ae 5936 vty_reset();
5937 bgp_zclient_reset();
5938 access_list_reset();
5939 prefix_list_reset();
718e3744 5940}
6b0655a2 5941
be92fc9f 5942bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5943{
d62a17ae 5944 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5945 && CHECK_FLAG(peer->af_cap[afi][safi],
5946 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5947}
5948
718e3744 5949/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5950 value. */
d62a17ae 5951int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5952 struct bgp_nlri *packet)
5953{
d7c0a89a
QY
5954 uint8_t *pnt;
5955 uint8_t *lim;
d62a17ae 5956 struct prefix p;
5957 int psize;
d62a17ae 5958 afi_t afi;
5959 safi_t safi;
be92fc9f 5960 bool addpath_capable;
d7c0a89a 5961 uint32_t addpath_id;
d62a17ae 5962
d62a17ae 5963 pnt = packet->nlri;
5964 lim = pnt + packet->length;
5965 afi = packet->afi;
5966 safi = packet->safi;
5967 addpath_id = 0;
be92fc9f 5968 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5969
5970 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5971 syntactic validity. If the field is syntactically incorrect,
5972 then the Error Subcode is set to Invalid Network Field. */
5973 for (; pnt < lim; pnt += psize) {
5974 /* Clear prefix structure. */
6006b807 5975 memset(&p, 0, sizeof(p));
d62a17ae 5976
be92fc9f 5977 if (addpath_capable) {
d62a17ae 5978
5979 /* When packet overflow occurs return immediately. */
761ed665 5980 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5981 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5982
a3a850a1 5983 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5984 addpath_id = ntohl(addpath_id);
d62a17ae 5985 pnt += BGP_ADDPATH_ID_LEN;
5986 }
718e3744 5987
d62a17ae 5988 /* Fetch prefix length. */
5989 p.prefixlen = *pnt++;
5990 /* afi/safi validity already verified by caller,
5991 * bgp_update_receive */
5992 p.family = afi2family(afi);
5993
5994 /* Prefix length check. */
5995 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5996 flog_err(
e50f7cfd 5997 EC_BGP_UPDATE_RCV,
14454c9f 5998 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5999 peer->host, p.prefixlen, packet->afi);
513386b5 6000 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6001 }
6b0655a2 6002
d62a17ae 6003 /* Packet size overflow check. */
6004 psize = PSIZE(p.prefixlen);
6005
6006 /* When packet overflow occur return immediately. */
6007 if (pnt + psize > lim) {
af4c2728 6008 flog_err(
e50f7cfd 6009 EC_BGP_UPDATE_RCV,
d62a17ae 6010 "%s [Error] Update packet error (prefix length %d overflows packet)",
6011 peer->host, p.prefixlen);
513386b5 6012 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6013 }
6014
6015 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6016 * prefix for the v4 and v6 afi's and unicast/multicast */
6017 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6018 flog_err(
e50f7cfd 6019 EC_BGP_UPDATE_RCV,
d62a17ae 6020 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6021 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6022 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6023 }
6024
6025 /* Fetch prefix from NLRI packet. */
a85297a7 6026 memcpy(p.u.val, pnt, psize);
d62a17ae 6027
6028 /* Check address. */
6029 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6030 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6031 /* From RFC4271 Section 6.3:
6032 *
6033 * If a prefix in the NLRI field is semantically
6034 * incorrect
6035 * (e.g., an unexpected multicast IP address),
6036 * an error SHOULD
6037 * be logged locally, and the prefix SHOULD be
6038 * ignored.
a4d82a8a 6039 */
af4c2728 6040 flog_err(
e50f7cfd 6041 EC_BGP_UPDATE_RCV,
23d0a753
DA
6042 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6043 peer->host, &p.u.prefix4);
d62a17ae 6044 continue;
6045 }
6046 }
6047
6048 /* Check address. */
6049 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6050 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6051 flog_err(
e50f7cfd 6052 EC_BGP_UPDATE_RCV,
c0d72166
DS
6053 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6054 peer->host, &p.u.prefix6);
d62a17ae 6055
6056 continue;
6057 }
6058 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6059 flog_err(
e50f7cfd 6060 EC_BGP_UPDATE_RCV,
c0d72166
DS
6061 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6062 peer->host, &p.u.prefix6);
d62a17ae 6063
6064 continue;
6065 }
6066 }
6067
6068 /* Normal process. */
6069 if (attr)
367b458c
DS
6070 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6071 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6072 NULL, 0, 0, NULL);
d62a17ae 6073 else
bf0c6163 6074 bgp_withdraw(peer, &p, addpath_id, afi, safi,
367b458c
DS
6075 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6076 NULL, 0, NULL);
d62a17ae 6077
513386b5
DA
6078 /* Do not send BGP notification twice when maximum-prefix count
6079 * overflow. */
6080 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6081 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6082 }
6083
6084 /* Packet length consistency check. */
6085 if (pnt != lim) {
af4c2728 6086 flog_err(
e50f7cfd 6087 EC_BGP_UPDATE_RCV,
d62a17ae 6088 "%s [Error] Update packet error (prefix length mismatch with total length)",
6089 peer->host);
513386b5 6090 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6091 }
6b0655a2 6092
513386b5 6093 return BGP_NLRI_PARSE_OK;
718e3744 6094}
6095
d62a17ae 6096static struct bgp_static *bgp_static_new(void)
718e3744 6097{
d62a17ae 6098 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6099}
6100
d62a17ae 6101static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6102{
0a22ddfb 6103 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6104 route_map_counter_decrement(bgp_static->rmap.map);
6105
c1aa9e7f
PG
6106 if (bgp_static->prd_pretty)
6107 XFREE(MTYPE_BGP, bgp_static->prd_pretty);
0a22ddfb 6108 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6109 XFREE(MTYPE_BGP_STATIC, bgp_static);
6110}
6111
5f040085 6112void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6113 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6114{
9bcb3eef 6115 struct bgp_dest *dest;
40381db7 6116 struct bgp_path_info *pi;
4b7e6066 6117 struct bgp_path_info *new;
40381db7 6118 struct bgp_path_info rmap_path;
d62a17ae 6119 struct attr attr;
6120 struct attr *attr_new;
b68885f9 6121 route_map_result_t ret;
49e5a4a0 6122#ifdef ENABLE_BGP_VNC
d62a17ae 6123 int vnc_implicit_withdraw = 0;
65efcfce 6124#endif
fee0f4c6 6125
d62a17ae 6126 assert(bgp_static);
dd8103a9 6127
9bcb3eef 6128 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6129
0f05ea43 6130 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6131
d62a17ae 6132 attr.nexthop = bgp_static->igpnexthop;
6133 attr.med = bgp_static->igpmetric;
6134 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6135
7226bc40
TA
6136 if (afi == AFI_IP)
6137 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6138
97a52c82
DA
6139 if (bgp_static->igpmetric)
6140 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6141
d62a17ae 6142 if (bgp_static->atomic)
6143 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6144
d62a17ae 6145 /* Store label index, if required. */
6146 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6147 attr.label_index = bgp_static->label_index;
6148 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6149 }
718e3744 6150
d62a17ae 6151 /* Apply route-map. */
6152 if (bgp_static->rmap.name) {
6153 struct attr attr_tmp = attr;
80ced710 6154
6006b807 6155 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6156 rmap_path.peer = bgp->peer_self;
6157 rmap_path.attr = &attr_tmp;
fee0f4c6 6158
d62a17ae 6159 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6160
1782514f 6161 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6162
d62a17ae 6163 bgp->peer_self->rmap_type = 0;
718e3744 6164
d62a17ae 6165 if (ret == RMAP_DENYMATCH) {
6166 /* Free uninterned attribute. */
6167 bgp_attr_flush(&attr_tmp);
718e3744 6168
d62a17ae 6169 /* Unintern original. */
6170 aspath_unintern(&attr.aspath);
6171 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6172 bgp_dest_unlock_node(dest);
d62a17ae 6173 return;
6174 }
7f323236 6175
637e5ba4 6176 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6177 bgp_attr_add_gshut_community(&attr_tmp);
6178
d62a17ae 6179 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6180 } else {
6181
637e5ba4 6182 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6183 bgp_attr_add_gshut_community(&attr);
6184
d62a17ae 6185 attr_new = bgp_attr_intern(&attr);
7f323236 6186 }
718e3744 6187
9bcb3eef 6188 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6189 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6190 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6191 break;
6192
40381db7
DS
6193 if (pi) {
6194 if (attrhash_cmp(pi->attr, attr_new)
6195 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6196 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6197 bgp_dest_unlock_node(dest);
d62a17ae 6198 bgp_attr_unintern(&attr_new);
6199 aspath_unintern(&attr.aspath);
6200 return;
6201 } else {
6202 /* The attribute is changed. */
9bcb3eef 6203 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6204
6205 /* Rewrite BGP route information. */
40381db7 6206 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6207 bgp_path_info_restore(dest, pi);
d62a17ae 6208 else
40381db7 6209 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6210#ifdef ENABLE_BGP_VNC
d62a17ae 6211 if ((afi == AFI_IP || afi == AFI_IP6)
6212 && (safi == SAFI_UNICAST)) {
40381db7 6213 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6214 /*
6215 * Implicit withdraw case.
40381db7 6216 * We have to do this before pi is
d62a17ae 6217 * changed
6218 */
6219 ++vnc_implicit_withdraw;
40381db7 6220 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6221 vnc_import_bgp_exterior_del_route(
40381db7 6222 bgp, p, pi);
d62a17ae 6223 }
6224 }
65efcfce 6225#endif
40381db7
DS
6226 bgp_attr_unintern(&pi->attr);
6227 pi->attr = attr_new;
083ec940 6228 pi->uptime = monotime(NULL);
49e5a4a0 6229#ifdef ENABLE_BGP_VNC
d62a17ae 6230 if ((afi == AFI_IP || afi == AFI_IP6)
6231 && (safi == SAFI_UNICAST)) {
6232 if (vnc_implicit_withdraw) {
40381db7 6233 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6234 vnc_import_bgp_exterior_add_route(
40381db7 6235 bgp, p, pi);
d62a17ae 6236 }
6237 }
65efcfce 6238#endif
718e3744 6239
d62a17ae 6240 /* Nexthop reachability check. */
892fedb6 6241 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6242 && (safi == SAFI_UNICAST
6243 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6244
6245 struct bgp *bgp_nexthop = bgp;
6246
40381db7
DS
6247 if (pi->extra && pi->extra->bgp_orig)
6248 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6249
6250 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6251 afi, safi, pi, NULL,
654a5978 6252 0, p))
9bcb3eef 6253 bgp_path_info_set_flag(dest, pi,
18ee8310 6254 BGP_PATH_VALID);
d62a17ae 6255 else {
6256 if (BGP_DEBUG(nht, NHT)) {
6257 char buf1[INET6_ADDRSTRLEN];
6258 inet_ntop(p->family,
6259 &p->u.prefix, buf1,
07380148 6260 sizeof(buf1));
d62a17ae 6261 zlog_debug(
6262 "%s(%s): Route not in table, not advertising",
15569c58 6263 __func__, buf1);
d62a17ae 6264 }
18ee8310 6265 bgp_path_info_unset_flag(
9bcb3eef 6266 dest, pi, BGP_PATH_VALID);
d62a17ae 6267 }
6268 } else {
6269 /* Delete the NHT structure if any, if we're
6270 * toggling between
6271 * enabling/disabling import check. We
6272 * deregister the route
6273 * from NHT to avoid overloading NHT and the
6274 * process interaction
6275 */
40381db7 6276 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6277 bgp_path_info_set_flag(dest, pi,
6278 BGP_PATH_VALID);
d62a17ae 6279 }
6280 /* Process change. */
40381db7 6281 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6282 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6283
6284 if (SAFI_UNICAST == safi
6285 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6286 || bgp->inst_type
6287 == BGP_INSTANCE_TYPE_DEFAULT)) {
6288 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6289 pi);
ddb5b488
PZ
6290 }
6291
9bcb3eef 6292 bgp_dest_unlock_node(dest);
d62a17ae 6293 aspath_unintern(&attr.aspath);
6294 return;
6295 }
718e3744 6296 }
718e3744 6297
d62a17ae 6298 /* Make new BGP info. */
6299 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6300 attr_new, dest);
d62a17ae 6301 /* Nexthop reachability check. */
892fedb6 6302 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6303 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6304 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6305 p))
9bcb3eef 6306 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6307 else {
6308 if (BGP_DEBUG(nht, NHT)) {
6309 char buf1[INET6_ADDRSTRLEN];
07380148 6310
d62a17ae 6311 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6312 sizeof(buf1));
d62a17ae 6313 zlog_debug(
6314 "%s(%s): Route not in table, not advertising",
15569c58 6315 __func__, buf1);
d62a17ae 6316 }
9bcb3eef 6317 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6318 }
6319 } else {
6320 /* Delete the NHT structure if any, if we're toggling between
6321 * enabling/disabling import check. We deregister the route
6322 * from NHT to avoid overloading NHT and the process interaction
6323 */
6324 bgp_unlink_nexthop(new);
6325
9bcb3eef 6326 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6327 }
078430f6 6328
d62a17ae 6329 /* Aggregate address increment. */
6330 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6331
d62a17ae 6332 /* Register new BGP information. */
9bcb3eef 6333 bgp_path_info_add(dest, new);
718e3744 6334
d62a17ae 6335 /* route_node_get lock */
9bcb3eef 6336 bgp_dest_unlock_node(dest);
d62a17ae 6337
6338 /* Process change. */
9bcb3eef 6339 bgp_process(bgp, dest, afi, safi);
d62a17ae 6340
ddb5b488
PZ
6341 if (SAFI_UNICAST == safi
6342 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6343 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6344 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6345 }
6346
d62a17ae 6347 /* Unintern original. */
6348 aspath_unintern(&attr.aspath);
718e3744 6349}
6350
5f040085 6351void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6352 safi_t safi)
718e3744 6353{
9bcb3eef 6354 struct bgp_dest *dest;
40381db7 6355 struct bgp_path_info *pi;
718e3744 6356
9bcb3eef 6357 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6358
d62a17ae 6359 /* Check selected route and self inserted route. */
9bcb3eef 6360 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6361 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6362 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6363 break;
6364
6365 /* Withdraw static BGP route from routing table. */
40381db7 6366 if (pi) {
ddb5b488
PZ
6367 if (SAFI_UNICAST == safi
6368 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6369 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6370 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6371 }
40381db7
DS
6372 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6373 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6374 bgp_path_info_delete(dest, pi);
6375 bgp_process(bgp, dest, afi, safi);
d62a17ae 6376 }
718e3744 6377
d62a17ae 6378 /* Unlock bgp_node_lookup. */
9bcb3eef 6379 bgp_dest_unlock_node(dest);
718e3744 6380}
6381
137446f9
LB
6382/*
6383 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6384 */
5f040085 6385static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6386 afi_t afi, safi_t safi,
6387 struct prefix_rd *prd)
718e3744 6388{
9bcb3eef 6389 struct bgp_dest *dest;
40381db7 6390 struct bgp_path_info *pi;
718e3744 6391
9bcb3eef 6392 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6393
d62a17ae 6394 /* Check selected route and self inserted route. */
9bcb3eef 6395 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6396 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6397 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6398 break;
718e3744 6399
d62a17ae 6400 /* Withdraw static BGP route from routing table. */
40381db7 6401 if (pi) {
49e5a4a0 6402#ifdef ENABLE_BGP_VNC
d62a17ae 6403 rfapiProcessWithdraw(
40381db7 6404 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6405 1); /* Kill, since it is an administrative change */
65efcfce 6406#endif
ddb5b488
PZ
6407 if (SAFI_MPLS_VPN == safi
6408 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6409 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6410 }
40381db7 6411 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6412 bgp_path_info_delete(dest, pi);
6413 bgp_process(bgp, dest, afi, safi);
d62a17ae 6414 }
718e3744 6415
d62a17ae 6416 /* Unlock bgp_node_lookup. */
9bcb3eef 6417 bgp_dest_unlock_node(dest);
718e3744 6418}
6419
5f040085 6420static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6421 struct bgp_static *bgp_static, afi_t afi,
6422 safi_t safi)
137446f9 6423{
9bcb3eef 6424 struct bgp_dest *dest;
4b7e6066 6425 struct bgp_path_info *new;
d62a17ae 6426 struct attr *attr_new;
6427 struct attr attr = {0};
40381db7 6428 struct bgp_path_info *pi;
49e5a4a0 6429#ifdef ENABLE_BGP_VNC
d62a17ae 6430 mpls_label_t label = 0;
65efcfce 6431#endif
d7c0a89a 6432 uint32_t num_labels = 0;
137446f9 6433
d62a17ae 6434 assert(bgp_static);
137446f9 6435
b57ba6d2
MK
6436 if (bgp_static->label != MPLS_INVALID_LABEL)
6437 num_labels = 1;
9bcb3eef
DS
6438 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6439 &bgp_static->prd);
137446f9 6440
0f05ea43 6441 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6442
d62a17ae 6443 attr.nexthop = bgp_static->igpnexthop;
6444 attr.med = bgp_static->igpmetric;
6445 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6446
d62a17ae 6447 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6448 || (safi == SAFI_ENCAP)) {
6449 if (afi == AFI_IP) {
6450 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6451 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6452 }
6453 }
6454 if (afi == AFI_L2VPN) {
b04c1e99
IR
6455 if (bgp_static->gatewayIp.family == AF_INET) {
6456 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6457 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6458 &bgp_static->gatewayIp.u.prefix4,
6459 IPV4_MAX_BYTELEN);
b04c1e99
IR
6460 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6461 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6462 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6463 &bgp_static->gatewayIp.u.prefix6,
6464 IPV6_MAX_BYTELEN);
b04c1e99 6465 }
0a50c248 6466 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6467 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6468 struct bgp_encap_type_vxlan bet;
6006b807 6469 memset(&bet, 0, sizeof(bet));
3714a385 6470 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6471 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6472 }
6473 if (bgp_static->router_mac) {
6474 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6475 }
6476 }
6477 /* Apply route-map. */
6478 if (bgp_static->rmap.name) {
6479 struct attr attr_tmp = attr;
40381db7 6480 struct bgp_path_info rmap_path;
b68885f9 6481 route_map_result_t ret;
137446f9 6482
40381db7
DS
6483 rmap_path.peer = bgp->peer_self;
6484 rmap_path.attr = &attr_tmp;
137446f9 6485
d62a17ae 6486 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6487
1782514f 6488 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6489
d62a17ae 6490 bgp->peer_self->rmap_type = 0;
137446f9 6491
d62a17ae 6492 if (ret == RMAP_DENYMATCH) {
6493 /* Free uninterned attribute. */
6494 bgp_attr_flush(&attr_tmp);
137446f9 6495
d62a17ae 6496 /* Unintern original. */
6497 aspath_unintern(&attr.aspath);
6498 bgp_static_withdraw_safi(bgp, p, afi, safi,
6499 &bgp_static->prd);
bbc52106 6500 bgp_dest_unlock_node(dest);
d62a17ae 6501 return;
6502 }
137446f9 6503
d62a17ae 6504 attr_new = bgp_attr_intern(&attr_tmp);
6505 } else {
6506 attr_new = bgp_attr_intern(&attr);
6507 }
137446f9 6508
9bcb3eef 6509 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6510 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6511 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6512 break;
6513
40381db7 6514 if (pi) {
40381db7 6515 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6516 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6517 bgp_dest_unlock_node(dest);
d62a17ae 6518 bgp_attr_unintern(&attr_new);
6519 aspath_unintern(&attr.aspath);
6520 return;
6521 } else {
6522 /* The attribute is changed. */
9bcb3eef 6523 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6524
6525 /* Rewrite BGP route information. */
40381db7 6526 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6527 bgp_path_info_restore(dest, pi);
d62a17ae 6528 else
40381db7
DS
6529 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6530 bgp_attr_unintern(&pi->attr);
6531 pi->attr = attr_new;
083ec940 6532 pi->uptime = monotime(NULL);
49e5a4a0 6533#ifdef ENABLE_BGP_VNC
40381db7
DS
6534 if (pi->extra)
6535 label = decode_label(&pi->extra->label[0]);
65efcfce 6536#endif
137446f9 6537
d62a17ae 6538 /* Process change. */
40381db7 6539 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6540 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6541
6542 if (SAFI_MPLS_VPN == safi
6543 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6544 vpn_leak_to_vrf_update(bgp, pi,
6545 &bgp_static->prd);
ddb5b488 6546 }
49e5a4a0 6547#ifdef ENABLE_BGP_VNC
40381db7
DS
6548 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6549 pi->attr, afi, safi, pi->type,
6550 pi->sub_type, &label);
65efcfce 6551#endif
9bcb3eef 6552 bgp_dest_unlock_node(dest);
d62a17ae 6553 aspath_unintern(&attr.aspath);
6554 return;
6555 }
6556 }
137446f9
LB
6557
6558
d62a17ae 6559 /* Make new BGP info. */
6560 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6561 attr_new, dest);
1defdda8 6562 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6563 bgp_path_info_extra_get(new);
b57ba6d2
MK
6564 if (num_labels) {
6565 new->extra->label[0] = bgp_static->label;
6566 new->extra->num_labels = num_labels;
6567 }
49e5a4a0 6568#ifdef ENABLE_BGP_VNC
d62a17ae 6569 label = decode_label(&bgp_static->label);
65efcfce 6570#endif
137446f9 6571
d62a17ae 6572 /* Aggregate address increment. */
6573 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6574
d62a17ae 6575 /* Register new BGP information. */
9bcb3eef 6576 bgp_path_info_add(dest, new);
d62a17ae 6577 /* route_node_get lock */
9bcb3eef 6578 bgp_dest_unlock_node(dest);
137446f9 6579
d62a17ae 6580 /* Process change. */
9bcb3eef 6581 bgp_process(bgp, dest, afi, safi);
137446f9 6582
ddb5b488
PZ
6583 if (SAFI_MPLS_VPN == safi
6584 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6585 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6586 }
49e5a4a0 6587#ifdef ENABLE_BGP_VNC
d62a17ae 6588 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6589 safi, new->type, new->sub_type, &label);
65efcfce
LB
6590#endif
6591
d62a17ae 6592 /* Unintern original. */
6593 aspath_unintern(&attr.aspath);
137446f9
LB
6594}
6595
718e3744 6596/* Configure static BGP network. When user don't run zebra, static
6597 route should be installed as valid. */
585f1adc
IR
6598static int bgp_static_set(struct vty *vty, const char *negate,
6599 const char *ip_str, afi_t afi, safi_t safi,
6600 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6601{
585f1adc
IR
6602 VTY_DECLVAR_CONTEXT(bgp, bgp);
6603 int ret;
d62a17ae 6604 struct prefix p;
6605 struct bgp_static *bgp_static;
9bcb3eef 6606 struct bgp_dest *dest;
d7c0a89a 6607 uint8_t need_update = 0;
d62a17ae 6608
585f1adc
IR
6609 /* Convert IP prefix string to struct prefix. */
6610 ret = str2prefix(ip_str, &p);
6611 if (!ret) {
6612 vty_out(vty, "%% Malformed prefix\n");
6613 return CMD_WARNING_CONFIG_FAILED;
6614 }
6615 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6616 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6617 return CMD_WARNING_CONFIG_FAILED;
6618 }
6619
d62a17ae 6620 apply_mask(&p);
718e3744 6621
e2a86ad9 6622 if (negate) {
718e3744 6623
e2a86ad9 6624 /* Set BGP static route configuration. */
9bcb3eef 6625 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6626
9bcb3eef 6627 if (!dest) {
585f1adc
IR
6628 vty_out(vty, "%% Can't find static route specified\n");
6629 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6630 }
6631
9bcb3eef 6632 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6633
e2a86ad9
DS
6634 if ((label_index != BGP_INVALID_LABEL_INDEX)
6635 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6636 vty_out(vty,
6637 "%% label-index doesn't match static route\n");
70d9b134 6638 bgp_dest_unlock_node(dest);
585f1adc 6639 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6640 }
d62a17ae 6641
e2a86ad9
DS
6642 if ((rmap && bgp_static->rmap.name)
6643 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6644 vty_out(vty,
6645 "%% route-map name doesn't match static route\n");
70d9b134 6646 bgp_dest_unlock_node(dest);
585f1adc 6647 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6648 }
718e3744 6649
e2a86ad9
DS
6650 /* Update BGP RIB. */
6651 if (!bgp_static->backdoor)
6652 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6653
e2a86ad9
DS
6654 /* Clear configuration. */
6655 bgp_static_free(bgp_static);
9bcb3eef
DS
6656 bgp_dest_set_bgp_static_info(dest, NULL);
6657 bgp_dest_unlock_node(dest);
6658 bgp_dest_unlock_node(dest);
e2a86ad9 6659 } else {
718e3744 6660
e2a86ad9 6661 /* Set BGP static route configuration. */
9bcb3eef
DS
6662 dest = bgp_node_get(bgp->route[afi][safi], &p);
6663 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6664 if (bgp_static) {
e2a86ad9 6665 /* Configuration change. */
e2a86ad9
DS
6666 /* Label index cannot be changed. */
6667 if (bgp_static->label_index != label_index) {
585f1adc 6668 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6669 bgp_dest_unlock_node(dest);
585f1adc 6670 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6671 }
d62a17ae 6672
e2a86ad9 6673 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6674 if (bgp_static->valid
6675 && bgp_static->backdoor != backdoor)
e2a86ad9 6676 need_update = 1;
718e3744 6677
e2a86ad9 6678 bgp_static->backdoor = backdoor;
718e3744 6679
e2a86ad9 6680 if (rmap) {
0a22ddfb
QY
6681 XFREE(MTYPE_ROUTE_MAP_NAME,
6682 bgp_static->rmap.name);
b4897fa5 6683 route_map_counter_decrement(
6684 bgp_static->rmap.map);
e2a86ad9
DS
6685 bgp_static->rmap.name =
6686 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6687 bgp_static->rmap.map =
6688 route_map_lookup_by_name(rmap);
b4897fa5 6689 route_map_counter_increment(
6690 bgp_static->rmap.map);
e2a86ad9 6691 } else {
0a22ddfb
QY
6692 XFREE(MTYPE_ROUTE_MAP_NAME,
6693 bgp_static->rmap.name);
b4897fa5 6694 route_map_counter_decrement(
6695 bgp_static->rmap.map);
e2a86ad9
DS
6696 bgp_static->rmap.map = NULL;
6697 bgp_static->valid = 0;
6698 }
9bcb3eef 6699 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6700 } else {
6701 /* New configuration. */
6702 bgp_static = bgp_static_new();
6703 bgp_static->backdoor = backdoor;
6704 bgp_static->valid = 0;
6705 bgp_static->igpmetric = 0;
975a328e 6706 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6707 bgp_static->label_index = label_index;
718e3744 6708
e2a86ad9 6709 if (rmap) {
0a22ddfb
QY
6710 XFREE(MTYPE_ROUTE_MAP_NAME,
6711 bgp_static->rmap.name);
b4897fa5 6712 route_map_counter_decrement(
6713 bgp_static->rmap.map);
e2a86ad9
DS
6714 bgp_static->rmap.name =
6715 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6716 bgp_static->rmap.map =
6717 route_map_lookup_by_name(rmap);
b4897fa5 6718 route_map_counter_increment(
6719 bgp_static->rmap.map);
e2a86ad9 6720 }
9bcb3eef 6721 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6722 }
d62a17ae 6723
e2a86ad9
DS
6724 bgp_static->valid = 1;
6725 if (need_update)
6726 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6727
e2a86ad9
DS
6728 if (!bgp_static->backdoor)
6729 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6730 }
d62a17ae 6731
585f1adc 6732 return CMD_SUCCESS;
d62a17ae 6733}
6734
6735void bgp_static_add(struct bgp *bgp)
6736{
6737 afi_t afi;
6738 safi_t safi;
9bcb3eef
DS
6739 struct bgp_dest *dest;
6740 struct bgp_dest *rm;
d62a17ae 6741 struct bgp_table *table;
6742 struct bgp_static *bgp_static;
6743
47fc6261 6744 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6745 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6746 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6747 dest = bgp_route_next(dest)) {
6748 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6749 continue;
ea47320b 6750
05c7a1cc
QY
6751 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6752 || (safi == SAFI_EVPN)) {
9bcb3eef 6753 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6754
6755 for (rm = bgp_table_top(table); rm;
6756 rm = bgp_route_next(rm)) {
a78beeb5 6757 bgp_static =
9bcb3eef 6758 bgp_dest_get_bgp_static_info(
5a8ba9fc 6759 rm);
9bcb3eef
DS
6760 bgp_static_update_safi(
6761 bgp, bgp_dest_get_prefix(rm),
6762 bgp_static, afi, safi);
d62a17ae 6763 }
05c7a1cc 6764 } else {
5a8ba9fc 6765 bgp_static_update(
9bcb3eef
DS
6766 bgp, bgp_dest_get_prefix(dest),
6767 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6768 safi);
ea47320b 6769 }
05c7a1cc 6770 }
47fc6261 6771 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6772}
6773
718e3744 6774/* Called from bgp_delete(). Delete all static routes from the BGP
6775 instance. */
d62a17ae 6776void bgp_static_delete(struct bgp *bgp)
6777{
6778 afi_t afi;
6779 safi_t safi;
9bcb3eef
DS
6780 struct bgp_dest *dest;
6781 struct bgp_dest *rm;
d62a17ae 6782 struct bgp_table *table;
6783 struct bgp_static *bgp_static;
6784
05c7a1cc 6785 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6786 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6787 dest = bgp_route_next(dest)) {
6788 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6789 continue;
ea47320b 6790
05c7a1cc
QY
6791 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6792 || (safi == SAFI_EVPN)) {
9bcb3eef 6793 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6794
6795 for (rm = bgp_table_top(table); rm;
6796 rm = bgp_route_next(rm)) {
a78beeb5 6797 bgp_static =
9bcb3eef 6798 bgp_dest_get_bgp_static_info(
5a8ba9fc 6799 rm);
c7d14ba6
PG
6800 if (!bgp_static)
6801 continue;
6802
05c7a1cc 6803 bgp_static_withdraw_safi(
9bcb3eef 6804 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6805 AFI_IP, safi,
6806 (struct prefix_rd *)
9bcb3eef
DS
6807 bgp_dest_get_prefix(
6808 dest));
ea47320b 6809 bgp_static_free(bgp_static);
811c6797 6810 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6811 NULL);
811c6797 6812 bgp_dest_unlock_node(rm);
d62a17ae 6813 }
05c7a1cc 6814 } else {
9bcb3eef 6815 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6816 bgp_static_withdraw(bgp,
9bcb3eef 6817 bgp_dest_get_prefix(dest),
b54892e0 6818 afi, safi);
05c7a1cc 6819 bgp_static_free(bgp_static);
9bcb3eef
DS
6820 bgp_dest_set_bgp_static_info(dest, NULL);
6821 bgp_dest_unlock_node(dest);
ea47320b 6822 }
05c7a1cc 6823 }
d62a17ae 6824}
6825
6826void bgp_static_redo_import_check(struct bgp *bgp)
6827{
6828 afi_t afi;
6829 safi_t safi;
9bcb3eef
DS
6830 struct bgp_dest *dest;
6831 struct bgp_dest *rm;
d62a17ae 6832 struct bgp_table *table;
6833 struct bgp_static *bgp_static;
6834
6835 /* Use this flag to force reprocessing of the route */
892fedb6 6836 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6837 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6838 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6839 dest = bgp_route_next(dest)) {
6840 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6841 continue;
ea47320b 6842
05c7a1cc
QY
6843 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6844 || (safi == SAFI_EVPN)) {
9bcb3eef 6845 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6846
6847 for (rm = bgp_table_top(table); rm;
6848 rm = bgp_route_next(rm)) {
a78beeb5 6849 bgp_static =
9bcb3eef 6850 bgp_dest_get_bgp_static_info(
5a8ba9fc 6851 rm);
9bcb3eef
DS
6852 bgp_static_update_safi(
6853 bgp, bgp_dest_get_prefix(rm),
6854 bgp_static, afi, safi);
d62a17ae 6855 }
05c7a1cc 6856 } else {
9bcb3eef
DS
6857 bgp_static = bgp_dest_get_bgp_static_info(dest);
6858 bgp_static_update(bgp,
6859 bgp_dest_get_prefix(dest),
6860 bgp_static, afi, safi);
ea47320b 6861 }
05c7a1cc
QY
6862 }
6863 }
892fedb6 6864 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6865}
6866
6867static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6868 safi_t safi)
6869{
6870 struct bgp_table *table;
9bcb3eef 6871 struct bgp_dest *dest;
40381db7 6872 struct bgp_path_info *pi;
d62a17ae 6873
dfb6fd1d
NT
6874 /* Do not install the aggregate route if BGP is in the
6875 * process of termination.
6876 */
892fedb6
DA
6877 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6878 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6879 return;
6880
d62a17ae 6881 table = bgp->rib[afi][safi];
9bcb3eef
DS
6882 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6883 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6884 if (pi->peer == bgp->peer_self
6885 && ((pi->type == ZEBRA_ROUTE_BGP
6886 && pi->sub_type == BGP_ROUTE_STATIC)
6887 || (pi->type != ZEBRA_ROUTE_BGP
6888 && pi->sub_type
d62a17ae 6889 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6890 bgp_aggregate_decrement(
6891 bgp, bgp_dest_get_prefix(dest), pi, afi,
6892 safi);
40381db7 6893 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6894 bgp_path_info_delete(dest, pi);
6895 bgp_process(bgp, dest, afi, safi);
d62a17ae 6896 }
6897 }
6898 }
ad4cbda1 6899}
6900
6901/*
6902 * Purge all networks and redistributed routes from routing table.
6903 * Invoked upon the instance going down.
6904 */
d62a17ae 6905void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6906{
d62a17ae 6907 afi_t afi;
6908 safi_t safi;
ad4cbda1 6909
05c7a1cc
QY
6910 FOREACH_AFI_SAFI (afi, safi)
6911 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6912}
6913
137446f9
LB
6914/*
6915 * gpz 110624
6916 * Currently this is used to set static routes for VPN and ENCAP.
6917 * I think it can probably be factored with bgp_static_set.
6918 */
d62a17ae 6919int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6920 const char *ip_str, const char *rd_str,
6921 const char *label_str, const char *rmap_str,
6922 int evpn_type, const char *esi, const char *gwip,
6923 const char *ethtag, const char *routermac)
6924{
6925 VTY_DECLVAR_CONTEXT(bgp, bgp);
6926 int ret;
6927 struct prefix p;
6928 struct prefix_rd prd;
9bcb3eef
DS
6929 struct bgp_dest *pdest;
6930 struct bgp_dest *dest;
d62a17ae 6931 struct bgp_table *table;
6932 struct bgp_static *bgp_static;
6933 mpls_label_t label = MPLS_INVALID_LABEL;
6934 struct prefix gw_ip;
6935
6936 /* validate ip prefix */
6937 ret = str2prefix(ip_str, &p);
6938 if (!ret) {
6939 vty_out(vty, "%% Malformed prefix\n");
6940 return CMD_WARNING_CONFIG_FAILED;
6941 }
6942 apply_mask(&p);
6943 if ((afi == AFI_L2VPN)
6944 && (bgp_build_evpn_prefix(evpn_type,
6945 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6946 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6947 return CMD_WARNING_CONFIG_FAILED;
6948 }
718e3744 6949
d62a17ae 6950 ret = str2prefix_rd(rd_str, &prd);
6951 if (!ret) {
6952 vty_out(vty, "%% Malformed rd\n");
6953 return CMD_WARNING_CONFIG_FAILED;
6954 }
718e3744 6955
d62a17ae 6956 if (label_str) {
6957 unsigned long label_val;
6958 label_val = strtoul(label_str, NULL, 10);
6959 encode_label(label_val, &label);
6960 }
9bedbb1e 6961
d62a17ae 6962 if (safi == SAFI_EVPN) {
6963 if (esi && str2esi(esi, NULL) == 0) {
6964 vty_out(vty, "%% Malformed ESI\n");
6965 return CMD_WARNING_CONFIG_FAILED;
6966 }
6967 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6968 vty_out(vty, "%% Malformed Router MAC\n");
6969 return CMD_WARNING_CONFIG_FAILED;
6970 }
6971 if (gwip) {
6006b807 6972 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6973 ret = str2prefix(gwip, &gw_ip);
6974 if (!ret) {
6975 vty_out(vty, "%% Malformed GatewayIp\n");
6976 return CMD_WARNING_CONFIG_FAILED;
6977 }
6978 if ((gw_ip.family == AF_INET
3714a385 6979 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6980 (struct prefix_evpn *)&p))
6981 || (gw_ip.family == AF_INET6
3714a385 6982 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6983 (struct prefix_evpn *)&p))) {
6984 vty_out(vty,
6985 "%% GatewayIp family differs with IP prefix\n");
6986 return CMD_WARNING_CONFIG_FAILED;
6987 }
6988 }
6989 }
9bcb3eef
DS
6990 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6991 if (!bgp_dest_has_bgp_path_info_data(pdest))
6992 bgp_dest_set_bgp_table_info(pdest,
67009e22 6993 bgp_table_init(bgp, afi, safi));
9bcb3eef 6994 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6995
9bcb3eef 6996 dest = bgp_node_get(table, &p);
d62a17ae 6997
9bcb3eef 6998 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6999 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7000 bgp_dest_unlock_node(dest);
d62a17ae 7001 } else {
7002 /* New configuration. */
7003 bgp_static = bgp_static_new();
7004 bgp_static->backdoor = 0;
7005 bgp_static->valid = 0;
7006 bgp_static->igpmetric = 0;
975a328e 7007 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7008 bgp_static->label = label;
7009 bgp_static->prd = prd;
7010
c1aa9e7f
PG
7011 if (rd_str)
7012 bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
d62a17ae 7013 if (rmap_str) {
0a22ddfb 7014 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7015 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7016 bgp_static->rmap.name =
7017 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7018 bgp_static->rmap.map =
7019 route_map_lookup_by_name(rmap_str);
b4897fa5 7020 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7021 }
718e3744 7022
d62a17ae 7023 if (safi == SAFI_EVPN) {
7024 if (esi) {
7025 bgp_static->eth_s_id =
7026 XCALLOC(MTYPE_ATTR,
0a50c248 7027 sizeof(esi_t));
d62a17ae 7028 str2esi(esi, bgp_static->eth_s_id);
7029 }
7030 if (routermac) {
7031 bgp_static->router_mac =
28328ea9 7032 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7033 (void)prefix_str2mac(routermac,
7034 bgp_static->router_mac);
d62a17ae 7035 }
7036 if (gwip)
7037 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7038 }
9bcb3eef 7039 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7040
d62a17ae 7041 bgp_static->valid = 1;
7042 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7043 }
718e3744 7044
d62a17ae 7045 return CMD_SUCCESS;
718e3744 7046}
7047
7048/* Configure static BGP network. */
d62a17ae 7049int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7050 const char *ip_str, const char *rd_str,
7051 const char *label_str, int evpn_type, const char *esi,
7052 const char *gwip, const char *ethtag)
7053{
7054 VTY_DECLVAR_CONTEXT(bgp, bgp);
7055 int ret;
7056 struct prefix p;
7057 struct prefix_rd prd;
9bcb3eef
DS
7058 struct bgp_dest *pdest;
7059 struct bgp_dest *dest;
d62a17ae 7060 struct bgp_table *table;
7061 struct bgp_static *bgp_static;
7062 mpls_label_t label = MPLS_INVALID_LABEL;
7063
7064 /* Convert IP prefix string to struct prefix. */
7065 ret = str2prefix(ip_str, &p);
7066 if (!ret) {
7067 vty_out(vty, "%% Malformed prefix\n");
7068 return CMD_WARNING_CONFIG_FAILED;
7069 }
7070 apply_mask(&p);
7071 if ((afi == AFI_L2VPN)
7072 && (bgp_build_evpn_prefix(evpn_type,
7073 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7074 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7075 return CMD_WARNING_CONFIG_FAILED;
7076 }
7077 ret = str2prefix_rd(rd_str, &prd);
7078 if (!ret) {
7079 vty_out(vty, "%% Malformed rd\n");
7080 return CMD_WARNING_CONFIG_FAILED;
7081 }
718e3744 7082
d62a17ae 7083 if (label_str) {
7084 unsigned long label_val;
7085 label_val = strtoul(label_str, NULL, 10);
7086 encode_label(label_val, &label);
7087 }
718e3744 7088
9bcb3eef
DS
7089 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7090 if (!bgp_dest_has_bgp_path_info_data(pdest))
7091 bgp_dest_set_bgp_table_info(pdest,
67009e22 7092 bgp_table_init(bgp, afi, safi));
d62a17ae 7093 else
9bcb3eef
DS
7094 bgp_dest_unlock_node(pdest);
7095 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7096
9bcb3eef 7097 dest = bgp_node_lookup(table, &p);
6b0655a2 7098
9bcb3eef 7099 if (dest) {
d62a17ae 7100 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7101
9bcb3eef 7102 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7103 bgp_static_free(bgp_static);
9bcb3eef
DS
7104 bgp_dest_set_bgp_static_info(dest, NULL);
7105 bgp_dest_unlock_node(dest);
7106 bgp_dest_unlock_node(dest);
d62a17ae 7107 } else
7108 vty_out(vty, "%% Can't find the route\n");
7109
7110 return CMD_SUCCESS;
7111}
7112
7113static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7114 const char *rmap_name)
7115{
7116 VTY_DECLVAR_CONTEXT(bgp, bgp);
7117 struct bgp_rmap *rmap;
7118
7119 rmap = &bgp->table_map[afi][safi];
7120 if (rmap_name) {
0a22ddfb 7121 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7122 route_map_counter_decrement(rmap->map);
d62a17ae 7123 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7124 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7125 route_map_counter_increment(rmap->map);
d62a17ae 7126 } else {
0a22ddfb 7127 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7128 route_map_counter_decrement(rmap->map);
d62a17ae 7129 rmap->map = NULL;
7130 }
73ac8160 7131
d62a17ae 7132 if (bgp_fibupd_safi(safi))
7133 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7134
d62a17ae 7135 return CMD_SUCCESS;
73ac8160
DS
7136}
7137
d62a17ae 7138static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7139 const char *rmap_name)
73ac8160 7140{
d62a17ae 7141 VTY_DECLVAR_CONTEXT(bgp, bgp);
7142 struct bgp_rmap *rmap;
73ac8160 7143
d62a17ae 7144 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7145 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7146 route_map_counter_decrement(rmap->map);
d62a17ae 7147 rmap->map = NULL;
73ac8160 7148
d62a17ae 7149 if (bgp_fibupd_safi(safi))
7150 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7151
d62a17ae 7152 return CMD_SUCCESS;
73ac8160
DS
7153}
7154
2b791107 7155void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7156 safi_t safi)
73ac8160 7157{
d62a17ae 7158 if (bgp->table_map[afi][safi].name) {
d62a17ae 7159 vty_out(vty, " table-map %s\n",
7160 bgp->table_map[afi][safi].name);
7161 }
73ac8160
DS
7162}
7163
73ac8160
DS
7164DEFUN (bgp_table_map,
7165 bgp_table_map_cmd,
7166 "table-map WORD",
7167 "BGP table to RIB route download filter\n"
7168 "Name of the route map\n")
7169{
d62a17ae 7170 int idx_word = 1;
7171 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7172 argv[idx_word]->arg);
73ac8160
DS
7173}
7174DEFUN (no_bgp_table_map,
7175 no_bgp_table_map_cmd,
7176 "no table-map WORD",
3a2d747c 7177 NO_STR
73ac8160
DS
7178 "BGP table to RIB route download filter\n"
7179 "Name of the route map\n")
7180{
d62a17ae 7181 int idx_word = 2;
7182 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7183 argv[idx_word]->arg);
73ac8160
DS
7184}
7185
585f1adc
IR
7186DEFPY(bgp_network,
7187 bgp_network_cmd,
7188 "[no] network \
7189 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7190 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7191 backdoor$backdoor}]",
7192 NO_STR
7193 "Specify a network to announce via BGP\n"
7194 "IPv4 prefix\n"
7195 "Network number\n"
7196 "Network mask\n"
7197 "Network mask\n"
7198 "Route-map to modify the attributes\n"
7199 "Name of the route map\n"
7200 "Label index to associate with the prefix\n"
7201 "Label index value\n"
7202 "Specify a BGP backdoor route\n")
7203{
7204 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7205
7206 if (address_str) {
7207 int ret;
718e3744 7208
e2a86ad9 7209 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7210 addr_prefix_str,
7211 sizeof(addr_prefix_str));
e2a86ad9
DS
7212 if (!ret) {
7213 vty_out(vty, "%% Inconsistent address and mask\n");
7214 return CMD_WARNING_CONFIG_FAILED;
7215 }
d62a17ae 7216 }
718e3744 7217
585f1adc
IR
7218 return bgp_static_set(
7219 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7220 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7221 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7222}
7223
585f1adc
IR
7224DEFPY(ipv6_bgp_network,
7225 ipv6_bgp_network_cmd,
7226 "[no] network X:X::X:X/M$prefix \
70dd370f 7227 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7228 NO_STR
7229 "Specify a network to announce via BGP\n"
7230 "IPv6 prefix\n"
7231 "Route-map to modify the attributes\n"
7232 "Name of the route map\n"
7233 "Label index to associate with the prefix\n"
7234 "Label index value\n")
37a87b8f 7235{
585f1adc
IR
7236 return bgp_static_set(
7237 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7238 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7239}
7240
d62a17ae 7241static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7242{
d62a17ae 7243 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7244}
7245
d62a17ae 7246static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7247{
365ab2e7
RZ
7248 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7249 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7250 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7251 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7252 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7253}
718e3744 7254
365ab2e7
RZ
7255/**
7256 * Helper function to avoid repeated code: prepare variables for a
7257 * `route_map_apply` call.
7258 *
7259 * \returns `true` on route map match, otherwise `false`.
7260 */
7261static bool aggr_suppress_map_test(struct bgp *bgp,
7262 struct bgp_aggregate *aggregate,
7263 struct bgp_path_info *pi)
7264{
7265 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7266 route_map_result_t rmr = RMAP_DENYMATCH;
7267 struct bgp_path_info rmap_path = {};
7268 struct attr attr = {};
7269
7270 /* No route map entries created, just don't match. */
7271 if (aggregate->suppress_map == NULL)
7272 return false;
7273
7274 /* Call route map matching and return result. */
17571c4a 7275 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7276 rmap_path.peer = bgp->peer_self;
7277 rmap_path.attr = &attr;
7278
7279 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7280 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7281 bgp->peer_self->rmap_type = 0;
7282
7283 bgp_attr_flush(&attr);
afb254d7 7284 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7285
7286 return rmr == RMAP_PERMITMATCH;
7287}
7288
4056a5f6
RZ
7289/** Test whether the aggregation has suppressed this path or not. */
7290static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7291 struct bgp_path_info *pi)
7292{
7293 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7294 return false;
7295
7296 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7297}
7298
7299/**
7300 * Suppress this path and keep the reference.
7301 *
7302 * \returns `true` if needs processing otherwise `false`.
7303 */
7304static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7305 struct bgp_path_info *pi)
7306{
7307 struct bgp_path_info_extra *pie;
7308
7309 /* Path is already suppressed by this aggregation. */
7310 if (aggr_suppress_exists(aggregate, pi))
7311 return false;
7312
7313 pie = bgp_path_info_extra_get(pi);
7314
7315 /* This is the first suppression, allocate memory and list it. */
7316 if (pie->aggr_suppressors == NULL)
7317 pie->aggr_suppressors = list_new();
7318
7319 listnode_add(pie->aggr_suppressors, aggregate);
7320
7321 /* Only mark for processing if suppressed. */
7322 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7323 if (BGP_DEBUG(update, UPDATE_OUT))
7324 zlog_debug("aggregate-address suppressing: %pFX",
7325 bgp_dest_get_prefix(pi->net));
7326
4056a5f6
RZ
7327 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7328 return true;
7329 }
7330
7331 return false;
7332}
7333
7334/**
7335 * Unsuppress this path and remove the reference.
7336 *
7337 * \returns `true` if needs processing otherwise `false`.
7338 */
7339static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7340 struct bgp_path_info *pi)
7341{
7342 /* Path wasn't suppressed. */
7343 if (!aggr_suppress_exists(aggregate, pi))
7344 return false;
7345
7346 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7347
7348 /* Unsuppress and free extra memory if last item. */
7349 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7350 if (BGP_DEBUG(update, UPDATE_OUT))
7351 zlog_debug("aggregate-address unsuppressing: %pFX",
7352 bgp_dest_get_prefix(pi->net));
7353
4056a5f6
RZ
7354 list_delete(&pi->extra->aggr_suppressors);
7355 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7356 return true;
7357 }
7358
7359 return false;
7360}
7361
3dc339cd
DA
7362static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7363 struct aspath *aspath,
7364 struct community *comm,
7365 struct ecommunity *ecomm,
7366 struct lcommunity *lcomm)
eaaf8adb
DS
7367{
7368 static struct aspath *ae = NULL;
17571c4a
PG
7369 enum asnotation_mode asnotation;
7370
7371 asnotation = bgp_get_asnotation(NULL);
eaaf8adb
DS
7372
7373 if (!ae)
17571c4a 7374 ae = aspath_empty(asnotation);
eaaf8adb 7375
40381db7 7376 if (!pi)
3dc339cd 7377 return false;
eaaf8adb 7378
40381db7 7379 if (origin != pi->attr->origin)
3dc339cd 7380 return false;
eaaf8adb 7381
40381db7 7382 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7383 return false;
29f7d023 7384
9a706b42 7385 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7386 return false;
eaaf8adb 7387
b53e67a3 7388 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7389 return false;
eaaf8adb 7390
1bcf3a96 7391 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7392 return false;
dd18c5a9 7393
40381db7 7394 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7395 return false;
7ce8a8e0 7396
3dc339cd 7397 return true;
eaaf8adb
DS
7398}
7399
5f040085
DS
7400static void bgp_aggregate_install(
7401 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7402 uint8_t origin, struct aspath *aspath, struct community *community,
7403 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7404 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7405{
9bcb3eef 7406 struct bgp_dest *dest;
c701010e 7407 struct bgp_table *table;
6f94b685 7408 struct bgp_path_info *pi, *orig, *new;
20894f50 7409 struct attr *attr;
c701010e
DS
7410
7411 table = bgp->rib[afi][safi];
7412
9bcb3eef 7413 dest = bgp_node_get(table, p);
eaaf8adb 7414
9bcb3eef 7415 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7416 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7417 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7418 break;
7419
6aabb15d
RZ
7420 /*
7421 * If we have paths with different MEDs, then don't install
7422 * (or uninstall) the aggregate route.
7423 */
7424 if (aggregate->match_med && aggregate->med_mismatched)
7425 goto uninstall_aggregate_route;
7426
c701010e 7427 if (aggregate->count > 0) {
eaaf8adb
DS
7428 /*
7429 * If the aggregate information has not changed
7430 * no need to re-install it again.
7431 */
6f94b685 7432 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7433 ecommunity, lcommunity)) {
9bcb3eef 7434 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7435
7436 if (aspath)
7437 aspath_free(aspath);
7438 if (community)
3c1f53de 7439 community_free(&community);
3da2cc32
DS
7440 if (ecommunity)
7441 ecommunity_free(&ecommunity);
dd18c5a9
DS
7442 if (lcommunity)
7443 lcommunity_free(&lcommunity);
eaaf8adb
DS
7444
7445 return;
7446 }
7447
7448 /*
7449 * Mark the old as unusable
7450 */
40381db7 7451 if (pi)
9bcb3eef 7452 bgp_path_info_delete(dest, pi);
eaaf8adb 7453
20894f50
DA
7454 attr = bgp_attr_aggregate_intern(
7455 bgp, origin, aspath, community, ecommunity, lcommunity,
7456 aggregate, atomic_aggregate, p);
7457
7458 if (!attr) {
8c0044f3 7459 bgp_dest_unlock_node(dest);
20894f50 7460 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7461 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7462 zlog_debug("%s: %pFX null attribute", __func__,
7463 p);
20894f50
DA
7464 return;
7465 }
7466
3da2cc32 7467 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7468 bgp->peer_self, attr, dest);
20894f50 7469
1defdda8 7470 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7471
9bcb3eef
DS
7472 bgp_path_info_add(dest, new);
7473 bgp_process(bgp, dest, afi, safi);
c701010e 7474 } else {
6aabb15d 7475 uninstall_aggregate_route:
6f94b685 7476 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7477 if (pi->peer == bgp->peer_self
7478 && pi->type == ZEBRA_ROUTE_BGP
7479 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7480 break;
7481
7482 /* Withdraw static BGP route from routing table. */
40381db7 7483 if (pi) {
9bcb3eef
DS
7484 bgp_path_info_delete(dest, pi);
7485 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7486 }
7487 }
7488
9bcb3eef 7489 bgp_dest_unlock_node(dest);
c701010e
DS
7490}
7491
6aabb15d
RZ
7492/**
7493 * Check if the current path has different MED than other known paths.
7494 *
7495 * \returns `true` if the MED matched the others else `false`.
7496 */
7497static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7498 struct bgp *bgp, struct bgp_path_info *pi)
7499{
7500 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7501
7502 /* This is the first route being analyzed. */
7503 if (!aggregate->med_initialized) {
7504 aggregate->med_initialized = true;
7505 aggregate->med_mismatched = false;
7506 aggregate->med_matched_value = cur_med;
7507 } else {
7508 /* Check if routes with different MED showed up. */
7509 if (cur_med != aggregate->med_matched_value)
7510 aggregate->med_mismatched = true;
7511 }
7512
7513 return !aggregate->med_mismatched;
7514}
7515
7516/**
7517 * Initializes and tests all routes in the aggregate address path for MED
7518 * values.
7519 *
7520 * \returns `true` if all MEDs are the same otherwise `false`.
7521 */
7522static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7523 struct bgp *bgp, const struct prefix *p,
7524 afi_t afi, safi_t safi)
7525{
7526 struct bgp_table *table = bgp->rib[afi][safi];
7527 const struct prefix *dest_p;
7528 struct bgp_dest *dest, *top;
7529 struct bgp_path_info *pi;
7530 bool med_matched = true;
7531
7532 aggregate->med_initialized = false;
7533
7534 top = bgp_node_get(table, p);
7535 for (dest = bgp_node_get(table, p); dest;
7536 dest = bgp_route_next_until(dest, top)) {
7537 dest_p = bgp_dest_get_prefix(dest);
7538 if (dest_p->prefixlen <= p->prefixlen)
7539 continue;
7540
7541 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7542 if (BGP_PATH_HOLDDOWN(pi))
7543 continue;
7544 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7545 continue;
7546 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7547 med_matched = false;
7548 break;
7549 }
7550 }
7551 if (!med_matched)
7552 break;
7553 }
7554 bgp_dest_unlock_node(top);
7555
7556 return med_matched;
7557}
7558
7559/**
7560 * Toggles the route suppression status for this aggregate address
7561 * configuration.
7562 */
4056a5f6
RZ
7563void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7564 struct bgp *bgp, const struct prefix *p,
7565 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7566{
7567 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7568 const struct prefix *dest_p;
7569 struct bgp_dest *dest, *top;
7570 struct bgp_path_info *pi;
7571 bool toggle_suppression;
7572
7573 /* We've found a different MED we must revert any suppressed routes. */
7574 top = bgp_node_get(table, p);
7575 for (dest = bgp_node_get(table, p); dest;
7576 dest = bgp_route_next_until(dest, top)) {
7577 dest_p = bgp_dest_get_prefix(dest);
7578 if (dest_p->prefixlen <= p->prefixlen)
7579 continue;
7580
7581 toggle_suppression = false;
7582 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7583 if (BGP_PATH_HOLDDOWN(pi))
7584 continue;
7585 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7586 continue;
7587
6aabb15d
RZ
7588 /* We are toggling suppression back. */
7589 if (suppress) {
6aabb15d 7590 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7591 if (aggr_suppress_path(aggregate, pi))
7592 toggle_suppression = true;
6aabb15d
RZ
7593 continue;
7594 }
7595
6aabb15d 7596 /* Install route if there is no more suppression. */
4056a5f6 7597 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7598 toggle_suppression = true;
6aabb15d
RZ
7599 }
7600
7601 if (toggle_suppression)
7602 bgp_process(bgp, dest, afi, safi);
7603 }
7604 bgp_dest_unlock_node(top);
7605}
7606
7607/**
7608 * Aggregate address MED matching incremental test: this function is called
7609 * when the initial aggregation occurred and we are only testing a single
7610 * new path.
7611 *
7612 * In addition to testing and setting the MED validity it also installs back
7613 * suppressed routes (if summary is configured).
7614 *
7615 * Must not be called in `bgp_aggregate_route`.
7616 */
7617static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7618 struct bgp *bgp, const struct prefix *p,
7619 afi_t afi, safi_t safi,
f66624f5 7620 struct bgp_path_info *pi)
6aabb15d
RZ
7621{
7622 /* MED matching disabled. */
7623 if (!aggregate->match_med)
7624 return;
7625
f66624f5
DA
7626 /* Aggregation with different MED, recheck if we have got equal MEDs
7627 * now.
6aabb15d 7628 */
f66624f5
DA
7629 if (aggregate->med_mismatched &&
7630 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7631 aggregate->summary_only)
7632 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7633 true);
7634 else
6aabb15d
RZ
7635 bgp_aggregate_med_match(aggregate, bgp, pi);
7636
7637 /* No mismatches, just quit. */
7638 if (!aggregate->med_mismatched)
7639 return;
7640
7641 /* Route summarization is disabled. */
7642 if (!aggregate->summary_only)
7643 return;
7644
7645 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7646}
7647
b5d58c32 7648/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7649void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7650 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7651{
7652 struct bgp_table *table;
9bcb3eef
DS
7653 struct bgp_dest *top;
7654 struct bgp_dest *dest;
d7c0a89a 7655 uint8_t origin;
d62a17ae 7656 struct aspath *aspath = NULL;
d62a17ae 7657 struct community *community = NULL;
3da2cc32 7658 struct ecommunity *ecommunity = NULL;
dd18c5a9 7659 struct lcommunity *lcommunity = NULL;
40381db7 7660 struct bgp_path_info *pi;
d62a17ae 7661 unsigned long match = 0;
d7c0a89a 7662 uint8_t atomic_aggregate = 0;
d62a17ae 7663
9f822fa2
S
7664 /* If the bgp instance is being deleted or self peer is deleted
7665 * then do not create aggregate route
7666 */
69a9680a
DA
7667 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
7668 (bgp->peer_self == NULL)) {
7669 bgp_aggregate_free(aggregate);
9f822fa2 7670 return;
69a9680a 7671 }
9f822fa2 7672
6aabb15d
RZ
7673 /* Initialize and test routes for MED difference. */
7674 if (aggregate->match_med)
7675 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7676
4056a5f6
RZ
7677 /*
7678 * Reset aggregate count: we might've been called from route map
7679 * update so in that case we must retest all more specific routes.
7680 *
7681 * \see `bgp_route_map_process_update`.
7682 */
7683 aggregate->count = 0;
7684 aggregate->incomplete_origin_count = 0;
7685 aggregate->incomplete_origin_count = 0;
7686 aggregate->egp_origin_count = 0;
7687
d62a17ae 7688 /* ORIGIN attribute: If at least one route among routes that are
7689 aggregated has ORIGIN with the value INCOMPLETE, then the
7690 aggregated route must have the ORIGIN attribute with the value
7691 INCOMPLETE. Otherwise, if at least one route among routes that
7692 are aggregated has ORIGIN with the value EGP, then the aggregated
7693 route must have the origin attribute with the value EGP. In all
7694 other case the value of the ORIGIN attribute of the aggregated
7695 route is INTERNAL. */
7696 origin = BGP_ORIGIN_IGP;
718e3744 7697
d62a17ae 7698 table = bgp->rib[afi][safi];
718e3744 7699
d62a17ae 7700 top = bgp_node_get(table, p);
9bcb3eef
DS
7701 for (dest = bgp_node_get(table, p); dest;
7702 dest = bgp_route_next_until(dest, top)) {
7703 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7704
9bcb3eef 7705 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7706 continue;
d62a17ae 7707
a77e2f4b
S
7708 /* If suppress fib is enabled and route not installed
7709 * in FIB, skip the route
7710 */
7711 if (!bgp_check_advertise(bgp, dest))
7712 continue;
7713
c2ff8b3e 7714 match = 0;
d62a17ae 7715
9bcb3eef 7716 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7717 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7718 continue;
718e3744 7719
40381db7 7720 if (pi->attr->flag
c2ff8b3e
DS
7721 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7722 atomic_aggregate = 1;
d62a17ae 7723
40381db7 7724 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7725 continue;
d62a17ae 7726
f273fef1
DS
7727 /*
7728 * summary-only aggregate route suppress
7729 * aggregated route announcements.
6aabb15d
RZ
7730 *
7731 * MED matching:
7732 * Don't create summaries if MED didn't match
7733 * otherwise neither the specific routes and the
7734 * aggregation will be announced.
f273fef1 7735 */
6aabb15d
RZ
7736 if (aggregate->summary_only
7737 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7738 if (aggr_suppress_path(aggregate, pi))
7739 match++;
d62a17ae 7740 }
c2ff8b3e 7741
365ab2e7
RZ
7742 /*
7743 * Suppress more specific routes that match the route
7744 * map results.
7745 *
7746 * MED matching:
7747 * Don't suppress routes if MED matching is enabled and
7748 * it mismatched otherwise we might end up with no
7749 * routes for this path.
7750 */
7751 if (aggregate->suppress_map_name
7752 && AGGREGATE_MED_VALID(aggregate)
7753 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7754 if (aggr_suppress_path(aggregate, pi))
7755 match++;
d62a17ae 7756 }
c2ff8b3e
DS
7757
7758 aggregate->count++;
7759
f273fef1
DS
7760 /*
7761 * If at least one route among routes that are
7762 * aggregated has ORIGIN with the value INCOMPLETE,
7763 * then the aggregated route MUST have the ORIGIN
7764 * attribute with the value INCOMPLETE. Otherwise, if
7765 * at least one route among routes that are aggregated
7766 * has ORIGIN with the value EGP, then the aggregated
7767 * route MUST have the ORIGIN attribute with the value
7768 * EGP.
7769 */
fc968841
NT
7770 switch (pi->attr->origin) {
7771 case BGP_ORIGIN_INCOMPLETE:
7772 aggregate->incomplete_origin_count++;
7773 break;
7774 case BGP_ORIGIN_EGP:
7775 aggregate->egp_origin_count++;
7776 break;
7777 default:
7778 /*Do nothing.
7779 */
7780 break;
7781 }
c2ff8b3e
DS
7782
7783 if (!aggregate->as_set)
7784 continue;
7785
f273fef1
DS
7786 /*
7787 * as-set aggregate route generate origin, as path,
7788 * and community aggregation.
7789 */
fc968841
NT
7790 /* Compute aggregate route's as-path.
7791 */
ef51a7d8 7792 bgp_compute_aggregate_aspath_hash(aggregate,
7793 pi->attr->aspath);
c2ff8b3e 7794
fc968841
NT
7795 /* Compute aggregate route's community.
7796 */
9a706b42 7797 if (bgp_attr_get_community(pi->attr))
21fec674 7798 bgp_compute_aggregate_community_hash(
9a706b42
DA
7799 aggregate,
7800 bgp_attr_get_community(pi->attr));
dd18c5a9 7801
fc968841
NT
7802 /* Compute aggregate route's extended community.
7803 */
b53e67a3 7804 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7805 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7806 aggregate,
7807 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7808
7809 /* Compute aggregate route's large community.
7810 */
1bcf3a96 7811 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7812 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7813 aggregate,
7814 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7815 }
c2ff8b3e 7816 if (match)
9bcb3eef 7817 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7818 }
21fec674 7819 if (aggregate->as_set) {
ef51a7d8 7820 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7821 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7822 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7823 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7824 }
7825
f1eb1f05 7826
9bcb3eef 7827 bgp_dest_unlock_node(top);
718e3744 7828
718e3744 7829
fc968841
NT
7830 if (aggregate->incomplete_origin_count > 0)
7831 origin = BGP_ORIGIN_INCOMPLETE;
7832 else if (aggregate->egp_origin_count > 0)
7833 origin = BGP_ORIGIN_EGP;
d62a17ae 7834
229757f1
DA
7835 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7836 origin = aggregate->origin;
7837
fc968841
NT
7838 if (aggregate->as_set) {
7839 if (aggregate->aspath)
7840 /* Retrieve aggregate route's as-path.
7841 */
7842 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7843
fc968841
NT
7844 if (aggregate->community)
7845 /* Retrieve aggregate route's community.
7846 */
7847 community = community_dup(aggregate->community);
3da2cc32 7848
fc968841
NT
7849 if (aggregate->ecommunity)
7850 /* Retrieve aggregate route's ecommunity.
7851 */
7852 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7853
fc968841
NT
7854 if (aggregate->lcommunity)
7855 /* Retrieve aggregate route's lcommunity.
7856 */
7857 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7858 }
718e3744 7859
c701010e 7860 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7861 ecommunity, lcommunity, atomic_aggregate,
7862 aggregate);
718e3744 7863}
7864
5f040085
DS
7865void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7866 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7867{
7868 struct bgp_table *table;
9bcb3eef
DS
7869 struct bgp_dest *top;
7870 struct bgp_dest *dest;
40381db7 7871 struct bgp_path_info *pi;
3b7db173
DS
7872 unsigned long match;
7873
7874 table = bgp->rib[afi][safi];
7875
7876 /* If routes exists below this node, generate aggregate routes. */
7877 top = bgp_node_get(table, p);
9bcb3eef
DS
7878 for (dest = bgp_node_get(table, p); dest;
7879 dest = bgp_route_next_until(dest, top)) {
7880 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7881
9bcb3eef 7882 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7883 continue;
7884 match = 0;
7885
9bcb3eef 7886 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7887 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7888 continue;
7889
40381db7 7890 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7891 continue;
7892
92b175bd
RZ
7893 /*
7894 * This route is suppressed: attempt to unsuppress it.
7895 *
7896 * `aggr_unsuppress_path` will fail if this particular
7897 * aggregate route was not the suppressor.
7898 */
7899 if (pi->extra && pi->extra->aggr_suppressors &&
7900 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7901 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7902 match++;
3b7db173 7903 }
365ab2e7 7904
3b7db173 7905 aggregate->count--;
fc968841
NT
7906
7907 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7908 aggregate->incomplete_origin_count--;
7909 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7910 aggregate->egp_origin_count--;
7911
7912 if (aggregate->as_set) {
7913 /* Remove as-path from aggregate.
7914 */
ef51a7d8 7915 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7916 aggregate,
7917 pi->attr->aspath);
7918
9a706b42 7919 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7920 /* Remove community from aggregate.
7921 */
21fec674 7922 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7923 aggregate,
7924 bgp_attr_get_community(
7925 pi->attr));
fc968841 7926
b53e67a3 7927 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7928 /* Remove ecommunity from aggregate.
7929 */
4edd83f9 7930 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7931 aggregate,
7932 bgp_attr_get_ecommunity(
7933 pi->attr));
fc968841 7934
1bcf3a96 7935 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7936 /* Remove lcommunity from aggregate.
7937 */
f1eb1f05 7938 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7939 aggregate,
7940 bgp_attr_get_lcommunity(
7941 pi->attr));
fc968841 7942 }
3b7db173
DS
7943 }
7944
7945 /* If this node was suppressed, process the change. */
7946 if (match)
9bcb3eef 7947 bgp_process(bgp, dest, afi, safi);
3b7db173 7948 }
f1eb1f05 7949 if (aggregate->as_set) {
ef51a7d8 7950 aspath_free(aggregate->aspath);
7951 aggregate->aspath = NULL;
21fec674 7952 if (aggregate->community)
7953 community_free(&aggregate->community);
4edd83f9 7954 if (aggregate->ecommunity)
7955 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7956 if (aggregate->lcommunity)
7957 lcommunity_free(&aggregate->lcommunity);
7958 }
7959
9bcb3eef 7960 bgp_dest_unlock_node(top);
3b7db173 7961}
718e3744 7962
5f040085
DS
7963static void bgp_add_route_to_aggregate(struct bgp *bgp,
7964 const struct prefix *aggr_p,
fc968841
NT
7965 struct bgp_path_info *pinew, afi_t afi,
7966 safi_t safi,
7967 struct bgp_aggregate *aggregate)
7968{
7969 uint8_t origin;
7970 struct aspath *aspath = NULL;
7971 uint8_t atomic_aggregate = 0;
7972 struct community *community = NULL;
7973 struct ecommunity *ecommunity = NULL;
7974 struct lcommunity *lcommunity = NULL;
7975
a4559740 7976 /* If the bgp instance is being deleted or self peer is deleted
7977 * then do not create aggregate route
7978 */
7979 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7980 || (bgp->peer_self == NULL))
7981 return;
7982
fc968841
NT
7983 /* ORIGIN attribute: If at least one route among routes that are
7984 * aggregated has ORIGIN with the value INCOMPLETE, then the
7985 * aggregated route must have the ORIGIN attribute with the value
7986 * INCOMPLETE. Otherwise, if at least one route among routes that
7987 * are aggregated has ORIGIN with the value EGP, then the aggregated
7988 * route must have the origin attribute with the value EGP. In all
7989 * other case the value of the ORIGIN attribute of the aggregated
7990 * route is INTERNAL.
7991 */
7992 origin = BGP_ORIGIN_IGP;
7993
7994 aggregate->count++;
7995
6aabb15d
RZ
7996 /*
7997 * This must be called before `summary` check to avoid
7998 * "suppressing" twice.
7999 */
8000 if (aggregate->match_med)
8001 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8002 pinew);
6aabb15d
RZ
8003
8004 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8005 aggr_suppress_path(aggregate, pinew);
fc968841 8006
365ab2e7
RZ
8007 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8008 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8009 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8010
8011 switch (pinew->attr->origin) {
8012 case BGP_ORIGIN_INCOMPLETE:
8013 aggregate->incomplete_origin_count++;
8014 break;
8015 case BGP_ORIGIN_EGP:
8016 aggregate->egp_origin_count++;
8017 break;
8018 default:
8019 /* Do nothing.
8020 */
8021 break;
8022 }
8023
8024 if (aggregate->incomplete_origin_count > 0)
8025 origin = BGP_ORIGIN_INCOMPLETE;
8026 else if (aggregate->egp_origin_count > 0)
8027 origin = BGP_ORIGIN_EGP;
8028
229757f1
DA
8029 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8030 origin = aggregate->origin;
8031
fc968841
NT
8032 if (aggregate->as_set) {
8033 /* Compute aggregate route's as-path.
8034 */
8035 bgp_compute_aggregate_aspath(aggregate,
8036 pinew->attr->aspath);
8037
8038 /* Compute aggregate route's community.
8039 */
9a706b42 8040 if (bgp_attr_get_community(pinew->attr))
fc968841 8041 bgp_compute_aggregate_community(
9a706b42 8042 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8043
8044 /* Compute aggregate route's extended community.
8045 */
b53e67a3 8046 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8047 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8048 aggregate,
8049 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8050
8051 /* Compute aggregate route's large community.
8052 */
1bcf3a96 8053 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8054 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8055 aggregate,
8056 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8057
8058 /* Retrieve aggregate route's as-path.
8059 */
8060 if (aggregate->aspath)
8061 aspath = aspath_dup(aggregate->aspath);
8062
8063 /* Retrieve aggregate route's community.
8064 */
8065 if (aggregate->community)
8066 community = community_dup(aggregate->community);
8067
8068 /* Retrieve aggregate route's ecommunity.
8069 */
8070 if (aggregate->ecommunity)
8071 ecommunity = ecommunity_dup(aggregate->ecommunity);
8072
8073 /* Retrieve aggregate route's lcommunity.
8074 */
8075 if (aggregate->lcommunity)
8076 lcommunity = lcommunity_dup(aggregate->lcommunity);
8077 }
8078
8079 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8080 aspath, community, ecommunity,
8081 lcommunity, atomic_aggregate, aggregate);
8082}
8083
8084static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8085 safi_t safi,
8086 struct bgp_path_info *pi,
8087 struct bgp_aggregate *aggregate,
5f040085 8088 const struct prefix *aggr_p)
fc968841
NT
8089{
8090 uint8_t origin;
8091 struct aspath *aspath = NULL;
8092 uint8_t atomic_aggregate = 0;
8093 struct community *community = NULL;
8094 struct ecommunity *ecommunity = NULL;
8095 struct lcommunity *lcommunity = NULL;
8096 unsigned long match = 0;
8097
a4559740 8098 /* If the bgp instance is being deleted or self peer is deleted
8099 * then do not create aggregate route
8100 */
8101 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8102 || (bgp->peer_self == NULL))
8103 return;
8104
fc968841
NT
8105 if (BGP_PATH_HOLDDOWN(pi))
8106 return;
8107
8108 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8109 return;
8110
4056a5f6
RZ
8111 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8112 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8113 match++;
fc968841 8114
365ab2e7 8115 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8116 && aggr_suppress_map_test(bgp, aggregate, pi))
8117 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8118 match++;
fc968841 8119
6aabb15d 8120 /*
365ab2e7 8121 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8122 * "unsuppressing" twice.
8123 */
8124 if (aggregate->match_med)
f66624f5 8125 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8126
fc968841
NT
8127 if (aggregate->count > 0)
8128 aggregate->count--;
8129
8130 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8131 aggregate->incomplete_origin_count--;
8132 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8133 aggregate->egp_origin_count--;
8134
8135 if (aggregate->as_set) {
8136 /* Remove as-path from aggregate.
8137 */
8138 bgp_remove_aspath_from_aggregate(aggregate,
8139 pi->attr->aspath);
8140
9a706b42 8141 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8142 /* Remove community from aggregate.
8143 */
8144 bgp_remove_community_from_aggregate(
9a706b42 8145 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8146
b53e67a3 8147 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8148 /* Remove ecommunity from aggregate.
8149 */
8150 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8151 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8152
1bcf3a96 8153 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8154 /* Remove lcommunity from aggregate.
8155 */
8156 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8157 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8158 }
8159
8160 /* If this node was suppressed, process the change. */
8161 if (match)
8162 bgp_process(bgp, pi->net, afi, safi);
8163
8164 origin = BGP_ORIGIN_IGP;
8165 if (aggregate->incomplete_origin_count > 0)
8166 origin = BGP_ORIGIN_INCOMPLETE;
8167 else if (aggregate->egp_origin_count > 0)
8168 origin = BGP_ORIGIN_EGP;
8169
229757f1
DA
8170 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8171 origin = aggregate->origin;
8172
fc968841
NT
8173 if (aggregate->as_set) {
8174 /* Retrieve aggregate route's as-path.
8175 */
8176 if (aggregate->aspath)
8177 aspath = aspath_dup(aggregate->aspath);
8178
8179 /* Retrieve aggregate route's community.
8180 */
8181 if (aggregate->community)
8182 community = community_dup(aggregate->community);
8183
8184 /* Retrieve aggregate route's ecommunity.
8185 */
8186 if (aggregate->ecommunity)
8187 ecommunity = ecommunity_dup(aggregate->ecommunity);
8188
8189 /* Retrieve aggregate route's lcommunity.
8190 */
8191 if (aggregate->lcommunity)
8192 lcommunity = lcommunity_dup(aggregate->lcommunity);
8193 }
8194
8195 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8196 aspath, community, ecommunity,
8197 lcommunity, atomic_aggregate, aggregate);
8198}
8199
5a1ae2c2 8200void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8201 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8202{
9bcb3eef
DS
8203 struct bgp_dest *child;
8204 struct bgp_dest *dest;
d62a17ae 8205 struct bgp_aggregate *aggregate;
8206 struct bgp_table *table;
718e3744 8207
d62a17ae 8208 table = bgp->aggregate[afi][safi];
f018db83 8209
d62a17ae 8210 /* No aggregates configured. */
8211 if (bgp_table_top_nolock(table) == NULL)
8212 return;
f018db83 8213
d62a17ae 8214 if (p->prefixlen == 0)
8215 return;
718e3744 8216
40381db7 8217 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8218 return;
718e3744 8219
a77e2f4b
S
8220 /* If suppress fib is enabled and route not installed
8221 * in FIB, do not update the aggregate route
8222 */
8223 if (!bgp_check_advertise(bgp, pi->net))
8224 return;
8225
d62a17ae 8226 child = bgp_node_get(table, p);
718e3744 8227
d62a17ae 8228 /* Aggregate address configuration check. */
9bcb3eef
DS
8229 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8230 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8231
9bcb3eef
DS
8232 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8233 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8234 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8235 aggregate);
d62a17ae 8236 }
b1e62edd 8237 }
9bcb3eef 8238 bgp_dest_unlock_node(child);
718e3744 8239}
8240
5a1ae2c2 8241void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8242 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8243{
9bcb3eef
DS
8244 struct bgp_dest *child;
8245 struct bgp_dest *dest;
d62a17ae 8246 struct bgp_aggregate *aggregate;
8247 struct bgp_table *table;
718e3744 8248
d62a17ae 8249 table = bgp->aggregate[afi][safi];
718e3744 8250
d62a17ae 8251 /* No aggregates configured. */
8252 if (bgp_table_top_nolock(table) == NULL)
8253 return;
718e3744 8254
d62a17ae 8255 if (p->prefixlen == 0)
8256 return;
718e3744 8257
d62a17ae 8258 child = bgp_node_get(table, p);
718e3744 8259
d62a17ae 8260 /* Aggregate address configuration check. */
9bcb3eef
DS
8261 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8262 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8263
9bcb3eef
DS
8264 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8265 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8266 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8267 aggregate, dest_p);
d62a17ae 8268 }
b1e62edd 8269 }
9bcb3eef 8270 bgp_dest_unlock_node(child);
d62a17ae 8271}
718e3744 8272
718e3744 8273/* Aggregate route attribute. */
8274#define AGGREGATE_SUMMARY_ONLY 1
8275#define AGGREGATE_AS_SET 1
fb29348a 8276#define AGGREGATE_AS_UNSET 0
718e3744 8277
229757f1
DA
8278static const char *bgp_origin2str(uint8_t origin)
8279{
8280 switch (origin) {
8281 case BGP_ORIGIN_IGP:
8282 return "igp";
8283 case BGP_ORIGIN_EGP:
8284 return "egp";
8285 case BGP_ORIGIN_INCOMPLETE:
8286 return "incomplete";
8287 }
8288 return "n/a";
8289}
8290
fdeb5a81 8291static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8292{
8293 switch (v_state) {
fdeb5a81
DS
8294 case RPKI_NOT_BEING_USED:
8295 return "not used";
8296 case RPKI_VALID:
b5b99af8 8297 return "valid";
fdeb5a81 8298 case RPKI_NOTFOUND:
b5b99af8 8299 return "not found";
fdeb5a81 8300 case RPKI_INVALID:
b5b99af8 8301 return "invalid";
b5b99af8 8302 }
fdeb5a81
DS
8303
8304 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8305 return "ERROR";
8306}
8307
585f1adc
IR
8308static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8309 afi_t afi, safi_t safi)
718e3744 8310{
585f1adc
IR
8311 VTY_DECLVAR_CONTEXT(bgp, bgp);
8312 int ret;
8313 struct prefix p;
9bcb3eef 8314 struct bgp_dest *dest;
d62a17ae 8315 struct bgp_aggregate *aggregate;
718e3744 8316
585f1adc
IR
8317 /* Convert string to prefix structure. */
8318 ret = str2prefix(prefix_str, &p);
8319 if (!ret) {
8320 vty_out(vty, "Malformed prefix\n");
8321 return CMD_WARNING_CONFIG_FAILED;
8322 }
8323 apply_mask(&p);
a4559740 8324
d62a17ae 8325 /* Old configuration check. */
585f1adc 8326 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8327 if (!dest) {
585f1adc
IR
8328 vty_out(vty,
8329 "%% There is no aggregate-address configuration.\n");
8330 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8331 }
f6269b4f 8332
9bcb3eef 8333 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8334 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8335 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8336 NULL, NULL, 0, aggregate);
d62a17ae 8337
8338 /* Unlock aggregate address configuration. */
9bcb3eef 8339 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8340
8341 if (aggregate->community)
8342 community_free(&aggregate->community);
8343
8344 if (aggregate->community_hash) {
8345 /* Delete all communities in the hash.
8346 */
8347 hash_clean(aggregate->community_hash,
8348 bgp_aggr_community_remove);
8349 /* Free up the community_hash.
8350 */
8351 hash_free(aggregate->community_hash);
8352 }
8353
8354 if (aggregate->ecommunity)
8355 ecommunity_free(&aggregate->ecommunity);
8356
8357 if (aggregate->ecommunity_hash) {
8358 /* Delete all ecommunities in the hash.
8359 */
8360 hash_clean(aggregate->ecommunity_hash,
8361 bgp_aggr_ecommunity_remove);
8362 /* Free up the ecommunity_hash.
8363 */
8364 hash_free(aggregate->ecommunity_hash);
8365 }
8366
8367 if (aggregate->lcommunity)
8368 lcommunity_free(&aggregate->lcommunity);
8369
8370 if (aggregate->lcommunity_hash) {
8371 /* Delete all lcommunities in the hash.
8372 */
8373 hash_clean(aggregate->lcommunity_hash,
8374 bgp_aggr_lcommunity_remove);
8375 /* Free up the lcommunity_hash.
8376 */
8377 hash_free(aggregate->lcommunity_hash);
8378 }
8379
8380 if (aggregate->aspath)
8381 aspath_free(aggregate->aspath);
8382
8383 if (aggregate->aspath_hash) {
8384 /* Delete all as-paths in the hash.
8385 */
8386 hash_clean(aggregate->aspath_hash,
8387 bgp_aggr_aspath_remove);
8388 /* Free up the aspath_hash.
8389 */
8390 hash_free(aggregate->aspath_hash);
8391 }
8392
d62a17ae 8393 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8394 bgp_dest_unlock_node(dest);
8395 bgp_dest_unlock_node(dest);
d62a17ae 8396
585f1adc 8397 return CMD_SUCCESS;
d62a17ae 8398}
8399
585f1adc
IR
8400static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8401 safi_t safi, const char *rmap,
8402 uint8_t summary_only, uint8_t as_set,
8403 uint8_t origin, bool match_med,
8404 const char *suppress_map)
d62a17ae 8405{
585f1adc 8406 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8407 int ret;
585f1adc 8408 struct prefix p;
9bcb3eef 8409 struct bgp_dest *dest;
d62a17ae 8410 struct bgp_aggregate *aggregate;
fb29348a 8411 uint8_t as_set_new = as_set;
d62a17ae 8412
365ab2e7 8413 if (suppress_map && summary_only) {
585f1adc 8414 vty_out(vty,
365ab2e7 8415 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8416 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8417 }
8418
585f1adc
IR
8419 /* Convert string to prefix structure. */
8420 ret = str2prefix(prefix_str, &p);
8421 if (!ret) {
8422 vty_out(vty, "Malformed prefix\n");
8423 return CMD_WARNING_CONFIG_FAILED;
8424 }
8425 apply_mask(&p);
d62a17ae 8426
585f1adc
IR
8427 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8428 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8429 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8430 prefix_str);
8431 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8432 }
8433
d62a17ae 8434 /* Old configuration check. */
585f1adc 8435 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8436 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8437
20894f50 8438 if (aggregate) {
585f1adc 8439 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8440 /* try to remove the old entry */
585f1adc 8441 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8442 if (ret) {
585f1adc 8443 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8444 bgp_dest_unlock_node(dest);
585f1adc 8445 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8446 }
8447 }
718e3744 8448
d62a17ae 8449 /* Make aggregate address structure. */
8450 aggregate = bgp_aggregate_new();
8451 aggregate->summary_only = summary_only;
6aabb15d 8452 aggregate->match_med = match_med;
fb29348a
DA
8453
8454 /* Network operators MUST NOT locally generate any new
8455 * announcements containing AS_SET or AS_CONFED_SET. If they have
8456 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8457 * SHOULD withdraw those routes and re-announce routes for the
8458 * aggregate or component prefixes (i.e., the more-specific routes
8459 * subsumed by the previously aggregated route) without AS_SET
8460 * or AS_CONFED_SET in the updates.
8461 */
7f972cd8 8462 if (bgp->reject_as_sets) {
fb29348a
DA
8463 if (as_set == AGGREGATE_AS_SET) {
8464 as_set_new = AGGREGATE_AS_UNSET;
8465 zlog_warn(
63efca0e 8466 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8467 __func__);
585f1adc 8468 vty_out(vty,
fb29348a
DA
8469 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8470 }
8471 }
8472
8473 aggregate->as_set = as_set_new;
d62a17ae 8474 aggregate->safi = safi;
229757f1
DA
8475 /* Override ORIGIN attribute if defined.
8476 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8477 * to IGP which is not what rfc4271 says.
8478 * This enables the same behavior, optionally.
8479 */
8480 aggregate->origin = origin;
20894f50
DA
8481
8482 if (rmap) {
8483 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8484 route_map_counter_decrement(aggregate->rmap.map);
8485 aggregate->rmap.name =
8486 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8487 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8488 route_map_counter_increment(aggregate->rmap.map);
8489 }
365ab2e7
RZ
8490
8491 if (suppress_map) {
8492 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8493 route_map_counter_decrement(aggregate->suppress_map);
8494
8495 aggregate->suppress_map_name =
8496 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8497 aggregate->suppress_map =
8498 route_map_lookup_by_name(aggregate->suppress_map_name);
8499 route_map_counter_increment(aggregate->suppress_map);
8500 }
8501
9bcb3eef 8502 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8503
d62a17ae 8504 /* Aggregate address insert into BGP routing table. */
585f1adc 8505 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8506
585f1adc 8507 return CMD_SUCCESS;
718e3744 8508}
8509
585f1adc
IR
8510DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8511 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8512 "as-set$as_set_s"
8513 "|summary-only$summary_only"
cacba915 8514 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8515 "|origin <egp|igp|incomplete>$origin_s"
8516 "|matching-MED-only$match_med"
cacba915 8517 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8518 "}]",
8519 NO_STR
8520 "Configure BGP aggregate entries\n"
764402fe
DA
8521 "Aggregate prefix\n"
8522 "Aggregate address\n"
8523 "Aggregate mask\n"
585f1adc
IR
8524 "Generate AS set path information\n"
8525 "Filter more specific routes from updates\n"
8526 "Apply route map to aggregate network\n"
8527 "Route map name\n"
8528 "BGP origin code\n"
8529 "Remote EGP\n"
8530 "Local IGP\n"
8531 "Unknown heritage\n"
8532 "Only aggregate routes with matching MED\n"
8533 "Suppress the selected more specific routes\n"
8534 "Route map with the route selectors\n")
8535{
8536 const char *prefix_s = NULL;
554b3b10 8537 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8538 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8539 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8540 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8541
554b3b10 8542 if (addr_str) {
7533cad7
QY
8543 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8544 sizeof(prefix_buf))
554b3b10
RZ
8545 == 0) {
8546 vty_out(vty, "%% Inconsistent address and mask\n");
8547 return CMD_WARNING_CONFIG_FAILED;
8548 }
585f1adc
IR
8549 prefix_s = prefix_buf;
8550 } else
8551 prefix_s = prefix_str;
37a87b8f 8552
585f1adc
IR
8553 if (origin_s) {
8554 if (strcmp(origin_s, "egp") == 0)
8555 origin = BGP_ORIGIN_EGP;
8556 else if (strcmp(origin_s, "igp") == 0)
8557 origin = BGP_ORIGIN_IGP;
8558 else if (strcmp(origin_s, "incomplete") == 0)
8559 origin = BGP_ORIGIN_INCOMPLETE;
8560 }
90e21f35 8561
585f1adc
IR
8562 if (as_set_s)
8563 as_set = AGGREGATE_AS_SET;
554b3b10 8564
585f1adc 8565 /* Handle configuration removal, otherwise installation. */
554b3b10 8566 if (no)
585f1adc
IR
8567 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8568
8569 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8570 summary_only != NULL, as_set, origin,
8571 match_med != NULL, suppress_map);
8572}
8573
8574DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8575 "[no] aggregate-address X:X::X:X/M$prefix [{"
8576 "as-set$as_set_s"
8577 "|summary-only$summary_only"
cacba915 8578 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8579 "|origin <egp|igp|incomplete>$origin_s"
8580 "|matching-MED-only$match_med"
cacba915 8581 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8582 "}]",
8583 NO_STR
8584 "Configure BGP aggregate entries\n"
8585 "Aggregate prefix\n"
8586 "Generate AS set path information\n"
8587 "Filter more specific routes from updates\n"
8588 "Apply route map to aggregate network\n"
8589 "Route map name\n"
8590 "BGP origin code\n"
8591 "Remote EGP\n"
8592 "Local IGP\n"
8593 "Unknown heritage\n"
8594 "Only aggregate routes with matching MED\n"
8595 "Suppress the selected more specific routes\n"
8596 "Route map with the route selectors\n")
8597{
8598 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8599 int as_set = AGGREGATE_AS_UNSET;
8600
8601 if (origin_s) {
8602 if (strcmp(origin_s, "egp") == 0)
8603 origin = BGP_ORIGIN_EGP;
8604 else if (strcmp(origin_s, "igp") == 0)
8605 origin = BGP_ORIGIN_IGP;
8606 else if (strcmp(origin_s, "incomplete") == 0)
8607 origin = BGP_ORIGIN_INCOMPLETE;
8608 }
8609
8610 if (as_set_s)
8611 as_set = AGGREGATE_AS_SET;
8612
8613 /* Handle configuration removal, otherwise installation. */
554b3b10 8614 if (no)
585f1adc
IR
8615 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8616 SAFI_UNICAST);
554b3b10 8617
585f1adc
IR
8618 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8619 rmap_name, summary_only != NULL, as_set,
8620 origin, match_med != NULL, suppress_map);
718e3744 8621}
8622
718e3744 8623/* Redistribute route treatment. */
d62a17ae 8624void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8625 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8626 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8627 enum blackhole_type bhtype, uint32_t metric,
8628 uint8_t type, unsigned short instance,
8629 route_tag_t tag)
d62a17ae 8630{
4b7e6066 8631 struct bgp_path_info *new;
40381db7
DS
8632 struct bgp_path_info *bpi;
8633 struct bgp_path_info rmap_path;
9bcb3eef 8634 struct bgp_dest *bn;
d62a17ae 8635 struct attr attr;
8636 struct attr *new_attr;
8637 afi_t afi;
b68885f9 8638 route_map_result_t ret;
d62a17ae 8639 struct bgp_redist *red;
8640
8641 /* Make default attribute. */
0f05ea43 8642 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8643 /*
8644 * This must not be NULL to satisfy Coverity SA
8645 */
8646 assert(attr.aspath);
9de1f7ff 8647
a4d82a8a 8648 switch (nhtype) {
9de1f7ff 8649 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8650 switch (p->family) {
8651 case AF_INET:
8652 attr.nexthop.s_addr = INADDR_ANY;
8653 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8654 break;
8655 case AF_INET6:
8656 memset(&attr.mp_nexthop_global, 0,
8657 sizeof(attr.mp_nexthop_global));
8658 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8659 break;
8660 }
9de1f7ff
DS
8661 break;
8662 case NEXTHOP_TYPE_IPV4:
8663 case NEXTHOP_TYPE_IPV4_IFINDEX:
8664 attr.nexthop = nexthop->ipv4;
7226bc40 8665 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8666 break;
8667 case NEXTHOP_TYPE_IPV6:
8668 case NEXTHOP_TYPE_IPV6_IFINDEX:
8669 attr.mp_nexthop_global = nexthop->ipv6;
8670 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8671 break;
8672 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8673 switch (p->family) {
8674 case AF_INET:
9de1f7ff 8675 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8676 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8677 break;
8678 case AF_INET6:
9de1f7ff
DS
8679 memset(&attr.mp_nexthop_global, 0,
8680 sizeof(attr.mp_nexthop_global));
74489921 8681 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8682 break;
74489921 8683 }
0789eb69 8684 attr.bh_type = bhtype;
9de1f7ff 8685 break;
d62a17ae 8686 }
0789eb69 8687 attr.nh_type = nhtype;
74489921 8688 attr.nh_ifindex = ifindex;
f04a80a5 8689
d62a17ae 8690 attr.med = metric;
957f74c3 8691 attr.distance = distance;
d62a17ae 8692 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8693 attr.tag = tag;
718e3744 8694
97a52c82
DA
8695 if (metric)
8696 bgp_attr_set_aigp_metric(&attr, metric);
8697
d62a17ae 8698 afi = family2afi(p->family);
6aeb9e78 8699
d62a17ae 8700 red = bgp_redist_lookup(bgp, afi, type, instance);
8701 if (red) {
8702 struct attr attr_new;
718e3744 8703
d62a17ae 8704 /* Copy attribute for modification. */
6f4f49b2 8705 attr_new = attr;
718e3744 8706
97a52c82 8707 if (red->redist_metric_flag) {
d62a17ae 8708 attr_new.med = red->redist_metric;
97a52c82
DA
8709 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8710 }
718e3744 8711
d62a17ae 8712 /* Apply route-map. */
8713 if (red->rmap.name) {
6006b807 8714 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8715 rmap_path.peer = bgp->peer_self;
8716 rmap_path.attr = &attr_new;
718e3744 8717
d62a17ae 8718 SET_FLAG(bgp->peer_self->rmap_type,
8719 PEER_RMAP_TYPE_REDISTRIBUTE);
8720
1782514f 8721 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8722
8723 bgp->peer_self->rmap_type = 0;
8724
8725 if (ret == RMAP_DENYMATCH) {
8726 /* Free uninterned attribute. */
8727 bgp_attr_flush(&attr_new);
8728
8729 /* Unintern original. */
8730 aspath_unintern(&attr.aspath);
8731 bgp_redistribute_delete(bgp, p, type, instance);
8732 return;
8733 }
8734 }
8735
637e5ba4 8736 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8737 bgp_attr_add_gshut_community(&attr_new);
8738
d62a17ae 8739 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8740 SAFI_UNICAST, p, NULL);
8741
8742 new_attr = bgp_attr_intern(&attr_new);
8743
9bcb3eef 8744 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8745 if (bpi->peer == bgp->peer_self
8746 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8747 break;
8748
40381db7 8749 if (bpi) {
d62a17ae 8750 /* Ensure the (source route) type is updated. */
40381db7
DS
8751 bpi->type = type;
8752 if (attrhash_cmp(bpi->attr, new_attr)
8753 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8754 bgp_attr_unintern(&new_attr);
8755 aspath_unintern(&attr.aspath);
9bcb3eef 8756 bgp_dest_unlock_node(bn);
d62a17ae 8757 return;
8758 } else {
8759 /* The attribute is changed. */
40381db7 8760 bgp_path_info_set_flag(bn, bpi,
18ee8310 8761 BGP_PATH_ATTR_CHANGED);
d62a17ae 8762
8763 /* Rewrite BGP route information. */
40381db7
DS
8764 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8765 bgp_path_info_restore(bn, bpi);
d62a17ae 8766 else
40381db7
DS
8767 bgp_aggregate_decrement(
8768 bgp, p, bpi, afi, SAFI_UNICAST);
8769 bgp_attr_unintern(&bpi->attr);
8770 bpi->attr = new_attr;
083ec940 8771 bpi->uptime = monotime(NULL);
d62a17ae 8772
8773 /* Process change. */
40381db7 8774 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8775 SAFI_UNICAST);
8776 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8777 bgp_dest_unlock_node(bn);
d62a17ae 8778 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8779
8780 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8781 || (bgp->inst_type
8782 == BGP_INSTANCE_TYPE_DEFAULT)) {
8783
8784 vpn_leak_from_vrf_update(
40381db7 8785 bgp_get_default(), bgp, bpi);
ddb5b488 8786 }
d62a17ae 8787 return;
8788 }
8789 }
8790
8791 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8792 bgp->peer_self, new_attr, bn);
1defdda8 8793 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8794
8795 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8796 bgp_path_info_add(bn, new);
9bcb3eef 8797 bgp_dest_unlock_node(bn);
be785e35 8798 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8799 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8800
8801 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8802 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8803
8804 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8805 }
d62a17ae 8806 }
8807
8808 /* Unintern original. */
8809 aspath_unintern(&attr.aspath);
718e3744 8810}
8811
d7c0a89a
QY
8812void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8813 unsigned short instance)
718e3744 8814{
d62a17ae 8815 afi_t afi;
9bcb3eef 8816 struct bgp_dest *dest;
40381db7 8817 struct bgp_path_info *pi;
d62a17ae 8818 struct bgp_redist *red;
718e3744 8819
d62a17ae 8820 afi = family2afi(p->family);
718e3744 8821
d62a17ae 8822 red = bgp_redist_lookup(bgp, afi, type, instance);
8823 if (red) {
9bcb3eef
DS
8824 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8825 SAFI_UNICAST, p, NULL);
d62a17ae 8826
9bcb3eef 8827 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8828 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8829 break;
8830
40381db7 8831 if (pi) {
ddb5b488
PZ
8832 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8833 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8834
8835 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8836 bgp, pi);
ddb5b488 8837 }
40381db7 8838 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8839 bgp_path_info_delete(dest, pi);
8840 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8841 }
9bcb3eef 8842 bgp_dest_unlock_node(dest);
d62a17ae 8843 }
8844}
8845
8846/* Withdraw specified route type's route. */
8847void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8848 unsigned short instance)
d62a17ae 8849{
9bcb3eef 8850 struct bgp_dest *dest;
40381db7 8851 struct bgp_path_info *pi;
d62a17ae 8852 struct bgp_table *table;
8853
8854 table = bgp->rib[afi][SAFI_UNICAST];
8855
9bcb3eef
DS
8856 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8858 if (pi->peer == bgp->peer_self && pi->type == type
8859 && pi->instance == instance)
d62a17ae 8860 break;
8861
40381db7 8862 if (pi) {
ddb5b488
PZ
8863 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8864 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8865
8866 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8867 bgp, pi);
ddb5b488 8868 }
9bcb3eef 8869 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8870 pi, afi, SAFI_UNICAST);
9bcb3eef 8871 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8872 if (!CHECK_FLAG(bgp->flags,
8873 BGP_FLAG_DELETE_IN_PROGRESS))
8874 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8875 else
8876 bgp_path_info_reap(dest, pi);
d62a17ae 8877 }
718e3744 8878 }
718e3744 8879}
6b0655a2 8880
718e3744 8881/* Static function to display route. */
7d3cae70
DA
8882static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8883 struct vty *vty, json_object *json, bool wide)
718e3744 8884{
be054588 8885 int len = 0;
07380148 8886 char buf[INET6_ADDRSTRLEN];
718e3744 8887
d62a17ae 8888 if (p->family == AF_INET) {
c6462ff4 8889 if (!json) {
8228a9a7 8890 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8891 } else {
8892 json_object_string_add(json, "prefix",
8893 inet_ntop(p->family,
8894 &p->u.prefix, buf,
07380148 8895 sizeof(buf)));
c6462ff4 8896 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8897 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8898 json_object_int_add(json, "version", dest->version);
c6462ff4 8899 }
d62a17ae 8900 } else if (p->family == AF_ETHERNET) {
8228a9a7 8901 len = vty_out(vty, "%pFX", p);
b03b8898 8902 } else if (p->family == AF_EVPN) {
57f7feb6 8903 if (!json)
2dbe669b 8904 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8905 else
60466a63 8906 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8907 } else if (p->family == AF_FLOWSPEC) {
8908 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8909 json ?
8910 NLRI_STRING_FORMAT_JSON_SIMPLE :
8911 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8912 } else {
c6462ff4 8913 if (!json)
8228a9a7 8914 len = vty_out(vty, "%pFX", p);
50e05855
AD
8915 else {
8916 json_object_string_add(json, "prefix",
07380148
DA
8917 inet_ntop(p->family,
8918 &p->u.prefix, buf,
8919 sizeof(buf)));
50e05855 8920 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8921 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8922 json_object_int_add(json, "version", dest->version);
37d4e0df 8923 }
9c92b5f7 8924 }
d62a17ae 8925
9c92b5f7 8926 if (!json) {
ae248832 8927 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8928 if (len < 1)
8929 vty_out(vty, "\n%*s", 20, " ");
8930 else
8931 vty_out(vty, "%*s", len, " ");
8932 }
718e3744 8933}
8934
d62a17ae 8935enum bgp_display_type {
8936 normal_list,
718e3744 8937};
8938
1d7260a1 8939const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8940{
8941 switch (reason) {
8942 case bgp_path_selection_none:
8943 return "Nothing to Select";
8944 case bgp_path_selection_first:
8945 return "First path received";
8946 case bgp_path_selection_evpn_sticky_mac:
8947 return "EVPN Sticky Mac";
8948 case bgp_path_selection_evpn_seq:
8949 return "EVPN sequence number";
8950 case bgp_path_selection_evpn_lower_ip:
8951 return "EVPN lower IP";
8952 case bgp_path_selection_evpn_local_path:
8953 return "EVPN local ES path";
8954 case bgp_path_selection_evpn_non_proxy:
8955 return "EVPN non proxy";
8956 case bgp_path_selection_weight:
8957 return "Weight";
8958 case bgp_path_selection_local_pref:
8959 return "Local Pref";
46dbf9d0
DA
8960 case bgp_path_selection_accept_own:
8961 return "Accept Own";
bbb46eb5
DA
8962 case bgp_path_selection_local_route:
8963 return "Local Route";
97a52c82
DA
8964 case bgp_path_selection_aigp:
8965 return "AIGP";
bbb46eb5
DA
8966 case bgp_path_selection_confed_as_path:
8967 return "Confederation based AS Path";
8968 case bgp_path_selection_as_path:
8969 return "AS Path";
8970 case bgp_path_selection_origin:
8971 return "Origin";
8972 case bgp_path_selection_med:
8973 return "MED";
8974 case bgp_path_selection_peer:
8975 return "Peer Type";
8976 case bgp_path_selection_confed:
8977 return "Confed Peer Type";
8978 case bgp_path_selection_igp_metric:
8979 return "IGP Metric";
8980 case bgp_path_selection_older:
8981 return "Older Path";
8982 case bgp_path_selection_router_id:
8983 return "Router ID";
8984 case bgp_path_selection_cluster_length:
bcab253c 8985 return "Cluster length";
bbb46eb5
DA
8986 case bgp_path_selection_stale:
8987 return "Path Staleness";
8988 case bgp_path_selection_local_configured:
8989 return "Locally configured route";
8990 case bgp_path_selection_neighbor_ip:
8991 return "Neighbor IP";
8992 case bgp_path_selection_default:
8993 return "Nothing left to compare";
8994 }
8995 return "Invalid (internal error)";
8996}
8997
18ee8310 8998/* Print the short form route status for a bgp_path_info */
4b7e6066 8999static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9000 struct bgp_path_info *path,
82c298be 9001 const struct prefix *p,
d62a17ae 9002 json_object *json_path)
718e3744 9003{
82c298be
DA
9004 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9005
d62a17ae 9006 if (json_path) {
b05a1c8b 9007
d62a17ae 9008 /* Route status display. */
9b6d8fcf 9009 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9010 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9011
9b6d8fcf 9012 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9013 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9014
4056a5f6 9015 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9016 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9017
9b6d8fcf
DS
9018 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9019 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9020 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9021
d62a17ae 9022 /* Selected */
9b6d8fcf 9023 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9024 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9025
9b6d8fcf 9026 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9027 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9028
bbb46eb5 9029 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9030 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9031 json_object_string_add(json_path, "selectionReason",
9032 bgp_path_selection_reason2str(
9033 path->net->reason));
9034 }
b05a1c8b 9035
9b6d8fcf 9036 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9037 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9038
d62a17ae 9039 /* Internal route. */
9b6d8fcf
DS
9040 if ((path->peer->as)
9041 && (path->peer->as == path->peer->local_as))
d62a17ae 9042 json_object_string_add(json_path, "pathFrom",
9043 "internal");
9044 else
9045 json_object_string_add(json_path, "pathFrom",
9046 "external");
b05a1c8b 9047
d62a17ae 9048 return;
9049 }
b05a1c8b 9050
82c298be
DA
9051 /* RPKI validation state */
9052 rpki_state =
9053 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9054
9055 if (rpki_state == RPKI_VALID)
9056 vty_out(vty, "V");
9057 else if (rpki_state == RPKI_INVALID)
9058 vty_out(vty, "I");
9059 else if (rpki_state == RPKI_NOTFOUND)
9060 vty_out(vty, "N");
eaeba5e8
WM
9061 else
9062 vty_out(vty, " ");
82c298be 9063
d62a17ae 9064 /* Route status display. */
9b6d8fcf 9065 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9066 vty_out(vty, "R");
9b6d8fcf 9067 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9068 vty_out(vty, "S");
4056a5f6 9069 else if (bgp_path_suppressed(path))
d62a17ae 9070 vty_out(vty, "s");
9b6d8fcf
DS
9071 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9072 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9073 vty_out(vty, "*");
9074 else
9075 vty_out(vty, " ");
9076
9077 /* Selected */
9b6d8fcf 9078 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9079 vty_out(vty, "h");
9b6d8fcf 9080 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9081 vty_out(vty, "d");
9b6d8fcf 9082 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9083 vty_out(vty, ">");
9b6d8fcf 9084 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9085 vty_out(vty, "=");
9086 else
9087 vty_out(vty, " ");
718e3744 9088
d62a17ae 9089 /* Internal route. */
9b6d8fcf
DS
9090 if (path->peer && (path->peer->as)
9091 && (path->peer->as == path->peer->local_as))
d62a17ae 9092 vty_out(vty, "i");
9093 else
9094 vty_out(vty, " ");
b40d939b 9095}
9096
2ba93fd6
DA
9097static char *bgp_nexthop_hostname(struct peer *peer,
9098 struct bgp_nexthop_cache *bnc)
25b5da8d 9099{
892fedb6 9100 if (peer->hostname
aef999a2 9101 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9102 return peer->hostname;
9103 return NULL;
9104}
9105
b40d939b 9106/* called from terminal list command */
bd494ec5 9107void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9108 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9109 json_object *json_paths, bool wide)
d62a17ae 9110{
aef999a2 9111 int len;
515c2602 9112 struct attr *attr = path->attr;
d62a17ae 9113 json_object *json_path = NULL;
9114 json_object *json_nexthops = NULL;
9115 json_object *json_nexthop_global = NULL;
9116 json_object *json_nexthop_ll = NULL;
6f214dd3 9117 json_object *json_ext_community = NULL;
9df8b37c 9118 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9119 bool nexthop_self =
9b6d8fcf 9120 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9121 bool nexthop_othervrf = false;
43089216 9122 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9123 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9124 char *nexthop_hostname =
9125 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9126 char esi_buf[ESI_STR_LEN];
d62a17ae 9127
9128 if (json_paths)
9129 json_path = json_object_new_object();
9130
9131 /* short status lead text */
82c298be 9132 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9133
9134 if (!json_paths) {
9135 /* print prefix and mask */
9136 if (!display)
7d3cae70 9137 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9138 else
ae248832 9139 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9140 } else {
7d3cae70 9141 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9142 }
47fc97cc 9143
9df8b37c
PZ
9144 /*
9145 * If vrf id of nexthop is different from that of prefix,
9146 * set up printable string to append
9147 */
9b6d8fcf 9148 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9149 const char *self = "";
9150
9151 if (nexthop_self)
9152 self = "<";
9153
9154 nexthop_othervrf = true;
9b6d8fcf 9155 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9156
9b6d8fcf 9157 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9158 snprintf(vrf_id_str, sizeof(vrf_id_str),
9159 "@%s%s", VRFID_NONE_STR, self);
9160 else
9161 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9162 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9163
9b6d8fcf
DS
9164 if (path->extra->bgp_orig->inst_type
9165 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9166
9b6d8fcf 9167 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9168 } else {
9169 const char *self = "";
9170
9171 if (nexthop_self)
9172 self = "<";
9173
9174 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9175 }
9176
445c2480
DS
9177 /*
9178 * For ENCAP and EVPN routes, nexthop address family is not
9179 * neccessarily the same as the prefix address family.
9180 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9181 * EVPN routes are also exchanged with a MP nexthop. Currently,
9182 * this
9183 * is only IPv4, the value will be present in either
9184 * attr->nexthop or
9185 * attr->mp_nexthop_global_in
9186 */
9187 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9188 char nexthop[128];
9189 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9190
9191 switch (af) {
9192 case AF_INET:
07380148
DA
9193 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9194 &attr->mp_nexthop_global_in);
445c2480
DS
9195 break;
9196 case AF_INET6:
07380148
DA
9197 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9198 &attr->mp_nexthop_global);
445c2480
DS
9199 break;
9200 default:
772270f3 9201 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9202 break;
d62a17ae 9203 }
d62a17ae 9204
445c2480
DS
9205 if (json_paths) {
9206 json_nexthop_global = json_object_new_object();
9207
515c2602
DA
9208 json_object_string_add(json_nexthop_global, "ip",
9209 nexthop);
9210
939a97f4 9211 if (path->peer->hostname)
515c2602
DA
9212 json_object_string_add(json_nexthop_global,
9213 "hostname",
939a97f4 9214 path->peer->hostname);
515c2602
DA
9215
9216 json_object_string_add(json_nexthop_global, "afi",
9217 (af == AF_INET) ? "ipv4"
9218 : "ipv6");
445c2480
DS
9219 json_object_boolean_true_add(json_nexthop_global,
9220 "used");
aef999a2
DA
9221 } else {
9222 if (nexthop_hostname)
9223 len = vty_out(vty, "%s(%s)%s", nexthop,
9224 nexthop_hostname, vrf_id_str);
9225 else
9226 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9227
ae248832 9228 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9229 if (len < 1)
9230 vty_out(vty, "\n%*s", 36, " ");
9231 else
9232 vty_out(vty, "%*s", len, " ");
9233 }
445c2480
DS
9234 } else if (safi == SAFI_EVPN) {
9235 if (json_paths) {
9236 json_nexthop_global = json_object_new_object();
9237
c949c771 9238 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9239 "%pI4",
9240 &attr->mp_nexthop_global_in);
515c2602 9241
939a97f4 9242 if (path->peer->hostname)
515c2602
DA
9243 json_object_string_add(json_nexthop_global,
9244 "hostname",
939a97f4 9245 path->peer->hostname);
515c2602 9246
a4d82a8a
PZ
9247 json_object_string_add(json_nexthop_global, "afi",
9248 "ipv4");
445c2480
DS
9249 json_object_boolean_true_add(json_nexthop_global,
9250 "used");
aef999a2
DA
9251 } else {
9252 if (nexthop_hostname)
7226bc40
TA
9253 len = vty_out(vty, "%pI4(%s)%s",
9254 &attr->mp_nexthop_global_in,
aef999a2
DA
9255 nexthop_hostname, vrf_id_str);
9256 else
7226bc40
TA
9257 len = vty_out(vty, "%pI4%s",
9258 &attr->mp_nexthop_global_in,
aef999a2
DA
9259 vrf_id_str);
9260
ae248832 9261 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9262 if (len < 1)
9263 vty_out(vty, "\n%*s", 36, " ");
9264 else
9265 vty_out(vty, "%*s", len, " ");
9266 }
d33fc23b 9267 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9268 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9269 if (json_paths) {
9270 json_nexthop_global = json_object_new_object();
515c2602 9271
026b914a
PG
9272 json_object_string_add(json_nexthop_global,
9273 "afi", "ipv4");
c949c771
DA
9274 json_object_string_addf(json_nexthop_global,
9275 "ip", "%pI4",
9276 &attr->nexthop);
515c2602 9277
939a97f4 9278 if (path->peer->hostname)
515c2602
DA
9279 json_object_string_add(
9280 json_nexthop_global, "hostname",
939a97f4 9281 path->peer->hostname);
515c2602 9282
50e05855
AD
9283 json_object_boolean_true_add(
9284 json_nexthop_global,
026b914a
PG
9285 "used");
9286 } else {
aef999a2
DA
9287 if (nexthop_hostname)
9288 len = vty_out(vty, "%pI4(%s)%s",
9289 &attr->nexthop,
9290 nexthop_hostname,
9291 vrf_id_str);
9292 else
9293 len = vty_out(vty, "%pI4%s",
9294 &attr->nexthop,
9295 vrf_id_str);
9296
ae248832 9297 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9298 if (len < 1)
9299 vty_out(vty, "\n%*s", 36, " ");
9300 else
9301 vty_out(vty, "%*s", len, " ");
026b914a
PG
9302 }
9303 }
7226bc40 9304 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9305 if (json_paths) {
9306 json_nexthop_global = json_object_new_object();
d62a17ae 9307
c949c771
DA
9308 json_object_string_addf(json_nexthop_global, "ip",
9309 "%pI4", &attr->nexthop);
515c2602 9310
939a97f4 9311 if (path->peer->hostname)
515c2602
DA
9312 json_object_string_add(json_nexthop_global,
9313 "hostname",
939a97f4 9314 path->peer->hostname);
445c2480 9315
a4d82a8a
PZ
9316 json_object_string_add(json_nexthop_global, "afi",
9317 "ipv4");
445c2480
DS
9318 json_object_boolean_true_add(json_nexthop_global,
9319 "used");
9320 } else {
aef999a2
DA
9321 if (nexthop_hostname)
9322 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9323 nexthop_hostname, vrf_id_str);
9324 else
9325 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9326 vrf_id_str);
9df8b37c 9327
ae248832 9328 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9329 if (len < 1)
9330 vty_out(vty, "\n%*s", 36, " ");
9331 else
9332 vty_out(vty, "%*s", len, " ");
d62a17ae 9333 }
445c2480 9334 }
b05a1c8b 9335
445c2480 9336 /* IPv6 Next Hop */
7226bc40 9337 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9338 if (json_paths) {
9339 json_nexthop_global = json_object_new_object();
c949c771
DA
9340 json_object_string_addf(json_nexthop_global, "ip",
9341 "%pI6",
9342 &attr->mp_nexthop_global);
515c2602 9343
939a97f4 9344 if (path->peer->hostname)
515c2602
DA
9345 json_object_string_add(json_nexthop_global,
9346 "hostname",
939a97f4 9347 path->peer->hostname);
515c2602 9348
a4d82a8a
PZ
9349 json_object_string_add(json_nexthop_global, "afi",
9350 "ipv6");
9351 json_object_string_add(json_nexthop_global, "scope",
9352 "global");
445c2480
DS
9353
9354 /* We display both LL & GL if both have been
9355 * received */
0606039c
DA
9356 if ((attr->mp_nexthop_len
9357 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9358 || (path->peer->conf_if)) {
a4d82a8a 9359 json_nexthop_ll = json_object_new_object();
c949c771
DA
9360 json_object_string_addf(
9361 json_nexthop_ll, "ip", "%pI6",
9362 &attr->mp_nexthop_local);
515c2602 9363
939a97f4 9364 if (path->peer->hostname)
515c2602
DA
9365 json_object_string_add(
9366 json_nexthop_ll, "hostname",
939a97f4 9367 path->peer->hostname);
515c2602 9368
a4d82a8a
PZ
9369 json_object_string_add(json_nexthop_ll, "afi",
9370 "ipv6");
9371 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9372 "link-local");
d62a17ae 9373
a4d82a8a 9374 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9375 &attr->mp_nexthop_local)
9376 != 0)
9377 && !attr->mp_nexthop_prefer_global)
d62a17ae 9378 json_object_boolean_true_add(
a4d82a8a 9379 json_nexthop_ll, "used");
445c2480
DS
9380 else
9381 json_object_boolean_true_add(
a4d82a8a 9382 json_nexthop_global, "used");
445c2480
DS
9383 } else
9384 json_object_boolean_true_add(
9385 json_nexthop_global, "used");
9386 } else {
9387 /* Display LL if LL/Global both in table unless
9388 * prefer-global is set */
2bb8b49c
DS
9389 if (((attr->mp_nexthop_len
9390 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9391 && !attr->mp_nexthop_prefer_global)
9392 || (path->peer->conf_if)) {
9b6d8fcf 9393 if (path->peer->conf_if) {
a4d82a8a 9394 len = vty_out(vty, "%s",
9b6d8fcf 9395 path->peer->conf_if);
ae248832
MK
9396 /* len of IPv6 addr + max len of def
9397 * ifname */
9398 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9399
9400 if (len < 1)
a4d82a8a 9401 vty_out(vty, "\n%*s", 36, " ");
445c2480 9402 else
a4d82a8a 9403 vty_out(vty, "%*s", len, " ");
d62a17ae 9404 } else {
aef999a2
DA
9405 if (nexthop_hostname)
9406 len = vty_out(
9407 vty, "%pI6(%s)%s",
9408 &attr->mp_nexthop_local,
9409 nexthop_hostname,
9410 vrf_id_str);
9411 else
9412 len = vty_out(
9413 vty, "%pI6%s",
9414 &attr->mp_nexthop_local,
9415 vrf_id_str);
9416
ae248832 9417 len = wide ? (41 - len) : (16 - len);
d62a17ae 9418
9419 if (len < 1)
a4d82a8a 9420 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9421 else
a4d82a8a 9422 vty_out(vty, "%*s", len, " ");
d62a17ae 9423 }
445c2480 9424 } else {
aef999a2
DA
9425 if (nexthop_hostname)
9426 len = vty_out(vty, "%pI6(%s)%s",
9427 &attr->mp_nexthop_global,
9428 nexthop_hostname,
9429 vrf_id_str);
9430 else
9431 len = vty_out(vty, "%pI6%s",
9432 &attr->mp_nexthop_global,
9433 vrf_id_str);
9434
ae248832 9435 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9436
9437 if (len < 1)
9438 vty_out(vty, "\n%*s", 36, " ");
9439 else
9440 vty_out(vty, "%*s", len, " ");
d62a17ae 9441 }
9442 }
445c2480 9443 }
718e3744 9444
445c2480
DS
9445 /* MED/Metric */
9446 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9447 if (json_paths)
50e05855 9448 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9449 else if (wide)
9450 vty_out(vty, "%7u", attr->med);
0fbac0b4 9451 else
445c2480 9452 vty_out(vty, "%10u", attr->med);
ae248832
MK
9453 else if (!json_paths) {
9454 if (wide)
9455 vty_out(vty, "%*s", 7, " ");
9456 else
9457 vty_out(vty, "%*s", 10, " ");
9458 }
d62a17ae 9459
445c2480
DS
9460 /* Local Pref */
9461 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9462 if (json_paths)
50e05855 9463 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9464 attr->local_pref);
9465 else
445c2480
DS
9466 vty_out(vty, "%7u", attr->local_pref);
9467 else if (!json_paths)
9468 vty_out(vty, " ");
d62a17ae 9469
445c2480
DS
9470 if (json_paths)
9471 json_object_int_add(json_path, "weight", attr->weight);
9472 else
9473 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9474
47e12884
DA
9475 if (json_paths)
9476 json_object_string_addf(json_path, "peerId", "%pSU",
9477 &path->peer->su);
b05a1c8b 9478
445c2480
DS
9479 /* Print aspath */
9480 if (attr->aspath) {
0fbac0b4 9481 if (json_paths)
50e05855 9482 json_object_string_add(json_path, "path",
0fbac0b4
DA
9483 attr->aspath->str);
9484 else
e678b143 9485 aspath_print_vty(vty, attr->aspath);
d62a17ae 9486 }
f1aa5d8a 9487
445c2480
DS
9488 /* Print origin */
9489 if (json_paths)
a4d82a8a
PZ
9490 json_object_string_add(json_path, "origin",
9491 bgp_origin_long_str[attr->origin]);
445c2480
DS
9492 else
9493 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9494
9df8b37c 9495 if (json_paths) {
d071f237 9496 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9497 json_object_string_add(json_path, "esi",
9498 esi_to_str(&attr->esi,
9499 esi_buf, sizeof(esi_buf)));
9500 }
6f214dd3
CS
9501 if (safi == SAFI_EVPN &&
9502 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9503 json_ext_community = json_object_new_object();
b53e67a3
DA
9504 json_object_string_add(
9505 json_ext_community, "string",
9506 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9507 json_object_object_add(json_path,
9508 "extendedCommunity",
9509 json_ext_community);
9510 }
9511
9df8b37c
PZ
9512 if (nexthop_self)
9513 json_object_boolean_true_add(json_path,
9514 "announceNexthopSelf");
9515 if (nexthop_othervrf) {
9516 json_object_string_add(json_path, "nhVrfName",
9517 nexthop_vrfname);
9518
9519 json_object_int_add(json_path, "nhVrfId",
9520 ((nexthop_vrfid == VRF_UNKNOWN)
9521 ? -1
9522 : (int)nexthop_vrfid));
9523 }
9524 }
9525
d62a17ae 9526 if (json_paths) {
9527 if (json_nexthop_global || json_nexthop_ll) {
9528 json_nexthops = json_object_new_array();
f1aa5d8a 9529
d62a17ae 9530 if (json_nexthop_global)
9531 json_object_array_add(json_nexthops,
9532 json_nexthop_global);
f1aa5d8a 9533
d62a17ae 9534 if (json_nexthop_ll)
9535 json_object_array_add(json_nexthops,
9536 json_nexthop_ll);
f1aa5d8a 9537
d62a17ae 9538 json_object_object_add(json_path, "nexthops",
9539 json_nexthops);
9540 }
9541
9542 json_object_array_add(json_paths, json_path);
9543 } else {
9544 vty_out(vty, "\n");
6f214dd3 9545
b5e140c8 9546 if (safi == SAFI_EVPN) {
d071f237 9547 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9548 /* XXX - add these params to the json out */
b5e140c8 9549 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9550 vty_out(vty, "ESI:%s",
9551 esi_to_str(&attr->esi, esi_buf,
9552 sizeof(esi_buf)));
60605cbc 9553
229587fb 9554 vty_out(vty, "\n");
b5e140c8
AK
9555 }
9556 if (attr->flag &
9557 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9558 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9559 vty_out(vty, "%s\n",
9560 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9561 }
6f214dd3
CS
9562 }
9563
49e5a4a0 9564#ifdef ENABLE_BGP_VNC
d62a17ae 9565 /* prints an additional line, indented, with VNC info, if
9566 * present */
9567 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9568 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9569#endif
d62a17ae 9570 }
9571}
718e3744 9572
9573/* called from terminal list command */
7d3cae70
DA
9574void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9575 const struct prefix *p, struct attr *attr, safi_t safi,
9576 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9577{
9578 json_object *json_status = NULL;
9579 json_object *json_net = NULL;
aef999a2 9580 int len;
d62a17ae 9581 char buff[BUFSIZ];
dc387b0f 9582
d62a17ae 9583 /* Route status display. */
9584 if (use_json) {
9585 json_status = json_object_new_object();
9586 json_net = json_object_new_object();
9587 } else {
146c574b 9588 vty_out(vty, " *");
d62a17ae 9589 vty_out(vty, ">");
9590 vty_out(vty, " ");
9591 }
718e3744 9592
d62a17ae 9593 /* print prefix and mask */
50e05855 9594 if (use_json) {
dc387b0f
LK
9595 if (safi == SAFI_EVPN)
9596 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9597 else if (p->family == AF_INET || p->family == AF_INET6) {
9598 json_object_string_add(
9599 json_net, "addrPrefix",
9600 inet_ntop(p->family, &p->u.prefix, buff,
9601 BUFSIZ));
9602 json_object_int_add(json_net, "prefixLen",
9603 p->prefixlen);
67d7e256 9604 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9605 }
50e05855 9606 } else
7d3cae70 9607 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9608
9609 /* Print attribute */
9610 if (attr) {
9611 if (use_json) {
7226bc40
TA
9612 if (p->family == AF_INET &&
9613 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9614 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9615 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9616 json_object_string_addf(
9617 json_net, "nextHop", "%pI4",
9618 &attr->mp_nexthop_global_in);
d62a17ae 9619 else
c949c771
DA
9620 json_object_string_addf(
9621 json_net, "nextHop", "%pI4",
9622 &attr->nexthop);
7226bc40
TA
9623 } else if (p->family == AF_INET6 ||
9624 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9625 json_object_string_addf(
9626 json_net, "nextHopGlobal", "%pI6",
9627 &attr->mp_nexthop_global);
7226bc40
TA
9628 } else if (p->family == AF_EVPN &&
9629 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9630 json_object_string_addf(
9631 json_net, "nextHop", "%pI4",
9632 &attr->mp_nexthop_global_in);
23d0a753 9633 }
d62a17ae 9634
9635 if (attr->flag
9636 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9637 json_object_int_add(json_net, "metric",
9638 attr->med);
9639
0fbac0b4 9640 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9641 json_object_int_add(json_net, "locPrf",
0fbac0b4 9642 attr->local_pref);
d62a17ae 9643
9644 json_object_int_add(json_net, "weight", attr->weight);
9645
9646 /* Print aspath */
0fbac0b4 9647 if (attr->aspath)
50e05855 9648 json_object_string_add(json_net, "path",
0fbac0b4 9649 attr->aspath->str);
d62a17ae 9650
9651 /* Print origin */
dd426a51
DA
9652#if CONFDATE > 20231208
9653CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9654#endif
d62a17ae 9655 json_object_string_add(json_net, "bgpOriginCode",
9656 bgp_origin_str[attr->origin]);
dd426a51
DA
9657 json_object_string_add(
9658 json_net, "origin",
9659 bgp_origin_long_str[attr->origin]);
d62a17ae 9660 } else {
7226bc40
TA
9661 if (p->family == AF_INET &&
9662 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9663 safi == SAFI_EVPN ||
9664 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9665 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9666 || safi == SAFI_EVPN)
23d0a753
DA
9667 vty_out(vty, "%-16pI4",
9668 &attr->mp_nexthop_global_in);
ae248832 9669 else if (wide)
23d0a753 9670 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9671 else
23d0a753 9672 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9673 } else if (p->family == AF_INET6 ||
9674 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9675 len = vty_out(vty, "%pI6",
9676 &attr->mp_nexthop_global);
ae248832 9677 len = wide ? (41 - len) : (16 - len);
d62a17ae 9678 if (len < 1)
9679 vty_out(vty, "\n%*s", 36, " ");
9680 else
9681 vty_out(vty, "%*s", len, " ");
9682 }
9683 if (attr->flag
9684 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9685 if (wide)
9686 vty_out(vty, "%7u", attr->med);
9687 else
9688 vty_out(vty, "%10u", attr->med);
9689 else if (wide)
9690 vty_out(vty, " ");
d62a17ae 9691 else
9692 vty_out(vty, " ");
718e3744 9693
d62a17ae 9694 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9695 vty_out(vty, "%7u", attr->local_pref);
9696 else
9697 vty_out(vty, " ");
9698
9699 vty_out(vty, "%7u ", attr->weight);
9700
9701 /* Print aspath */
9702 if (attr->aspath)
e678b143 9703 aspath_print_vty(vty, attr->aspath);
d62a17ae 9704
9705 /* Print origin */
9706 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9707 }
9708 }
9709 if (use_json) {
4d65410c
DA
9710 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9711
dd426a51
DA
9712#if CONFDATE > 20231208
9713CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9714#endif
d62a17ae 9715 json_object_boolean_true_add(json_status, "*");
9716 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9717 json_object_boolean_true_add(json_net, "valid");
9718 json_object_boolean_true_add(json_net, "best");
4d65410c 9719
dd426a51 9720 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9721 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9722 json_object_boolean_true_add(json_net, "multipath");
9723 }
d62a17ae 9724 json_object_object_add(json_net, "appliedStatusSymbols",
9725 json_status);
511211bf 9726 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9727 } else
9728 vty_out(vty, "\n");
9729}
9730
bd494ec5 9731void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9732 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9733 json_object *json)
9734{
9735 json_object *json_out = NULL;
9736 struct attr *attr;
9737 mpls_label_t label = MPLS_INVALID_LABEL;
9738
9b6d8fcf 9739 if (!path->extra)
d62a17ae 9740 return;
9741
9742 if (json)
9743 json_out = json_object_new_object();
9744
9745 /* short status lead text */
82c298be 9746 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9747
9748 /* print prefix and mask */
9749 if (json == NULL) {
9750 if (!display)
7d3cae70 9751 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9752 else
9753 vty_out(vty, "%*s", 17, " ");
9754 }
9755
9756 /* Print attribute */
9b6d8fcf 9757 attr = path->attr;
7226bc40
TA
9758 if (((p->family == AF_INET) &&
9759 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9760 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9761 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9762 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9763 || safi == SAFI_EVPN) {
9764 if (json)
c949c771
DA
9765 json_object_string_addf(
9766 json_out, "mpNexthopGlobalIn", "%pI4",
9767 &attr->mp_nexthop_global_in);
05864da7 9768 else
23d0a753
DA
9769 vty_out(vty, "%-16pI4",
9770 &attr->mp_nexthop_global_in);
05864da7
DS
9771 } else {
9772 if (json)
c949c771
DA
9773 json_object_string_addf(json_out, "nexthop",
9774 "%pI4", &attr->nexthop);
05864da7 9775 else
23d0a753 9776 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9777 }
7226bc40
TA
9778 } else if (((p->family == AF_INET6) &&
9779 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9780 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9781 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9782 char buf_a[512];
9783
9784 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9785 if (json)
c949c771
DA
9786 json_object_string_addf(
9787 json_out, "mpNexthopGlobalIn", "%pI6",
9788 &attr->mp_nexthop_global);
05864da7
DS
9789 else
9790 vty_out(vty, "%s",
9791 inet_ntop(AF_INET6,
9792 &attr->mp_nexthop_global,
9793 buf_a, sizeof(buf_a)));
9794 } else if (attr->mp_nexthop_len
9795 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9796 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9797 &attr->mp_nexthop_global,
9798 &attr->mp_nexthop_local);
9799 if (json)
9800 json_object_string_add(json_out,
9801 "mpNexthopGlobalLocal",
9802 buf_a);
9803 else
9804 vty_out(vty, "%s", buf_a);
d62a17ae 9805 }
9806 }
9807
9b6d8fcf 9808 label = decode_label(&path->extra->label[0]);
d62a17ae 9809
9810 if (bgp_is_valid_label(&label)) {
9811 if (json) {
9812 json_object_int_add(json_out, "notag", label);
9813 json_object_array_add(json, json_out);
9814 } else {
9815 vty_out(vty, "notag/%d", label);
9816 vty_out(vty, "\n");
9817 }
700ddfed
PG
9818 } else if (!json)
9819 vty_out(vty, "\n");
d62a17ae 9820}
718e3744 9821
bd494ec5 9822void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9823 struct bgp_path_info *path, int display,
d62a17ae 9824 json_object *json_paths)
718e3744 9825{
d62a17ae 9826 struct attr *attr;
d62a17ae 9827 json_object *json_path = NULL;
14f51eba
LK
9828 json_object *json_nexthop = NULL;
9829 json_object *json_overlay = NULL;
856ca177 9830
9b6d8fcf 9831 if (!path->extra)
d62a17ae 9832 return;
718e3744 9833
14f51eba
LK
9834 if (json_paths) {
9835 json_path = json_object_new_object();
9836 json_overlay = json_object_new_object();
9837 json_nexthop = json_object_new_object();
9838 }
9839
d62a17ae 9840 /* short status lead text */
82c298be 9841 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9842
d62a17ae 9843 /* print prefix and mask */
9844 if (!display)
7d3cae70 9845 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9846 else
9847 vty_out(vty, "%*s", 17, " ");
9848
9849 /* Print attribute */
9b6d8fcf 9850 attr = path->attr;
05864da7 9851 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9852
05864da7
DS
9853 switch (af) {
9854 case AF_INET:
05864da7 9855 if (!json_path) {
db66cf7c 9856 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9857 } else {
db66cf7c
DA
9858 json_object_string_addf(json_nexthop, "ip", "%pI4",
9859 &attr->mp_nexthop_global_in);
14f51eba 9860
05864da7 9861 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9862
05864da7
DS
9863 json_object_object_add(json_path, "nexthop",
9864 json_nexthop);
9865 }
9866 break;
9867 case AF_INET6:
05864da7 9868 if (!json_path) {
db66cf7c
DA
9869 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9870 &attr->mp_nexthop_local);
05864da7 9871 } else {
db66cf7c
DA
9872 json_object_string_addf(json_nexthop, "ipv6Global",
9873 "%pI6",
9874 &attr->mp_nexthop_global);
14f51eba 9875
db66cf7c
DA
9876 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9877 "%pI6",
9878 &attr->mp_nexthop_local);
14f51eba 9879
05864da7 9880 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9881
05864da7
DS
9882 json_object_object_add(json_path, "nexthop",
9883 json_nexthop);
9884 }
9885 break;
9886 default:
9887 if (!json_path) {
9888 vty_out(vty, "?");
9889 } else {
77a2f8e5
DA
9890 json_object_string_add(json_nexthop, "error",
9891 "Unsupported address-family");
d62a17ae 9892 }
05864da7 9893 }
988258b4 9894
6c924775
DS
9895 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9896
05864da7 9897 if (!json_path)
db66cf7c 9898 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9899 else
db66cf7c 9900 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9901
b53e67a3 9902 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9903 char *mac = NULL;
9904 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9905 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9906 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9907
9908 if (routermac)
9909 mac = ecom_mac2str((char *)routermac->val);
9910 if (mac) {
9911 if (!json_path) {
c4efd0f4 9912 vty_out(vty, "/%s", mac);
05864da7
DS
9913 } else {
9914 json_object_string_add(json_overlay, "rmac",
9915 mac);
988258b4 9916 }
05864da7 9917 XFREE(MTYPE_TMP, mac);
988258b4 9918 }
05864da7 9919 }
718e3744 9920
05864da7
DS
9921 if (!json_path) {
9922 vty_out(vty, "\n");
9923 } else {
9924 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9925
05864da7 9926 json_object_array_add(json_paths, json_path);
14f51eba 9927 }
d62a17ae 9928}
718e3744 9929
d62a17ae 9930/* dampening route */
5f040085
DS
9931static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9932 struct bgp_path_info *path, int display,
9933 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9934 json_object *json_paths)
d62a17ae 9935{
e5be8c1d 9936 struct attr *attr = path->attr;
d62a17ae 9937 int len;
9938 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9939 json_object *json_path = NULL;
9940
9941 if (use_json)
9942 json_path = json_object_new_object();
d62a17ae 9943
9944 /* short status lead text */
e5be8c1d 9945 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9946
9947 /* print prefix and mask */
9948 if (!use_json) {
9949 if (!display)
7d3cae70 9950 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9951 else
9952 vty_out(vty, "%*s", 17, " ");
d62a17ae 9953
e5be8c1d
DA
9954 len = vty_out(vty, "%s", path->peer->host);
9955 len = 17 - len;
9956
9957 if (len < 1)
d62a17ae 9958 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9959 else
9960 vty_out(vty, "%*s", len, " ");
d62a17ae 9961
9b6d8fcf
DS
9962 vty_out(vty, "%s ",
9963 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9964 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9965 use_json, NULL));
d62a17ae 9966
e5be8c1d 9967 if (attr->aspath)
e678b143 9968 aspath_print_vty(vty, attr->aspath);
05864da7 9969
05864da7
DS
9970 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9971
d62a17ae 9972 vty_out(vty, "\n");
e5be8c1d
DA
9973 } else {
9974 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9975 safi, use_json, json_path);
9976
9977 if (attr->aspath)
9978 json_object_string_add(json_path, "asPath",
9979 attr->aspath->str);
9980
9981 json_object_string_add(json_path, "origin",
9982 bgp_origin_str[attr->origin]);
9983 json_object_string_add(json_path, "peerHost", path->peer->host);
9984
9985 json_object_array_add(json_paths, json_path);
9986 }
d62a17ae 9987}
718e3744 9988
d62a17ae 9989/* flap route */
5f040085
DS
9990static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9991 struct bgp_path_info *path, int display,
9992 afi_t afi, safi_t safi, bool use_json,
31258046 9993 json_object *json_paths)
784d3a42 9994{
31258046 9995 struct attr *attr = path->attr;
d62a17ae 9996 struct bgp_damp_info *bdi;
9997 char timebuf[BGP_UPTIME_LEN];
9998 int len;
31258046 9999 json_object *json_path = NULL;
784d3a42 10000
9b6d8fcf 10001 if (!path->extra)
d62a17ae 10002 return;
784d3a42 10003
31258046
DA
10004 if (use_json)
10005 json_path = json_object_new_object();
10006
9b6d8fcf 10007 bdi = path->extra->damp_info;
784d3a42 10008
d62a17ae 10009 /* short status lead text */
31258046 10010 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10011
d62a17ae 10012 if (!use_json) {
10013 if (!display)
7d3cae70 10014 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10015 else
10016 vty_out(vty, "%*s", 17, " ");
784d3a42 10017
31258046
DA
10018 len = vty_out(vty, "%s", path->peer->host);
10019 len = 16 - len;
10020 if (len < 1)
d62a17ae 10021 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10022 else
10023 vty_out(vty, "%*s", len, " ");
784d3a42 10024
31258046
DA
10025 len = vty_out(vty, "%d", bdi->flap);
10026 len = 5 - len;
10027 if (len < 1)
d62a17ae 10028 vty_out(vty, " ");
d62a17ae 10029 else
10030 vty_out(vty, "%*s", len, " ");
d62a17ae 10031
996c9314
LB
10032 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10033 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10034
31258046
DA
10035 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10036 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10037 vty_out(vty, "%s ",
9b6d8fcf 10038 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10039 BGP_UPTIME_LEN, afi,
31258046
DA
10040 safi, use_json, NULL));
10041 else
d62a17ae 10042 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10043
31258046 10044 if (attr->aspath)
e678b143 10045 aspath_print_vty(vty, attr->aspath);
05864da7 10046
05864da7
DS
10047 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10048
d62a17ae 10049 vty_out(vty, "\n");
31258046
DA
10050 } else {
10051 json_object_string_add(json_path, "peerHost", path->peer->host);
10052 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10053
10054 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10055 json_path);
10056
10057 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10058 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10059 bgp_damp_reuse_time_vty(vty, path, timebuf,
10060 BGP_UPTIME_LEN, afi, safi,
10061 use_json, json_path);
10062
10063 if (attr->aspath)
10064 json_object_string_add(json_path, "asPath",
10065 attr->aspath->str);
10066
10067 json_object_string_add(json_path, "origin",
10068 bgp_origin_str[attr->origin]);
10069
10070 json_object_array_add(json_paths, json_path);
10071 }
d62a17ae 10072}
10073
10074static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10075 int *first, const char *header,
10076 json_object *json_adv_to)
10077{
d62a17ae 10078 json_object *json_peer = NULL;
10079
10080 if (json_adv_to) {
10081 /* 'advertised-to' is a dictionary of peers we have advertised
10082 * this
10083 * prefix too. The key is the peer's IP or swpX, the value is
10084 * the
10085 * hostname if we know it and "" if not.
10086 */
10087 json_peer = json_object_new_object();
10088
10089 if (peer->hostname)
10090 json_object_string_add(json_peer, "hostname",
10091 peer->hostname);
10092
10093 if (peer->conf_if)
10094 json_object_object_add(json_adv_to, peer->conf_if,
10095 json_peer);
10096 else
47e12884
DA
10097 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10098 &peer->su);
d62a17ae 10099 } else {
10100 if (*first) {
10101 vty_out(vty, "%s", header);
10102 *first = 0;
10103 }
10104
10105 if (peer->hostname
892fedb6 10106 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10107 if (peer->conf_if)
10108 vty_out(vty, " %s(%s)", peer->hostname,
10109 peer->conf_if);
10110 else
47e12884
DA
10111 vty_out(vty, " %s(%pSU)", peer->hostname,
10112 &peer->su);
d62a17ae 10113 } else {
10114 if (peer->conf_if)
10115 vty_out(vty, " %s", peer->conf_if);
10116 else
47e12884 10117 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10118 }
10119 }
784d3a42
PG
10120}
10121
dcc68b5e
MS
10122static void route_vty_out_tx_ids(struct vty *vty,
10123 struct bgp_addpath_info_data *d)
10124{
10125 int i;
10126
10127 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10128 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10129 d->addpath_tx_id[i],
10130 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10131 }
10132}
10133
5e4d4c8a 10134static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10135 struct bgp_path_info *pi,
10136 struct attr *attr,
10137 json_object *json_path)
5e4d4c8a
AK
10138{
10139 char esi_buf[ESI_STR_LEN];
10140 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10141 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10142 ATTR_ES_PEER_ROUTER);
10143 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10144 ATTR_ES_PEER_ACTIVE);
10145 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10146 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10147 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10148 if (json_path) {
10149 json_object *json_es_info = NULL;
10150
10151 json_object_string_add(
10152 json_path, "esi",
10153 esi_buf);
10154 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10155 json_es_info = json_object_new_object();
10156 if (es_local)
10157 json_object_boolean_true_add(
10158 json_es_info, "localEs");
10159 if (peer_active)
10160 json_object_boolean_true_add(
10161 json_es_info, "peerActive");
10162 if (peer_proxy)
10163 json_object_boolean_true_add(
10164 json_es_info, "peerProxy");
10165 if (peer_router)
10166 json_object_boolean_true_add(
10167 json_es_info, "peerRouter");
10168 if (attr->mm_sync_seqnum)
10169 json_object_int_add(
10170 json_es_info, "peerSeq",
10171 attr->mm_sync_seqnum);
10172 json_object_object_add(
10173 json_path, "es_info",
10174 json_es_info);
10175 }
10176 } else {
10177 if (bgp_evpn_attr_is_sync(attr))
10178 vty_out(vty,
10179 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10180 esi_buf,
10181 es_local ? "local-es":"",
10182 peer_proxy ? "proxy " : "",
10183 peer_active ? "active ":"",
10184 peer_router ? "router ":"",
10185 attr->mm_sync_seqnum);
10186 else
10187 vty_out(vty, " ESI %s %s\n",
10188 esi_buf,
10189 es_local ? "local-es":"");
10190 }
10191}
10192
4933eaaf 10193void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10194 const struct prefix *p, struct bgp_path_info *path,
10195 afi_t afi, safi_t safi,
4027d19b
DS
10196 enum rpki_states rpki_curr_state,
10197 json_object *json_paths)
d62a17ae 10198{
10199 char buf[INET6_ADDRSTRLEN];
100290e4 10200 char tag_buf[30];
515c2602 10201 struct attr *attr = path->attr;
d62a17ae 10202 time_t tbuf;
10203 json_object *json_bestpath = NULL;
10204 json_object *json_cluster_list = NULL;
10205 json_object *json_cluster_list_list = NULL;
10206 json_object *json_ext_community = NULL;
10207 json_object *json_last_update = NULL;
7fd077aa 10208 json_object *json_pmsi = NULL;
d62a17ae 10209 json_object *json_nexthop_global = NULL;
10210 json_object *json_nexthop_ll = NULL;
10211 json_object *json_nexthops = NULL;
10212 json_object *json_path = NULL;
10213 json_object *json_peer = NULL;
10214 json_object *json_string = NULL;
10215 json_object *json_adv_to = NULL;
10216 int first = 0;
10217 struct listnode *node, *nnode;
10218 struct peer *peer;
be92fc9f 10219 bool addpath_capable;
d62a17ae 10220 int has_adj;
10221 unsigned int first_as;
1defdda8 10222 bool nexthop_self =
9b6d8fcf 10223 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10224 int i;
2ba93fd6
DA
10225 char *nexthop_hostname =
10226 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10227 uint32_t ttl = 0;
10228 uint32_t bos = 0;
10229 uint32_t exp = 0;
10230 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10231 tag_buf[0] = '\0';
f0cde006
LS
10232 struct bgp_path_info *bpi_ultimate =
10233 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10234
10235 if (json_paths) {
10236 json_path = json_object_new_object();
10237 json_peer = json_object_new_object();
10238 json_nexthop_global = json_object_new_object();
10239 }
10240
8304dabf
AD
10241 if (safi == SAFI_EVPN) {
10242 if (!json_paths)
34c7f35f 10243 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10244 }
10245
44c69747 10246 if (path->extra) {
9b6d8fcf
DS
10247 if (path->extra && path->extra->num_labels) {
10248 bgp_evpn_label2str(path->extra->label,
10249 path->extra->num_labels, tag_buf,
a4d82a8a 10250 sizeof(tag_buf));
d62a17ae 10251 }
d7325ee7 10252 if (safi == SAFI_EVPN) {
44c69747 10253 if (!json_paths) {
44c69747
LK
10254 if (tag_buf[0] != '\0')
10255 vty_out(vty, " VNI %s", tag_buf);
44c69747 10256 } else {
1ce23106 10257 if (tag_buf[0])
77a2f8e5
DA
10258 json_object_string_add(json_path, "vni",
10259 tag_buf);
44c69747 10260 }
d7325ee7 10261 }
d62a17ae 10262 }
d62a17ae 10263
8304dabf
AD
10264 if (safi == SAFI_EVPN
10265 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10266 char gwip_buf[INET6_ADDRSTRLEN];
10267
860e740b
IR
10268 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10269 sizeof(gwip_buf));
8304dabf
AD
10270
10271 if (json_paths)
10272 json_object_string_add(json_path, "gatewayIP",
10273 gwip_buf);
10274 else
10275 vty_out(vty, " Gateway IP %s", gwip_buf);
10276 }
10277
2bf9780b 10278 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10279 vty_out(vty, "\n");
10280
100290e4
SW
10281
10282 if (path->extra && path->extra->parent && !json_paths) {
10283 struct bgp_path_info *parent_ri;
10284 struct bgp_dest *dest, *pdest;
10285
10286 parent_ri = (struct bgp_path_info *)path->extra->parent;
10287 dest = parent_ri->net;
10288 if (dest && dest->pdest) {
10289 pdest = dest->pdest;
10290 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10291 vty_out(vty, " Imported from ");
10292 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10293 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10294 pdest));
10295 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10296 (struct prefix_evpn *)
10297 bgp_dest_get_prefix(dest),
10298 tag_buf);
6012963e 10299 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10300 vty_out(vty, ", L3NHG %s",
6012963e
SW
10301 CHECK_FLAG(
10302 attr->es_flags,
10303 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10304 ? "active"
10305 : "inactive");
10306 vty_out(vty, "\n");
10307
4a8cd6ad
PG
10308 } else {
10309 vty_out(vty, " Imported from ");
10310 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10311 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10312 pdest));
10313 vty_out(vty, ":%pFX\n",
100290e4
SW
10314 (struct prefix_evpn *)
10315 bgp_dest_get_prefix(dest));
4a8cd6ad 10316 }
100290e4
SW
10317 }
10318 }
10319
05864da7
DS
10320 /* Line1 display AS-path, Aggregator */
10321 if (attr->aspath) {
10322 if (json_paths) {
10323 if (!attr->aspath->json)
10324 aspath_str_update(attr->aspath, true);
10325 json_object_lock(attr->aspath->json);
10326 json_object_object_add(json_path, "aspath",
10327 attr->aspath->json);
10328 } else {
10329 if (attr->aspath->segments)
e678b143 10330 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10331 else
05864da7 10332 vty_out(vty, " Local");
d62a17ae 10333 }
05864da7 10334 }
d62a17ae 10335
05864da7
DS
10336 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10337 if (json_paths)
10338 json_object_boolean_true_add(json_path, "removed");
10339 else
10340 vty_out(vty, ", (removed)");
10341 }
d62a17ae 10342
05864da7
DS
10343 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10344 if (json_paths)
10345 json_object_boolean_true_add(json_path, "stale");
10346 else
10347 vty_out(vty, ", (stale)");
10348 }
d62a17ae 10349
05864da7
DS
10350 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10351 if (json_paths) {
10352 json_object_int_add(json_path, "aggregatorAs",
10353 attr->aggregator_as);
c949c771
DA
10354 json_object_string_addf(json_path, "aggregatorId",
10355 "%pI4", &attr->aggregator_addr);
05864da7 10356 } else {
88d495a9
DA
10357 vty_out(vty, ", (aggregated by %u %pI4)",
10358 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10359 }
05864da7 10360 }
d62a17ae 10361
05864da7
DS
10362 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10363 PEER_FLAG_REFLECTOR_CLIENT)) {
10364 if (json_paths)
10365 json_object_boolean_true_add(json_path,
10366 "rxedFromRrClient");
10367 else
10368 vty_out(vty, ", (Received from a RR-client)");
10369 }
d62a17ae 10370
05864da7
DS
10371 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10372 PEER_FLAG_RSERVER_CLIENT)) {
10373 if (json_paths)
10374 json_object_boolean_true_add(json_path,
10375 "rxedFromRsClient");
10376 else
10377 vty_out(vty, ", (Received from a RS-client)");
10378 }
d62a17ae 10379
05864da7
DS
10380 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10381 if (json_paths)
10382 json_object_boolean_true_add(json_path,
10383 "dampeningHistoryEntry");
10384 else
10385 vty_out(vty, ", (history entry)");
10386 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10387 if (json_paths)
10388 json_object_boolean_true_add(json_path,
10389 "dampeningSuppressed");
10390 else
10391 vty_out(vty, ", (suppressed due to dampening)");
10392 }
d62a17ae 10393
05864da7
DS
10394 if (!json_paths)
10395 vty_out(vty, "\n");
d62a17ae 10396
05864da7
DS
10397 /* Line2 display Next-hop, Neighbor, Router-id */
10398 /* Display the nexthop */
b54892e0 10399
34c7f35f
SW
10400 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10401 p->family == AF_EVPN) &&
7226bc40
TA
10402 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10403 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10404 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10405 || safi == SAFI_EVPN) {
515c2602 10406 if (json_paths) {
c949c771
DA
10407 json_object_string_addf(
10408 json_nexthop_global, "ip", "%pI4",
10409 &attr->mp_nexthop_global_in);
515c2602 10410
939a97f4 10411 if (path->peer->hostname)
515c2602
DA
10412 json_object_string_add(
10413 json_nexthop_global, "hostname",
939a97f4 10414 path->peer->hostname);
aef999a2
DA
10415 } else {
10416 if (nexthop_hostname)
10417 vty_out(vty, " %pI4(%s)",
10418 &attr->mp_nexthop_global_in,
10419 nexthop_hostname);
10420 else
10421 vty_out(vty, " %pI4",
10422 &attr->mp_nexthop_global_in);
10423 }
d62a17ae 10424 } else {
515c2602 10425 if (json_paths) {
c949c771
DA
10426 json_object_string_addf(json_nexthop_global,
10427 "ip", "%pI4",
10428 &attr->nexthop);
515c2602 10429
939a97f4 10430 if (path->peer->hostname)
515c2602
DA
10431 json_object_string_add(
10432 json_nexthop_global, "hostname",
939a97f4 10433 path->peer->hostname);
aef999a2
DA
10434 } else {
10435 if (nexthop_hostname)
10436 vty_out(vty, " %pI4(%s)",
10437 &attr->nexthop,
10438 nexthop_hostname);
10439 else
10440 vty_out(vty, " %pI4",
10441 &attr->nexthop);
10442 }
d62a17ae 10443 }
10444
05864da7
DS
10445 if (json_paths)
10446 json_object_string_add(json_nexthop_global, "afi",
10447 "ipv4");
10448 } else {
10449 if (json_paths) {
c949c771
DA
10450 json_object_string_addf(json_nexthop_global, "ip",
10451 "%pI6",
10452 &attr->mp_nexthop_global);
515c2602 10453
939a97f4 10454 if (path->peer->hostname)
515c2602
DA
10455 json_object_string_add(json_nexthop_global,
10456 "hostname",
939a97f4 10457 path->peer->hostname);
515c2602 10458
05864da7
DS
10459 json_object_string_add(json_nexthop_global, "afi",
10460 "ipv6");
10461 json_object_string_add(json_nexthop_global, "scope",
10462 "global");
10463 } else {
aef999a2
DA
10464 if (nexthop_hostname)
10465 vty_out(vty, " %pI6(%s)",
10466 &attr->mp_nexthop_global,
10467 nexthop_hostname);
10468 else
10469 vty_out(vty, " %pI6",
10470 &attr->mp_nexthop_global);
d62a17ae 10471 }
05864da7 10472 }
d62a17ae 10473
05864da7 10474 /* Display the IGP cost or 'inaccessible' */
f0cde006 10475 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10476 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10477
10478 if (json_paths) {
05864da7
DS
10479 json_object_boolean_false_add(json_nexthop_global,
10480 "accessible");
95ba22d5
DA
10481 json_object_boolean_add(json_nexthop_global,
10482 "importCheckEnabled", import);
10483 } else {
10484 vty_out(vty, " (inaccessible%s)",
10485 import ? ", import-check enabled" : "");
10486 }
05864da7 10487 } else {
f0cde006 10488 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10489 if (json_paths)
f0cde006
LS
10490 json_object_int_add(
10491 json_nexthop_global, "metric",
10492 bpi_ultimate->extra->igpmetric);
d62a17ae 10493 else
05864da7 10494 vty_out(vty, " (metric %u)",
f0cde006 10495 bpi_ultimate->extra->igpmetric);
d62a17ae 10496 }
10497
05864da7 10498 /* IGP cost is 0, display this only for json */
d62a17ae 10499 else {
d62a17ae 10500 if (json_paths)
05864da7
DS
10501 json_object_int_add(json_nexthop_global,
10502 "metric", 0);
d62a17ae 10503 }
d62a17ae 10504
05864da7
DS
10505 if (json_paths)
10506 json_object_boolean_true_add(json_nexthop_global,
10507 "accessible");
10508 }
d62a17ae 10509
05864da7
DS
10510 /* Display peer "from" output */
10511 /* This path was originated locally */
10512 if (path->peer == bgp->peer_self) {
d62a17ae 10513
34c7f35f 10514 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10515 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10516 if (json_paths)
05864da7
DS
10517 json_object_string_add(json_peer, "peerId",
10518 "0.0.0.0");
d62a17ae 10519 else
05864da7
DS
10520 vty_out(vty, " from 0.0.0.0 ");
10521 } else {
d62a17ae 10522 if (json_paths)
05864da7
DS
10523 json_object_string_add(json_peer, "peerId",
10524 "::");
d62a17ae 10525 else
05864da7 10526 vty_out(vty, " from :: ");
d62a17ae 10527 }
d62a17ae 10528
4e9a9863 10529 if (json_paths)
c949c771
DA
10530 json_object_string_addf(json_peer, "routerId", "%pI4",
10531 &bgp->router_id);
4e9a9863 10532 else
23d0a753 10533 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10534 }
d62a17ae 10535
05864da7
DS
10536 /* We RXed this path from one of our peers */
10537 else {
10538
10539 if (json_paths) {
47e12884
DA
10540 json_object_string_addf(json_peer, "peerId", "%pSU",
10541 &path->peer->su);
c949c771
DA
10542 json_object_string_addf(json_peer, "routerId", "%pI4",
10543 &path->peer->remote_id);
05864da7
DS
10544
10545 if (path->peer->hostname)
10546 json_object_string_add(json_peer, "hostname",
10547 path->peer->hostname);
10548
10549 if (path->peer->domainname)
10550 json_object_string_add(json_peer, "domainname",
10551 path->peer->domainname);
10552
10553 if (path->peer->conf_if)
10554 json_object_string_add(json_peer, "interface",
10555 path->peer->conf_if);
10556 } else {
10557 if (path->peer->conf_if) {
10558 if (path->peer->hostname
892fedb6
DA
10559 && CHECK_FLAG(path->peer->bgp->flags,
10560 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10561 vty_out(vty, " from %s(%s)",
10562 path->peer->hostname,
10563 path->peer->conf_if);
d62a17ae 10564 else
05864da7 10565 vty_out(vty, " from %s",
9b6d8fcf 10566 path->peer->conf_if);
d62a17ae 10567 } else {
05864da7 10568 if (path->peer->hostname
892fedb6
DA
10569 && CHECK_FLAG(path->peer->bgp->flags,
10570 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10571 vty_out(vty, " from %s(%s)",
10572 path->peer->hostname,
10573 path->peer->host);
d62a17ae 10574 else
47e12884
DA
10575 vty_out(vty, " from %pSU",
10576 &path->peer->su);
d62a17ae 10577 }
d62a17ae 10578
05864da7 10579 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10580 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10581 else
07380148 10582 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10583 }
05864da7 10584 }
9df8b37c 10585
05864da7
DS
10586 /*
10587 * Note when vrfid of nexthop is different from that of prefix
10588 */
10589 if (path->extra && path->extra->bgp_orig) {
10590 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10591
05864da7
DS
10592 if (json_paths) {
10593 const char *vn;
9df8b37c 10594
05864da7
DS
10595 if (path->extra->bgp_orig->inst_type
10596 == BGP_INSTANCE_TYPE_DEFAULT)
10597 vn = VRF_DEFAULT_NAME;
10598 else
10599 vn = path->extra->bgp_orig->name;
9df8b37c 10600
05864da7 10601 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10602
05864da7
DS
10603 if (nexthop_vrfid == VRF_UNKNOWN) {
10604 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10605 } else {
05864da7
DS
10606 json_object_int_add(json_path, "nhVrfId",
10607 (int)nexthop_vrfid);
9df8b37c 10608 }
05864da7
DS
10609 } else {
10610 if (nexthop_vrfid == VRF_UNKNOWN)
10611 vty_out(vty, " vrf ?");
137147c6
DS
10612 else {
10613 struct vrf *vrf;
10614
10615 vrf = vrf_lookup_by_id(nexthop_vrfid);
10616 vty_out(vty, " vrf %s(%u)",
10617 VRF_LOGNAME(vrf), nexthop_vrfid);
10618 }
9df8b37c 10619 }
05864da7 10620 }
9df8b37c 10621
05864da7
DS
10622 if (nexthop_self) {
10623 if (json_paths) {
10624 json_object_boolean_true_add(json_path,
10625 "announceNexthopSelf");
10626 } else {
10627 vty_out(vty, " announce-nh-self");
9df8b37c 10628 }
05864da7 10629 }
9df8b37c 10630
05864da7
DS
10631 if (!json_paths)
10632 vty_out(vty, "\n");
d62a17ae 10633
05864da7
DS
10634 /* display the link-local nexthop */
10635 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10636 if (json_paths) {
10637 json_nexthop_ll = json_object_new_object();
c949c771
DA
10638 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10639 &attr->mp_nexthop_local);
515c2602 10640
939a97f4 10641 if (path->peer->hostname)
515c2602
DA
10642 json_object_string_add(json_nexthop_ll,
10643 "hostname",
939a97f4 10644 path->peer->hostname);
515c2602 10645
05864da7
DS
10646 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10647 json_object_string_add(json_nexthop_ll, "scope",
10648 "link-local");
d62a17ae 10649
05864da7
DS
10650 json_object_boolean_true_add(json_nexthop_ll,
10651 "accessible");
d62a17ae 10652
2bb8b49c 10653 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10654 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10655 "used");
10656 else
10657 json_object_boolean_true_add(
10658 json_nexthop_global, "used");
10659 } else {
10660 vty_out(vty, " (%s) %s\n",
10661 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10662 buf, INET6_ADDRSTRLEN),
2bb8b49c 10663 attr->mp_nexthop_prefer_global
05864da7
DS
10664 ? "(prefer-global)"
10665 : "(used)");
d62a17ae 10666 }
05864da7
DS
10667 }
10668 /* If we do not have a link-local nexthop then we must flag the
10669 global as "used" */
10670 else {
10671 if (json_paths)
10672 json_object_boolean_true_add(json_nexthop_global,
10673 "used");
10674 }
d62a17ae 10675
b5e140c8 10676 if (safi == SAFI_EVPN &&
5e4d4c8a 10677 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10678 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10679 }
10680
05864da7
DS
10681 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10682 * Int/Ext/Local, Atomic, best */
10683 if (json_paths)
10684 json_object_string_add(json_path, "origin",
10685 bgp_origin_long_str[attr->origin]);
10686 else
10687 vty_out(vty, " Origin %s",
10688 bgp_origin_long_str[attr->origin]);
9df8b37c 10689
05864da7 10690 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10691 if (json_paths)
05864da7 10692 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10693 else
05864da7
DS
10694 vty_out(vty, ", metric %u", attr->med);
10695 }
9df8b37c 10696
05864da7
DS
10697 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10698 if (json_paths)
0fbac0b4 10699 json_object_int_add(json_path, "locPrf",
05864da7
DS
10700 attr->local_pref);
10701 else
10702 vty_out(vty, ", localpref %u", attr->local_pref);
10703 }
9df8b37c 10704
97a52c82
DA
10705 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10706 if (json_paths)
10707 json_object_int_add(json_path, "aigpMetric",
10708 bgp_attr_get_aigp_metric(attr));
10709 else
10710 vty_out(vty, ", aigp-metric %" PRIu64,
10711 bgp_attr_get_aigp_metric(attr));
10712 }
10713
05864da7
DS
10714 if (attr->weight != 0) {
10715 if (json_paths)
10716 json_object_int_add(json_path, "weight", attr->weight);
10717 else
10718 vty_out(vty, ", weight %u", attr->weight);
10719 }
9df8b37c 10720
05864da7
DS
10721 if (attr->tag != 0) {
10722 if (json_paths)
10723 json_object_int_add(json_path, "tag", attr->tag);
10724 else
10725 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10726 }
9df8b37c 10727
05864da7
DS
10728 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10729 if (json_paths)
10730 json_object_boolean_false_add(json_path, "valid");
10731 else
10732 vty_out(vty, ", invalid");
10733 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10734 if (json_paths)
10735 json_object_boolean_true_add(json_path, "valid");
10736 else
10737 vty_out(vty, ", valid");
10738 }
9df8b37c 10739
7d3cae70
DA
10740 if (json_paths)
10741 json_object_int_add(json_path, "version", bn->version);
10742
05864da7
DS
10743 if (path->peer != bgp->peer_self) {
10744 if (path->peer->as == path->peer->local_as) {
10745 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10746 if (json_paths)
10747 json_object_string_add(
10748 json_peer, "type",
10749 "confed-internal");
d62a17ae 10750 else
05864da7 10751 vty_out(vty, ", confed-internal");
d62a17ae 10752 } else {
05864da7
DS
10753 if (json_paths)
10754 json_object_string_add(
10755 json_peer, "type", "internal");
10756 else
10757 vty_out(vty, ", internal");
9df8b37c 10758 }
05864da7
DS
10759 } else {
10760 if (bgp_confederation_peers_check(bgp,
10761 path->peer->as)) {
10762 if (json_paths)
10763 json_object_string_add(
10764 json_peer, "type",
10765 "confed-external");
d62a17ae 10766 else
05864da7 10767 vty_out(vty, ", confed-external");
d62a17ae 10768 } else {
05864da7
DS
10769 if (json_paths)
10770 json_object_string_add(
10771 json_peer, "type", "external");
10772 else
10773 vty_out(vty, ", external");
d62a17ae 10774 }
10775 }
05864da7
DS
10776 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10777 if (json_paths) {
10778 json_object_boolean_true_add(json_path, "aggregated");
10779 json_object_boolean_true_add(json_path, "local");
10780 } else {
10781 vty_out(vty, ", aggregated, local");
10782 }
10783 } else if (path->type != ZEBRA_ROUTE_BGP) {
10784 if (json_paths)
10785 json_object_boolean_true_add(json_path, "sourced");
10786 else
10787 vty_out(vty, ", sourced");
10788 } else {
10789 if (json_paths) {
10790 json_object_boolean_true_add(json_path, "sourced");
10791 json_object_boolean_true_add(json_path, "local");
10792 } else {
10793 vty_out(vty, ", sourced, local");
d62a17ae 10794 }
05864da7 10795 }
718e3744 10796
05864da7 10797 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10798 if (json_paths)
05864da7
DS
10799 json_object_boolean_true_add(json_path,
10800 "atomicAggregate");
d62a17ae 10801 else
05864da7
DS
10802 vty_out(vty, ", atomic-aggregate");
10803 }
d62a17ae 10804
d864dd9e
EB
10805 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10806 if (json_paths)
10807 json_object_int_add(json_path, "otc", attr->otc);
10808 else
10809 vty_out(vty, ", otc %u", attr->otc);
10810 }
10811
05864da7
DS
10812 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10813 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10814 && bgp_path_info_mpath_count(path))) {
10815 if (json_paths)
10816 json_object_boolean_true_add(json_path, "multipath");
10817 else
10818 vty_out(vty, ", multipath");
10819 }
50e05855 10820
05864da7
DS
10821 // Mark the bestpath(s)
10822 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10823 first_as = aspath_get_first_as(attr->aspath);
718e3744 10824
05864da7
DS
10825 if (json_paths) {
10826 if (!json_bestpath)
10827 json_bestpath = json_object_new_object();
10828 json_object_int_add(json_bestpath, "bestpathFromAs",
10829 first_as);
10830 } else {
10831 if (first_as)
10832 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10833 else
05864da7 10834 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10835 }
05864da7 10836 }
718e3744 10837
05864da7
DS
10838 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10839 if (json_paths) {
10840 if (!json_bestpath)
10841 json_bestpath = json_object_new_object();
10842 json_object_boolean_true_add(json_bestpath, "overall");
10843 json_object_string_add(
10844 json_bestpath, "selectionReason",
10845 bgp_path_selection_reason2str(bn->reason));
10846 } else {
10847 vty_out(vty, ", best");
10848 vty_out(vty, " (%s)",
10849 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10850 }
05864da7 10851 }
718e3744 10852
4027d19b 10853 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10854 if (json_paths)
10855 json_object_string_add(
10856 json_path, "rpkiValidationState",
4027d19b 10857 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10858 else
1d327209 10859 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10860 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10861 }
10862
05864da7
DS
10863 if (json_bestpath)
10864 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10865
05864da7
DS
10866 if (!json_paths)
10867 vty_out(vty, "\n");
10868
10869 /* Line 4 display Community */
29e72930 10870 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10871 if (json_paths) {
9a706b42
DA
10872 if (!bgp_attr_get_community(attr)->json)
10873 community_str(bgp_attr_get_community(attr),
c0945b78 10874 true, true);
9a706b42
DA
10875 json_object_lock(bgp_attr_get_community(attr)->json);
10876 json_object_object_add(
10877 json_path, "community",
10878 bgp_attr_get_community(attr)->json);
05864da7
DS
10879 } else {
10880 vty_out(vty, " Community: %s\n",
9a706b42 10881 bgp_attr_get_community(attr)->str);
d62a17ae 10882 }
05864da7 10883 }
718e3744 10884
05864da7
DS
10885 /* Line 5 display Extended-community */
10886 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10887 if (json_paths) {
10888 json_ext_community = json_object_new_object();
b53e67a3
DA
10889 json_object_string_add(
10890 json_ext_community, "string",
10891 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10892 json_object_object_add(json_path, "extendedCommunity",
10893 json_ext_community);
d62a17ae 10894 } else {
05864da7 10895 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10896 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10897 }
05864da7 10898 }
718e3744 10899
05864da7
DS
10900 /* Line 6 display Large community */
10901 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10902 if (json_paths) {
1bcf3a96
DA
10903 if (!bgp_attr_get_lcommunity(attr)->json)
10904 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10905 true, true);
1bcf3a96
DA
10906 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10907 json_object_object_add(
10908 json_path, "largeCommunity",
10909 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10910 } else {
10911 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10912 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10913 }
05864da7 10914 }
718e3744 10915
05864da7
DS
10916 /* Line 7 display Originator, Cluster-id */
10917 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10918 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10919 char buf[BUFSIZ] = {0};
10920
05864da7 10921 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10922 if (json_paths)
c949c771
DA
10923 json_object_string_addf(json_path,
10924 "originatorId", "%pI4",
10925 &attr->originator_id);
d62a17ae 10926 else
23d0a753
DA
10927 vty_out(vty, " Originator: %pI4",
10928 &attr->originator_id);
d62a17ae 10929 }
856ca177 10930
05864da7 10931 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10932 struct cluster_list *cluster =
10933 bgp_attr_get_cluster(attr);
05864da7 10934 int i;
d62a17ae 10935
10936 if (json_paths) {
05864da7
DS
10937 json_cluster_list = json_object_new_object();
10938 json_cluster_list_list =
10939 json_object_new_array();
10940
779fee93 10941 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10942 json_string = json_object_new_string(
779fee93
DS
10943 inet_ntop(AF_INET,
10944 &cluster->list[i],
10945 buf, sizeof(buf)));
05864da7
DS
10946 json_object_array_add(
10947 json_cluster_list_list,
10948 json_string);
10949 }
718e3744 10950
05864da7
DS
10951 /*
10952 * struct cluster_list does not have
10953 * "str" variable like aspath and community
10954 * do. Add this someday if someone asks
10955 * for it.
10956 * json_object_string_add(json_cluster_list,
779fee93 10957 * "string", cluster->str);
05864da7
DS
10958 */
10959 json_object_object_add(json_cluster_list,
10960 "list",
10961 json_cluster_list_list);
10962 json_object_object_add(json_path, "clusterList",
10963 json_cluster_list);
0dc8ee70 10964 } else {
05864da7
DS
10965 vty_out(vty, ", Cluster list: ");
10966
779fee93 10967 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10968 vty_out(vty, "%pI4 ",
779fee93 10969 &cluster->list[i]);
05864da7 10970 }
0dc8ee70 10971 }
d62a17ae 10972 }
718e3744 10973
d62a17ae 10974 if (!json_paths)
10975 vty_out(vty, "\n");
05864da7 10976 }
d62a17ae 10977
05864da7 10978 if (path->extra && path->extra->damp_info)
b4f7f45b 10979 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10980
05864da7
DS
10981 /* Remote Label */
10982 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10983 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10984 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10985 &bos);
d62a17ae 10986
05864da7
DS
10987 if (json_paths)
10988 json_object_int_add(json_path, "remoteLabel", label);
10989 else
10990 vty_out(vty, " Remote label: %d\n", label);
10991 }
d62a17ae 10992
e496b420
HS
10993 /* Remote SID */
10994 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10995 if (json_paths)
07380148
DA
10996 json_object_string_addf(json_path, "remoteSid", "%pI6",
10997 &path->extra->sid[0].sid);
e496b420 10998 else
07380148
DA
10999 vty_out(vty, " Remote SID: %pI6\n",
11000 &path->extra->sid[0].sid);
e496b420
HS
11001 }
11002
05864da7
DS
11003 /* Label Index */
11004 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11005 if (json_paths)
11006 json_object_int_add(json_path, "labelIndex",
11007 attr->label_index);
11008 else
11009 vty_out(vty, " Label Index: %d\n",
11010 attr->label_index);
11011 }
d62a17ae 11012
05864da7
DS
11013 /* Line 8 display Addpath IDs */
11014 if (path->addpath_rx_id
11015 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11016 if (json_paths) {
11017 json_object_int_add(json_path, "addpathRxId",
11018 path->addpath_rx_id);
d62a17ae 11019
05864da7
DS
11020 /* Keep backwards compatibility with the old API
11021 * by putting TX All's ID in the old field
11022 */
11023 json_object_int_add(
11024 json_path, "addpathTxId",
11025 path->tx_addpath
11026 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11027
05864da7
DS
11028 /* ... but create a specific field for each
11029 * strategy
11030 */
11031 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11032 json_object_int_add(
11033 json_path,
11034 bgp_addpath_names(i)->id_json_name,
11035 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11036 }
05864da7
DS
11037 } else {
11038 vty_out(vty, " AddPath ID: RX %u, ",
11039 path->addpath_rx_id);
d62a17ae 11040
05864da7 11041 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11042 }
05864da7 11043 }
520d5d76 11044
05864da7
DS
11045 /* If we used addpath to TX a non-bestpath we need to display
11046 * "Advertised to" on a path-by-path basis
11047 */
11048 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11049 first = 1;
dcc68b5e 11050
05864da7
DS
11051 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11052 addpath_capable =
11053 bgp_addpath_encode_tx(peer, afi, safi);
11054 has_adj = bgp_adj_out_lookup(
11055 peer, path->net,
11056 bgp_addpath_id_for_peer(peer, afi, safi,
11057 &path->tx_addpath));
11058
11059 if ((addpath_capable && has_adj)
11060 || (!addpath_capable && has_adj
11061 && CHECK_FLAG(path->flags,
11062 BGP_PATH_SELECTED))) {
11063 if (json_path && !json_adv_to)
11064 json_adv_to = json_object_new_object();
dcc68b5e 11065
05864da7
DS
11066 route_vty_out_advertised_to(
11067 vty, peer, &first,
11068 " Advertised to:", json_adv_to);
d62a17ae 11069 }
11070 }
718e3744 11071
05864da7
DS
11072 if (json_path) {
11073 if (json_adv_to) {
11074 json_object_object_add(
11075 json_path, "advertisedTo", json_adv_to);
d62a17ae 11076 }
05864da7
DS
11077 } else {
11078 if (!first) {
11079 vty_out(vty, "\n");
d62a17ae 11080 }
11081 }
05864da7 11082 }
b05a1c8b 11083
05864da7 11084 /* Line 9 display Uptime */
083ec940 11085 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11086 if (json_paths) {
11087 json_last_update = json_object_new_object();
11088 json_object_int_add(json_last_update, "epoch", tbuf);
11089 json_object_string_add(json_last_update, "string",
11090 ctime(&tbuf));
11091 json_object_object_add(json_path, "lastUpdate",
11092 json_last_update);
11093 } else
11094 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11095
05864da7
DS
11096 /* Line 10 display PMSI tunnel attribute, if present */
11097 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11098 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11099 bgp_attr_get_pmsi_tnl_type(attr),
11100 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11101
05864da7
DS
11102 if (json_paths) {
11103 json_pmsi = json_object_new_object();
11104 json_object_string_add(json_pmsi, "tunnelType", str);
11105 json_object_int_add(json_pmsi, "label",
11106 label2vni(&attr->label));
11107 json_object_object_add(json_path, "pmsi", json_pmsi);
11108 } else
11109 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11110 str, label2vni(&attr->label));
d62a17ae 11111 }
f1aa5d8a 11112
848e8cf6
DA
11113 if (path->peer->t_gr_restart &&
11114 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11115 unsigned long gr_remaining =
11116 thread_timer_remain_second(path->peer->t_gr_restart);
11117
11118 if (json_paths) {
11119 json_object_int_add(json_path,
11120 "gracefulRestartSecondsRemaining",
11121 gr_remaining);
11122 } else
11123 vty_out(vty,
11124 " Time until Graceful Restart stale route deleted: %lu\n",
11125 gr_remaining);
11126 }
11127
9a706b42
DA
11128 if (path->peer->t_llgr_stale[afi][safi] &&
11129 bgp_attr_get_community(attr) &&
11130 community_include(bgp_attr_get_community(attr),
11131 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11132 unsigned long llgr_remaining = thread_timer_remain_second(
11133 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11134
48ebba04
DA
11135 if (json_paths) {
11136 json_object_int_add(json_path, "llgrSecondsRemaining",
11137 llgr_remaining);
11138 } else
11139 vty_out(vty,
11140 " Time until Long-lived stale route deleted: %lu\n",
11141 llgr_remaining);
11142 }
11143
92269aa2
DS
11144 /* Output some debug about internal state of the dest flags */
11145 if (json_paths) {
11146 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11147 json_object_boolean_true_add(json_path, "processScheduled");
11148 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11149 json_object_boolean_true_add(json_path, "userCleared");
11150 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11151 json_object_boolean_true_add(json_path, "labelChanged");
11152 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11153 json_object_boolean_true_add(json_path, "registeredForLabel");
11154 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11155 json_object_boolean_true_add(json_path, "selectDefered");
11156 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11157 json_object_boolean_true_add(json_path, "fibInstalled");
11158 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11159 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11160
d62a17ae 11161 if (json_nexthop_global || json_nexthop_ll) {
11162 json_nexthops = json_object_new_array();
f1aa5d8a 11163
d62a17ae 11164 if (json_nexthop_global)
11165 json_object_array_add(json_nexthops,
11166 json_nexthop_global);
f1aa5d8a 11167
d62a17ae 11168 if (json_nexthop_ll)
11169 json_object_array_add(json_nexthops,
11170 json_nexthop_ll);
f1aa5d8a 11171
d62a17ae 11172 json_object_object_add(json_path, "nexthops",
11173 json_nexthops);
11174 }
11175
11176 json_object_object_add(json_path, "peer", json_peer);
11177 json_object_array_add(json_paths, json_path);
05864da7 11178 }
b366b518
BB
11179}
11180
96ade3ed 11181#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11182#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11183#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11184
a4d82a8a 11185static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11186 afi_t afi, safi_t safi, enum bgp_show_type type,
11187 bool use_json);
7f323236
DW
11188static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11189 const char *comstr, int exact, afi_t afi,
96c81f66 11190 safi_t safi, uint16_t show_flags);
d62a17ae 11191
1ae44dfc 11192static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11193 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11194 void *output_arg, const char *rd, int is_last,
96f3485c 11195 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11196 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11197 enum rpki_states rpki_target_state)
d62a17ae 11198{
40381db7 11199 struct bgp_path_info *pi;
9bcb3eef 11200 struct bgp_dest *dest;
2aad8c42
MS
11201 bool header = true;
11202 bool json_detail_header = false;
d62a17ae 11203 int display;
1ae44dfc
LB
11204 unsigned long output_count = 0;
11205 unsigned long total_count = 0;
d62a17ae 11206 struct prefix *p;
d62a17ae 11207 json_object *json_paths = NULL;
11208 int first = 1;
96f3485c
MK
11209 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11210 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11211 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11212 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11213 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11214
1ae44dfc 11215 if (output_cum && *output_cum != 0)
2aad8c42 11216 header = false;
1ae44dfc 11217
9386b588 11218 if (use_json && !*json_header_depth) {
96f3485c
MK
11219 if (all)
11220 *json_header_depth = 1;
11221 else {
11222 vty_out(vty, "{\n");
11223 *json_header_depth = 2;
11224 }
d62a17ae 11225 vty_out(vty,
23d0a753
DA
11226 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11227 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11228 " \"localAS\": ",
a8bf7d9c 11229 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11230 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11231 ? VRF_DEFAULT_NAME
11232 : bgp->name,
11233 table->version, &bgp->router_id,
e84c7c12
PG
11234 bgp->default_local_pref);
11235 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11236 ((bgp->asnotation == ASNOTATION_DOT) &&
11237 (bgp->as < UINT16_MAX)))
11238 vty_out(vty, "%u", bgp->as);
11239 else {
11240 vty_out(vty, "\"");
11241 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11242 vty_out(vty, "\"");
11243 }
11244 vty_out(vty, ",\n \"routes\": { ");
9386b588 11245 if (rd) {
445c2480 11246 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11247 ++*json_header_depth;
11248 }
d62a17ae 11249 }
718e3744 11250
445c2480
DS
11251 if (use_json && rd) {
11252 vty_out(vty, " \"%s\" : { ", rd);
11253 }
11254
2aad8c42 11255 /* Check for 'json detail', where we need header output once per dest */
67799a48 11256 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11257 type != bgp_show_type_damp_neighbor &&
11258 type != bgp_show_type_flap_statistics &&
11259 type != bgp_show_type_flap_neighbor)
11260 json_detail_header = true;
11261
d62a17ae 11262 /* Start processing of routes. */
9bcb3eef
DS
11263 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11264 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11265 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11266 bool json_detail_header_used = false;
b54892e0 11267
9bcb3eef 11268 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11269 if (pi == NULL)
98ce9a06 11270 continue;
d62a17ae 11271
98ce9a06 11272 display = 0;
98ce9a06
DS
11273 if (use_json)
11274 json_paths = json_object_new_array();
11275 else
11276 json_paths = NULL;
d62a17ae 11277
6f94b685 11278 for (; pi; pi = pi->next) {
9a706b42
DA
11279 struct community *picomm = NULL;
11280
11281 picomm = bgp_attr_get_community(pi->attr);
11282
98ce9a06 11283 total_count++;
1e2ce4f1 11284
7d3cae70
DA
11285 if (type == bgp_show_type_prefix_version) {
11286 uint32_t version =
11287 strtoul(output_arg, NULL, 10);
11288 if (dest->version < version)
11289 continue;
11290 }
11291
a70a28a5
DA
11292 if (type == bgp_show_type_community_alias) {
11293 char *alias = output_arg;
11294 char **communities;
11295 int num;
11296 bool found = false;
11297
9a706b42
DA
11298 if (picomm) {
11299 frrstr_split(picomm->str, " ",
11300 &communities, &num);
a70a28a5
DA
11301 for (int i = 0; i < num; i++) {
11302 const char *com2alias =
11303 bgp_community2alias(
11304 communities[i]);
cd9cc0e6
IR
11305 if (!found
11306 && strcmp(alias, com2alias)
11307 == 0)
a70a28a5 11308 found = true;
cd9cc0e6
IR
11309 XFREE(MTYPE_TMP,
11310 communities[i]);
a70a28a5 11311 }
cd9cc0e6 11312 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11313 }
11314
1bcf3a96
DA
11315 if (!found &&
11316 bgp_attr_get_lcommunity(pi->attr)) {
11317 frrstr_split(bgp_attr_get_lcommunity(
11318 pi->attr)
11319 ->str,
a70a28a5
DA
11320 " ", &communities, &num);
11321 for (int i = 0; i < num; i++) {
11322 const char *com2alias =
11323 bgp_community2alias(
11324 communities[i]);
cd9cc0e6
IR
11325 if (!found
11326 && strcmp(alias, com2alias)
11327 == 0)
a70a28a5 11328 found = true;
cd9cc0e6
IR
11329 XFREE(MTYPE_TMP,
11330 communities[i]);
a70a28a5 11331 }
cd9cc0e6 11332 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11333 }
11334
11335 if (!found)
11336 continue;
11337 }
11338
1e2ce4f1
DS
11339 if (type == bgp_show_type_rpki) {
11340 if (dest_p->family == AF_INET
11341 || dest_p->family == AF_INET6)
4027d19b 11342 rpki_curr_state = hook_call(
1e2ce4f1
DS
11343 bgp_rpki_prefix_status,
11344 pi->peer, pi->attr, dest_p);
4027d19b
DS
11345 if (rpki_target_state != RPKI_NOT_BEING_USED
11346 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11347 continue;
11348 }
11349
98ce9a06
DS
11350 if (type == bgp_show_type_flap_statistics
11351 || type == bgp_show_type_flap_neighbor
11352 || type == bgp_show_type_dampend_paths
11353 || type == bgp_show_type_damp_neighbor) {
40381db7 11354 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11355 continue;
11356 }
11357 if (type == bgp_show_type_regexp) {
11358 regex_t *regex = output_arg;
d62a17ae 11359
40381db7 11360 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11361 == REG_NOMATCH)
11362 continue;
11363 }
11364 if (type == bgp_show_type_prefix_list) {
11365 struct prefix_list *plist = output_arg;
d62a17ae 11366
9bcb3eef 11367 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11368 != PREFIX_PERMIT)
11369 continue;
11370 }
ed126382
DA
11371 if (type == bgp_show_type_access_list) {
11372 struct access_list *alist = output_arg;
11373
11374 if (access_list_apply(alist, dest_p) !=
11375 FILTER_PERMIT)
11376 continue;
11377 }
98ce9a06
DS
11378 if (type == bgp_show_type_filter_list) {
11379 struct as_list *as_list = output_arg;
d62a17ae 11380
40381db7 11381 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11382 != AS_FILTER_PERMIT)
11383 continue;
11384 }
11385 if (type == bgp_show_type_route_map) {
11386 struct route_map *rmap = output_arg;
9b6d8fcf 11387 struct bgp_path_info path;
636632c3
DA
11388 struct bgp_path_info_extra extra;
11389 struct attr dummy_attr = {};
b68885f9 11390 route_map_result_t ret;
d62a17ae 11391
6f4f49b2 11392 dummy_attr = *pi->attr;
d62a17ae 11393
636632c3
DA
11394 prep_for_rmap_apply(&path, &extra, dest, pi,
11395 pi->peer, &dummy_attr);
d62a17ae 11396
1782514f 11397 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11398 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11399 if (ret == RMAP_DENYMATCH)
11400 continue;
11401 }
11402 if (type == bgp_show_type_neighbor
11403 || type == bgp_show_type_flap_neighbor
11404 || type == bgp_show_type_damp_neighbor) {
11405 union sockunion *su = output_arg;
11406
40381db7
DS
11407 if (pi->peer == NULL
11408 || pi->peer->su_remote == NULL
11409 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11410 continue;
11411 }
11412 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11413 uint32_t destination;
d62a17ae 11414
9bcb3eef 11415 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11416 if (IN_CLASSC(destination)
9bcb3eef 11417 && dest_p->prefixlen == 24)
98ce9a06
DS
11418 continue;
11419 if (IN_CLASSB(destination)
9bcb3eef 11420 && dest_p->prefixlen == 16)
98ce9a06
DS
11421 continue;
11422 if (IN_CLASSA(destination)
9bcb3eef 11423 && dest_p->prefixlen == 8)
98ce9a06
DS
11424 continue;
11425 }
11426 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11427 p = output_arg;
9bcb3eef 11428 if (!prefix_match(p, dest_p))
98ce9a06
DS
11429 continue;
11430 }
11431 if (type == bgp_show_type_community_all) {
9a706b42 11432 if (!picomm)
98ce9a06
DS
11433 continue;
11434 }
11435 if (type == bgp_show_type_community) {
11436 struct community *com = output_arg;
d62a17ae 11437
9a706b42 11438 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11439 continue;
11440 }
11441 if (type == bgp_show_type_community_exact) {
11442 struct community *com = output_arg;
d62a17ae 11443
9a706b42 11444 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11445 continue;
11446 }
11447 if (type == bgp_show_type_community_list) {
11448 struct community_list *list = output_arg;
d62a17ae 11449
9a706b42 11450 if (!community_list_match(picomm, list))
98ce9a06
DS
11451 continue;
11452 }
a4d82a8a 11453 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11454 struct community_list *list = output_arg;
d62a17ae 11455
9a706b42 11456 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11457 continue;
11458 }
11459 if (type == bgp_show_type_lcommunity) {
11460 struct lcommunity *lcom = output_arg;
d62a17ae 11461
1bcf3a96
DA
11462 if (!bgp_attr_get_lcommunity(pi->attr) ||
11463 !lcommunity_match(
11464 bgp_attr_get_lcommunity(pi->attr),
11465 lcom))
98ce9a06
DS
11466 continue;
11467 }
36a206db 11468
11469 if (type == bgp_show_type_lcommunity_exact) {
11470 struct lcommunity *lcom = output_arg;
11471
1bcf3a96
DA
11472 if (!bgp_attr_get_lcommunity(pi->attr) ||
11473 !lcommunity_cmp(
11474 bgp_attr_get_lcommunity(pi->attr),
11475 lcom))
36a206db 11476 continue;
11477 }
98ce9a06
DS
11478 if (type == bgp_show_type_lcommunity_list) {
11479 struct community_list *list = output_arg;
d62a17ae 11480
1bcf3a96
DA
11481 if (!lcommunity_list_match(
11482 bgp_attr_get_lcommunity(pi->attr),
11483 list))
98ce9a06
DS
11484 continue;
11485 }
36a206db 11486 if (type
11487 == bgp_show_type_lcommunity_list_exact) {
11488 struct community_list *list = output_arg;
11489
11490 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11491 bgp_attr_get_lcommunity(pi->attr),
11492 list))
36a206db 11493 continue;
11494 }
98ce9a06 11495 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11496 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11497 continue;
11498 }
11499 if (type == bgp_show_type_dampend_paths
11500 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11501 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11502 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11503 continue;
11504 }
83856649
KQ
11505 if (type == bgp_show_type_self_originated) {
11506 if (pi->peer != bgp->peer_self)
11507 continue;
11508 }
98ce9a06
DS
11509
11510 if (!use_json && header) {
23d0a753
DA
11511 vty_out(vty,
11512 "BGP table version is %" PRIu64
11513 ", local router ID is %pI4, vrf id ",
11514 table->version, &bgp->router_id);
9df8b37c
PZ
11515 if (bgp->vrf_id == VRF_UNKNOWN)
11516 vty_out(vty, "%s", VRFID_NONE_STR);
11517 else
11518 vty_out(vty, "%u", bgp->vrf_id);
11519 vty_out(vty, "\n");
01eced22
AD
11520 vty_out(vty, "Default local pref %u, ",
11521 bgp->default_local_pref);
e84c7c12
PG
11522 vty_out(vty, "local AS ");
11523 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11524 &bgp->as);
11525 vty_out(vty, "\n");
509d82bd 11526 if (!detail_routes) {
9a1aae2d
DA
11527 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11528 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11529 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11530 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11531 }
d62a17ae 11532 if (type == bgp_show_type_dampend_paths
11533 || type == bgp_show_type_damp_neighbor)
98ce9a06 11534 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11535 else if (type == bgp_show_type_flap_statistics
11536 || type == bgp_show_type_flap_neighbor)
98ce9a06 11537 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11538 else if (!detail_routes)
ae248832
MK
11539 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11540 : BGP_SHOW_HEADER));
2aad8c42
MS
11541 header = false;
11542
d62a17ae 11543 }
98ce9a06
DS
11544 if (rd != NULL && !display && !output_count) {
11545 if (!use_json)
11546 vty_out(vty,
11547 "Route Distinguisher: %s\n",
11548 rd);
d62a17ae 11549 }
98ce9a06
DS
11550 if (type == bgp_show_type_dampend_paths
11551 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11552 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11553 AFI_IP, safi, use_json,
11554 json_paths);
98ce9a06
DS
11555 else if (type == bgp_show_type_flap_statistics
11556 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11557 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11558 AFI_IP, safi, use_json,
11559 json_paths);
f280c93b 11560 else {
27bb782a
DA
11561 if (detail_routes || detail_json) {
11562 const struct prefix_rd *prd = NULL;
9a1aae2d 11563
27bb782a
DA
11564 if (dest->pdest)
11565 prd = bgp_rd_from_dest(
11566 dest->pdest, safi);
9a1aae2d
DA
11567
11568 if (!use_json)
11569 route_vty_out_detail_header(
11570 vty, bgp, dest,
11571 bgp_dest_get_prefix(
11572 dest),
11573 prd, table->afi, safi,
f9f2d188 11574 NULL, false);
9a1aae2d 11575
f280c93b 11576 route_vty_out_detail(
27bb782a 11577 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11578 family2afi(dest_p->family),
11579 safi, RPKI_NOT_BEING_USED,
11580 json_paths);
9a1aae2d 11581 } else {
f280c93b
DA
11582 route_vty_out(vty, dest_p, pi, display,
11583 safi, json_paths, wide);
9a1aae2d 11584 }
f280c93b 11585 }
98ce9a06 11586 display++;
d62a17ae 11587 }
11588
98ce9a06
DS
11589 if (display) {
11590 output_count++;
11591 if (!use_json)
11592 continue;
11593
625d2931 11594 /* encode prefix */
9bcb3eef 11595 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11596 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11597
1840384b 11598
b54892e0
DS
11599 bgp_fs_nlri_get_string(
11600 (unsigned char *)
9bcb3eef
DS
11601 dest_p->u.prefix_flowspec.ptr,
11602 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11603 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11604 family2afi(dest_p->u
11605 .prefix_flowspec.family));
625d2931 11606 if (first)
b54892e0 11607 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11608 dest_p->u.prefix_flowspec
b54892e0 11609 .prefixlen);
625d2931 11610 else
b54892e0 11611 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11612 dest_p->u.prefix_flowspec
b54892e0 11613 .prefixlen);
625d2931 11614 } else {
625d2931 11615 if (first)
1b78780b 11616 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11617 else
1b78780b 11618 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11619 }
f9f2d188
TA
11620
11621 if (json_detail_header && json_paths != NULL) {
11622 const struct prefix_rd *prd;
11623
11624 vty_out(vty, "{\n");
11625
11626 prd = bgp_rd_from_dest(dest, safi);
11627
11628 route_vty_out_detail_header(
11629 vty, bgp, dest,
11630 bgp_dest_get_prefix(dest), prd,
11631 table->afi, safi, json_paths, true);
11632
11633 vty_out(vty, "\"paths\": ");
11634 json_detail_header_used = true;
11635 }
11636
d7c6467b
DS
11637 /*
11638 * We are using no_pretty here because under
11639 * extremely high settings( say lots and lots of
11640 * routes with lots and lots of ways to reach
11641 * that route via different paths ) this can
11642 * save several minutes of output when FRR
11643 * is run on older cpu's or more underperforming
11644 * routers out there
11645 */
11646 vty_json_no_pretty(vty, json_paths);
f9f2d188
TA
11647
11648 if (json_detail_header_used)
11649 vty_out(vty, "} ");
11650
449feb8e 11651 json_paths = NULL;
98ce9a06 11652 first = 0;
1f83ed02
DS
11653 } else
11654 json_object_free(json_paths);
98ce9a06
DS
11655 }
11656
1ae44dfc
LB
11657 if (output_cum) {
11658 output_count += *output_cum;
11659 *output_cum = output_count;
11660 }
11661 if (total_cum) {
11662 total_count += *total_cum;
11663 *total_cum = total_count;
11664 }
d62a17ae 11665 if (use_json) {
9386b588 11666 if (rd) {
a4d82a8a 11667 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11668 }
11669 if (is_last) {
a4d82a8a
PZ
11670 unsigned long i;
11671 for (i = 0; i < *json_header_depth; ++i)
11672 vty_out(vty, " } ");
96f3485c
MK
11673 if (!all)
11674 vty_out(vty, "\n");
9386b588 11675 }
d62a17ae 11676 } else {
1ae44dfc
LB
11677 if (is_last) {
11678 /* No route is displayed */
11679 if (output_count == 0) {
11680 if (type == bgp_show_type_normal)
11681 vty_out(vty,
11682 "No BGP prefixes displayed, %ld exist\n",
11683 total_count);
11684 } else
d62a17ae 11685 vty_out(vty,
1ae44dfc
LB
11686 "\nDisplayed %ld routes and %ld total paths\n",
11687 output_count, total_count);
11688 }
d62a17ae 11689 }
718e3744 11690
d62a17ae 11691 return CMD_SUCCESS;
718e3744 11692}
11693
1ae44dfc
LB
11694int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11695 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11696 enum bgp_show_type type, void *output_arg,
11697 uint16_t show_flags)
1ae44dfc 11698{
9bcb3eef 11699 struct bgp_dest *dest, *next;
1ae44dfc
LB
11700 unsigned long output_cum = 0;
11701 unsigned long total_cum = 0;
9386b588 11702 unsigned long json_header_depth = 0;
67009e22 11703 struct bgp_table *itable;
0136788c 11704 bool show_msg;
27bb782a 11705 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11706
11707 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11708
9bcb3eef
DS
11709 for (dest = bgp_table_top(table); dest; dest = next) {
11710 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11711
9bcb3eef
DS
11712 next = bgp_route_next(dest);
11713 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11714 continue;
67009e22 11715
9bcb3eef 11716 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11717 if (itable != NULL) {
1ae44dfc 11718 struct prefix_rd prd;
06b9f471 11719 char rd[RD_ADDRSTRLEN];
1ae44dfc 11720
9bcb3eef 11721 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11722 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11723 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11724 rd, next == NULL, &output_cum,
11725 &total_cum, &json_header_depth,
1e2ce4f1 11726 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11727 if (next == NULL)
11728 show_msg = false;
1ae44dfc
LB
11729 }
11730 }
0136788c
LB
11731 if (show_msg) {
11732 if (output_cum == 0)
11733 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11734 total_cum);
11735 else
11736 vty_out(vty,
11737 "\nDisplayed %ld routes and %ld total paths\n",
11738 output_cum, total_cum);
0224b329
DA
11739 } else {
11740 if (use_json && output_cum == 0)
11741 vty_out(vty, "{}\n");
0136788c 11742 }
1ae44dfc
LB
11743 return CMD_SUCCESS;
11744}
2aad8c42 11745
d62a17ae 11746static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11747 enum bgp_show_type type, void *output_arg,
96c81f66 11748 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11749{
d62a17ae 11750 struct bgp_table *table;
9386b588 11751 unsigned long json_header_depth = 0;
96f3485c 11752 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11753
d62a17ae 11754 if (bgp == NULL) {
11755 bgp = bgp_get_default();
11756 }
fee0f4c6 11757
d62a17ae 11758 if (bgp == NULL) {
11759 if (!use_json)
11760 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11761 else
11762 vty_out(vty, "{}\n");
d62a17ae 11763 return CMD_WARNING;
11764 }
4dd6177e 11765
cd8c2a27
MS
11766 /* Labeled-unicast routes live in the unicast table. */
11767 if (safi == SAFI_LABELED_UNICAST)
11768 safi = SAFI_UNICAST;
11769
1ae44dfc 11770 table = bgp->rib[afi][safi];
d62a17ae 11771 /* use MPLS and ENCAP specific shows until they are merged */
11772 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11773 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11774 output_arg, show_flags);
d62a17ae 11775 }
dba3c1d3
PG
11776
11777 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11778 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11779 output_arg, use_json,
11780 1, NULL, NULL);
11781 }
fee0f4c6 11782
0adc5bbb
LS
11783 if (safi == SAFI_EVPN)
11784 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11785
96f3485c 11786 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11787 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11788 rpki_target_state);
fee0f4c6 11789}
11790
d62a17ae 11791static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11792 safi_t safi, uint16_t show_flags)
f186de26 11793{
d62a17ae 11794 struct listnode *node, *nnode;
11795 struct bgp *bgp;
11796 int is_first = 1;
9f049418 11797 bool route_output = false;
96f3485c 11798 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11799
d62a17ae 11800 if (use_json)
11801 vty_out(vty, "{\n");
9f689658 11802
d62a17ae 11803 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11804 route_output = true;
d62a17ae 11805 if (use_json) {
11806 if (!is_first)
11807 vty_out(vty, ",\n");
11808 else
11809 is_first = 0;
11810
11811 vty_out(vty, "\"%s\":",
11812 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11813 ? VRF_DEFAULT_NAME
d62a17ae 11814 : bgp->name);
11815 } else {
11816 vty_out(vty, "\nInstance %s:\n",
11817 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11818 ? VRF_DEFAULT_NAME
d62a17ae 11819 : bgp->name);
11820 }
11821 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11822 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11823 }
9f689658 11824
d62a17ae 11825 if (use_json)
11826 vty_out(vty, "}\n");
9f049418
DS
11827 else if (!route_output)
11828 vty_out(vty, "%% BGP instance not found\n");
f186de26 11829}
11830
718e3744 11831/* Header of detailed BGP route information */
d62a17ae 11832void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11833 struct bgp_dest *dest, const struct prefix *p,
11834 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11835 safi_t safi, json_object *json,
11836 bool incremental_print)
d62a17ae 11837{
40381db7 11838 struct bgp_path_info *pi;
d62a17ae 11839 struct peer *peer;
11840 struct listnode *node, *nnode;
06b9f471 11841 char buf1[RD_ADDRSTRLEN];
d62a17ae 11842 int count = 0;
11843 int best = 0;
11844 int suppress = 0;
c5f1e1b2
C
11845 int accept_own = 0;
11846 int route_filter_translated_v4 = 0;
11847 int route_filter_v4 = 0;
11848 int route_filter_translated_v6 = 0;
11849 int route_filter_v6 = 0;
11850 int llgr_stale = 0;
11851 int no_llgr = 0;
11852 int accept_own_nexthop = 0;
11853 int blackhole = 0;
d62a17ae 11854 int no_export = 0;
11855 int no_advertise = 0;
11856 int local_as = 0;
c5f1e1b2 11857 int no_peer = 0;
d62a17ae 11858 int first = 1;
11859 int has_valid_label = 0;
11860 mpls_label_t label = 0;
11861 json_object *json_adv_to = NULL;
67f67ba4
DA
11862 uint32_t ttl = 0;
11863 uint32_t bos = 0;
11864 uint32_t exp = 0;
9bedbb1e 11865
67f67ba4 11866 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11867
67f67ba4 11868 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11869
44c69747 11870 if (safi == SAFI_EVPN) {
44c69747 11871 if (!json) {
2dbe669b 11872 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11873 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11874 bgp->asnotation)
f137734b 11875 : "",
2dbe669b 11876 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11877 } else {
4a8cd6ad
PG
11878 json_object_string_add(
11879 json, "rd",
11880 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11881 bgp->asnotation)
11882 : "");
44c69747
LK
11883 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11884 }
11885 } else {
11886 if (!json) {
9119ef3a
DA
11887 vty_out(vty,
11888 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11889 "\n",
d62a17ae 11890 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7 11891 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11892 sizeof(buf1),
11893 bgp->asnotation)
8228a9a7 11894 : ""),
9119ef3a
DA
11895 safi == SAFI_MPLS_VPN ? ":" : "", p,
11896 dest->version);
cd1964ff 11897
9119ef3a 11898 } else {
f9f2d188
TA
11899 if (incremental_print) {
11900 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11901 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11902 dest->version);
11903 } else {
11904 json_object_string_addf(json, "prefix", "%pFX",
11905 p);
11906 json_object_int_add(json, "version",
11907 dest->version);
11908 }
9119ef3a 11909 }
44c69747
LK
11910 }
11911
11912 if (has_valid_label) {
f9f2d188
TA
11913 if (json) {
11914 if (incremental_print)
11915 vty_out(vty, "\"localLabel\": \"%u\",\n",
11916 label);
11917 else
11918 json_object_int_add(json, "localLabel", label);
11919 } else
d62a17ae 11920 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11921 }
11922
11923 if (!json)
d62a17ae 11924 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11925 vty_out(vty, "not allocated\n");
718e3744 11926
9bcb3eef 11927 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11928 struct community *picomm = NULL;
11929
11930 picomm = bgp_attr_get_community(pi->attr);
11931
d62a17ae 11932 count++;
40381db7 11933 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11934 best = count;
4056a5f6 11935 if (bgp_path_suppressed(pi))
d62a17ae 11936 suppress = 1;
cee9c031 11937
9a706b42 11938 if (!picomm)
cee9c031
QY
11939 continue;
11940
11941 no_advertise += community_include(
9a706b42
DA
11942 picomm, COMMUNITY_NO_ADVERTISE);
11943 no_export +=
11944 community_include(picomm, COMMUNITY_NO_EXPORT);
11945 local_as +=
11946 community_include(picomm, COMMUNITY_LOCAL_AS);
11947 accept_own +=
11948 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11949 route_filter_translated_v4 += community_include(
9a706b42 11950 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11951 route_filter_translated_v6 += community_include(
9a706b42 11952 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11953 route_filter_v4 += community_include(
9a706b42 11954 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11955 route_filter_v6 += community_include(
9a706b42
DA
11956 picomm, COMMUNITY_ROUTE_FILTER_v6);
11957 llgr_stale +=
11958 community_include(picomm, COMMUNITY_LLGR_STALE);
11959 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11960 accept_own_nexthop += community_include(
11961 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11962 blackhole +=
11963 community_include(picomm, COMMUNITY_BLACKHOLE);
11964 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11965 }
718e3744 11966 }
718e3744 11967
d62a17ae 11968 if (!json) {
11969 vty_out(vty, "Paths: (%d available", count);
11970 if (best) {
11971 vty_out(vty, ", best #%d", best);
b84060bb
PG
11972 if (safi == SAFI_UNICAST) {
11973 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11974 vty_out(vty, ", table %s",
11975 VRF_DEFAULT_NAME);
11976 else
11977 vty_out(vty, ", vrf %s",
11978 bgp->name);
11979 }
d62a17ae 11980 } else
11981 vty_out(vty, ", no best path");
11982
c5f1e1b2
C
11983 if (accept_own)
11984 vty_out(vty,
11985 ", accept own local route exported and imported in different VRF");
11986 else if (route_filter_translated_v4)
11987 vty_out(vty,
11988 ", mark translated RTs for VPNv4 route filtering");
11989 else if (route_filter_v4)
11990 vty_out(vty,
11991 ", attach RT as-is for VPNv4 route filtering");
11992 else if (route_filter_translated_v6)
11993 vty_out(vty,
11994 ", mark translated RTs for VPNv6 route filtering");
11995 else if (route_filter_v6)
11996 vty_out(vty,
11997 ", attach RT as-is for VPNv6 route filtering");
11998 else if (llgr_stale)
11999 vty_out(vty,
1479ed2f 12000 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
12001 else if (no_llgr)
12002 vty_out(vty,
12003 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12004 else if (accept_own_nexthop)
12005 vty_out(vty,
12006 ", accept local nexthop");
12007 else if (blackhole)
12008 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 12009 else if (no_export)
12010 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
12011 else if (no_advertise)
12012 vty_out(vty, ", not advertised to any peer");
d62a17ae 12013 else if (local_as)
12014 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
12015 else if (no_peer)
12016 vty_out(vty,
12017 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 12018
12019 if (suppress)
12020 vty_out(vty,
12021 ", Advertisements suppressed by an aggregate.");
12022 vty_out(vty, ")\n");
12023 }
718e3744 12024
d62a17ae 12025 /* If we are not using addpath then we can display Advertised to and
12026 * that will
12027 * show what peers we advertised the bestpath to. If we are using
12028 * addpath
12029 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12030 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12031 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12032 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12033 if (json && !json_adv_to)
12034 json_adv_to = json_object_new_object();
12035
12036 route_vty_out_advertised_to(
12037 vty, peer, &first,
12038 " Advertised to non peer-group peers:\n ",
12039 json_adv_to);
12040 }
12041 }
12042
f9f2d188
TA
12043 if (json && json_adv_to) {
12044 if (incremental_print) {
12045 vty_out(vty, "\"advertisedTo\": ");
12046 vty_json(vty, json_adv_to);
12047 vty_out(vty, ",");
12048 } else
d62a17ae 12049 json_object_object_add(json, "advertisedTo",
12050 json_adv_to);
d62a17ae 12051 } else {
f9f2d188 12052 if (!json && first)
d62a17ae 12053 vty_out(vty, " Not advertised to any peer");
12054 vty_out(vty, "\n");
12055 }
12056 }
718e3744 12057}
12058
edfee30d 12059static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12060 struct bgp_dest *bgp_node, struct vty *vty,
12061 struct bgp *bgp, afi_t afi, safi_t safi,
12062 json_object *json, enum bgp_path_type pathtype,
4027d19b 12063 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12064{
12065 struct bgp_path_info *pi;
12066 int header = 1;
44c69747
LK
12067 json_object *json_header = NULL;
12068 json_object *json_paths = NULL;
4933eaaf 12069 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12070
9bcb3eef 12071 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12072 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12073
12074 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12075 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12076 pi->peer, pi->attr, p);
4933eaaf 12077
4027d19b
DS
12078 if (rpki_target_state != RPKI_NOT_BEING_USED
12079 && rpki_curr_state != rpki_target_state)
4933eaaf 12080 continue;
44c69747
LK
12081
12082 if (json && !json_paths) {
12083 /* Instantiate json_paths only if path is valid */
12084 json_paths = json_object_new_array();
c4f64ea9 12085 if (pfx_rd)
44c69747 12086 json_header = json_object_new_object();
c4f64ea9 12087 else
44c69747
LK
12088 json_header = json;
12089 }
12090
12091 if (header) {
12092 route_vty_out_detail_header(
34c7f35f
SW
12093 vty, bgp, bgp_node,
12094 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12095 safi, json_header, false);
44c69747
LK
12096 header = 0;
12097 }
12098 (*display)++;
12099
12100 if (pathtype == BGP_PATH_SHOW_ALL
12101 || (pathtype == BGP_PATH_SHOW_BESTPATH
12102 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12103 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12104 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12105 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12106 route_vty_out_detail(vty, bgp, bgp_node,
12107 bgp_dest_get_prefix(bgp_node), pi,
12108 AFI_IP, safi, rpki_curr_state,
12109 json_paths);
44c69747
LK
12110 }
12111
12112 if (json && json_paths) {
12113 json_object_object_add(json_header, "paths", json_paths);
12114
12115 if (pfx_rd)
4a8cd6ad
PG
12116 json_object_object_addf(
12117 json, json_header,
12118 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12119 }
12120}
12121
2aad8c42
MS
12122/*
12123 * Return rd based on safi
12124 */
46dbf9d0
DA
12125const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12126 safi_t safi)
2aad8c42
MS
12127{
12128 switch (safi) {
12129 case SAFI_MPLS_VPN:
12130 case SAFI_ENCAP:
12131 case SAFI_EVPN:
12132 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12133 case SAFI_UNSPEC:
12134 case SAFI_UNICAST:
12135 case SAFI_MULTICAST:
12136 case SAFI_LABELED_UNICAST:
12137 case SAFI_FLOWSPEC:
12138 case SAFI_MAX:
2aad8c42 12139 return NULL;
2aad8c42 12140 }
58cf0823
DS
12141
12142 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12143}
12144
718e3744 12145/* Display specified route of BGP table. */
d62a17ae 12146static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12147 struct bgp_table *rib, const char *ip_str,
12148 afi_t afi, safi_t safi,
4027d19b 12149 enum rpki_states rpki_target_state,
d62a17ae 12150 struct prefix_rd *prd, int prefix_check,
9f049418 12151 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12152{
12153 int ret;
d62a17ae 12154 int display = 0;
12155 struct prefix match;
9bcb3eef
DS
12156 struct bgp_dest *dest;
12157 struct bgp_dest *rm;
d62a17ae 12158 struct bgp_table *table;
12159 json_object *json = NULL;
12160 json_object *json_paths = NULL;
12161
12162 /* Check IP address argument. */
12163 ret = str2prefix(ip_str, &match);
12164 if (!ret) {
12165 vty_out(vty, "address is malformed\n");
12166 return CMD_WARNING;
12167 }
718e3744 12168
d62a17ae 12169 match.family = afi2family(afi);
b05a1c8b 12170
44c69747 12171 if (use_json)
d62a17ae 12172 json = json_object_new_object();
718e3744 12173
44c69747 12174 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12175 for (dest = bgp_table_top(rib); dest;
12176 dest = bgp_route_next(dest)) {
12177 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12178
9bcb3eef 12179 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12180 continue;
9bcb3eef 12181 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12182 if (!table)
ea47320b 12183 continue;
d62a17ae 12184
4953391b
DA
12185 rm = bgp_node_match(table, &match);
12186 if (rm == NULL)
ea47320b 12187 continue;
d62a17ae 12188
9bcb3eef 12189 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12190 if (prefix_check
b54892e0 12191 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12192 bgp_dest_unlock_node(rm);
ea47320b
DL
12193 continue;
12194 }
d62a17ae 12195
9bcb3eef 12196 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12197 bgp, afi, safi, json, pathtype,
4027d19b 12198 &display, rpki_target_state);
44c69747 12199
9bcb3eef 12200 bgp_dest_unlock_node(rm);
44c69747
LK
12201 }
12202 } else if (safi == SAFI_EVPN) {
9bcb3eef 12203 struct bgp_dest *longest_pfx;
cded3b72 12204 bool is_exact_pfxlen_match = false;
44c69747 12205
9bcb3eef
DS
12206 for (dest = bgp_table_top(rib); dest;
12207 dest = bgp_route_next(dest)) {
12208 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12209
9bcb3eef 12210 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12211 continue;
9bcb3eef 12212 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12213 if (!table)
12214 continue;
12215
12216 longest_pfx = NULL;
cded3b72 12217 is_exact_pfxlen_match = false;
44c69747
LK
12218 /*
12219 * Search through all the prefixes for a match. The
12220 * pfx's are enumerated in ascending order of pfxlens.
12221 * So, the last pfx match is the longest match. Set
12222 * is_exact_pfxlen_match when we get exact pfxlen match
12223 */
12224 for (rm = bgp_table_top(table); rm;
12225 rm = bgp_route_next(rm)) {
b54892e0 12226 const struct prefix *rm_p =
9bcb3eef 12227 bgp_dest_get_prefix(rm);
44c69747
LK
12228 /*
12229 * Get prefixlen of the ip-prefix within type5
12230 * evpn route
12231 */
b54892e0
DS
12232 if (evpn_type5_prefix_match(rm_p, &match)
12233 && rm->info) {
44c69747
LK
12234 longest_pfx = rm;
12235 int type5_pfxlen =
b54892e0
DS
12236 bgp_evpn_get_type5_prefixlen(
12237 rm_p);
44c69747 12238 if (type5_pfxlen == match.prefixlen) {
cded3b72 12239 is_exact_pfxlen_match = true;
9bcb3eef 12240 bgp_dest_unlock_node(rm);
44c69747
LK
12241 break;
12242 }
d62a17ae 12243 }
12244 }
ea47320b 12245
44c69747
LK
12246 if (!longest_pfx)
12247 continue;
12248
12249 if (prefix_check && !is_exact_pfxlen_match)
12250 continue;
12251
12252 rm = longest_pfx;
9bcb3eef 12253 bgp_dest_lock_node(rm);
44c69747 12254
9bcb3eef 12255 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12256 bgp, afi, safi, json, pathtype,
4027d19b 12257 &display, rpki_target_state);
44c69747 12258
9bcb3eef 12259 bgp_dest_unlock_node(rm);
d62a17ae 12260 }
98a9dbc7 12261 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12262 if (use_json)
12263 json_paths = json_object_new_array();
12264
63a0b7a9
PG
12265 display = bgp_flowspec_display_match_per_ip(afi, rib,
12266 &match, prefix_check,
12267 vty,
12268 use_json,
12269 json_paths);
d5f20468
SP
12270 if (use_json) {
12271 if (display)
12272 json_object_object_add(json, "paths",
12273 json_paths);
12274 else
12275 json_object_free(json_paths);
12276 }
d62a17ae 12277 } else {
4953391b
DA
12278 dest = bgp_node_match(rib, &match);
12279 if (dest != NULL) {
9bcb3eef 12280 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12281 if (!prefix_check
9bcb3eef
DS
12282 || dest_p->prefixlen == match.prefixlen) {
12283 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12284 safi, json, pathtype,
4027d19b 12285 &display, rpki_target_state);
d62a17ae 12286 }
12287
9bcb3eef 12288 bgp_dest_unlock_node(dest);
d62a17ae 12289 }
12290 }
e5eee9af 12291
d62a17ae 12292 if (use_json) {
75eeda93 12293 vty_json(vty, json);
d62a17ae 12294 } else {
12295 if (!display) {
12296 vty_out(vty, "%% Network not in table\n");
12297 return CMD_WARNING;
12298 }
12299 }
b05a1c8b 12300
d62a17ae 12301 return CMD_SUCCESS;
718e3744 12302}
12303
fee0f4c6 12304/* Display specified route of Main RIB */
d62a17ae 12305static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12306 afi_t afi, safi_t safi, struct prefix_rd *prd,
12307 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12308 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12309{
9b86009a 12310 if (!bgp) {
d62a17ae 12311 bgp = bgp_get_default();
9b86009a
RW
12312 if (!bgp) {
12313 if (!use_json)
12314 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12315 else
12316 vty_out(vty, "{}\n");
9b86009a
RW
12317 return CMD_WARNING;
12318 }
12319 }
d62a17ae 12320
12321 /* labeled-unicast routes live in the unicast table */
12322 if (safi == SAFI_LABELED_UNICAST)
12323 safi = SAFI_UNICAST;
12324
12325 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12326 afi, safi, rpki_target_state, prd,
8aa22bbb 12327 prefix_check, pathtype, use_json);
d62a17ae 12328}
12329
12330static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12331 struct cmd_token **argv, bool exact, afi_t afi,
12332 safi_t safi, bool uj)
d62a17ae 12333{
12334 struct lcommunity *lcom;
12335 struct buffer *b;
12336 int i;
12337 char *str;
12338 int first = 0;
96c81f66 12339 uint16_t show_flags = 0;
4f28b2b5 12340 int ret;
96f3485c
MK
12341
12342 if (uj)
12343 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12344
12345 b = buffer_new(1024);
12346 for (i = 0; i < argc; i++) {
12347 if (first)
12348 buffer_putc(b, ' ');
12349 else {
12350 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12351 first = 1;
12352 buffer_putstr(b, argv[i]->arg);
12353 }
12354 }
12355 }
12356 buffer_putc(b, '\0');
57d187bc 12357
d62a17ae 12358 str = buffer_getstr(b);
12359 buffer_free(b);
57d187bc 12360
d62a17ae 12361 lcom = lcommunity_str2com(str);
12362 XFREE(MTYPE_TMP, str);
12363 if (!lcom) {
12364 vty_out(vty, "%% Large-community malformed\n");
12365 return CMD_WARNING;
12366 }
57d187bc 12367
4f28b2b5 12368 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12369 (exact ? bgp_show_type_lcommunity_exact
12370 : bgp_show_type_lcommunity),
12371 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12372
12373 lcommunity_free(&lcom);
12374 return ret;
57d187bc
JS
12375}
12376
d62a17ae 12377static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12378 const char *lcom, bool exact, afi_t afi,
12379 safi_t safi, bool uj)
57d187bc 12380{
d62a17ae 12381 struct community_list *list;
96c81f66 12382 uint16_t show_flags = 0;
96f3485c
MK
12383
12384 if (uj)
12385 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12386
57d187bc 12387
e237b0d2 12388 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12389 LARGE_COMMUNITY_LIST_MASTER);
12390 if (list == NULL) {
12391 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12392 lcom);
12393 return CMD_WARNING;
12394 }
57d187bc 12395
36a206db 12396 return bgp_show(vty, bgp, afi, safi,
12397 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12398 : bgp_show_type_lcommunity_list),
1e2ce4f1 12399 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12400}
12401
52951b63
DS
12402DEFUN (show_ip_bgp_large_community_list,
12403 show_ip_bgp_large_community_list_cmd,
77a3a95e 12404 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
52951b63
DS
12405 SHOW_STR
12406 IP_STR
12407 BGP_STR
12408 BGP_INSTANCE_HELP_STR
9bedbb1e 12409 BGP_AFI_HELP_STR
4dd6177e 12410 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12411 "Display routes matching the large-community-list\n"
12412 "large-community-list number\n"
12413 "large-community-list name\n"
36a206db 12414 "Exact match of the large-communities\n"
52951b63
DS
12415 JSON_STR)
12416{
d62a17ae 12417 afi_t afi = AFI_IP6;
12418 safi_t safi = SAFI_UNICAST;
12419 int idx = 0;
36a206db 12420 bool exact_match = 0;
4d678463 12421 struct bgp *bgp = NULL;
9f049418 12422 bool uj = use_json(argc, argv);
d62a17ae 12423
ef3364f0
DA
12424 if (uj)
12425 argc--;
4d678463 12426
ef3364f0
DA
12427 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12428 &bgp, uj);
12429 if (!idx)
12430 return CMD_WARNING;
d62a17ae 12431
12432 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12433
12434 const char *clist_number_or_name = argv[++idx]->arg;
12435
12436 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12437 exact_match = 1;
12438
12439 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12440 exact_match, afi, safi, uj);
52951b63
DS
12441}
12442DEFUN (show_ip_bgp_large_community,
12443 show_ip_bgp_large_community_cmd,
36a206db 12444 "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
12445 SHOW_STR
12446 IP_STR
12447 BGP_STR
12448 BGP_INSTANCE_HELP_STR
9bedbb1e 12449 BGP_AFI_HELP_STR
4dd6177e 12450 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12451 "Display routes matching the large-communities\n"
12452 "List of large-community numbers\n"
36a206db 12453 "Exact match of the large-communities\n"
52951b63
DS
12454 JSON_STR)
12455{
d62a17ae 12456 afi_t afi = AFI_IP6;
12457 safi_t safi = SAFI_UNICAST;
12458 int idx = 0;
36a206db 12459 bool exact_match = 0;
4d678463 12460 struct bgp *bgp = NULL;
9f049418 12461 bool uj = use_json(argc, argv);
96c81f66 12462 uint16_t show_flags = 0;
d62a17ae 12463
96f3485c
MK
12464 if (uj) {
12465 argc--;
12466 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12467 }
4d678463 12468
96f3485c
MK
12469 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12470 &bgp, uj);
12471 if (!idx)
12472 return CMD_WARNING;
d62a17ae 12473
36a206db 12474 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12475 if (argv_find(argv, argc, "exact-match", &idx)) {
12476 argc--;
36a206db 12477 exact_match = 1;
1857760c 12478 }
36a206db 12479 return bgp_show_lcommunity(vty, bgp, argc, argv,
12480 exact_match, afi, safi, uj);
12481 } else
d62a17ae 12482 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12483 bgp_show_type_lcommunity_all, NULL, show_flags,
12484 RPKI_NOT_BEING_USED);
52951b63
DS
12485}
12486
71f1613a
DA
12487static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12488 safi_t safi, struct json_object *json_array);
d62a17ae 12489static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12490 safi_t safi, struct json_object *json);
e01ca200 12491
7b2ff250 12492
9ab0cf58
PG
12493DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12494 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12495 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12496 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12497{
12498 bool uj = use_json(argc, argv);
12499 struct bgp *bgp = NULL;
ec76a1d1
DA
12500 safi_t safi = SAFI_UNICAST;
12501 afi_t afi = AFI_IP6;
4265b261 12502 int idx = 0;
6c9d22e2
PG
12503 struct json_object *json_all = NULL;
12504 struct json_object *json_afi_safi = NULL;
4265b261
PG
12505
12506 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12507 &bgp, false);
71f1613a 12508 if (!idx)
4265b261 12509 return CMD_WARNING;
6c9d22e2 12510
4265b261 12511 if (uj)
6c9d22e2 12512 json_all = json_object_new_object();
4265b261 12513
9ab0cf58
PG
12514 FOREACH_AFI_SAFI (afi, safi) {
12515 /*
12516 * So limit output to those afi/safi pairs that
12517 * actually have something interesting in them
12518 */
12519 if (strmatch(get_afi_safi_str(afi, safi, true),
12520 "Unknown")) {
12521 continue;
12522 }
12523 if (uj) {
12524 json_afi_safi = json_object_new_array();
12525 json_object_object_add(
12526 json_all,
12527 get_afi_safi_str(afi, safi, true),
12528 json_afi_safi);
12529 } else {
12530 json_afi_safi = NULL;
6c9d22e2 12531 }
9ab0cf58
PG
12532
12533 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12534 }
6c9d22e2 12535
3757f964
DA
12536 if (uj)
12537 vty_json(vty, json_all);
6c9d22e2 12538
4265b261
PG
12539 return CMD_SUCCESS;
12540}
12541
7b2ff250 12542/* BGP route print out function without JSON */
14718643
PG
12543DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12544 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12545 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12546 SHOW_STR
12547 IP_STR
12548 BGP_STR
12549 BGP_INSTANCE_HELP_STR
12550 L2VPN_HELP_STR
12551 EVPN_HELP_STR
12552 "BGP RIB advertisement statistics\n"
12553 JSON_STR)
12554{
ec76a1d1
DA
12555 afi_t afi = AFI_IP6;
12556 safi_t safi = SAFI_UNICAST;
14718643
PG
12557 struct bgp *bgp = NULL;
12558 int idx = 0, ret;
12559 bool uj = use_json(argc, argv);
12560 struct json_object *json_afi_safi = NULL, *json = NULL;
12561
12562 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12563 &bgp, false);
12564 if (!idx)
12565 return CMD_WARNING;
12566
12567 if (uj)
12568 json_afi_safi = json_object_new_array();
12569 else
12570 json_afi_safi = NULL;
12571
12572 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12573
12574 if (uj) {
12575 json = json_object_new_object();
12576 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12577 json_afi_safi);
3757f964 12578 vty_json(vty, json);
14718643
PG
12579 }
12580 return ret;
12581}
12582
893cccd0 12583/* BGP route print out function without JSON */
9ab0cf58
PG
12584DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12585 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12586 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12587 "]]\
893cccd0 12588 statistics [json]",
9ab0cf58
PG
12589 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12590 BGP_SAFI_WITH_LABEL_HELP_STR
12591 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12592{
ec76a1d1
DA
12593 afi_t afi = AFI_IP6;
12594 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12595 struct bgp *bgp = NULL;
12596 int idx = 0, ret;
12597 bool uj = use_json(argc, argv);
6c9d22e2 12598 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12599
12600 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12601 &bgp, false);
12602 if (!idx)
12603 return CMD_WARNING;
6c9d22e2 12604
893cccd0 12605 if (uj)
6c9d22e2
PG
12606 json_afi_safi = json_object_new_array();
12607 else
12608 json_afi_safi = NULL;
12609
12610 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12611
12612 if (uj) {
12613 json = json_object_new_object();
12614 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12615 json_afi_safi);
3757f964 12616 vty_json(vty, json);
893cccd0
PG
12617 }
12618 return ret;
893cccd0 12619}
7b2ff250 12620
fe0f234d 12621DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12622 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12623 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12624 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12625 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12626 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12627 "Display the entries for all address families\n"
9ab0cf58
PG
12628 "Display detailed information about dampening\n"
12629 "Display detail of configured dampening parameters\n"
fe0f234d 12630 JSON_STR)
718e3744 12631{
d62a17ae 12632 afi_t afi = AFI_IP6;
12633 safi_t safi = SAFI_UNICAST;
d62a17ae 12634 struct bgp *bgp = NULL;
12635 int idx = 0;
96c81f66 12636 uint16_t show_flags = 0;
fe0f234d
RW
12637 bool uj = use_json(argc, argv);
12638
12639 if (uj) {
12640 argc--;
12641 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12642 }
96f3485c
MK
12643
12644 /* [<ipv4|ipv6> [all]] */
12645 if (all) {
12646 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12647 if (argv_find(argv, argc, "ipv4", &idx))
12648 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12649
12650 if (argv_find(argv, argc, "ipv6", &idx))
12651 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12652 }
d62a17ae 12653
12654 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12655 &bgp, false);
d62a17ae 12656 if (!idx)
12657 return CMD_WARNING;
12658
fe0f234d 12659 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12660}
12661
fe0f234d
RW
12662/* BGP route print out function */
12663DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12664 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12665 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12666 "]]\
96f3485c 12667 [all$all]\
cf4898bc
QY
12668 [cidr-only\
12669 |dampening <flap-statistics|dampened-paths>\
12670 |community [AA:NN|local-AS|no-advertise|no-export\
12671 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12672 |accept-own|accept-own-nexthop|route-filter-v6\
12673 |route-filter-v4|route-filter-translated-v6\
12674 |route-filter-translated-v4] [exact-match]\
70799983 12675 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12676 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12677 |prefix-list WORD\
ed126382 12678 |access-list ACCESSLIST_NAME\
70dd370f 12679 |route-map RMAP_NAME\
1e2ce4f1 12680 |rpki <invalid|valid|notfound>\
7d3cae70 12681 |version (1-4294967295)\
b4ad2fae 12682 |alias ALIAS_NAME\
39c3c736
RW
12683 |A.B.C.D/M longer-prefixes\
12684 |X:X::X:X/M longer-prefixes\
83856649 12685 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12686 |detail-routes$detail_routes\
67799a48 12687 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12688 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12689 BGP_SAFI_WITH_LABEL_HELP_STR
12690 "Display the entries for all address families\n"
12691 "Display only routes with non-natural netmasks\n"
12692 "Display detailed information about dampening\n"
12693 "Display flap statistics of routes\n"
12694 "Display paths suppressed due to dampening\n"
12695 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12696 "Do not send outside local AS (well-known community)\n"
12697 "Do not advertise to any peer (well-known community)\n"
12698 "Do not export to next AS (well-known community)\n"
12699 "Graceful shutdown (well-known community)\n"
12700 "Do not export to any peer (well-known community)\n"
12701 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12702 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12703 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12704 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12705 "Should accept VPN route with local nexthop (well-known community)\n"
12706 "RT VPNv6 route filtering (well-known community)\n"
12707 "RT VPNv4 route filtering (well-known community)\n"
12708 "RT translated VPNv6 route filtering (well-known community)\n"
12709 "RT translated VPNv4 route filtering (well-known community)\n"
12710 "Exact match of the communities\n"
70799983
RW
12711 "Community-list number\n"
12712 "Community-list name\n"
12713 "Display routes matching the community-list\n"
12714 "Exact match of the communities\n"
a7129347
RW
12715 "Display routes conforming to the filter-list\n"
12716 "Regular expression access list name\n"
6deaf579
RW
12717 "Display routes conforming to the prefix-list\n"
12718 "Prefix-list name\n"
ed126382
DA
12719 "Display routes conforming to the access-list\n"
12720 "Access-list name\n"
bf1a944a
RW
12721 "Display routes matching the route-map\n"
12722 "A route-map to match on\n"
a70a28a5
DA
12723 "RPKI route types\n"
12724 "A valid path as determined by rpki\n"
12725 "A invalid path as determined by rpki\n"
12726 "A path that has no rpki data\n"
12727 "Display prefixes with matching version numbers\n"
12728 "Version number and above\n"
12729 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12730 "BGP community alias\n"
12731 "IPv4 prefix\n"
12732 "Display route and more specific routes\n"
12733 "IPv6 prefix\n"
12734 "Display route and more specific routes\n"
83856649 12735 BGP_SELF_ORIG_HELP_STR
509d82bd 12736 "Display detailed version of all routes\n"
39c3c736 12737 JSON_STR
a70a28a5
DA
12738 "Display detailed version of JSON output\n"
12739 "Increase table width for longer prefixes\n")
7b2ff250
DW
12740{
12741 afi_t afi = AFI_IP6;
12742 safi_t safi = SAFI_UNICAST;
12743 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12744 void *output_arg = NULL;
7b2ff250
DW
12745 struct bgp *bgp = NULL;
12746 int idx = 0;
d0086e8e 12747 int exact_match = 0;
96f3485c
MK
12748 char *community = NULL;
12749 bool first = true;
96c81f66 12750 uint16_t show_flags = 0;
4027d19b 12751 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12752 struct prefix p;
96f3485c
MK
12753
12754 if (uj) {
9f049418 12755 argc--;
96f3485c
MK
12756 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12757 }
12758
67799a48
DA
12759 if (detail_json)
12760 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12761
509d82bd
DA
12762 if (detail_routes)
12763 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12764
96f3485c
MK
12765 /* [<ipv4|ipv6> [all]] */
12766 if (all) {
12767 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12768
12769 if (argv_find(argv, argc, "ipv4", &idx))
12770 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12771
12772 if (argv_find(argv, argc, "ipv6", &idx))
12773 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12774 }
12775
12776 if (wide)
12777 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12778
12779 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12780 &bgp, uj);
7b2ff250
DW
12781 if (!idx)
12782 return CMD_WARNING;
12783
7b2ff250 12784 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12785 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12786
12787 if (argv_find(argv, argc, "dampening", &idx)) {
12788 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12789 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12790 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12791 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12792 }
12793
12794 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12795 char *maybecomm = NULL;
d0086e8e 12796
79bc257a
RW
12797 if (idx + 1 < argc) {
12798 if (argv[idx + 1]->type == VARIABLE_TKN)
12799 maybecomm = argv[idx + 1]->arg;
12800 else
12801 maybecomm = argv[idx + 1]->text;
12802 }
12803
cf4898bc
QY
12804 if (maybecomm && !strmatch(maybecomm, "json")
12805 && !strmatch(maybecomm, "exact-match"))
12806 community = maybecomm;
d0086e8e 12807
cf4898bc
QY
12808 if (argv_find(argv, argc, "exact-match", &idx))
12809 exact_match = 1;
d0086e8e 12810
96f3485c
MK
12811 if (!community)
12812 sh_type = bgp_show_type_community_all;
12813 }
12814
70799983
RW
12815 if (argv_find(argv, argc, "community-list", &idx)) {
12816 const char *clist_number_or_name = argv[++idx]->arg;
12817 struct community_list *list;
12818
12819 if (argv_find(argv, argc, "exact-match", &idx))
12820 exact_match = 1;
12821
12822 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12823 COMMUNITY_LIST_MASTER);
12824 if (list == NULL) {
606d49a4 12825 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12826 clist_number_or_name);
12827 return CMD_WARNING;
12828 }
12829
12830 if (exact_match)
12831 sh_type = bgp_show_type_community_list_exact;
12832 else
12833 sh_type = bgp_show_type_community_list;
12834 output_arg = list;
12835 }
12836
a7129347
RW
12837 if (argv_find(argv, argc, "filter-list", &idx)) {
12838 const char *filter = argv[++idx]->arg;
12839 struct as_list *as_list;
12840
12841 as_list = as_list_lookup(filter);
12842 if (as_list == NULL) {
606d49a4 12843 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12844 filter);
12845 return CMD_WARNING;
12846 }
12847
12848 sh_type = bgp_show_type_filter_list;
12849 output_arg = as_list;
12850 }
12851
6deaf579
RW
12852 if (argv_find(argv, argc, "prefix-list", &idx)) {
12853 const char *prefix_list_str = argv[++idx]->arg;
12854 struct prefix_list *plist;
12855
12856 plist = prefix_list_lookup(afi, prefix_list_str);
12857 if (plist == NULL) {
606d49a4 12858 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12859 prefix_list_str);
12860 return CMD_WARNING;
12861 }
12862
12863 sh_type = bgp_show_type_prefix_list;
12864 output_arg = plist;
12865 }
12866
ed126382
DA
12867 if (argv_find(argv, argc, "access-list", &idx)) {
12868 const char *access_list_str = argv[++idx]->arg;
12869 struct access_list *alist;
12870
12871 alist = access_list_lookup(afi, access_list_str);
12872 if (!alist) {
606d49a4 12873 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12874 access_list_str);
12875 return CMD_WARNING;
12876 }
12877
12878 sh_type = bgp_show_type_access_list;
12879 output_arg = alist;
12880 }
12881
bf1a944a
RW
12882 if (argv_find(argv, argc, "route-map", &idx)) {
12883 const char *rmap_str = argv[++idx]->arg;
12884 struct route_map *rmap;
12885
12886 rmap = route_map_lookup_by_name(rmap_str);
12887 if (!rmap) {
606d49a4 12888 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12889 return CMD_WARNING;
12890 }
12891
12892 sh_type = bgp_show_type_route_map;
12893 output_arg = rmap;
12894 }
12895
1e2ce4f1
DS
12896 if (argv_find(argv, argc, "rpki", &idx)) {
12897 sh_type = bgp_show_type_rpki;
12898 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12899 rpki_target_state = RPKI_VALID;
1e2ce4f1 12900 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12901 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12902 }
12903
7d3cae70
DA
12904 /* Display prefixes with matching version numbers */
12905 if (argv_find(argv, argc, "version", &idx)) {
12906 sh_type = bgp_show_type_prefix_version;
2391833e 12907 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12908 }
12909
a70a28a5
DA
12910 /* Display prefixes with matching BGP community alias */
12911 if (argv_find(argv, argc, "alias", &idx)) {
12912 sh_type = bgp_show_type_community_alias;
2391833e 12913 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12914 }
12915
39c3c736
RW
12916 /* prefix-longer */
12917 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12918 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12919 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12920
12921 if (!str2prefix(prefix_str, &p)) {
12922 vty_out(vty, "%% Malformed Prefix\n");
12923 return CMD_WARNING;
12924 }
12925
12926 sh_type = bgp_show_type_prefix_longer;
12927 output_arg = &p;
a70a28a5
DA
12928 }
12929
83856649
KQ
12930 /* self originated only */
12931 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12932 sh_type = bgp_show_type_self_originated;
12933
96f3485c
MK
12934 if (!all) {
12935 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12936 if (community)
12937 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12938 exact_match, afi, safi,
12939 show_flags);
2391833e 12940 else
a70a28a5 12941 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12942 output_arg, show_flags,
a70a28a5 12943 rpki_target_state);
96f3485c 12944 } else {
fa5ac378
DA
12945 struct listnode *node;
12946 struct bgp *abgp;
96f3485c
MK
12947 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12948 * AFI_IP6 */
12949
12950 if (uj)
12951 vty_out(vty, "{\n");
12952
12953 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12954 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12955 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12956 ? AFI_IP
12957 : AFI_IP6;
fa5ac378
DA
12958 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12959 FOREACH_SAFI (safi) {
12960 if (!bgp_afi_safi_peer_exists(abgp, afi,
12961 safi))
12962 continue;
96f3485c 12963
fa5ac378
DA
12964 if (uj) {
12965 if (first)
12966 first = false;
12967 else
12968 vty_out(vty, ",\n");
12969 vty_out(vty, "\"%s\":{\n",
12970 get_afi_safi_str(afi,
12971 safi,
12972 true));
12973 } else
12974 vty_out(vty,
12975 "\nFor address family: %s\n",
12976 get_afi_safi_str(
12977 afi, safi,
12978 false));
12979
12980 if (community)
12981 bgp_show_community(
12982 vty, abgp, community,
12983 exact_match, afi, safi,
12984 show_flags);
96f3485c 12985 else
fa5ac378
DA
12986 bgp_show(vty, abgp, afi, safi,
12987 sh_type, output_arg,
12988 show_flags,
12989 rpki_target_state);
12990 if (uj)
12991 vty_out(vty, "}\n");
12992 }
96f3485c
MK
12993 }
12994 } else {
12995 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12996 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12997 FOREACH_AFI_SAFI (afi, safi) {
12998 if (!bgp_afi_safi_peer_exists(abgp, afi,
12999 safi))
13000 continue;
96f3485c 13001
fa5ac378
DA
13002 if (uj) {
13003 if (first)
13004 first = false;
13005 else
13006 vty_out(vty, ",\n");
13007
13008 vty_out(vty, "\"%s\":{\n",
13009 get_afi_safi_str(afi,
13010 safi,
13011 true));
13012 } else
13013 vty_out(vty,
13014 "\nFor address family: %s\n",
13015 get_afi_safi_str(
13016 afi, safi,
13017 false));
13018
13019 if (community)
13020 bgp_show_community(
13021 vty, abgp, community,
13022 exact_match, afi, safi,
13023 show_flags);
96f3485c 13024 else
fa5ac378
DA
13025 bgp_show(vty, abgp, afi, safi,
13026 sh_type, output_arg,
13027 show_flags,
13028 rpki_target_state);
13029 if (uj)
13030 vty_out(vty, "}\n");
13031 }
96f3485c
MK
13032 }
13033 }
13034 if (uj)
13035 vty_out(vty, "}\n");
13036 }
13037 return CMD_SUCCESS;
a636c635 13038}
47fc97cc 13039
718e3744 13040DEFUN (show_ip_bgp_route,
13041 show_ip_bgp_route_cmd,
8aa22bbb 13042 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
718e3744 13043 SHOW_STR
13044 IP_STR
13045 BGP_STR
a636c635 13046 BGP_INSTANCE_HELP_STR
4f280b15 13047 BGP_AFI_HELP_STR
4dd6177e 13048 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13049 "Network in the BGP routing table to display\n"
0c7b1b01 13050 "IPv4 prefix\n"
8c3deaae 13051 "Network in the BGP routing table to display\n"
0c7b1b01 13052 "IPv6 prefix\n"
4092b06c 13053 "Display only the bestpath\n"
b05a1c8b 13054 "Display only multipaths\n"
8aa22bbb
DS
13055 "Display only paths that match the specified rpki state\n"
13056 "A valid path as determined by rpki\n"
13057 "A invalid path as determined by rpki\n"
13058 "A path that has no rpki data\n"
9973d184 13059 JSON_STR)
4092b06c 13060{
d62a17ae 13061 int prefix_check = 0;
ae19d7dd 13062
d62a17ae 13063 afi_t afi = AFI_IP6;
13064 safi_t safi = SAFI_UNICAST;
13065 char *prefix = NULL;
13066 struct bgp *bgp = NULL;
13067 enum bgp_path_type path_type;
9f049418 13068 bool uj = use_json(argc, argv);
b05a1c8b 13069
d62a17ae 13070 int idx = 0;
ae19d7dd 13071
d62a17ae 13072 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13073 &bgp, uj);
d62a17ae 13074 if (!idx)
13075 return CMD_WARNING;
c41247f5 13076
d62a17ae 13077 if (!bgp) {
13078 vty_out(vty,
13079 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13080 return CMD_WARNING;
13081 }
a636c635 13082
d62a17ae 13083 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13084 if (argv_find(argv, argc, "A.B.C.D", &idx)
13085 || argv_find(argv, argc, "X:X::X:X", &idx))
13086 prefix_check = 0;
13087 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13088 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13089 prefix_check = 1;
13090
13091 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13092 && afi != AFI_IP6) {
13093 vty_out(vty,
13094 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13095 return CMD_WARNING;
13096 }
13097 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13098 && afi != AFI_IP) {
13099 vty_out(vty,
13100 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13101 return CMD_WARNING;
13102 }
13103
13104 prefix = argv[idx]->arg;
13105
13106 /* [<bestpath|multipath>] */
13107 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13108 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13109 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13110 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13111 else
360660c6 13112 path_type = BGP_PATH_SHOW_ALL;
a636c635 13113
d62a17ae 13114 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13115 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13116}
13117
8c3deaae
QY
13118DEFUN (show_ip_bgp_regexp,
13119 show_ip_bgp_regexp_cmd,
3e5b31b3 13120 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13121 SHOW_STR
13122 IP_STR
13123 BGP_STR
b00b230a 13124 BGP_INSTANCE_HELP_STR
4f280b15 13125 BGP_AFI_HELP_STR
4dd6177e 13126 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13127 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13128 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13129 JSON_STR)
8c3deaae 13130{
d62a17ae 13131 afi_t afi = AFI_IP6;
13132 safi_t safi = SAFI_UNICAST;
13133 struct bgp *bgp = NULL;
3e5b31b3
DA
13134 bool uj = use_json(argc, argv);
13135 char *regstr = NULL;
8c3deaae 13136
d62a17ae 13137 int idx = 0;
13138 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13139 &bgp, false);
d62a17ae 13140 if (!idx)
13141 return CMD_WARNING;
8c3deaae 13142
d62a17ae 13143 // get index of regex
3e5b31b3
DA
13144 if (argv_find(argv, argc, "REGEX", &idx))
13145 regstr = argv[idx]->arg;
8c3deaae 13146
5f71d11c 13147 assert(regstr);
3e5b31b3
DA
13148 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13149 bgp_show_type_regexp, uj);
8c3deaae
QY
13150}
13151
ae248832 13152DEFPY (show_ip_bgp_instance_all,
a636c635 13153 show_ip_bgp_instance_all_cmd,
ae248832 13154 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13155 SHOW_STR
a636c635 13156 IP_STR
4092b06c 13157 BGP_STR
a636c635 13158 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13159 BGP_AFI_HELP_STR
4dd6177e 13160 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13161 JSON_STR
13162 "Increase table width for longer prefixes\n")
4092b06c 13163{
54d05dea 13164 afi_t afi = AFI_IP6;
d62a17ae 13165 safi_t safi = SAFI_UNICAST;
13166 struct bgp *bgp = NULL;
d62a17ae 13167 int idx = 0;
96c81f66 13168 uint16_t show_flags = 0;
ae19d7dd 13169
96f3485c 13170 if (uj) {
d62a17ae 13171 argc--;
96f3485c
MK
13172 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13173 }
13174
13175 if (wide)
13176 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13177
9f049418
DS
13178 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13179 &bgp, uj);
13180 if (!idx)
13181 return CMD_WARNING;
13182
96f3485c 13183 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13184 return CMD_SUCCESS;
e3e29b32
LB
13185}
13186
a4d82a8a 13187static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13188 afi_t afi, safi_t safi, enum bgp_show_type type,
13189 bool use_json)
718e3744 13190{
d62a17ae 13191 regex_t *regex;
13192 int rc;
96c81f66 13193 uint16_t show_flags = 0;
96f3485c
MK
13194
13195 if (use_json)
13196 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13197
c3900853 13198 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13199 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13200 regstr);
13201 return CMD_WARNING_CONFIG_FAILED;
13202 }
13203
d62a17ae 13204 regex = bgp_regcomp(regstr);
13205 if (!regex) {
13206 vty_out(vty, "Can't compile regexp %s\n", regstr);
13207 return CMD_WARNING;
13208 }
a636c635 13209
1e2ce4f1
DS
13210 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13211 RPKI_NOT_BEING_USED);
d62a17ae 13212 bgp_regex_free(regex);
13213 return rc;
e3e29b32
LB
13214}
13215
7f323236
DW
13216static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13217 const char *comstr, int exact, afi_t afi,
96c81f66 13218 safi_t safi, uint16_t show_flags)
d62a17ae 13219{
13220 struct community *com;
d62a17ae 13221 int ret = 0;
13222
7f323236 13223 com = community_str2com(comstr);
d62a17ae 13224 if (!com) {
7f323236 13225 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13226 return CMD_WARNING;
13227 }
13228
13229 ret = bgp_show(vty, bgp, afi, safi,
13230 (exact ? bgp_show_type_community_exact
13231 : bgp_show_type_community),
1e2ce4f1 13232 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13233 community_free(&com);
46c3ce83 13234
d62a17ae 13235 return ret;
718e3744 13236}
13237
d62a17ae 13238enum bgp_stats {
13239 BGP_STATS_MAXBITLEN = 0,
13240 BGP_STATS_RIB,
13241 BGP_STATS_PREFIXES,
13242 BGP_STATS_TOTPLEN,
13243 BGP_STATS_UNAGGREGATEABLE,
13244 BGP_STATS_MAX_AGGREGATEABLE,
13245 BGP_STATS_AGGREGATES,
13246 BGP_STATS_SPACE,
13247 BGP_STATS_ASPATH_COUNT,
13248 BGP_STATS_ASPATH_MAXHOPS,
13249 BGP_STATS_ASPATH_TOTHOPS,
13250 BGP_STATS_ASPATH_MAXSIZE,
13251 BGP_STATS_ASPATH_TOTSIZE,
13252 BGP_STATS_ASN_HIGHEST,
13253 BGP_STATS_MAX,
a636c635 13254};
2815e61f 13255
9ab0cf58 13256#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13257#define TABLE_STATS_IDX_JSON 1
13258
13259static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13260 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13261 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13262 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13263 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13264 "unaggregateablePrefixes"},
13265 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13266 "maximumAggregateablePrefixes"},
13267 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13268 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13269 [BGP_STATS_SPACE] = {"Address space advertised",
13270 "addressSpaceAdvertised"},
9ab0cf58
PG
13271 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13272 "advertisementsWithPaths"},
13273 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13274 "longestAsPath"},
13275 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13276 "largestAsPath"},
13277 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13278 "averageAsPathLengthHops"},
13279 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13280 "averageAsPathSizeBytes"},
13281 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13282 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13283};
2815e61f 13284
d62a17ae 13285struct bgp_table_stats {
13286 struct bgp_table *table;
13287 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13288
13289 unsigned long long
13290 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13291 1];
13292
8d0ab76d 13293 double total_space;
ff7924f6
PJ
13294};
13295
9bcb3eef 13296static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13297 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13298{
9bcb3eef 13299 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13300 struct bgp_path_info *pi;
b54892e0 13301 const struct prefix *rn_p;
d62a17ae 13302
9bcb3eef 13303 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13304 return;
d62a17ae 13305
9bcb3eef 13306 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13307 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13308 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13309
0747643e 13310 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13311 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13312 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13313 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13314
9bcb3eef 13315 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13316 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13317 /* announced address space */
13318 if (space)
b54892e0 13319 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13320 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13321 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13322
9c14ec72 13323
9bcb3eef 13324 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13325 ts->counts[BGP_STATS_RIB]++;
13326
05864da7
DS
13327 if (CHECK_FLAG(pi->attr->flag,
13328 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13329 ts->counts[BGP_STATS_AGGREGATES]++;
13330
13331 /* as-path stats */
05864da7 13332 if (pi->attr->aspath) {
9c14ec72
RW
13333 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13334 unsigned int size = aspath_size(pi->attr->aspath);
13335 as_t highest = aspath_highest(pi->attr->aspath);
13336
13337 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13338
13339 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13340 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13341
13342 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13343 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13344
13345 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13346 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13347 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13348 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13349 }
13350 }
13351}
13352
cc9f21da 13353static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13354{
9bcb3eef
DS
13355 struct bgp_dest *dest, *ndest;
13356 struct bgp_dest *top;
9c14ec72
RW
13357 struct bgp_table_stats *ts = THREAD_ARG(t);
13358 unsigned int space = 0;
13359
13360 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13361 return;
9c14ec72
RW
13362
13363 switch (ts->table->afi) {
13364 case AFI_IP:
13365 space = IPV4_MAX_BITLEN;
13366 break;
13367 case AFI_IP6:
13368 space = IPV6_MAX_BITLEN;
13369 break;
3ba7b4af
TA
13370 case AFI_L2VPN:
13371 space = EVPN_ROUTE_PREFIXLEN;
13372 break;
58cf0823
DS
13373 case AFI_UNSPEC:
13374 case AFI_MAX:
cc9f21da 13375 return;
9c14ec72
RW
13376 }
13377
13378 ts->counts[BGP_STATS_MAXBITLEN] = space;
13379
9bcb3eef 13380 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13381 if (ts->table->safi == SAFI_MPLS_VPN
13382 || ts->table->safi == SAFI_ENCAP
13383 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13384 struct bgp_table *table;
13385
9bcb3eef 13386 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13387 if (!table)
13388 continue;
13389
13390 top = bgp_table_top(table);
9bcb3eef
DS
13391 for (ndest = bgp_table_top(table); ndest;
13392 ndest = bgp_route_next(ndest))
13393 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13394 } else {
9bcb3eef 13395 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13396 }
13397 }
2815e61f 13398}
ff7924f6 13399
71f1613a
DA
13400static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13401 struct json_object *json_array)
13402{
13403 struct listnode *node, *nnode;
13404 struct bgp *bgp;
13405
13406 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13407 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13408}
13409
13410static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13411 safi_t safi, struct json_object *json_array)
2815e61f 13412{
d62a17ae 13413 struct bgp_table_stats ts;
13414 unsigned int i;
893cccd0
PG
13415 int ret = CMD_SUCCESS;
13416 char temp_buf[20];
6c9d22e2 13417 struct json_object *json = NULL;
0747643e
AQ
13418 uint32_t bitlen = 0;
13419 struct json_object *json_bitlen;
6c9d22e2
PG
13420
13421 if (json_array)
13422 json = json_object_new_object();
019386c2 13423
d62a17ae 13424 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13425 char warning_msg[50];
13426
13427 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13428 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13429 safi);
6c9d22e2
PG
13430
13431 if (!json)
893cccd0
PG
13432 vty_out(vty, "%s\n", warning_msg);
13433 else
9ab0cf58 13434 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13435
893cccd0
PG
13436 ret = CMD_WARNING;
13437 goto end_table_stats;
d62a17ae 13438 }
019386c2 13439
893cccd0 13440 if (!json)
5290ceab
DA
13441 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13442 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13443 else
13444 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13445
d62a17ae 13446 /* labeled-unicast routes live in the unicast table */
13447 if (safi == SAFI_LABELED_UNICAST)
13448 safi = SAFI_UNICAST;
019386c2 13449
d62a17ae 13450 memset(&ts, 0, sizeof(ts));
13451 ts.table = bgp->rib[afi][safi];
13452 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13453
d62a17ae 13454 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13455 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13456 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13457 continue;
13458
13459 switch (i) {
d62a17ae 13460 case BGP_STATS_ASPATH_TOTHOPS:
13461 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13462 if (!json) {
9ab0cf58
PG
13463 snprintf(
13464 temp_buf, sizeof(temp_buf), "%12.2f",
13465 ts.counts[i]
13466 ? (float)ts.counts[i]
13467 / (float)ts.counts
13468 [BGP_STATS_ASPATH_COUNT]
13469 : 0);
893cccd0 13470 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13471 table_stats_strs[i]
13472 [TABLE_STATS_IDX_VTY],
893cccd0 13473 temp_buf);
9ab0cf58
PG
13474 } else {
13475 json_object_double_add(
13476 json,
13477 table_stats_strs[i]
13478 [TABLE_STATS_IDX_JSON],
13479 ts.counts[i]
13480 ? (double)ts.counts[i]
13481 / (double)ts.counts
d62a17ae 13482 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13483 : 0);
13484 }
d62a17ae 13485 break;
13486 case BGP_STATS_TOTPLEN:
6c9d22e2 13487 if (!json) {
9ab0cf58
PG
13488 snprintf(
13489 temp_buf, sizeof(temp_buf), "%12.2f",
13490 ts.counts[i]
13491 ? (float)ts.counts[i]
13492 / (float)ts.counts
13493 [BGP_STATS_PREFIXES]
13494 : 0);
893cccd0 13495 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13496 table_stats_strs[i]
13497 [TABLE_STATS_IDX_VTY],
893cccd0 13498 temp_buf);
9ab0cf58
PG
13499 } else {
13500 json_object_double_add(
13501 json,
13502 table_stats_strs[i]
13503 [TABLE_STATS_IDX_JSON],
13504 ts.counts[i]
13505 ? (double)ts.counts[i]
13506 / (double)ts.counts
d62a17ae 13507 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13508 : 0);
13509 }
d62a17ae 13510 break;
13511 case BGP_STATS_SPACE:
6c9d22e2
PG
13512 if (!json) {
13513 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13514 ts.total_space);
893cccd0 13515 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13516 table_stats_strs[i]
13517 [TABLE_STATS_IDX_VTY],
893cccd0 13518 temp_buf);
9ab0cf58
PG
13519 } else {
13520 json_object_double_add(
13521 json,
13522 table_stats_strs[i]
13523 [TABLE_STATS_IDX_JSON],
13524 (double)ts.total_space);
13525 }
8d0ab76d 13526 if (afi == AFI_IP6) {
6c9d22e2
PG
13527 if (!json) {
13528 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13529 "%12g",
13530 ts.total_space
13531 * pow(2.0, -128 + 32));
6c9d22e2
PG
13532 vty_out(vty, "%30s: %s\n",
13533 "/32 equivalent %s\n",
13534 temp_buf);
9ab0cf58
PG
13535 } else {
13536 json_object_double_add(
13537 json, "/32equivalent",
13538 (double)(ts.total_space
13539 * pow(2.0,
13540 -128 + 32)));
13541 }
6c9d22e2
PG
13542 if (!json) {
13543 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13544 "%12g",
13545 ts.total_space
13546 * pow(2.0, -128 + 48));
6c9d22e2
PG
13547 vty_out(vty, "%30s: %s\n",
13548 "/48 equivalent %s\n",
13549 temp_buf);
9ab0cf58
PG
13550 } else {
13551 json_object_double_add(
13552 json, "/48equivalent",
13553 (double)(ts.total_space
13554 * pow(2.0,
13555 -128 + 48)));
13556 }
8d0ab76d 13557 } else {
6c9d22e2
PG
13558 if (!json) {
13559 snprintf(temp_buf, sizeof(temp_buf),
13560 "%12.2f",
9ab0cf58
PG
13561 ts.total_space * 100.
13562 * pow(2.0, -32));
6c9d22e2 13563 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13564 "% announced ", temp_buf);
13565 } else {
13566 json_object_double_add(
13567 json, "%announced",
13568 (double)(ts.total_space * 100.
13569 * pow(2.0, -32)));
13570 }
6c9d22e2
PG
13571 if (!json) {
13572 snprintf(temp_buf, sizeof(temp_buf),
13573 "%12.2f",
9ab0cf58
PG
13574 ts.total_space
13575 * pow(2.0, -32 + 8));
6c9d22e2
PG
13576 vty_out(vty, "%30s: %s\n",
13577 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13578 } else {
13579 json_object_double_add(
13580 json, "/8equivalent",
13581 (double)(ts.total_space
13582 * pow(2.0, -32 + 8)));
13583 }
6c9d22e2
PG
13584 if (!json) {
13585 snprintf(temp_buf, sizeof(temp_buf),
13586 "%12.2f",
9ab0cf58
PG
13587 ts.total_space
13588 * pow(2.0, -32 + 24));
6c9d22e2 13589 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13590 "/24 equivalent ", temp_buf);
13591 } else {
13592 json_object_double_add(
13593 json, "/24equivalent",
13594 (double)(ts.total_space
13595 * pow(2.0, -32 + 24)));
13596 }
8d0ab76d 13597 }
d62a17ae 13598 break;
13599 default:
6c9d22e2
PG
13600 if (!json) {
13601 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13602 ts.counts[i]);
893cccd0 13603 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13604 table_stats_strs[i]
13605 [TABLE_STATS_IDX_VTY],
13606 temp_buf);
13607 } else {
13608 json_object_int_add(
13609 json,
13610 table_stats_strs[i]
13611 [TABLE_STATS_IDX_JSON],
13612 ts.counts[i]);
13613 }
d62a17ae 13614 }
893cccd0
PG
13615 if (!json)
13616 vty_out(vty, "\n");
d62a17ae 13617 }
0747643e
AQ
13618
13619 switch (afi) {
13620 case AFI_IP:
13621 bitlen = IPV4_MAX_BITLEN;
13622 break;
13623 case AFI_IP6:
13624 bitlen = IPV6_MAX_BITLEN;
13625 break;
13626 case AFI_L2VPN:
13627 bitlen = EVPN_ROUTE_PREFIXLEN;
13628 break;
58cf0823
DS
13629 case AFI_UNSPEC:
13630 case AFI_MAX:
0747643e
AQ
13631 break;
13632 }
13633
13634 if (json) {
13635 json_bitlen = json_object_new_array();
13636
13637 for (i = 0; i <= bitlen; i++) {
13638 struct json_object *ind_bit = json_object_new_object();
13639
13640 if (!ts.prefix_len_count[i])
13641 continue;
13642
13643 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13644 json_object_int_add(ind_bit, temp_buf,
13645 ts.prefix_len_count[i]);
13646 json_object_array_add(json_bitlen, ind_bit);
13647 }
13648 json_object_object_add(json, "prefixLength", json_bitlen);
13649 }
13650
9ab0cf58 13651end_table_stats:
6c9d22e2
PG
13652 if (json)
13653 json_object_array_add(json_array, json);
893cccd0 13654 return ret;
d62a17ae 13655}
13656
71f1613a
DA
13657static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13658 safi_t safi, struct json_object *json_array)
13659{
13660 if (!bgp) {
13661 bgp_table_stats_all(vty, afi, safi, json_array);
13662 return CMD_SUCCESS;
13663 }
13664
13665 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13666}
13667
d62a17ae 13668enum bgp_pcounts {
13669 PCOUNT_ADJ_IN = 0,
13670 PCOUNT_DAMPED,
13671 PCOUNT_REMOVED,
13672 PCOUNT_HISTORY,
13673 PCOUNT_STALE,
13674 PCOUNT_VALID,
13675 PCOUNT_ALL,
13676 PCOUNT_COUNTED,
7e3d9632 13677 PCOUNT_BPATH_SELECTED,
d62a17ae 13678 PCOUNT_PFCNT, /* the figure we display to users */
13679 PCOUNT_MAX,
a636c635 13680};
718e3744 13681
2b64873d 13682static const char *const pcount_strs[] = {
9d303b37
DL
13683 [PCOUNT_ADJ_IN] = "Adj-in",
13684 [PCOUNT_DAMPED] = "Damped",
13685 [PCOUNT_REMOVED] = "Removed",
13686 [PCOUNT_HISTORY] = "History",
13687 [PCOUNT_STALE] = "Stale",
13688 [PCOUNT_VALID] = "Valid",
13689 [PCOUNT_ALL] = "All RIB",
13690 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13691 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13692 [PCOUNT_PFCNT] = "Useable",
13693 [PCOUNT_MAX] = NULL,
a636c635 13694};
718e3744 13695
d62a17ae 13696struct peer_pcounts {
13697 unsigned int count[PCOUNT_MAX];
13698 const struct peer *peer;
13699 const struct bgp_table *table;
54317cba 13700 safi_t safi;
a636c635 13701};
47fc97cc 13702
9bcb3eef 13703static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13704{
54317cba
JW
13705 const struct bgp_adj_in *ain;
13706 const struct bgp_path_info *pi;
d62a17ae 13707 const struct peer *peer = pc->peer;
13708
54317cba
JW
13709 for (ain = rn->adj_in; ain; ain = ain->next)
13710 if (ain->peer == peer)
13711 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13712
9bcb3eef 13713 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13714
54317cba
JW
13715 if (pi->peer != peer)
13716 continue;
d62a17ae 13717
54317cba 13718 pc->count[PCOUNT_ALL]++;
d62a17ae 13719
54317cba
JW
13720 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13721 pc->count[PCOUNT_DAMPED]++;
13722 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13723 pc->count[PCOUNT_HISTORY]++;
13724 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13725 pc->count[PCOUNT_REMOVED]++;
13726 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13727 pc->count[PCOUNT_STALE]++;
13728 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13729 pc->count[PCOUNT_VALID]++;
13730 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13731 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13732 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13733 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13734
13735 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13736 pc->count[PCOUNT_COUNTED]++;
13737 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13738 flog_err(
13739 EC_LIB_DEVELOPMENT,
13740 "Attempting to count but flags say it is unusable");
13741 } else {
40381db7 13742 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13743 flog_err(
13744 EC_LIB_DEVELOPMENT,
13745 "Not counted but flags say we should");
d62a17ae 13746 }
13747 }
54317cba
JW
13748}
13749
cc9f21da 13750static void bgp_peer_count_walker(struct thread *t)
54317cba 13751{
9bcb3eef 13752 struct bgp_dest *rn, *rm;
54317cba
JW
13753 const struct bgp_table *table;
13754 struct peer_pcounts *pc = THREAD_ARG(t);
13755
13756 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13757 || pc->safi == SAFI_EVPN) {
13758 /* Special handling for 2-level routing tables. */
13759 for (rn = bgp_table_top(pc->table); rn;
13760 rn = bgp_route_next(rn)) {
9bcb3eef 13761 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13762 if (table != NULL)
13763 for (rm = bgp_table_top(table); rm;
13764 rm = bgp_route_next(rm))
13765 bgp_peer_count_proc(rm, pc);
13766 }
13767 } else
13768 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13769 bgp_peer_count_proc(rn, pc);
718e3744 13770}
13771
d62a17ae 13772static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13773 safi_t safi, bool use_json)
856ca177 13774{
d62a17ae 13775 struct peer_pcounts pcounts = {.peer = peer};
13776 unsigned int i;
13777 json_object *json = NULL;
13778 json_object *json_loop = NULL;
856ca177 13779
d62a17ae 13780 if (use_json) {
13781 json = json_object_new_object();
13782 json_loop = json_object_new_object();
13783 }
718e3744 13784
d62a17ae 13785 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13786 || !peer->bgp->rib[afi][safi]) {
13787 if (use_json) {
13788 json_object_string_add(
13789 json, "warning",
13790 "No such neighbor or address family");
13791 vty_out(vty, "%s\n", json_object_to_json_string(json));
13792 json_object_free(json);
d5f20468 13793 json_object_free(json_loop);
d62a17ae 13794 } else
13795 vty_out(vty, "%% No such neighbor or address family\n");
13796
13797 return CMD_WARNING;
13798 }
2a71e9ce 13799
d62a17ae 13800 memset(&pcounts, 0, sizeof(pcounts));
13801 pcounts.peer = peer;
13802 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13803 pcounts.safi = safi;
d62a17ae 13804
13805 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13806 * stats for the thread-walk (i.e. ensure this can't be blamed on
13807 * on just vty_read()).
13808 */
d62a17ae 13809 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13810
13811 if (use_json) {
13812 json_object_string_add(json, "prefixCountsFor", peer->host);
13813 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13814 get_afi_safi_str(afi, safi, true));
d62a17ae 13815 json_object_int_add(json, "pfxCounter",
13816 peer->pcount[afi][safi]);
13817
13818 for (i = 0; i < PCOUNT_MAX; i++)
13819 json_object_int_add(json_loop, pcount_strs[i],
13820 pcounts.count[i]);
13821
13822 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13823
13824 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13825 json_object_string_add(json, "pfxctDriftFor",
13826 peer->host);
13827 json_object_string_add(
13828 json, "recommended",
13829 "Please report this bug, with the above command output");
13830 }
75eeda93 13831 vty_json(vty, json);
d62a17ae 13832 } else {
13833
13834 if (peer->hostname
892fedb6 13835 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13836 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13837 peer->hostname, peer->host,
5cb5f4d0 13838 get_afi_safi_str(afi, safi, false));
d62a17ae 13839 } else {
13840 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13841 get_afi_safi_str(afi, safi, false));
d62a17ae 13842 }
13843
6cde4b45 13844 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13845 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13846
13847 for (i = 0; i < PCOUNT_MAX; i++)
13848 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13849 pcounts.count[i]);
13850
13851 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13852 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13853 vty_out(vty,
13854 "Please report this bug, with the above command output\n");
13855 }
13856 }
13857
13858 return CMD_SUCCESS;
718e3744 13859}
13860
a636c635
DW
13861DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13862 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13863 "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 13864 SHOW_STR
13865 IP_STR
13866 BGP_STR
8386ac43 13867 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13868 BGP_AFI_HELP_STR
13869 BGP_SAFI_HELP_STR
0b16f239
DS
13870 "Detailed information on TCP and BGP neighbor connections\n"
13871 "Neighbor to display information about\n"
13872 "Neighbor to display information about\n"
91d37724 13873 "Neighbor on BGP configured interface\n"
a636c635 13874 "Display detailed prefix count information\n"
9973d184 13875 JSON_STR)
0b16f239 13876{
d62a17ae 13877 afi_t afi = AFI_IP6;
13878 safi_t safi = SAFI_UNICAST;
13879 struct peer *peer;
13880 int idx = 0;
13881 struct bgp *bgp = NULL;
9f049418
DS
13882 bool uj = use_json(argc, argv);
13883
13884 if (uj)
13885 argc--;
856ca177 13886
d62a17ae 13887 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13888 &bgp, uj);
d62a17ae 13889 if (!idx)
13890 return CMD_WARNING;
0b16f239 13891
d62a17ae 13892 argv_find(argv, argc, "neighbors", &idx);
13893 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13894 if (!peer)
13895 return CMD_WARNING;
bb46e94f 13896
29c8d9da 13897 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13898}
0b16f239 13899
d6902373
PG
13900#ifdef KEEP_OLD_VPN_COMMANDS
13901DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13902 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13903 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13904 SHOW_STR
13905 IP_STR
13906 BGP_STR
d6902373 13907 BGP_VPNVX_HELP_STR
91d37724 13908 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13909 "Detailed information on TCP and BGP neighbor connections\n"
13910 "Neighbor to display information about\n"
13911 "Neighbor to display information about\n"
91d37724 13912 "Neighbor on BGP configured interface\n"
a636c635 13913 "Display detailed prefix count information\n"
9973d184 13914 JSON_STR)
a636c635 13915{
d62a17ae 13916 int idx_peer = 6;
13917 struct peer *peer;
9f049418 13918 bool uj = use_json(argc, argv);
a636c635 13919
d62a17ae 13920 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13921 if (!peer)
13922 return CMD_WARNING;
13923
13924 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13925}
13926
d6902373
PG
13927DEFUN (show_ip_bgp_vpn_all_route_prefix,
13928 show_ip_bgp_vpn_all_route_prefix_cmd,
13929 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13930 SHOW_STR
13931 IP_STR
13932 BGP_STR
d6902373 13933 BGP_VPNVX_HELP_STR
91d37724
QY
13934 "Display information about all VPNv4 NLRIs\n"
13935 "Network in the BGP routing table to display\n"
3a2d747c 13936 "Network in the BGP routing table to display\n"
9973d184 13937 JSON_STR)
91d37724 13938{
d62a17ae 13939 int idx = 0;
13940 char *network = NULL;
13941 struct bgp *bgp = bgp_get_default();
13942 if (!bgp) {
13943 vty_out(vty, "Can't find default instance\n");
13944 return CMD_WARNING;
13945 }
87e34b58 13946
d62a17ae 13947 if (argv_find(argv, argc, "A.B.C.D", &idx))
13948 network = argv[idx]->arg;
13949 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13950 network = argv[idx]->arg;
13951 else {
13952 vty_out(vty, "Unable to figure out Network\n");
13953 return CMD_WARNING;
13954 }
87e34b58 13955
d62a17ae 13956 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13957 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13958 use_json(argc, argv));
91d37724 13959}
d6902373 13960#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13961
44c69747
LK
13962DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13963 show_bgp_l2vpn_evpn_route_prefix_cmd,
13964 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13965 SHOW_STR
4c63a661
PG
13966 BGP_STR
13967 L2VPN_HELP_STR
13968 EVPN_HELP_STR
44c69747
LK
13969 "Network in the BGP routing table to display\n"
13970 "Network in the BGP routing table to display\n"
4c63a661
PG
13971 "Network in the BGP routing table to display\n"
13972 "Network in the BGP routing table to display\n"
13973 JSON_STR)
13974{
d62a17ae 13975 int idx = 0;
13976 char *network = NULL;
44c69747 13977 int prefix_check = 0;
a636c635 13978
44c69747
LK
13979 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13980 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13981 network = argv[idx]->arg;
44c69747 13982 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13983 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13984 network = argv[idx]->arg;
44c69747
LK
13985 prefix_check = 1;
13986 } else {
d62a17ae 13987 vty_out(vty, "Unable to figure out Network\n");
13988 return CMD_WARNING;
13989 }
44c69747
LK
13990 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13991 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13992 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13993}
13994
114fc229 13995static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13996 struct bgp_table *table, int *header1,
13997 int *header2, json_object *json,
13998 json_object *json_scode,
e960b4ca
TA
13999 json_object *json_ocode, bool wide,
14000 bool detail)
2f9bc755
DS
14001{
14002 uint64_t version = table ? table->version : 0;
14003
14004 if (*header1) {
14005 if (json) {
14006 json_object_int_add(json, "bgpTableVersion", version);
c949c771 14007 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 14008 "%pI4", &peer->bgp->router_id);
2f9bc755 14009 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
14010 peer->bgp->default_local_pref);
14011 json_object_int_add(json, "localAS",
14012 peer->change_local_as
14013 ? peer->change_local_as
14014 : peer->local_as);
2f9bc755
DS
14015 json_object_object_add(json, "bgpStatusCodes",
14016 json_scode);
14017 json_object_object_add(json, "bgpOriginCodes",
14018 json_ocode);
14019 } else {
14020 vty_out(vty,
23d0a753
DA
14021 "BGP table version is %" PRIu64
14022 ", local router ID is %pI4, vrf id ",
114fc229
DA
14023 version, &peer->bgp->router_id);
14024 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
14025 vty_out(vty, "%s", VRFID_NONE_STR);
14026 else
114fc229 14027 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14028 vty_out(vty, "\n");
14029 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14030 peer->bgp->default_local_pref);
14031 vty_out(vty, "local AS %u\n",
14032 peer->change_local_as ? peer->change_local_as
14033 : peer->local_as);
e960b4ca
TA
14034 if (!detail) {
14035 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14036 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14037 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14038 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14039 }
2f9bc755
DS
14040 }
14041 *header1 = 0;
14042 }
14043 if (*header2) {
e960b4ca 14044 if (!json && !detail)
2f9bc755
DS
14045 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14046 : BGP_SHOW_HEADER));
14047 *header2 = 0;
14048 }
14049}
14050
d9478df0
TA
14051static void
14052show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14053 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14054 const char *rmap_name, json_object *json, json_object *json_ar,
14055 json_object *json_scode, json_object *json_ocode,
96c81f66 14056 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14057 const struct prefix *match, unsigned long *output_count,
14058 unsigned long *filtered_count)
d62a17ae 14059{
3880b4ec
TA
14060 struct bgp_adj_in *ain = NULL;
14061 struct bgp_adj_out *adj = NULL;
9bcb3eef 14062 struct bgp_dest *dest;
d62a17ae 14063 struct bgp *bgp;
d62a17ae 14064 struct attr attr;
14065 int ret;
14066 struct update_subgroup *subgrp;
3880b4ec 14067 struct peer_af *paf = NULL;
f99def61 14068 bool route_filtered;
e960b4ca 14069 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14070 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14071 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14072 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14073 || (safi == SAFI_EVPN))
14074 ? true
14075 : false;
e960b4ca
TA
14076 int display = 0;
14077 json_object *json_net = NULL;
a636c635 14078
d62a17ae 14079 bgp = peer->bgp;
a636c635 14080
3880b4ec
TA
14081 /* If the user supplied a prefix, look for a matching route instead
14082 * of walking the whole table.
14083 */
14084 if (match) {
14085 dest = bgp_node_match(table, match);
14086 if (!dest) {
14087 if (!use_json)
14088 vty_out(vty, "Network not in table\n");
14089 return;
14090 }
14091
14092 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14093
14094 if (rn_p->prefixlen != match->prefixlen) {
14095 if (!use_json)
14096 vty_out(vty, "Network not in table\n");
14097 bgp_dest_unlock_node(dest);
14098 return;
14099 }
14100
14101 if (type == bgp_show_adj_route_received ||
14102 type == bgp_show_adj_route_filtered) {
14103 for (ain = dest->adj_in; ain; ain = ain->next) {
14104 if (ain->peer == peer) {
14105 attr = *ain->attr;
14106 break;
14107 }
14108 }
14109 /* bail out if if adj_out is empty, or
14110 * if the prefix isn't in this peer's
14111 * adj_in
14112 */
14113 if (!ain || ain->peer != peer) {
14114 if (!use_json)
14115 vty_out(vty, "Network not in table\n");
14116 bgp_dest_unlock_node(dest);
14117 return;
14118 }
14119 } else if (type == bgp_show_adj_route_advertised) {
14120 bool peer_found = false;
14121
14122 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14123 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14124 if (paf->peer == peer && adj->attr) {
14125 attr = *adj->attr;
14126 peer_found = true;
14127 break;
14128 }
14129 }
14130 if (peer_found)
14131 break;
14132 }
14133 /* bail out if if adj_out is empty, or
14134 * if the prefix isn't in this peer's
14135 * adj_out
14136 */
14137 if (!paf || !peer_found) {
14138 if (!use_json)
14139 vty_out(vty, "Network not in table\n");
14140 bgp_dest_unlock_node(dest);
14141 return;
14142 }
14143 }
14144
14145 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14146 rmap_name);
14147
14148 if (ret != RMAP_DENY) {
14149 show_adj_route_header(vty, peer, table, header1,
14150 header2, json, json_scode,
14151 json_ocode, wide, detail);
14152
14153 if (use_json)
14154 json_net = json_object_new_object();
14155
14156 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14157 afi, safi, json_net,
14158 BGP_PATH_SHOW_ALL, &display,
14159 RPKI_NOT_BEING_USED);
14160 if (use_json)
14161 json_object_object_addf(json_ar, json_net,
14162 "%pFX", rn_p);
14163 (*output_count)++;
14164 } else
14165 (*filtered_count)++;
14166
14167 bgp_attr_flush(&attr);
14168 bgp_dest_unlock_node(dest);
14169 return;
14170 }
14171
14172
d62a17ae 14173 subgrp = peer_subgroup(peer, afi, safi);
14174
6392aaa6 14175 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14176 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14177 if (use_json) {
14178 json_object_int_add(json, "bgpTableVersion",
14179 table->version);
c949c771
DA
14180 json_object_string_addf(json, "bgpLocalRouterId",
14181 "%pI4", &bgp->router_id);
01eced22
AD
14182 json_object_int_add(json, "defaultLocPrf",
14183 bgp->default_local_pref);
114fc229
DA
14184 json_object_int_add(json, "localAS",
14185 peer->change_local_as
14186 ? peer->change_local_as
14187 : peer->local_as);
d62a17ae 14188 json_object_object_add(json, "bgpStatusCodes",
14189 json_scode);
14190 json_object_object_add(json, "bgpOriginCodes",
14191 json_ocode);
07d0c4ed
DA
14192 json_object_string_add(
14193 json, "bgpOriginatingDefaultNetwork",
14194 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14195 } else {
23d0a753
DA
14196 vty_out(vty,
14197 "BGP table version is %" PRIu64
14198 ", local router ID is %pI4, vrf id ",
14199 table->version, &bgp->router_id);
9df8b37c
PZ
14200 if (bgp->vrf_id == VRF_UNKNOWN)
14201 vty_out(vty, "%s", VRFID_NONE_STR);
14202 else
14203 vty_out(vty, "%u", bgp->vrf_id);
14204 vty_out(vty, "\n");
01eced22
AD
14205 vty_out(vty, "Default local pref %u, ",
14206 bgp->default_local_pref);
114fc229
DA
14207 vty_out(vty, "local AS %u\n",
14208 peer->change_local_as ? peer->change_local_as
14209 : peer->local_as);
e960b4ca
TA
14210 if (!detail) {
14211 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14212 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14213 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14214 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14215 }
d62a17ae 14216
07d0c4ed
DA
14217 vty_out(vty, "Originating default network %s\n\n",
14218 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14219 }
65565c9a 14220 (*output_count)++;
d9478df0 14221 *header1 = 0;
d62a17ae 14222 }
a636c635 14223
9bcb3eef 14224 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14225 if (type == bgp_show_adj_route_received
14226 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14227 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14228 if (ain->peer != peer)
ea47320b 14229 continue;
6392aaa6 14230
114fc229 14231 show_adj_route_header(vty, peer, table, header1,
d9478df0 14232 header2, json, json_scode,
e960b4ca 14233 json_ocode, wide, detail);
d9478df0
TA
14234
14235 if ((safi == SAFI_MPLS_VPN)
14236 || (safi == SAFI_ENCAP)
14237 || (safi == SAFI_EVPN)) {
14238 if (use_json)
14239 json_object_string_add(
14240 json_ar, "rd", rd_str);
14241 else if (show_rd && rd_str) {
14242 vty_out(vty,
14243 "Route Distinguisher: %s\n",
14244 rd_str);
14245 show_rd = false;
14246 }
14247 }
6392aaa6 14248
6f4f49b2 14249 attr = *ain->attr;
f99def61
AD
14250 route_filtered = false;
14251
14252 /* Filter prefix using distribute list,
14253 * filter list or prefix list
14254 */
b54892e0 14255 const struct prefix *rn_p =
9bcb3eef 14256 bgp_dest_get_prefix(dest);
b54892e0
DS
14257 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14258 safi))
14259 == FILTER_DENY)
f99def61
AD
14260 route_filtered = true;
14261
14262 /* Filter prefix using route-map */
b54892e0
DS
14263 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14264 safi, rmap_name, NULL,
14265 0, NULL);
6392aaa6 14266
13c8e163
AD
14267 if (type == bgp_show_adj_route_filtered &&
14268 !route_filtered && ret != RMAP_DENY) {
d498917e 14269 bgp_attr_flush(&attr);
6392aaa6 14270 continue;
d62a17ae 14271 }
6392aaa6 14272
d9478df0
TA
14273 if (type == bgp_show_adj_route_received
14274 && (route_filtered || ret == RMAP_DENY))
14275 (*filtered_count)++;
6392aaa6 14276
e960b4ca
TA
14277 if (detail) {
14278 if (use_json)
14279 json_net =
14280 json_object_new_object();
14281 bgp_show_path_info(
14282 NULL /* prefix_rd */, dest, vty,
14283 bgp, afi, safi, json_net,
14284 BGP_PATH_SHOW_ALL, &display,
14285 RPKI_NOT_BEING_USED);
14286 if (use_json)
14287 json_object_object_addf(
14288 json_ar, json_net,
14289 "%pFX", rn_p);
14290 } else
14291 route_vty_out_tmp(vty, dest, rn_p,
14292 &attr, safi, use_json,
14293 json_ar, wide);
d498917e 14294 bgp_attr_flush(&attr);
d9478df0 14295 (*output_count)++;
d62a17ae 14296 }
6392aaa6 14297 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14298 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14299 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14300 if (paf->peer != peer || !adj->attr)
924c3f6a 14301 continue;
d62a17ae 14302
e960b4ca
TA
14303 show_adj_route_header(
14304 vty, peer, table, header1,
14305 header2, json, json_scode,
14306 json_ocode, wide, detail);
d62a17ae 14307
b54892e0 14308 const struct prefix *rn_p =
9bcb3eef 14309 bgp_dest_get_prefix(dest);
b54892e0 14310
6f4f49b2 14311 attr = *adj->attr;
b755861b 14312 ret = bgp_output_modifier(
b54892e0 14313 peer, rn_p, &attr, afi, safi,
b755861b 14314 rmap_name);
f46d8e1e 14315
b755861b 14316 if (ret != RMAP_DENY) {
d9478df0
TA
14317 if ((safi == SAFI_MPLS_VPN)
14318 || (safi == SAFI_ENCAP)
14319 || (safi == SAFI_EVPN)) {
14320 if (use_json)
14321 json_object_string_add(
14322 json_ar,
14323 "rd",
14324 rd_str);
14325 else if (show_rd
14326 && rd_str) {
14327 vty_out(vty,
14328 "Route Distinguisher: %s\n",
14329 rd_str);
14330 show_rd = false;
14331 }
14332 }
e960b4ca
TA
14333 if (detail) {
14334 if (use_json)
14335 json_net =
14336 json_object_new_object();
14337 bgp_show_path_info(
14338 NULL /* prefix_rd
14339 */
14340 ,
14341 dest, vty, bgp,
14342 afi, safi,
14343 json_net,
14344 BGP_PATH_SHOW_ALL,
14345 &display,
14346 RPKI_NOT_BEING_USED);
14347 if (use_json)
14348 json_object_object_addf(
14349 json_ar,
14350 json_net,
14351 "%pFX",
14352 rn_p);
14353 } else
14354 route_vty_out_tmp(
14355 vty, dest, rn_p,
14356 &attr, safi,
14357 use_json,
14358 json_ar, wide);
d9478df0 14359 (*output_count)++;
b755861b 14360 } else {
d9478df0 14361 (*filtered_count)++;
a2addae8 14362 }
b755861b 14363
d498917e 14364 bgp_attr_flush(&attr);
924c3f6a 14365 }
f20ce998
DS
14366 } else if (type == bgp_show_adj_route_bestpath) {
14367 struct bgp_path_info *pi;
14368
114fc229
DA
14369 show_adj_route_header(vty, peer, table, header1,
14370 header2, json, json_scode,
e960b4ca 14371 json_ocode, wide, detail);
f20ce998 14372
aa9bf57e
TA
14373 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14374
f20ce998
DS
14375 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14376 pi = pi->next) {
14377 if (pi->peer != peer)
14378 continue;
14379
14380 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14381 continue;
14382
aa9bf57e
TA
14383 if (detail) {
14384 if (use_json)
14385 json_net =
14386 json_object_new_object();
14387 bgp_show_path_info(
14388 NULL /* prefix_rd */, dest, vty,
14389 bgp, afi, safi, json_net,
14390 BGP_PATH_SHOW_BESTPATH,
14391 &display, RPKI_NOT_BEING_USED);
14392 if (use_json)
14393 json_object_object_addf(
14394 json_ar, json_net,
14395 "%pFX", rn_p);
14396 } else
14397 route_vty_out_tmp(
14398 vty, dest, rn_p, pi->attr, safi,
14399 use_json, json_ar, wide);
d9478df0 14400 (*output_count)++;
f20ce998 14401 }
d62a17ae 14402 }
14403 }
a636c635 14404}
2a71e9ce 14405
d62a17ae 14406static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14407 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14408 const char *rmap_name, const struct prefix *match,
14409 uint16_t show_flags)
0b16f239 14410{
d9478df0
TA
14411 struct bgp *bgp;
14412 struct bgp_table *table;
d62a17ae 14413 json_object *json = NULL;
d9478df0
TA
14414 json_object *json_scode = NULL;
14415 json_object *json_ocode = NULL;
14416 json_object *json_ar = NULL;
96f3485c 14417 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14418
d9478df0
TA
14419 /* Init BGP headers here so they're only displayed once
14420 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14421 */
14422 int header1 = 1;
14423 int header2 = 1;
14424
14425 /*
14426 * Initialize variables for each RD
14427 * All prefixes under an RD is aggregated within "json_routes"
14428 */
14429 char rd_str[BUFSIZ] = {0};
14430 json_object *json_routes = NULL;
14431
14432
14433 /* For 2-tier tables, prefix counts need to be
14434 * maintained across multiple runs of show_adj_route()
14435 */
14436 unsigned long output_count_per_rd;
14437 unsigned long filtered_count_per_rd;
14438 unsigned long output_count = 0;
14439 unsigned long filtered_count = 0;
14440
14441 if (use_json) {
d62a17ae 14442 json = json_object_new_object();
d9478df0
TA
14443 json_ar = json_object_new_object();
14444 json_scode = json_object_new_object();
14445 json_ocode = json_object_new_object();
dd426a51
DA
14446#if CONFDATE > 20231208
14447CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14448#endif
d9478df0
TA
14449 json_object_string_add(json_scode, "suppressed", "s");
14450 json_object_string_add(json_scode, "damped", "d");
14451 json_object_string_add(json_scode, "history", "h");
14452 json_object_string_add(json_scode, "valid", "*");
14453 json_object_string_add(json_scode, "best", ">");
14454 json_object_string_add(json_scode, "multipath", "=");
14455 json_object_string_add(json_scode, "internal", "i");
14456 json_object_string_add(json_scode, "ribFailure", "r");
14457 json_object_string_add(json_scode, "stale", "S");
14458 json_object_string_add(json_scode, "removed", "R");
14459
dd426a51
DA
14460#if CONFDATE > 20231208
14461CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14462#endif
d9478df0
TA
14463 json_object_string_add(json_ocode, "igp", "i");
14464 json_object_string_add(json_ocode, "egp", "e");
14465 json_object_string_add(json_ocode, "incomplete", "?");
14466 }
0b16f239 14467
d62a17ae 14468 if (!peer || !peer->afc[afi][safi]) {
14469 if (use_json) {
14470 json_object_string_add(
14471 json, "warning",
14472 "No such neighbor or address family");
14473 vty_out(vty, "%s\n", json_object_to_json_string(json));
14474 json_object_free(json);
690c3134
MW
14475 json_object_free(json_ar);
14476 json_object_free(json_scode);
14477 json_object_free(json_ocode);
d62a17ae 14478 } else
14479 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14480
d62a17ae 14481 return CMD_WARNING;
14482 }
14483
6392aaa6
PM
14484 if ((type == bgp_show_adj_route_received
14485 || type == bgp_show_adj_route_filtered)
d62a17ae 14486 && !CHECK_FLAG(peer->af_flags[afi][safi],
14487 PEER_FLAG_SOFT_RECONFIG)) {
14488 if (use_json) {
14489 json_object_string_add(
14490 json, "warning",
14491 "Inbound soft reconfiguration not enabled");
14492 vty_out(vty, "%s\n", json_object_to_json_string(json));
14493 json_object_free(json);
690c3134
MW
14494 json_object_free(json_ar);
14495 json_object_free(json_scode);
14496 json_object_free(json_ocode);
d62a17ae 14497 } else
14498 vty_out(vty,
14499 "%% Inbound soft reconfiguration not enabled\n");
14500
14501 return CMD_WARNING;
14502 }
0b16f239 14503
d9478df0
TA
14504 bgp = peer->bgp;
14505
14506 /* labeled-unicast routes live in the unicast table */
14507 if (safi == SAFI_LABELED_UNICAST)
14508 table = bgp->rib[afi][SAFI_UNICAST];
14509 else
14510 table = bgp->rib[afi][safi];
14511
14512 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14513 || (safi == SAFI_EVPN)) {
14514
14515 struct bgp_dest *dest;
14516
14517 for (dest = bgp_table_top(table); dest;
14518 dest = bgp_route_next(dest)) {
14519 table = bgp_dest_get_bgp_table_info(dest);
14520 if (!table)
14521 continue;
14522
14523 output_count_per_rd = 0;
14524 filtered_count_per_rd = 0;
14525
14526 if (use_json)
14527 json_routes = json_object_new_object();
14528
14529 const struct prefix_rd *prd;
14530 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14531 dest);
14532
4a8cd6ad
PG
14533 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14534 bgp->asnotation);
d9478df0 14535
3880b4ec
TA
14536 show_adj_route(
14537 vty, peer, table, afi, safi, type, rmap_name,
14538 json, json_routes, json_scode, json_ocode,
14539 show_flags, &header1, &header2, rd_str, match,
14540 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14541
14542 /* Don't include an empty RD in the output! */
14543 if (json_routes && (output_count_per_rd > 0))
14544 json_object_object_add(json_ar, rd_str,
14545 json_routes);
14546
14547 output_count += output_count_per_rd;
14548 filtered_count += filtered_count_per_rd;
14549 }
14550 } else
14551 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14552 json, json_ar, json_scode, json_ocode,
3880b4ec 14553 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14554 &output_count, &filtered_count);
14555
14556 if (use_json) {
c1984955
TA
14557 if (type == bgp_show_adj_route_advertised)
14558 json_object_object_add(json, "advertisedRoutes",
14559 json_ar);
14560 else
14561 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14562 json_object_int_add(json, "totalPrefixCounter", output_count);
14563 json_object_int_add(json, "filteredPrefixCounter",
14564 filtered_count);
14565
690c3134
MW
14566 /*
14567 * These fields only give up ownership to `json` when `header1`
14568 * is used (set to zero). See code in `show_adj_route` and
14569 * `show_adj_route_header`.
14570 */
14571 if (header1 == 1) {
d9478df0
TA
14572 json_object_free(json_scode);
14573 json_object_free(json_ocode);
14574 }
14575
75eeda93 14576 vty_json(vty, json);
d9478df0 14577 } else if (output_count > 0) {
3880b4ec 14578 if (!match && filtered_count > 0)
d9478df0
TA
14579 vty_out(vty,
14580 "\nTotal number of prefixes %ld (%ld filtered)\n",
14581 output_count, filtered_count);
14582 else
14583 vty_out(vty, "\nTotal number of prefixes %ld\n",
14584 output_count);
14585 }
0b16f239 14586
d62a17ae 14587 return CMD_SUCCESS;
a636c635 14588}
50ef26d4 14589
f20ce998
DS
14590DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14591 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14592 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
f20ce998
DS
14593 SHOW_STR
14594 IP_STR
14595 BGP_STR
14596 BGP_INSTANCE_HELP_STR
14597 BGP_AFI_HELP_STR
14598 BGP_SAFI_WITH_LABEL_HELP_STR
14599 "Detailed information on TCP and BGP neighbor connections\n"
14600 "Neighbor to display information about\n"
14601 "Neighbor to display information about\n"
14602 "Neighbor on BGP configured interface\n"
14603 "Display the routes selected by best path\n"
aa9bf57e 14604 "Display detailed version of routes\n"
f20ce998
DS
14605 JSON_STR
14606 "Increase table width for longer prefixes\n")
14607{
14608 afi_t afi = AFI_IP6;
14609 safi_t safi = SAFI_UNICAST;
14610 char *rmap_name = NULL;
14611 char *peerstr = NULL;
14612 struct bgp *bgp = NULL;
14613 struct peer *peer;
14614 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14615 int idx = 0;
96c81f66 14616 uint16_t show_flags = 0;
96f3485c 14617
aa9bf57e
TA
14618 if (detail)
14619 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14620
96f3485c
MK
14621 if (uj)
14622 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14623
14624 if (wide)
14625 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14626
14627 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14628 &bgp, uj);
14629
14630 if (!idx)
14631 return CMD_WARNING;
14632
14633 argv_find(argv, argc, "neighbors", &idx);
14634 peerstr = argv[++idx]->arg;
14635
14636 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14637 if (!peer)
14638 return CMD_WARNING;
14639
3880b4ec 14640 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14641 show_flags);
f20ce998
DS
14642}
14643
e960b4ca
TA
14644DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14645 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14646 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
e960b4ca
TA
14647 SHOW_STR
14648 IP_STR
14649 BGP_STR
14650 BGP_INSTANCE_HELP_STR
14651 BGP_AFI_HELP_STR
14652 BGP_SAFI_WITH_LABEL_HELP_STR
14653 "Display the entries for all address families\n"
14654 "Detailed information on TCP and BGP neighbor connections\n"
14655 "Neighbor to display information about\n"
14656 "Neighbor to display information about\n"
14657 "Neighbor on BGP configured interface\n"
14658 "Display the routes advertised to a BGP neighbor\n"
14659 "Display the received routes from neighbor\n"
14660 "Display the filtered routes received from neighbor\n"
14661 "Route-map to modify the attributes\n"
14662 "Name of the route map\n"
3880b4ec
TA
14663 "IPv4 prefix\n"
14664 "IPv6 prefix\n"
e960b4ca
TA
14665 "Display detailed version of routes\n"
14666 JSON_STR
14667 "Increase table width for longer prefixes\n")
718e3744 14668{
d62a17ae 14669 afi_t afi = AFI_IP6;
14670 safi_t safi = SAFI_UNICAST;
d62a17ae 14671 char *peerstr = NULL;
d62a17ae 14672 struct bgp *bgp = NULL;
14673 struct peer *peer;
6392aaa6 14674 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14675 int idx = 0;
96f3485c 14676 bool first = true;
96c81f66 14677 uint16_t show_flags = 0;
75ce3b14
DA
14678 struct listnode *node;
14679 struct bgp *abgp;
6392aaa6 14680
3880b4ec 14681 if (detail || prefix_str)
e960b4ca
TA
14682 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14683
96f3485c 14684 if (uj) {
d62a17ae 14685 argc--;
96f3485c
MK
14686 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14687 }
14688
14689 if (all) {
14690 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14691 if (argv_find(argv, argc, "ipv4", &idx))
14692 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14693
14694 if (argv_find(argv, argc, "ipv6", &idx))
14695 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14696 }
14697
14698 if (wide)
14699 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14700
9f049418
DS
14701 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14702 &bgp, uj);
14703 if (!idx)
14704 return CMD_WARNING;
14705
d62a17ae 14706 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14707 argv_find(argv, argc, "neighbors", &idx);
14708 peerstr = argv[++idx]->arg;
8c3deaae 14709
d62a17ae 14710 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14711 if (!peer)
14712 return CMD_WARNING;
856ca177 14713
d62a17ae 14714 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14715 type = bgp_show_adj_route_advertised;
14716 else if (argv_find(argv, argc, "received-routes", &idx))
14717 type = bgp_show_adj_route_received;
14718 else if (argv_find(argv, argc, "filtered-routes", &idx))
14719 type = bgp_show_adj_route_filtered;
14720
96f3485c 14721 if (!all)
70dd370f 14722 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14723 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14724 if (uj)
14725 vty_out(vty, "{\n");
14726
14727 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14728 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14729 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14730 : AFI_IP6;
75ce3b14
DA
14731 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14732 FOREACH_SAFI (safi) {
14733 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14734 continue;
96f3485c 14735
75ce3b14
DA
14736 if (uj) {
14737 if (first)
14738 first = false;
14739 else
14740 vty_out(vty, ",\n");
14741 vty_out(vty, "\"%s\":",
14742 get_afi_safi_str(afi, safi,
14743 true));
14744 } else
14745 vty_out(vty,
14746 "\nFor address family: %s\n",
14747 get_afi_safi_str(afi, safi,
14748 false));
96f3485c 14749
75ce3b14 14750 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14751 route_map, prefix, show_flags);
75ce3b14 14752 }
96f3485c
MK
14753 }
14754 } else {
75ce3b14
DA
14755 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14756 FOREACH_AFI_SAFI (afi, safi) {
14757 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14758 continue;
96f3485c 14759
75ce3b14
DA
14760 if (uj) {
14761 if (first)
14762 first = false;
14763 else
14764 vty_out(vty, ",\n");
14765 vty_out(vty, "\"%s\":",
14766 get_afi_safi_str(afi, safi,
14767 true));
14768 } else
14769 vty_out(vty,
14770 "\nFor address family: %s\n",
14771 get_afi_safi_str(afi, safi,
14772 false));
96f3485c 14773
75ce3b14 14774 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14775 route_map, prefix, show_flags);
75ce3b14 14776 }
96f3485c
MK
14777 }
14778 }
14779 if (uj)
14780 vty_out(vty, "}\n");
14781
14782 return CMD_SUCCESS;
95cbbd2a
ML
14783}
14784
718e3744 14785DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14786 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14787 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14788 SHOW_STR
14789 IP_STR
14790 BGP_STR
d3120452 14791 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14792 BGP_AF_STR
14793 BGP_AF_STR
14794 BGP_AF_MODIFIER_STR
718e3744 14795 "Detailed information on TCP and BGP neighbor connections\n"
14796 "Neighbor to display information about\n"
14797 "Neighbor to display information about\n"
91d37724 14798 "Neighbor on BGP configured interface\n"
718e3744 14799 "Display information received from a BGP neighbor\n"
856ca177 14800 "Display the prefixlist filter\n"
9973d184 14801 JSON_STR)
718e3744 14802{
d62a17ae 14803 afi_t afi = AFI_IP6;
14804 safi_t safi = SAFI_UNICAST;
14805 char *peerstr = NULL;
d62a17ae 14806 char name[BUFSIZ];
d62a17ae 14807 struct peer *peer;
d3120452 14808 int count;
d62a17ae 14809 int idx = 0;
d3120452
IR
14810 struct bgp *bgp = NULL;
14811 bool uj = use_json(argc, argv);
14812
14813 if (uj)
14814 argc--;
14815
14816 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14817 &bgp, uj);
14818 if (!idx)
14819 return CMD_WARNING;
d62a17ae 14820
d62a17ae 14821 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14822 argv_find(argv, argc, "neighbors", &idx);
14823 peerstr = argv[++idx]->arg;
14824
d3120452
IR
14825 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14826 if (!peer)
14827 return CMD_WARNING;
718e3744 14828
4ced1a2c 14829 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14830 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14831 if (count) {
14832 if (!uj)
14833 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14834 get_afi_safi_str(afi, safi, false));
d62a17ae 14835 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14836 } else {
14837 if (uj)
14838 vty_out(vty, "{}\n");
14839 else
14840 vty_out(vty, "No functional output\n");
14841 }
718e3744 14842
d62a17ae 14843 return CMD_SUCCESS;
14844}
14845
14846static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14847 afi_t afi, safi_t safi,
9f049418 14848 enum bgp_show_type type, bool use_json)
d62a17ae 14849{
96c81f66 14850 uint16_t show_flags = 0;
96f3485c
MK
14851
14852 if (use_json)
14853 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14854
d62a17ae 14855 if (!peer || !peer->afc[afi][safi]) {
14856 if (use_json) {
14857 json_object *json_no = NULL;
14858 json_no = json_object_new_object();
14859 json_object_string_add(
14860 json_no, "warning",
14861 "No such neighbor or address family");
14862 vty_out(vty, "%s\n",
14863 json_object_to_json_string(json_no));
14864 json_object_free(json_no);
14865 } else
14866 vty_out(vty, "%% No such neighbor or address family\n");
14867 return CMD_WARNING;
14868 }
47fc97cc 14869
7daf25a3
TA
14870 /* labeled-unicast routes live in the unicast table */
14871 if (safi == SAFI_LABELED_UNICAST)
14872 safi = SAFI_UNICAST;
14873
1e2ce4f1
DS
14874 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14875 RPKI_NOT_BEING_USED);
718e3744 14876}
14877
dba3c1d3
PG
14878DEFUN (show_ip_bgp_flowspec_routes_detailed,
14879 show_ip_bgp_flowspec_routes_detailed_cmd,
14880 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14881 SHOW_STR
14882 IP_STR
14883 BGP_STR
14884 BGP_INSTANCE_HELP_STR
14885 BGP_AFI_HELP_STR
14886 "SAFI Flowspec\n"
14887 "Detailed information on flowspec entries\n"
14888 JSON_STR)
14889{
458c1475 14890 afi_t afi = AFI_IP6;
dba3c1d3
PG
14891 safi_t safi = SAFI_UNICAST;
14892 struct bgp *bgp = NULL;
14893 int idx = 0;
9f049418 14894 bool uj = use_json(argc, argv);
81dcd881 14895 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14896
96f3485c 14897 if (uj) {
9f049418 14898 argc--;
96f3485c
MK
14899 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14900 }
dba3c1d3
PG
14901
14902 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14903 &bgp, uj);
dba3c1d3
PG
14904 if (!idx)
14905 return CMD_WARNING;
14906
96f3485c 14907 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14908 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14909}
14910
718e3744 14911DEFUN (show_ip_bgp_neighbor_routes,
14912 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14913 "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 14914 SHOW_STR
14915 IP_STR
14916 BGP_STR
8386ac43 14917 BGP_INSTANCE_HELP_STR
4f280b15 14918 BGP_AFI_HELP_STR
4dd6177e 14919 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14920 "Detailed information on TCP and BGP neighbor connections\n"
14921 "Neighbor to display information about\n"
14922 "Neighbor to display information about\n"
91d37724 14923 "Neighbor on BGP configured interface\n"
2525cf39 14924 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14925 "Display the dampened routes received from neighbor\n"
14926 "Display routes learned from neighbor\n"
9973d184 14927 JSON_STR)
718e3744 14928{
d62a17ae 14929 char *peerstr = NULL;
14930 struct bgp *bgp = NULL;
14931 afi_t afi = AFI_IP6;
14932 safi_t safi = SAFI_UNICAST;
14933 struct peer *peer;
14934 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14935 int idx = 0;
9f049418
DS
14936 bool uj = use_json(argc, argv);
14937
14938 if (uj)
14939 argc--;
bb46e94f 14940
d62a17ae 14941 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14942 &bgp, uj);
d62a17ae 14943 if (!idx)
14944 return CMD_WARNING;
c493f2d8 14945
d62a17ae 14946 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14947 argv_find(argv, argc, "neighbors", &idx);
14948 peerstr = argv[++idx]->arg;
8c3deaae 14949
d62a17ae 14950 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14951 if (!peer)
d62a17ae 14952 return CMD_WARNING;
bb46e94f 14953
d62a17ae 14954 if (argv_find(argv, argc, "flap-statistics", &idx))
14955 sh_type = bgp_show_type_flap_neighbor;
14956 else if (argv_find(argv, argc, "dampened-routes", &idx))
14957 sh_type = bgp_show_type_damp_neighbor;
14958 else if (argv_find(argv, argc, "routes", &idx))
14959 sh_type = bgp_show_type_neighbor;
2525cf39 14960
d62a17ae 14961 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14962}
6b0655a2 14963
734b349e 14964struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14965
d62a17ae 14966struct bgp_distance {
14967 /* Distance value for the IP source prefix. */
d7c0a89a 14968 uint8_t distance;
718e3744 14969
d62a17ae 14970 /* Name of the access-list to be matched. */
14971 char *access_list;
718e3744 14972};
14973
4f280b15
LB
14974DEFUN (show_bgp_afi_vpn_rd_route,
14975 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14976 "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
14977 SHOW_STR
14978 BGP_STR
14979 BGP_AFI_HELP_STR
00e6edb9 14980 BGP_AF_MODIFIER_STR
4f280b15
LB
14981 "Display information for a route distinguisher\n"
14982 "Route Distinguisher\n"
a111dd97 14983 "All Route Distinguishers\n"
7395a2c9
DS
14984 "Network in the BGP routing table to display\n"
14985 "Network in the BGP routing table to display\n"
14986 JSON_STR)
4f280b15 14987{
d62a17ae 14988 int ret;
14989 struct prefix_rd prd;
14990 afi_t afi = AFI_MAX;
14991 int idx = 0;
4f280b15 14992
ff6566f3
DS
14993 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14994 vty_out(vty, "%% Malformed Address Family\n");
14995 return CMD_WARNING;
14996 }
14997
a111dd97
TA
14998 if (!strcmp(argv[5]->arg, "all"))
14999 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
15000 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
15001 RPKI_NOT_BEING_USED,
15002 use_json(argc, argv));
15003
d62a17ae 15004 ret = str2prefix_rd(argv[5]->arg, &prd);
15005 if (!ret) {
15006 vty_out(vty, "%% Malformed Route Distinguisher\n");
15007 return CMD_WARNING;
15008 }
ff6566f3 15009
d62a17ae 15010 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
15011 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
15012 use_json(argc, argv));
4f280b15
LB
15013}
15014
d62a17ae 15015static struct bgp_distance *bgp_distance_new(void)
718e3744 15016{
d62a17ae 15017 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 15018}
15019
d62a17ae 15020static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 15021{
d62a17ae 15022 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 15023}
15024
585f1adc
IR
15025static int bgp_distance_set(struct vty *vty, const char *distance_str,
15026 const char *ip_str, const char *access_list_str)
718e3744 15027{
d62a17ae 15028 int ret;
585f1adc
IR
15029 afi_t afi;
15030 safi_t safi;
d62a17ae 15031 struct prefix p;
585f1adc 15032 uint8_t distance;
9bcb3eef 15033 struct bgp_dest *dest;
d62a17ae 15034 struct bgp_distance *bdistance;
718e3744 15035
585f1adc
IR
15036 afi = bgp_node_afi(vty);
15037 safi = bgp_node_safi(vty);
15038
d62a17ae 15039 ret = str2prefix(ip_str, &p);
15040 if (ret == 0) {
585f1adc 15041 vty_out(vty, "Malformed prefix\n");
d62a17ae 15042 return CMD_WARNING_CONFIG_FAILED;
15043 }
718e3744 15044
585f1adc
IR
15045 distance = atoi(distance_str);
15046
d62a17ae 15047 /* Get BGP distance node. */
9bcb3eef
DS
15048 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15049 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15050 if (bdistance)
9bcb3eef 15051 bgp_dest_unlock_node(dest);
ca2e160d 15052 else {
d62a17ae 15053 bdistance = bgp_distance_new();
9bcb3eef 15054 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15055 }
718e3744 15056
d62a17ae 15057 /* Set distance value. */
15058 bdistance->distance = distance;
718e3744 15059
d62a17ae 15060 /* Reset access-list configuration. */
e1b36e13 15061 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15062 if (access_list_str)
15063 bdistance->access_list =
15064 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15065
d62a17ae 15066 return CMD_SUCCESS;
718e3744 15067}
15068
585f1adc
IR
15069static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15070 const char *ip_str, const char *access_list_str)
718e3744 15071{
d62a17ae 15072 int ret;
585f1adc
IR
15073 afi_t afi;
15074 safi_t safi;
d62a17ae 15075 struct prefix p;
585f1adc 15076 int distance;
9bcb3eef 15077 struct bgp_dest *dest;
d62a17ae 15078 struct bgp_distance *bdistance;
718e3744 15079
585f1adc
IR
15080 afi = bgp_node_afi(vty);
15081 safi = bgp_node_safi(vty);
15082
d62a17ae 15083 ret = str2prefix(ip_str, &p);
15084 if (ret == 0) {
585f1adc 15085 vty_out(vty, "Malformed prefix\n");
d62a17ae 15086 return CMD_WARNING_CONFIG_FAILED;
15087 }
718e3744 15088
9bcb3eef
DS
15089 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15090 if (!dest) {
585f1adc 15091 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15092 return CMD_WARNING_CONFIG_FAILED;
15093 }
718e3744 15094
9bcb3eef 15095 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15096 distance = atoi(distance_str);
1f9a9fff 15097
d62a17ae 15098 if (bdistance->distance != distance) {
585f1adc 15099 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15100 bgp_dest_unlock_node(dest);
d62a17ae 15101 return CMD_WARNING_CONFIG_FAILED;
15102 }
718e3744 15103
0a22ddfb 15104 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15105 bgp_distance_free(bdistance);
718e3744 15106
9bcb3eef
DS
15107 bgp_dest_set_bgp_path_info(dest, NULL);
15108 bgp_dest_unlock_node(dest);
15109 bgp_dest_unlock_node(dest);
718e3744 15110
d62a17ae 15111 return CMD_SUCCESS;
718e3744 15112}
15113
718e3744 15114/* Apply BGP information to distance method. */
b8685f9b 15115uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15116 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15117{
9bcb3eef 15118 struct bgp_dest *dest;
801bb996 15119 struct prefix q = {0};
d62a17ae 15120 struct peer *peer;
15121 struct bgp_distance *bdistance;
15122 struct access_list *alist;
15123 struct bgp_static *bgp_static;
a04f1c42 15124 struct bgp_path_info *bpi_ultimate;
d62a17ae 15125
15126 if (!bgp)
15127 return 0;
15128
40381db7 15129 peer = pinfo->peer;
d62a17ae 15130
7b7d48e5
DS
15131 if (pinfo->attr->distance)
15132 return pinfo->attr->distance;
15133
a04f1c42
PG
15134 /* get peer origin to calculate appropriate distance */
15135 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15136 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15137 peer = bpi_ultimate->peer;
15138 }
15139
801bb996
CS
15140 /* Check source address.
15141 * Note: for aggregate route, peer can have unspec af type.
15142 */
15143 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15144 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15145 return 0;
15146
9bcb3eef
DS
15147 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15148 if (dest) {
15149 bdistance = bgp_dest_get_bgp_distance_info(dest);
15150 bgp_dest_unlock_node(dest);
d62a17ae 15151
15152 if (bdistance->access_list) {
15153 alist = access_list_lookup(afi, bdistance->access_list);
15154 if (alist
15155 && access_list_apply(alist, p) == FILTER_PERMIT)
15156 return bdistance->distance;
15157 } else
15158 return bdistance->distance;
718e3744 15159 }
718e3744 15160
d62a17ae 15161 /* Backdoor check. */
9bcb3eef
DS
15162 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15163 if (dest) {
15164 bgp_static = bgp_dest_get_bgp_static_info(dest);
15165 bgp_dest_unlock_node(dest);
718e3744 15166
d62a17ae 15167 if (bgp_static->backdoor) {
15168 if (bgp->distance_local[afi][safi])
15169 return bgp->distance_local[afi][safi];
15170 else
15171 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15172 }
718e3744 15173 }
718e3744 15174
d62a17ae 15175 if (peer->sort == BGP_PEER_EBGP) {
15176 if (bgp->distance_ebgp[afi][safi])
15177 return bgp->distance_ebgp[afi][safi];
15178 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15179 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15180 if (bgp->distance_ibgp[afi][safi])
15181 return bgp->distance_ibgp[afi][safi];
15182 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15183 } else {
15184 if (bgp->distance_local[afi][safi])
15185 return bgp->distance_local[afi][safi];
15186 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15187 }
718e3744 15188}
15189
a612fb77
DA
15190/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15191 * we should tell ZEBRA update the routes for a specific
15192 * AFI/SAFI to reflect changes in RIB.
15193 */
585f1adc
IR
15194static void bgp_announce_routes_distance_update(struct bgp *bgp,
15195 afi_t update_afi,
15196 safi_t update_safi)
a612fb77
DA
15197{
15198 afi_t afi;
15199 safi_t safi;
15200
15201 FOREACH_AFI_SAFI (afi, safi) {
15202 if (!bgp_fibupd_safi(safi))
15203 continue;
15204
8b54bc30
DA
15205 if (afi != update_afi && safi != update_safi)
15206 continue;
15207
15208 if (BGP_DEBUG(zebra, ZEBRA))
15209 zlog_debug(
15210 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15211 __func__, afi, safi);
15212 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15213 }
15214}
15215
585f1adc
IR
15216DEFUN (bgp_distance,
15217 bgp_distance_cmd,
15218 "distance bgp (1-255) (1-255) (1-255)",
15219 "Define an administrative distance\n"
15220 "BGP distance\n"
15221 "Distance for routes external to the AS\n"
15222 "Distance for routes internal to the AS\n"
15223 "Distance for local routes\n")
718e3744 15224{
585f1adc 15225 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15226 int idx_number = 2;
15227 int idx_number_2 = 3;
15228 int idx_number_3 = 4;
585f1adc
IR
15229 int distance_ebgp = atoi(argv[idx_number]->arg);
15230 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15231 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15232 afi_t afi;
15233 safi_t safi;
718e3744 15234
d62a17ae 15235 afi = bgp_node_afi(vty);
15236 safi = bgp_node_safi(vty);
718e3744 15237
585f1adc
IR
15238 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15239 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15240 || bgp->distance_local[afi][safi] != distance_local) {
15241 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15242 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15243 bgp->distance_local[afi][safi] = distance_local;
15244 bgp_announce_routes_distance_update(bgp, afi, safi);
15245 }
15246 return CMD_SUCCESS;
15247}
37a87b8f 15248
585f1adc
IR
15249DEFUN (no_bgp_distance,
15250 no_bgp_distance_cmd,
15251 "no distance bgp [(1-255) (1-255) (1-255)]",
15252 NO_STR
15253 "Define an administrative distance\n"
15254 "BGP distance\n"
15255 "Distance for routes external to the AS\n"
15256 "Distance for routes internal to the AS\n"
15257 "Distance for local routes\n")
718e3744 15258{
585f1adc 15259 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15260 afi_t afi;
15261 safi_t safi;
37a87b8f
CS
15262
15263 afi = bgp_node_afi(vty);
15264 safi = bgp_node_safi(vty);
15265
585f1adc
IR
15266 if (bgp->distance_ebgp[afi][safi] != 0
15267 || bgp->distance_ibgp[afi][safi] != 0
15268 || bgp->distance_local[afi][safi] != 0) {
15269 bgp->distance_ebgp[afi][safi] = 0;
15270 bgp->distance_ibgp[afi][safi] = 0;
15271 bgp->distance_local[afi][safi] = 0;
15272 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15273 }
585f1adc
IR
15274 return CMD_SUCCESS;
15275}
37a87b8f 15276
37a87b8f 15277
585f1adc
IR
15278DEFUN (bgp_distance_source,
15279 bgp_distance_source_cmd,
15280 "distance (1-255) A.B.C.D/M",
15281 "Define an administrative distance\n"
15282 "Administrative distance\n"
15283 "IP source prefix\n")
15284{
15285 int idx_number = 1;
15286 int idx_ipv4_prefixlen = 2;
15287 bgp_distance_set(vty, argv[idx_number]->arg,
15288 argv[idx_ipv4_prefixlen]->arg, NULL);
15289 return CMD_SUCCESS;
734b349e
MZ
15290}
15291
585f1adc
IR
15292DEFUN (no_bgp_distance_source,
15293 no_bgp_distance_source_cmd,
15294 "no distance (1-255) A.B.C.D/M",
15295 NO_STR
15296 "Define an administrative distance\n"
15297 "Administrative distance\n"
15298 "IP source prefix\n")
37a87b8f 15299{
585f1adc
IR
15300 int idx_number = 2;
15301 int idx_ipv4_prefixlen = 3;
15302 bgp_distance_unset(vty, argv[idx_number]->arg,
15303 argv[idx_ipv4_prefixlen]->arg, NULL);
15304 return CMD_SUCCESS;
37a87b8f
CS
15305}
15306
585f1adc
IR
15307DEFUN (bgp_distance_source_access_list,
15308 bgp_distance_source_access_list_cmd,
15309 "distance (1-255) A.B.C.D/M WORD",
15310 "Define an administrative distance\n"
15311 "Administrative distance\n"
15312 "IP source prefix\n"
15313 "Access list name\n")
37a87b8f 15314{
585f1adc
IR
15315 int idx_number = 1;
15316 int idx_ipv4_prefixlen = 2;
15317 int idx_word = 3;
15318 bgp_distance_set(vty, argv[idx_number]->arg,
15319 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15320 return CMD_SUCCESS;
15321}
718e3744 15322
585f1adc
IR
15323DEFUN (no_bgp_distance_source_access_list,
15324 no_bgp_distance_source_access_list_cmd,
15325 "no distance (1-255) A.B.C.D/M WORD",
15326 NO_STR
15327 "Define an administrative distance\n"
15328 "Administrative distance\n"
15329 "IP source prefix\n"
15330 "Access list name\n")
15331{
15332 int idx_number = 2;
15333 int idx_ipv4_prefixlen = 3;
15334 int idx_word = 4;
15335 bgp_distance_unset(vty, argv[idx_number]->arg,
15336 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15337 return CMD_SUCCESS;
15338}
37a87b8f 15339
585f1adc
IR
15340DEFUN (ipv6_bgp_distance_source,
15341 ipv6_bgp_distance_source_cmd,
15342 "distance (1-255) X:X::X:X/M",
15343 "Define an administrative distance\n"
15344 "Administrative distance\n"
15345 "IP source prefix\n")
15346{
15347 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15348 return CMD_SUCCESS;
15349}
7ebe9748 15350
585f1adc
IR
15351DEFUN (no_ipv6_bgp_distance_source,
15352 no_ipv6_bgp_distance_source_cmd,
15353 "no distance (1-255) X:X::X:X/M",
15354 NO_STR
15355 "Define an administrative distance\n"
15356 "Administrative distance\n"
15357 "IP source prefix\n")
15358{
15359 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15360 return CMD_SUCCESS;
15361}
37a87b8f 15362
585f1adc
IR
15363DEFUN (ipv6_bgp_distance_source_access_list,
15364 ipv6_bgp_distance_source_access_list_cmd,
15365 "distance (1-255) X:X::X:X/M WORD",
15366 "Define an administrative distance\n"
15367 "Administrative distance\n"
15368 "IP source prefix\n"
15369 "Access list name\n")
15370{
15371 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15372 return CMD_SUCCESS;
718e3744 15373}
15374
585f1adc
IR
15375DEFUN (no_ipv6_bgp_distance_source_access_list,
15376 no_ipv6_bgp_distance_source_access_list_cmd,
15377 "no distance (1-255) X:X::X:X/M WORD",
15378 NO_STR
15379 "Define an administrative distance\n"
15380 "Administrative distance\n"
15381 "IP source prefix\n"
15382 "Access list name\n")
718e3744 15383{
585f1adc
IR
15384 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15385 return CMD_SUCCESS;
15386}
37a87b8f 15387
585f1adc
IR
15388DEFUN (bgp_damp_set,
15389 bgp_damp_set_cmd,
a30fec23 15390 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15391 "BGP Specific commands\n"
15392 "Enable route-flap dampening\n"
15393 "Half-life time for the penalty\n"
15394 "Value to start reusing a route\n"
15395 "Value to start suppressing a route\n"
15396 "Maximum duration to suppress a stable route\n")
15397{
15398 VTY_DECLVAR_CONTEXT(bgp, bgp);
15399 int idx_half_life = 2;
15400 int idx_reuse = 3;
15401 int idx_suppress = 4;
15402 int idx_max_suppress = 5;
37a87b8f
CS
15403 int half = DEFAULT_HALF_LIFE * 60;
15404 int reuse = DEFAULT_REUSE;
15405 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15406 int max = 4 * half;
15407
15408 if (argc == 6) {
15409 half = atoi(argv[idx_half_life]->arg) * 60;
15410 reuse = atoi(argv[idx_reuse]->arg);
15411 suppress = atoi(argv[idx_suppress]->arg);
15412 max = atoi(argv[idx_max_suppress]->arg) * 60;
15413 } else if (argc == 3) {
15414 half = atoi(argv[idx_half_life]->arg) * 60;
15415 max = 4 * half;
15416 }
15417
15418 /*
15419 * These can't be 0 but our SA doesn't understand the
15420 * way our cli is constructed
15421 */
15422 assert(reuse);
15423 assert(half);
15424 if (suppress < reuse) {
15425 vty_out(vty,
15426 "Suppress value cannot be less than reuse value \n");
15427 return 0;
15428 }
15429
15430 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15431 reuse, suppress, max);
15432}
15433
15434DEFUN (bgp_damp_unset,
15435 bgp_damp_unset_cmd,
a30fec23 15436 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15437 NO_STR
15438 "BGP Specific commands\n"
15439 "Enable route-flap dampening\n"
15440 "Half-life time for the penalty\n"
15441 "Value to start reusing a route\n"
15442 "Value to start suppressing a route\n"
15443 "Maximum duration to suppress a stable route\n")
15444{
15445 VTY_DECLVAR_CONTEXT(bgp, bgp);
15446 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15447}
15448
718e3744 15449/* Display specified route of BGP table. */
d62a17ae 15450static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15451 const char *ip_str, afi_t afi, safi_t safi,
15452 struct prefix_rd *prd, int prefix_check)
15453{
15454 int ret;
15455 struct prefix match;
9bcb3eef
DS
15456 struct bgp_dest *dest;
15457 struct bgp_dest *rm;
40381db7
DS
15458 struct bgp_path_info *pi;
15459 struct bgp_path_info *pi_temp;
d62a17ae 15460 struct bgp *bgp;
15461 struct bgp_table *table;
15462
15463 /* BGP structure lookup. */
15464 if (view_name) {
15465 bgp = bgp_lookup_by_name(view_name);
15466 if (bgp == NULL) {
15467 vty_out(vty, "%% Can't find BGP instance %s\n",
15468 view_name);
15469 return CMD_WARNING;
15470 }
15471 } else {
15472 bgp = bgp_get_default();
15473 if (bgp == NULL) {
15474 vty_out(vty, "%% No BGP process is configured\n");
15475 return CMD_WARNING;
15476 }
718e3744 15477 }
718e3744 15478
d62a17ae 15479 /* Check IP address argument. */
15480 ret = str2prefix(ip_str, &match);
15481 if (!ret) {
15482 vty_out(vty, "%% address is malformed\n");
15483 return CMD_WARNING;
15484 }
718e3744 15485
d62a17ae 15486 match.family = afi2family(afi);
15487
15488 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15489 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15490 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15491 dest = bgp_route_next(dest)) {
15492 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15493
9bcb3eef 15494 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15495 continue;
9bcb3eef 15496 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15497 if (!table)
ea47320b 15498 continue;
4953391b
DA
15499 rm = bgp_node_match(table, &match);
15500 if (rm == NULL)
ea47320b 15501 continue;
d62a17ae 15502
9bcb3eef 15503 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15504
ea47320b 15505 if (!prefix_check
b54892e0 15506 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15507 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15508 while (pi) {
15509 if (pi->extra && pi->extra->damp_info) {
15510 pi_temp = pi->next;
ea47320b 15511 bgp_damp_info_free(
19971c9a 15512 pi->extra->damp_info,
5c8846f6 15513 1, afi, safi);
40381db7 15514 pi = pi_temp;
ea47320b 15515 } else
40381db7 15516 pi = pi->next;
d62a17ae 15517 }
ea47320b
DL
15518 }
15519
9bcb3eef 15520 bgp_dest_unlock_node(rm);
d62a17ae 15521 }
15522 } else {
4953391b
DA
15523 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15524 if (dest != NULL) {
9bcb3eef 15525 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15526
d62a17ae 15527 if (!prefix_check
9bcb3eef
DS
15528 || dest_p->prefixlen == match.prefixlen) {
15529 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15530 while (pi) {
15531 if (pi->extra && pi->extra->damp_info) {
15532 pi_temp = pi->next;
d62a17ae 15533 bgp_damp_info_free(
19971c9a 15534 pi->extra->damp_info,
5c8846f6 15535 1, afi, safi);
40381db7 15536 pi = pi_temp;
d62a17ae 15537 } else
40381db7 15538 pi = pi->next;
d62a17ae 15539 }
15540 }
15541
9bcb3eef 15542 bgp_dest_unlock_node(dest);
d62a17ae 15543 }
15544 }
718e3744 15545
d62a17ae 15546 return CMD_SUCCESS;
718e3744 15547}
15548
15549DEFUN (clear_ip_bgp_dampening,
15550 clear_ip_bgp_dampening_cmd,
15551 "clear ip bgp dampening",
15552 CLEAR_STR
15553 IP_STR
15554 BGP_STR
15555 "Clear route flap dampening information\n")
15556{
b4f7f45b 15557 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15558 return CMD_SUCCESS;
718e3744 15559}
15560
15561DEFUN (clear_ip_bgp_dampening_prefix,
15562 clear_ip_bgp_dampening_prefix_cmd,
15563 "clear ip bgp dampening A.B.C.D/M",
15564 CLEAR_STR
15565 IP_STR
15566 BGP_STR
15567 "Clear route flap dampening information\n"
0c7b1b01 15568 "IPv4 prefix\n")
718e3744 15569{
d62a17ae 15570 int idx_ipv4_prefixlen = 4;
15571 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15572 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15573}
15574
15575DEFUN (clear_ip_bgp_dampening_address,
15576 clear_ip_bgp_dampening_address_cmd,
15577 "clear ip bgp dampening A.B.C.D",
15578 CLEAR_STR
15579 IP_STR
15580 BGP_STR
15581 "Clear route flap dampening information\n"
15582 "Network to clear damping information\n")
15583{
d62a17ae 15584 int idx_ipv4 = 4;
15585 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15586 SAFI_UNICAST, NULL, 0);
718e3744 15587}
15588
15589DEFUN (clear_ip_bgp_dampening_address_mask,
15590 clear_ip_bgp_dampening_address_mask_cmd,
15591 "clear ip bgp dampening A.B.C.D A.B.C.D",
15592 CLEAR_STR
15593 IP_STR
15594 BGP_STR
15595 "Clear route flap dampening information\n"
15596 "Network to clear damping information\n"
15597 "Network mask\n")
15598{
d62a17ae 15599 int idx_ipv4 = 4;
15600 int idx_ipv4_2 = 5;
15601 int ret;
15602 char prefix_str[BUFSIZ];
718e3744 15603
d62a17ae 15604 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15605 prefix_str, sizeof(prefix_str));
d62a17ae 15606 if (!ret) {
15607 vty_out(vty, "%% Inconsistent address and mask\n");
15608 return CMD_WARNING;
15609 }
718e3744 15610
d62a17ae 15611 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15612 NULL, 0);
718e3744 15613}
6b0655a2 15614
e3b78da8 15615static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15616{
15617 struct vty *vty = arg;
e3b78da8 15618 struct peer *peer = bucket->data;
825d9834 15619
47e12884 15620 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15621}
15622
2a0e69ae
DS
15623DEFUN (show_bgp_listeners,
15624 show_bgp_listeners_cmd,
15625 "show bgp listeners",
15626 SHOW_STR
15627 BGP_STR
15628 "Display Listen Sockets and who created them\n")
15629{
15630 bgp_dump_listener_info(vty);
15631
15632 return CMD_SUCCESS;
15633}
15634
825d9834
DS
15635DEFUN (show_bgp_peerhash,
15636 show_bgp_peerhash_cmd,
15637 "show bgp peerhash",
15638 SHOW_STR
15639 BGP_STR
15640 "Display information about the BGP peerhash\n")
15641{
15642 struct list *instances = bm->bgp;
15643 struct listnode *node;
15644 struct bgp *bgp;
15645
15646 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15647 vty_out(vty, "BGP: %s\n", bgp->name);
15648 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15649 vty);
15650 }
15651
15652 return CMD_SUCCESS;
15653}
15654
587ff0fd 15655/* also used for encap safi */
2b791107
DL
15656static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15657 afi_t afi, safi_t safi)
d62a17ae 15658{
9bcb3eef
DS
15659 struct bgp_dest *pdest;
15660 struct bgp_dest *dest;
d62a17ae 15661 struct bgp_table *table;
b54892e0 15662 const struct prefix *p;
d62a17ae 15663 struct bgp_static *bgp_static;
15664 mpls_label_t label;
d62a17ae 15665
15666 /* Network configuration. */
9bcb3eef
DS
15667 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15668 pdest = bgp_route_next(pdest)) {
15669 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15670 if (!table)
ea47320b 15671 continue;
d62a17ae 15672
9bcb3eef
DS
15673 for (dest = bgp_table_top(table); dest;
15674 dest = bgp_route_next(dest)) {
15675 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15676 if (bgp_static == NULL)
ea47320b 15677 continue;
d62a17ae 15678
9bcb3eef 15679 p = bgp_dest_get_prefix(dest);
d62a17ae 15680
ea47320b 15681 /* "network" configuration display. */
ea47320b
DL
15682 label = decode_label(&bgp_static->label);
15683
c1aa9e7f
PG
15684 vty_out(vty, " network %pFX rd %s", p,
15685 bgp_static->prd_pretty);
ea47320b
DL
15686 if (safi == SAFI_MPLS_VPN)
15687 vty_out(vty, " label %u", label);
15688
15689 if (bgp_static->rmap.name)
15690 vty_out(vty, " route-map %s",
15691 bgp_static->rmap.name);
e2a86ad9
DS
15692
15693 if (bgp_static->backdoor)
15694 vty_out(vty, " backdoor");
15695
ea47320b
DL
15696 vty_out(vty, "\n");
15697 }
15698 }
d62a17ae 15699}
15700
2b791107
DL
15701static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15702 afi_t afi, safi_t safi)
d62a17ae 15703{
9bcb3eef
DS
15704 struct bgp_dest *pdest;
15705 struct bgp_dest *dest;
d62a17ae 15706 struct bgp_table *table;
b54892e0 15707 const struct prefix *p;
d62a17ae 15708 struct bgp_static *bgp_static;
ff44f570 15709 char buf[PREFIX_STRLEN * 2];
d62a17ae 15710 char buf2[SU_ADDRSTRLEN];
5f933e1e 15711 char esi_buf[ESI_STR_LEN];
d62a17ae 15712
15713 /* Network configuration. */
9bcb3eef
DS
15714 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15715 pdest = bgp_route_next(pdest)) {
15716 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15717 if (!table)
ea47320b 15718 continue;
d62a17ae 15719
9bcb3eef
DS
15720 for (dest = bgp_table_top(table); dest;
15721 dest = bgp_route_next(dest)) {
15722 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15723 if (bgp_static == NULL)
ea47320b 15724 continue;
d62a17ae 15725
ea47320b 15726 char *macrouter = NULL;
d62a17ae 15727
ea47320b
DL
15728 if (bgp_static->router_mac)
15729 macrouter = prefix_mac2str(
15730 bgp_static->router_mac, NULL, 0);
15731 if (bgp_static->eth_s_id)
0a50c248
AK
15732 esi_to_str(bgp_static->eth_s_id,
15733 esi_buf, sizeof(esi_buf));
9bcb3eef 15734 p = bgp_dest_get_prefix(dest);
d62a17ae 15735
ea47320b 15736 /* "network" configuration display. */
197cb530
PG
15737 if (p->u.prefix_evpn.route_type == 5) {
15738 char local_buf[PREFIX_STRLEN];
07380148 15739
3714a385 15740 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15741 struct prefix_evpn *)p)
15742 ? AF_INET
15743 : AF_INET6;
3714a385 15744 inet_ntop(family,
07380148
DA
15745 &p->u.prefix_evpn.prefix_addr.ip.ip
15746 .addr,
15747 local_buf, sizeof(local_buf));
772270f3
QY
15748 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15749 p->u.prefix_evpn.prefix_addr
15750 .ip_prefix_length);
197cb530
PG
15751 } else {
15752 prefix2str(p, buf, sizeof(buf));
15753 }
ea47320b 15754
a4d82a8a
PZ
15755 if (bgp_static->gatewayIp.family == AF_INET
15756 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15757 inet_ntop(bgp_static->gatewayIp.family,
15758 &bgp_static->gatewayIp.u.prefix, buf2,
15759 sizeof(buf2));
ea47320b 15760 vty_out(vty,
c1aa9e7f
PG
15761 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15762 buf, bgp_static->prd_pretty,
15763 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15764 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15765 macrouter);
15766
0a22ddfb 15767 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15768 }
15769 }
3da6fcd5
PG
15770}
15771
718e3744 15772/* Configuration of static route announcement and aggregate
15773 information. */
2b791107
DL
15774void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15775 safi_t safi)
d62a17ae 15776{
9bcb3eef 15777 struct bgp_dest *dest;
b54892e0 15778 const struct prefix *p;
d62a17ae 15779 struct bgp_static *bgp_static;
15780 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15781
2b791107
DL
15782 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15783 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15784 return;
15785 }
d62a17ae 15786
2b791107
DL
15787 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15788 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15789 return;
15790 }
d62a17ae 15791
15792 /* Network configuration. */
9bcb3eef
DS
15793 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15794 dest = bgp_route_next(dest)) {
15795 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15796 if (bgp_static == NULL)
ea47320b 15797 continue;
d62a17ae 15798
9bcb3eef 15799 p = bgp_dest_get_prefix(dest);
d62a17ae 15800
8228a9a7 15801 vty_out(vty, " network %pFX", p);
d62a17ae 15802
ea47320b
DL
15803 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15804 vty_out(vty, " label-index %u",
15805 bgp_static->label_index);
d62a17ae 15806
ea47320b
DL
15807 if (bgp_static->rmap.name)
15808 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15809
15810 if (bgp_static->backdoor)
15811 vty_out(vty, " backdoor");
718e3744 15812
ea47320b
DL
15813 vty_out(vty, "\n");
15814 }
15815
d62a17ae 15816 /* Aggregate-address configuration. */
9bcb3eef
DS
15817 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15818 dest = bgp_route_next(dest)) {
15819 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15820 if (bgp_aggregate == NULL)
ea47320b 15821 continue;
d62a17ae 15822
9bcb3eef 15823 p = bgp_dest_get_prefix(dest);
d62a17ae 15824
8228a9a7 15825 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15826
ea47320b
DL
15827 if (bgp_aggregate->as_set)
15828 vty_out(vty, " as-set");
d62a17ae 15829
ea47320b
DL
15830 if (bgp_aggregate->summary_only)
15831 vty_out(vty, " summary-only");
718e3744 15832
20894f50
DA
15833 if (bgp_aggregate->rmap.name)
15834 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15835
229757f1
DA
15836 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15837 vty_out(vty, " origin %s",
15838 bgp_origin2str(bgp_aggregate->origin));
15839
6aabb15d
RZ
15840 if (bgp_aggregate->match_med)
15841 vty_out(vty, " matching-MED-only");
15842
365ab2e7
RZ
15843 if (bgp_aggregate->suppress_map_name)
15844 vty_out(vty, " suppress-map %s",
15845 bgp_aggregate->suppress_map_name);
15846
ea47320b
DL
15847 vty_out(vty, "\n");
15848 }
d62a17ae 15849}
734b349e 15850
2b791107 15851void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15852 safi_t safi)
d62a17ae 15853{
9bcb3eef 15854 struct bgp_dest *dest;
d62a17ae 15855 struct bgp_distance *bdistance;
15856
15857 /* Distance configuration. */
15858 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15859 && bgp->distance_local[afi][safi]
15860 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15861 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15862 || bgp->distance_local[afi][safi]
15863 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15864 vty_out(vty, " distance bgp %d %d %d\n",
15865 bgp->distance_ebgp[afi][safi],
15866 bgp->distance_ibgp[afi][safi],
15867 bgp->distance_local[afi][safi]);
15868 }
734b349e 15869
9bcb3eef
DS
15870 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15871 dest = bgp_route_next(dest)) {
15872 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15873 if (bdistance != NULL)
56ca3b5b 15874 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15875 bdistance->distance, dest,
d62a17ae 15876 bdistance->access_list ? bdistance->access_list
15877 : "");
ca2e160d 15878 }
718e3744 15879}
15880
15881/* Allocate routing table structure and install commands. */
d62a17ae 15882void bgp_route_init(void)
15883{
15884 afi_t afi;
15885 safi_t safi;
15886
15887 /* Init BGP distance table. */
05c7a1cc 15888 FOREACH_AFI_SAFI (afi, safi)
960035b2 15889 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15890
15891 /* IPv4 BGP commands. */
15892 install_element(BGP_NODE, &bgp_table_map_cmd);
15893 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15894 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15895
554b3b10 15896 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15897
15898 /* IPv4 unicast configuration. */
15899 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15900 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15901 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15902
554b3b10 15903 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15904
15905 /* IPv4 multicast configuration. */
15906 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15907 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15908 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15909 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15910
15911 /* IPv4 labeled-unicast configuration. */
fb985e0c 15912 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15913 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15914
d62a17ae 15915 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15916 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15917 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15918 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15919 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15920 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15921 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15922 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15923
15924 install_element(VIEW_NODE,
15925 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15926 install_element(VIEW_NODE,
15927 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15928 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15929 install_element(VIEW_NODE,
15930 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15931#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15932 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15933#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15934 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15935 install_element(VIEW_NODE,
44c69747 15936 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15937
d62a17ae 15938 /* BGP dampening clear commands */
15939 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15940 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15941
d62a17ae 15942 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15943 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15944
15945 /* prefix count */
15946 install_element(ENABLE_NODE,
15947 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15948#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15949 install_element(ENABLE_NODE,
15950 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15951#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15952
d62a17ae 15953 /* New config IPv6 BGP commands. */
15954 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15955 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15956 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15957
554b3b10 15958 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15959
15960 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15961
fb985e0c
DA
15962 /* IPv6 labeled unicast address family. */
15963 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15964 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15965
d62a17ae 15966 install_element(BGP_NODE, &bgp_distance_cmd);
15967 install_element(BGP_NODE, &no_bgp_distance_cmd);
15968 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15969 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15970 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15971 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15972 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15973 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15974 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15975 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15976 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15977 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15978 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15979 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15980 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15981 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15982 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15983 install_element(BGP_IPV4M_NODE,
15984 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15985 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15986 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15987 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15988 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15989 install_element(BGP_IPV6_NODE,
15990 &ipv6_bgp_distance_source_access_list_cmd);
15991 install_element(BGP_IPV6_NODE,
15992 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15993 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15994 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15995 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15996 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15997 install_element(BGP_IPV6M_NODE,
15998 &ipv6_bgp_distance_source_access_list_cmd);
15999 install_element(BGP_IPV6M_NODE,
16000 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16001
ef5f4b23 16002 /* BGP dampening */
585f1adc
IR
16003 install_element(BGP_NODE, &bgp_damp_set_cmd);
16004 install_element(BGP_NODE, &bgp_damp_unset_cmd);
16005 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
16006 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
16007 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
16008 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
16009 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
16010 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
16011 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
16012 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
16013 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
16014 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
16015 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
16016 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 16017
16018 /* Large Communities */
16019 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
16020 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
16021
16022 /* show bgp ipv4 flowspec detailed */
16023 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
16024
2a0e69ae 16025 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 16026 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 16027}
16028
16029void bgp_route_finish(void)
16030{
16031 afi_t afi;
16032 safi_t safi;
16033
05c7a1cc
QY
16034 FOREACH_AFI_SAFI (afi, safi) {
16035 bgp_table_unlock(bgp_distance_table[afi][safi]);
16036 bgp_distance_table[afi][safi] = NULL;
16037 }
228da428 16038}